1 | ;
|
2 |
|
3 | var ono = require('ono'),
|
4 | $Ref = require('./ref'),
|
5 | url = require('./util/url');
|
6 |
|
7 | module.exports = $Refs;
|
8 |
|
9 | /**
|
10 | * This class is a map of JSON references and their resolved values.
|
11 | */
|
12 | function $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 | */
|
178 | function 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 | }
|