UNPKG

5.38 kBJavaScriptView Raw
1'use strict';
2
3var ono = require('ono'),
4 $Ref = require('./ref'),
5 url = require('./util/url');
6
7module.exports = $Refs;
8
9/**
10 * This class is a map of JSON references and their resolved values.
11 */
12function $Refs () {
13 /**
14 * Indicates whether the schema contains any circular references.
15 *
16 * @type {boolean}
17 */
18 this.circular = false;
19
20 /**
21 * A map of paths/urls to {@link $Ref} objects
22 *
23 * @type {object}
24 * @protected
25 */
26 this._$refs = {};
27
28 /**
29 * The {@link $Ref} object that is the root of the JSON schema.
30 *
31 * @type {$Ref}
32 * @protected
33 */
34 this._root$Ref = null;
35}
36
37/**
38 * Returns the paths of all the files/URLs that are referenced by the JSON schema,
39 * including the schema itself.
40 *
41 * @param {...string|string[]} [types] - Only return paths of the given types ("file", "http", etc.)
42 * @returns {string[]}
43 */
44$Refs.prototype.paths = function (types) {
45 var paths = getPaths(this._$refs, arguments);
46 return paths.map(function (path) {
47 return path.decoded;
48 });
49};
50
51/**
52 * Returns the map of JSON references and their resolved values.
53 *
54 * @param {...string|string[]} [types] - Only return references of the given types ("file", "http", etc.)
55 * @returns {object}
56 */
57$Refs.prototype.values = function (types) {
58 var $refs = this._$refs;
59 var paths = getPaths($refs, arguments);
60 return paths.reduce(function (obj, path) {
61 obj[path.decoded] = $refs[path.encoded].value;
62 return obj;
63 }, {});
64};
65
66/**
67 * Returns a POJO (plain old JavaScript object) for serialization as JSON.
68 *
69 * @returns {object}
70 */
71$Refs.prototype.toJSON = $Refs.prototype.values;
72
73/**
74 * Determines whether the given JSON reference exists.
75 *
76 * @param {string} path - The path being resolved, optionally with a JSON pointer in the hash
77 * @param {$RefParserOptions} [options]
78 * @returns {boolean}
79 */
80$Refs.prototype.exists = function (path, options) {
81 try {
82 this._resolve(path, options);
83 return true;
84 }
85 catch (e) {
86 return false;
87 }
88};
89
90/**
91 * Resolves the given JSON reference and returns the resolved value.
92 *
93 * @param {string} path - The path being resolved, with a JSON pointer in the hash
94 * @param {$RefParserOptions} [options]
95 * @returns {*} - Returns the resolved value
96 */
97$Refs.prototype.get = function (path, options) {
98 return this._resolve(path, options).value;
99};
100
101/**
102 * Sets the value of a nested property within this {@link $Ref#value}.
103 * If the property, or any of its parents don't exist, they will be created.
104 *
105 * @param {string} path - The path of the property to set, optionally with a JSON pointer in the hash
106 * @param {*} value - The value to assign
107 */
108$Refs.prototype.set = function (path, value) {
109 var absPath = url.resolve(this._root$Ref.path, path);
110 var withoutHash = url.stripHash(absPath);
111 var $ref = this._$refs[withoutHash];
112
113 if (!$ref) {
114 throw ono('Error resolving $ref pointer "%s". \n"%s" not found.', path, withoutHash);
115 }
116
117 $ref.set(absPath, value);
118};
119
120/**
121 * Creates a new {@link $Ref} object and adds it to this {@link $Refs} object.
122 *
123 * @param {string} path - The file path or URL of the referenced file
124 */
125$Refs.prototype._add = function (path) {
126 var withoutHash = url.stripHash(path);
127
128 var $ref = new $Ref();
129 $ref.path = withoutHash;
130 $ref.$refs = this;
131
132 this._$refs[withoutHash] = $ref;
133 this._root$Ref = this._root$Ref || $ref;
134
135 return $ref;
136};
137
138/**
139 * Resolves the given JSON reference.
140 *
141 * @param {string} path - The path being resolved, optionally with a JSON pointer in the hash
142 * @param {$RefParserOptions} [options]
143 * @returns {Pointer}
144 * @protected
145 */
146$Refs.prototype._resolve = function (path, options) {
147 var absPath = url.resolve(this._root$Ref.path, path);
148 var withoutHash = url.stripHash(absPath);
149 var $ref = this._$refs[withoutHash];
150
151 if (!$ref) {
152 throw ono('Error resolving $ref pointer "%s". \n"%s" not found.', path, withoutHash);
153 }
154
155 return $ref.resolve(absPath, options, path);
156};
157
158/**
159 * Returns the specified {@link $Ref} object, or undefined.
160 *
161 * @param {string} path - The path being resolved, optionally with a JSON pointer in the hash
162 * @returns {$Ref|undefined}
163 * @protected
164 */
165$Refs.prototype._get$Ref = function (path) {
166 path = url.resolve(this._root$Ref.path, path);
167 var withoutHash = url.stripHash(path);
168 return this._$refs[withoutHash];
169};
170
171/**
172 * Returns the encoded and decoded paths keys of the given object.
173 *
174 * @param {object} $refs - The object whose keys are URL-encoded paths
175 * @param {...string|string[]} [types] - Only return paths of the given types ("file", "http", etc.)
176 * @returns {object[]}
177 */
178function getPaths ($refs, types) {
179 var paths = Object.keys($refs);
180
181 // Filter the paths by type
182 types = Array.isArray(types[0]) ? types[0] : Array.prototype.slice.call(types);
183 if (types.length > 0 && types[0]) {
184 paths = paths.filter(function (key) {
185 return types.indexOf($refs[key].pathType) !== -1;
186 });
187 }
188
189 // Decode local filesystem paths
190 return paths.map(function (path) {
191 return {
192 encoded: path,
193 decoded: $refs[path].pathType === 'file' ? url.toFileSystemPath(path, true) : path
194 };
195 });
196}