diff --git a/dist/ref-parser.js b/dist/ref-parser.js index 0baf2f40..bb6e396d 100644 --- a/dist/ref-parser.js +++ b/dist/ref-parser.js @@ -1,6 +1,6 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.$RefParser = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {\n keys.splice(0, 0, keys.splice(defs, 1)[0]);\n }\n\n keys.forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n\n if ($Ref.is$Ref(value)) {\n // Skip this $ref if we've already inventoried it\n if (!inventory.some(function(i) { return i.parent === obj && i.key === key; })) {\n inventory$Ref(obj, key, path, keyPathFromRoot, inventory, $refs, options);\n }\n }\n else {\n crawl(value, keyPath, keyPathFromRoot, inventory, $refs, options);\n }\n });\n }\n}\n\n/**\n * Inventories the given JSON Reference (i.e. records detailed information about it so we can\n * optimize all $refs in the schema), and then crawls the resolved value.\n *\n * @param {object} $refParent - The object that contains a JSON Reference as one of its keys\n * @param {string} $refKey - The key in `$refParent` that is a JSON Reference\n * @param {string} path - The full path of the JSON Reference at `$refKey`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of the JSON Reference at `$refKey`, from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction inventory$Ref($refParent, $refKey, path, pathFromRoot, inventory, $refs, options) {\n var $ref = $refParent[$refKey];\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n var depth = Pointer.parse(pathFromRoot).length;\n var file = util.path.stripHash(pointer.path);\n var hash = util.path.getHash(pointer.path);\n var external = file !== $refs._basePath;\n var extended = Object.keys($ref).length > 1;\n\n inventory.push({\n $ref: $ref, // The JSON Reference (e.g. {$ref: string})\n parent: $refParent, // The object that contains this $ref pointer\n key: $refKey, // The key in `parent` that is the $ref pointer\n pathFromRoot: pathFromRoot, // The path to the $ref pointer, from the JSON Schema root\n depth: depth, // How far from the JSON Schema root is this $ref pointer?\n file: file, // The file that the $ref pointer resolves to\n hash: hash, // The hash within `file` that the $ref pointer resolves to\n value: pointer.value, // The resolved value of the $ref pointer\n circular: pointer.circular, // Is this $ref pointer DIRECTLY circular? (i.e. it references itself)\n extended: extended, // Does this $ref extend its resolved value? (i.e. it has extra properties, in addition to \"$ref\")\n external: external // Does this $ref pointer point to a file other than the main JSON Schema file?\n });\n\n // Recursively crawl the resolved value\n crawl(pointer.value, pointer.path, pathFromRoot, inventory, $refs, options);\n}\n\n/**\n * Re-maps every $ref pointer, so that they're all relative to the root of the JSON Schema.\n * Each referenced value is dereferenced EXACTLY ONCE. All subsequent references to the same\n * value are re-mapped to point to the first reference.\n *\n * @example:\n * {\n * first: { $ref: somefile.json#/some/part },\n * second: { $ref: somefile.json#/another/part },\n * third: { $ref: somefile.json },\n * fourth: { $ref: somefile.json#/some/part/sub/part }\n * }\n *\n * In this example, there are four references to the same file, but since the third reference points\n * to the ENTIRE file, that's the only one we need to dereference. The other three can just be\n * remapped to point inside the third one.\n *\n * On the other hand, if the third reference DIDN'T exist, then the first and second would both need\n * to be dereferenced, since they point to different parts of the file. The fourth reference does NOT\n * need to be dereferenced, because it can be remapped to point inside the first one.\n *\n * @param {object[]} inventory\n */\nfunction remap(inventory) {\n // Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them\n inventory.sort(function(a, b) {\n if (a.file !== b.file) {\n return a.file < b.file ? -1 : +1; // Group all the $refs that point to the same file\n }\n else if (a.hash !== b.hash) {\n return a.hash < b.hash ? -1 : +1; // Group all the $refs that point to the same part of the file\n }\n else if (a.circular !== b.circular) {\n return a.circular ? -1 : +1; // If the $ref points to itself, then sort it higher than other $refs that point to this $ref\n }\n else if (a.extended !== b.extended) {\n return a.extended ? +1 : -1; // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value\n }\n else if (a.depth !== b.depth) {\n return a.depth - b.depth; // Sort $refs by how close they are to the JSON Schema root\n }\n else {\n // If all else is equal, use the $ref that's in the \"definitions\" property\n return b.pathFromRoot.lastIndexOf('/definitions') - a.pathFromRoot.lastIndexOf('/definitions');\n }\n });\n\n var file, hash, pathFromRoot;\n inventory.forEach(function(i) {\n util.debug('Re-mapping $ref pointer \"%s\" at %s', i.$ref.$ref, i.pathFromRoot);\n\n if (!i.external) {\n // This $ref already resolves to the main JSON Schema file\n i.$ref.$ref = i.hash;\n }\n else if (i.file !== file || i.hash.indexOf(hash) !== 0) {\n // We've moved to a new file or new hash\n file = i.file;\n hash = i.hash;\n pathFromRoot = i.pathFromRoot;\n\n // This is the first $ref to point to this value, so dereference the value.\n // Any other $refs that point to the same value will point to this $ref instead\n i.$ref = i.parent[i.key] = util.dereference(i.$ref, i.value);\n\n if (i.circular) {\n // This $ref points to itself\n i.$ref.$ref = i.pathFromRoot;\n }\n }\n else {\n // This $ref points to the same value as the prevous $ref\n i.$ref.$ref = Pointer.join(pathFromRoot, Pointer.parse(i.hash));\n }\n\n util.debug(' new value: %s', (i.$ref && i.$ref.$ref) ? i.$ref.$ref : '[object Object]');\n });\n}\n", + "/** !\n * JSON Schema $Ref Parser v2.2.0\n *\n * @link https://github.com/BigstickCarpet/json-schema-ref-parser\n * @license MIT\n */\n'use strict';\n\nvar $Ref = require('./ref'),\n Pointer = require('./pointer'),\n util = require('./util'),\n url = require('url');\n\nmodule.exports = bundle;\n\n/**\n * Bundles all external JSON references into the main JSON schema, thus resulting in a schema that\n * only has *internal* references, not any *external* references.\n * This method mutates the JSON schema object, adding new references and re-mapping existing ones.\n *\n * @param {$RefParser} parser\n * @param {$RefParserOptions} options\n */\nfunction bundle(parser, options) {\n util.debug('Bundling $ref pointers in %s', parser.$refs._basePath);\n\n // Build an inventory of all $ref pointers in the JSON Schema\n var inventory = [];\n crawl(parser.schema, parser.$refs._basePath + '#', '#', inventory, parser.$refs, options);\n\n // Remap all $ref pointers\n remap(inventory);\n}\n\n/**\n * Recursively crawls the given value, and inventories all JSON references.\n *\n * @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.\n * @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `obj` from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction crawl(obj, path, pathFromRoot, inventory, $refs, options) {\n if (obj && typeof obj === 'object') {\n var keys = Object.keys(obj);\n\n // Most people will expect references to be bundled into the the \"definitions\" property,\n // so we always crawl that property first, if it exists.\n var defs = keys.indexOf('definitions');\n if (defs > 0) {\n keys.splice(0, 0, keys.splice(defs, 1)[0]);\n }\n\n keys.forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n\n if ($Ref.is$Ref(value)) {\n // Skip this $ref if we've already inventoried it\n if (!inventory.some(function(i) { return i.parent === obj && i.key === key; })) {\n inventory$Ref(obj, key, path, keyPathFromRoot, inventory, $refs, options);\n }\n }\n else {\n crawl(value, keyPath, keyPathFromRoot, inventory, $refs, options);\n }\n });\n }\n}\n\n/**\n * Inventories the given JSON Reference (i.e. records detailed information about it so we can\n * optimize all $refs in the schema), and then crawls the resolved value.\n *\n * @param {object} $refParent - The object that contains a JSON Reference as one of its keys\n * @param {string} $refKey - The key in `$refParent` that is a JSON Reference\n * @param {string} path - The full path of the JSON Reference at `$refKey`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of the JSON Reference at `$refKey`, from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction inventory$Ref($refParent, $refKey, path, pathFromRoot, inventory, $refs, options) {\n var $ref = $refParent[$refKey];\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n var depth = Pointer.parse(pathFromRoot).length;\n var file = util.path.stripHash(pointer.path);\n var hash = util.path.getHash(pointer.path);\n var external = file !== $refs._basePath;\n var extended = Object.keys($ref).length > 1;\n\n inventory.push({\n $ref: $ref, // The JSON Reference (e.g. {$ref: string})\n parent: $refParent, // The object that contains this $ref pointer\n key: $refKey, // The key in `parent` that is the $ref pointer\n pathFromRoot: pathFromRoot, // The path to the $ref pointer, from the JSON Schema root\n depth: depth, // How far from the JSON Schema root is this $ref pointer?\n file: file, // The file that the $ref pointer resolves to\n hash: hash, // The hash within `file` that the $ref pointer resolves to\n value: pointer.value, // The resolved value of the $ref pointer\n circular: pointer.circular, // Is this $ref pointer DIRECTLY circular? (i.e. it references itself)\n extended: extended, // Does this $ref extend its resolved value? (i.e. it has extra properties, in addition to \"$ref\")\n external: external // Does this $ref pointer point to a file other than the main JSON Schema file?\n });\n\n // Recursively crawl the resolved value\n crawl(pointer.value, pointer.path, pathFromRoot, inventory, $refs, options);\n}\n\n/**\n * Re-maps every $ref pointer, so that they're all relative to the root of the JSON Schema.\n * Each referenced value is dereferenced EXACTLY ONCE. All subsequent references to the same\n * value are re-mapped to point to the first reference.\n *\n * @example:\n * {\n * first: { $ref: somefile.json#/some/part },\n * second: { $ref: somefile.json#/another/part },\n * third: { $ref: somefile.json },\n * fourth: { $ref: somefile.json#/some/part/sub/part }\n * }\n *\n * In this example, there are four references to the same file, but since the third reference points\n * to the ENTIRE file, that's the only one we need to dereference. The other three can just be\n * remapped to point inside the third one.\n *\n * On the other hand, if the third reference DIDN'T exist, then the first and second would both need\n * to be dereferenced, since they point to different parts of the file. The fourth reference does NOT\n * need to be dereferenced, because it can be remapped to point inside the first one.\n *\n * @param {object[]} inventory\n */\nfunction remap(inventory) {\n // Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them\n inventory.sort(function(a, b) {\n if (a.file !== b.file) {\n return a.file < b.file ? -1 : +1; // Group all the $refs that point to the same file\n }\n else if (a.hash !== b.hash) {\n return a.hash < b.hash ? -1 : +1; // Group all the $refs that point to the same part of the file\n }\n else if (a.circular !== b.circular) {\n return a.circular ? -1 : +1; // If the $ref points to itself, then sort it higher than other $refs that point to this $ref\n }\n else if (a.extended !== b.extended) {\n return a.extended ? +1 : -1; // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value\n }\n else if (a.depth !== b.depth) {\n return a.depth - b.depth; // Sort $refs by how close they are to the JSON Schema root\n }\n else {\n // If all else is equal, use the $ref that's in the \"definitions\" property\n return b.pathFromRoot.lastIndexOf('/definitions') - a.pathFromRoot.lastIndexOf('/definitions');\n }\n });\n\n var file, hash, pathFromRoot;\n inventory.forEach(function(i) {\n util.debug('Re-mapping $ref pointer \"%s\" at %s', i.$ref.$ref, i.pathFromRoot);\n\n if (!i.external) {\n // This $ref already resolves to the main JSON Schema file\n i.$ref.$ref = i.hash;\n }\n else if (i.file !== file || i.hash.indexOf(hash) !== 0) {\n // We've moved to a new file or new hash\n file = i.file;\n hash = i.hash;\n pathFromRoot = i.pathFromRoot;\n\n // This is the first $ref to point to this value, so dereference the value.\n // Any other $refs that point to the same value will point to this $ref instead\n i.$ref = i.parent[i.key] = util.dereference(i.$ref, i.value);\n\n if (i.circular) {\n // This $ref points to itself\n i.$ref.$ref = i.pathFromRoot;\n }\n }\n else {\n // This $ref points to the same value as the prevous $ref\n i.$ref.$ref = Pointer.join(pathFromRoot, Pointer.parse(i.hash));\n }\n\n util.debug(' new value: %s', (i.$ref && i.$ref.$ref) ? i.$ref.$ref : '[object Object]');\n });\n}\n", "'use strict';\n\nvar $Ref = require('./ref'),\n Pointer = require('./pointer'),\n util = require('./util'),\n ono = require('ono'),\n url = require('url');\n\nmodule.exports = dereference;\n\n/**\n * Crawls the JSON schema, finds all JSON references, and dereferences them.\n * This method mutates the JSON schema object, replacing JSON references with their resolved value.\n *\n * @param {$RefParser} parser\n * @param {$RefParserOptions} options\n */\nfunction dereference(parser, options) {\n util.debug('Dereferencing $ref pointers in %s', parser.$refs._basePath);\n parser.$refs.circular = false;\n crawl(parser.schema, parser.$refs._basePath, '#', [], parser.$refs, options);\n}\n\n/**\n * Recursively crawls the given value, and dereferences any JSON references.\n *\n * @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.\n * @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `obj` from the schema root\n * @param {object[]} parents - An array of the parent objects that have already been dereferenced\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {boolean} - Returns true if a circular reference was found\n */\nfunction crawl(obj, path, pathFromRoot, parents, $refs, options) {\n var isCircular = false;\n\n if (obj && typeof obj === 'object') {\n parents.push(obj);\n\n Object.keys(obj).forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n var circular = false;\n\n if ($Ref.isAllowed$Ref(value, options)) {\n var dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, $refs, options);\n circular = dereferenced.circular;\n obj[key] = dereferenced.value;\n }\n else {\n if (parents.indexOf(value) === -1) {\n circular = crawl(value, keyPath, keyPathFromRoot, parents, $refs, options);\n }\n else {\n circular = foundCircularReference(keyPath, $refs, options);\n }\n }\n\n // Set the \"isCircular\" flag if this or any other property is circular\n isCircular = isCircular || circular;\n });\n\n parents.pop();\n }\n return isCircular;\n}\n\n/**\n * Dereferences the given JSON Reference, and then crawls the resulting value.\n *\n * @param {{$ref: string}} $ref - The JSON Reference to resolve\n * @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `$ref` from the schema root\n * @param {object[]} parents - An array of the parent objects that have already been dereferenced\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {object}\n */\nfunction dereference$Ref($ref, path, pathFromRoot, parents, $refs, options) {\n util.debug('Dereferencing $ref pointer \"%s\" at %s', $ref.$ref, path);\n\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n\n // Check for circular references\n var directCircular = pointer.circular;\n var circular = directCircular || parents.indexOf(pointer.value) !== -1;\n circular && foundCircularReference(path, $refs, options);\n\n // Dereference the JSON reference\n var dereferencedValue = util.dereference($ref, pointer.value);\n\n // Crawl the dereferenced value (unless it's circular)\n if (!circular) {\n // If the `crawl` method returns true, then dereferenced value is circular\n circular = crawl(dereferencedValue, pointer.path, pathFromRoot, parents, $refs, options);\n }\n\n if (circular && !directCircular && options.$refs.circular === 'ignore') {\n // The user has chosen to \"ignore\" circular references, so don't change the value\n dereferencedValue = $ref;\n }\n\n if (directCircular) {\n // The pointer is a DIRECT circular reference (i.e. it references itself).\n // So replace the $ref path with the absolute path from the JSON Schema root\n dereferencedValue.$ref = pathFromRoot;\n }\n\n return {\n circular: circular,\n value: dereferencedValue\n };\n}\n\n/**\n * Called when a circular reference is found.\n * It sets the {@link $Refs#circular} flag, and throws an error if options.$refs.circular is false.\n *\n * @param {string} keyPath - The JSON Reference path of the circular reference\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {boolean} - always returns true, to indicate that a circular reference was found\n */\nfunction foundCircularReference(keyPath, $refs, options) {\n $refs.circular = true;\n if (!options.$refs.circular) {\n throw ono.reference('Circular $ref pointer found at %s', keyPath);\n }\n return true;\n}\n", "'use strict';\n\nvar http = require('http'),\n https = require('https'),\n url = require('url'),\n util = require('./util'),\n Promise = require('./promise'),\n ono = require('ono');\n\nmodule.exports = download;\n\n/**\n * Downloads the given file.\n *\n * @param {Url|string} u - The url to download (can be a parsed {@link Url} object)\n * @param {$RefParserOptions} options\n * @param {number} [redirects] - The redirect URLs that have already been followed\n *\n * @returns {Promise}\n * The promise resolves with the raw downloaded data, or rejects if there is an HTTP error.\n */\nfunction download(u, options, redirects) {\n return new Promise(function(resolve, reject) {\n u = url.parse(u);\n redirects = redirects || [];\n redirects.push(u.href);\n\n get(u, options)\n .then(function(res) {\n if (res.statusCode >= 400) {\n throw ono({status: res.statusCode}, 'HTTP ERROR %d', res.statusCode);\n }\n else if (res.statusCode >= 300) {\n if (redirects.length > options.http.redirects) {\n reject(ono({status: res.statusCode}, 'Error downloading %s. \\nToo many redirects: \\n %s',\n redirects[0], redirects.join(' \\n ')));\n }\n else if (!res.headers.location) {\n throw ono({status: res.statusCode}, 'HTTP %d redirect with no location header', res.statusCode);\n }\n else {\n util.debug('HTTP %d redirect %s -> %s', res.statusCode, u.href, res.headers.location);\n var redirectTo = url.resolve(u, res.headers.location);\n download(redirectTo, options, redirects).then(resolve, reject);\n }\n }\n else if (res.statusCode === 204 && !options.allow.empty) {\n throw ono({status: 204}, 'HTTP 204 (No Content)');\n }\n else {\n resolve(res.body || new Buffer(0));\n }\n })\n .catch(function(err) {\n reject(ono(err, 'Error downloading', u.href));\n });\n });\n}\n\n/**\n * Sends an HTTP GET request.\n *\n * @param {Url} u - A parsed {@link Url} object\n * @param {$RefParserOptions} options\n *\n * @returns {Promise}\n * The promise resolves with the HTTP Response object.\n */\nfunction get(u, options) {\n return new Promise(function(resolve, reject) {\n util.debug('GET', u.href);\n\n var protocol = u.protocol === 'https:' ? https : http;\n var req = protocol.get({\n hostname: u.hostname,\n port: u.port,\n path: u.path,\n auth: u.auth,\n headers: options.http.headers,\n withCredentials: options.http.withCredentials\n });\n\n if (typeof req.setTimeout === 'function') {\n req.setTimeout(options.http.timeout);\n }\n\n req.on('timeout', function() {\n req.abort();\n });\n\n req.on('error', reject);\n\n req.once('response', function(res) {\n res.body = new Buffer(0);\n\n res.on('data', function(data) {\n res.body = Buffer.concat([res.body, new Buffer(data)]);\n });\n\n res.on('error', reject);\n\n res.on('end', function() {\n resolve(res);\n });\n });\n });\n}\n", "'use strict';\n\nvar Promise = require('./promise'),\n Options = require('./options'),\n $Refs = require('./refs'),\n $Ref = require('./ref'),\n read = require('./read'),\n resolve = require('./resolve'),\n bundle = require('./bundle'),\n dereference = require('./dereference'),\n util = require('./util'),\n url = require('url'),\n maybe = require('call-me-maybe'),\n ono = require('ono');\n\nmodule.exports = $RefParser;\nmodule.exports.YAML = require('./yaml');\n\n/**\n * This class parses a JSON schema, builds a map of its JSON references and their resolved values,\n * and provides methods for traversing, manipulating, and dereferencing those references.\n *\n * @constructor\n */\nfunction $RefParser() {\n /**\n * The parsed (and possibly dereferenced) JSON schema object\n *\n * @type {object}\n * @readonly\n */\n this.schema = null;\n\n /**\n * The resolved JSON references\n *\n * @type {$Refs}\n */\n this.$refs = new $Refs();\n}\n\n/**\n * Parses the given JSON schema.\n * This method does not resolve any JSON references.\n * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed\n * @param {function} [callback] - An error-first callback. The second parameter is the parsed JSON schema object.\n * @returns {Promise} - The returned promise resolves with the parsed JSON schema object.\n */\n$RefParser.parse = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().parse(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema.\n * This method does not resolve any JSON references.\n * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed\n * @param {function} [callback] - An error-first callback. The second parameter is the parsed JSON schema object.\n * @returns {Promise} - The returned promise resolves with the parsed JSON schema object.\n */\n$RefParser.prototype.parse = function(schema, options, callback) {\n var args = normalizeArgs(arguments);\n\n if (args.schema && typeof args.schema === 'object') {\n // The schema is an object, not a path/url\n this.schema = args.schema;\n this.$refs._basePath = '';\n var $ref = new $Ref(this.$refs, this.$refs._basePath);\n $ref.setValue(this.schema, args.options);\n\n return maybe(args.callback, Promise.resolve(this.schema));\n }\n\n if (!args.schema || typeof args.schema !== 'string') {\n var err = ono('Expected a file path, URL, or object. Got %s', args.schema);\n return maybe(args.callback, Promise.reject(err));\n }\n\n var me = this;\n\n // Resolve the absolute path of the schema\n args.schema = util.path.localPathToUrl(args.schema);\n args.schema = url.resolve(util.path.cwd(), args.schema);\n this.$refs._basePath = util.path.stripHash(args.schema);\n\n // Read the schema file/url\n return read(args.schema, this.$refs, args.options)\n .then(function(result) {\n var value = result.$ref.value;\n if (!value || typeof value !== 'object' || value instanceof Buffer) {\n throw ono.syntax('\"%s\" is not a valid JSON Schema', me.$refs._basePath);\n }\n else {\n me.schema = value;\n return maybe(args.callback, Promise.resolve(me.schema));\n }\n })\n .catch(function(e) {\n return maybe(args.callback, Promise.reject(e));\n });\n};\n\n/**\n * Parses the given JSON schema and resolves any JSON references, including references in\n * externally-referenced files.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed and resolved\n * @param {function} [callback]\n * - An error-first callback. The second parameter is a {@link $Refs} object containing the resolved JSON references\n *\n * @returns {Promise}\n * The returned promise resolves with a {@link $Refs} object containing the resolved JSON references\n */\n$RefParser.resolve = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().resolve(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema and resolves any JSON references, including references in\n * externally-referenced files.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed and resolved\n * @param {function} [callback]\n * - An error-first callback. The second parameter is a {@link $Refs} object containing the resolved JSON references\n *\n * @returns {Promise}\n * The returned promise resolves with a {@link $Refs} object containing the resolved JSON references\n */\n$RefParser.prototype.resolve = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.parse(args.schema, args.options)\n .then(function() {\n return resolve(me, args.options);\n })\n .then(function() {\n return maybe(args.callback, Promise.resolve(me.$refs));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and bundles all external references\n * into the main JSON schema. This produces a JSON schema that only has *internal* references,\n * not any *external* references.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the bundled JSON schema object\n * @returns {Promise} - The returned promise resolves with the bundled JSON schema object.\n */\n$RefParser.bundle = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().bundle(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and bundles all external references\n * into the main JSON schema. This produces a JSON schema that only has *internal* references,\n * not any *external* references.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the bundled JSON schema object\n * @returns {Promise} - The returned promise resolves with the bundled JSON schema object.\n */\n$RefParser.prototype.bundle = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.resolve(args.schema, args.options)\n .then(function() {\n bundle(me, args.options);\n return maybe(args.callback, Promise.resolve(me.schema));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and dereferences the JSON schema.\n * That is, all JSON references are replaced with their resolved values.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the dereferenced JSON schema object\n * @returns {Promise} - The returned promise resolves with the dereferenced JSON schema object.\n */\n$RefParser.dereference = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().dereference(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and dereferences the JSON schema.\n * That is, all JSON references are replaced with their resolved values.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the dereferenced JSON schema object\n * @returns {Promise} - The returned promise resolves with the dereferenced JSON schema object.\n */\n$RefParser.prototype.dereference = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.resolve(args.schema, args.options)\n .then(function() {\n dereference(me, args.options);\n return maybe(args.callback, Promise.resolve(me.schema));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Normalizes the given arguments, accounting for optional args.\n *\n * @param {Arguments} args\n * @returns {object}\n */\nfunction normalizeArgs(args) {\n var options = args[1], callback = args[2];\n if (typeof options === 'function') {\n callback = options;\n options = undefined;\n }\n if (!(options instanceof Options)) {\n options = new Options(options);\n }\n return {\n schema: args[0],\n options: options,\n callback: callback\n };\n}\n", diff --git a/dist/ref-parser.min.js b/dist/ref-parser.min.js index 3ed79b7c..45df7c8a 100644 --- a/dist/ref-parser.min.js +++ b/dist/ref-parser.min.js @@ -1,6 +1,6 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.$RefParser = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {\n keys.splice(0, 0, keys.splice(defs, 1)[0]);\n }\n\n keys.forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n\n if ($Ref.is$Ref(value)) {\n // Skip this $ref if we've already inventoried it\n if (!inventory.some(function(i) { return i.parent === obj && i.key === key; })) {\n inventory$Ref(obj, key, path, keyPathFromRoot, inventory, $refs, options);\n }\n }\n else {\n crawl(value, keyPath, keyPathFromRoot, inventory, $refs, options);\n }\n });\n }\n}\n\n/**\n * Inventories the given JSON Reference (i.e. records detailed information about it so we can\n * optimize all $refs in the schema), and then crawls the resolved value.\n *\n * @param {object} $refParent - The object that contains a JSON Reference as one of its keys\n * @param {string} $refKey - The key in `$refParent` that is a JSON Reference\n * @param {string} path - The full path of the JSON Reference at `$refKey`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of the JSON Reference at `$refKey`, from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction inventory$Ref($refParent, $refKey, path, pathFromRoot, inventory, $refs, options) {\n var $ref = $refParent[$refKey];\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n var depth = Pointer.parse(pathFromRoot).length;\n var file = util.path.stripHash(pointer.path);\n var hash = util.path.getHash(pointer.path);\n var external = file !== $refs._basePath;\n var extended = Object.keys($ref).length > 1;\n\n inventory.push({\n $ref: $ref, // The JSON Reference (e.g. {$ref: string})\n parent: $refParent, // The object that contains this $ref pointer\n key: $refKey, // The key in `parent` that is the $ref pointer\n pathFromRoot: pathFromRoot, // The path to the $ref pointer, from the JSON Schema root\n depth: depth, // How far from the JSON Schema root is this $ref pointer?\n file: file, // The file that the $ref pointer resolves to\n hash: hash, // The hash within `file` that the $ref pointer resolves to\n value: pointer.value, // The resolved value of the $ref pointer\n circular: pointer.circular, // Is this $ref pointer DIRECTLY circular? (i.e. it references itself)\n extended: extended, // Does this $ref extend its resolved value? (i.e. it has extra properties, in addition to \"$ref\")\n external: external // Does this $ref pointer point to a file other than the main JSON Schema file?\n });\n\n // Recursively crawl the resolved value\n crawl(pointer.value, pointer.path, pathFromRoot, inventory, $refs, options);\n}\n\n/**\n * Re-maps every $ref pointer, so that they're all relative to the root of the JSON Schema.\n * Each referenced value is dereferenced EXACTLY ONCE. All subsequent references to the same\n * value are re-mapped to point to the first reference.\n *\n * @example:\n * {\n * first: { $ref: somefile.json#/some/part },\n * second: { $ref: somefile.json#/another/part },\n * third: { $ref: somefile.json },\n * fourth: { $ref: somefile.json#/some/part/sub/part }\n * }\n *\n * In this example, there are four references to the same file, but since the third reference points\n * to the ENTIRE file, that's the only one we need to dereference. The other three can just be\n * remapped to point inside the third one.\n *\n * On the other hand, if the third reference DIDN'T exist, then the first and second would both need\n * to be dereferenced, since they point to different parts of the file. The fourth reference does NOT\n * need to be dereferenced, because it can be remapped to point inside the first one.\n *\n * @param {object[]} inventory\n */\nfunction remap(inventory) {\n // Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them\n inventory.sort(function(a, b) {\n if (a.file !== b.file) {\n return a.file < b.file ? -1 : +1; // Group all the $refs that point to the same file\n }\n else if (a.hash !== b.hash) {\n return a.hash < b.hash ? -1 : +1; // Group all the $refs that point to the same part of the file\n }\n else if (a.circular !== b.circular) {\n return a.circular ? -1 : +1; // If the $ref points to itself, then sort it higher than other $refs that point to this $ref\n }\n else if (a.extended !== b.extended) {\n return a.extended ? +1 : -1; // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value\n }\n else if (a.depth !== b.depth) {\n return a.depth - b.depth; // Sort $refs by how close they are to the JSON Schema root\n }\n else {\n // If all else is equal, use the $ref that's in the \"definitions\" property\n return b.pathFromRoot.lastIndexOf('/definitions') - a.pathFromRoot.lastIndexOf('/definitions');\n }\n });\n\n var file, hash, pathFromRoot;\n inventory.forEach(function(i) {\n util.debug('Re-mapping $ref pointer \"%s\" at %s', i.$ref.$ref, i.pathFromRoot);\n\n if (!i.external) {\n // This $ref already resolves to the main JSON Schema file\n i.$ref.$ref = i.hash;\n }\n else if (i.file !== file || i.hash.indexOf(hash) !== 0) {\n // We've moved to a new file or new hash\n file = i.file;\n hash = i.hash;\n pathFromRoot = i.pathFromRoot;\n\n // This is the first $ref to point to this value, so dereference the value.\n // Any other $refs that point to the same value will point to this $ref instead\n i.$ref = i.parent[i.key] = util.dereference(i.$ref, i.value);\n\n if (i.circular) {\n // This $ref points to itself\n i.$ref.$ref = i.pathFromRoot;\n }\n }\n else {\n // This $ref points to the same value as the prevous $ref\n i.$ref.$ref = Pointer.join(pathFromRoot, Pointer.parse(i.hash));\n }\n\n util.debug(' new value: %s', (i.$ref && i.$ref.$ref) ? i.$ref.$ref : '[object Object]');\n });\n}\n", + "/** !\n * JSON Schema $Ref Parser v2.2.0\n *\n * @link https://github.com/BigstickCarpet/json-schema-ref-parser\n * @license MIT\n */\n'use strict';\n\nvar $Ref = require('./ref'),\n Pointer = require('./pointer'),\n util = require('./util'),\n url = require('url');\n\nmodule.exports = bundle;\n\n/**\n * Bundles all external JSON references into the main JSON schema, thus resulting in a schema that\n * only has *internal* references, not any *external* references.\n * This method mutates the JSON schema object, adding new references and re-mapping existing ones.\n *\n * @param {$RefParser} parser\n * @param {$RefParserOptions} options\n */\nfunction bundle(parser, options) {\n util.debug('Bundling $ref pointers in %s', parser.$refs._basePath);\n\n // Build an inventory of all $ref pointers in the JSON Schema\n var inventory = [];\n crawl(parser.schema, parser.$refs._basePath + '#', '#', inventory, parser.$refs, options);\n\n // Remap all $ref pointers\n remap(inventory);\n}\n\n/**\n * Recursively crawls the given value, and inventories all JSON references.\n *\n * @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.\n * @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `obj` from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction crawl(obj, path, pathFromRoot, inventory, $refs, options) {\n if (obj && typeof obj === 'object') {\n var keys = Object.keys(obj);\n\n // Most people will expect references to be bundled into the the \"definitions\" property,\n // so we always crawl that property first, if it exists.\n var defs = keys.indexOf('definitions');\n if (defs > 0) {\n keys.splice(0, 0, keys.splice(defs, 1)[0]);\n }\n\n keys.forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n\n if ($Ref.is$Ref(value)) {\n // Skip this $ref if we've already inventoried it\n if (!inventory.some(function(i) { return i.parent === obj && i.key === key; })) {\n inventory$Ref(obj, key, path, keyPathFromRoot, inventory, $refs, options);\n }\n }\n else {\n crawl(value, keyPath, keyPathFromRoot, inventory, $refs, options);\n }\n });\n }\n}\n\n/**\n * Inventories the given JSON Reference (i.e. records detailed information about it so we can\n * optimize all $refs in the schema), and then crawls the resolved value.\n *\n * @param {object} $refParent - The object that contains a JSON Reference as one of its keys\n * @param {string} $refKey - The key in `$refParent` that is a JSON Reference\n * @param {string} path - The full path of the JSON Reference at `$refKey`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of the JSON Reference at `$refKey`, from the schema root\n * @param {object[]} inventory - An array of already-inventoried $ref pointers\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n */\nfunction inventory$Ref($refParent, $refKey, path, pathFromRoot, inventory, $refs, options) {\n var $ref = $refParent[$refKey];\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n var depth = Pointer.parse(pathFromRoot).length;\n var file = util.path.stripHash(pointer.path);\n var hash = util.path.getHash(pointer.path);\n var external = file !== $refs._basePath;\n var extended = Object.keys($ref).length > 1;\n\n inventory.push({\n $ref: $ref, // The JSON Reference (e.g. {$ref: string})\n parent: $refParent, // The object that contains this $ref pointer\n key: $refKey, // The key in `parent` that is the $ref pointer\n pathFromRoot: pathFromRoot, // The path to the $ref pointer, from the JSON Schema root\n depth: depth, // How far from the JSON Schema root is this $ref pointer?\n file: file, // The file that the $ref pointer resolves to\n hash: hash, // The hash within `file` that the $ref pointer resolves to\n value: pointer.value, // The resolved value of the $ref pointer\n circular: pointer.circular, // Is this $ref pointer DIRECTLY circular? (i.e. it references itself)\n extended: extended, // Does this $ref extend its resolved value? (i.e. it has extra properties, in addition to \"$ref\")\n external: external // Does this $ref pointer point to a file other than the main JSON Schema file?\n });\n\n // Recursively crawl the resolved value\n crawl(pointer.value, pointer.path, pathFromRoot, inventory, $refs, options);\n}\n\n/**\n * Re-maps every $ref pointer, so that they're all relative to the root of the JSON Schema.\n * Each referenced value is dereferenced EXACTLY ONCE. All subsequent references to the same\n * value are re-mapped to point to the first reference.\n *\n * @example:\n * {\n * first: { $ref: somefile.json#/some/part },\n * second: { $ref: somefile.json#/another/part },\n * third: { $ref: somefile.json },\n * fourth: { $ref: somefile.json#/some/part/sub/part }\n * }\n *\n * In this example, there are four references to the same file, but since the third reference points\n * to the ENTIRE file, that's the only one we need to dereference. The other three can just be\n * remapped to point inside the third one.\n *\n * On the other hand, if the third reference DIDN'T exist, then the first and second would both need\n * to be dereferenced, since they point to different parts of the file. The fourth reference does NOT\n * need to be dereferenced, because it can be remapped to point inside the first one.\n *\n * @param {object[]} inventory\n */\nfunction remap(inventory) {\n // Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them\n inventory.sort(function(a, b) {\n if (a.file !== b.file) {\n return a.file < b.file ? -1 : +1; // Group all the $refs that point to the same file\n }\n else if (a.hash !== b.hash) {\n return a.hash < b.hash ? -1 : +1; // Group all the $refs that point to the same part of the file\n }\n else if (a.circular !== b.circular) {\n return a.circular ? -1 : +1; // If the $ref points to itself, then sort it higher than other $refs that point to this $ref\n }\n else if (a.extended !== b.extended) {\n return a.extended ? +1 : -1; // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value\n }\n else if (a.depth !== b.depth) {\n return a.depth - b.depth; // Sort $refs by how close they are to the JSON Schema root\n }\n else {\n // If all else is equal, use the $ref that's in the \"definitions\" property\n return b.pathFromRoot.lastIndexOf('/definitions') - a.pathFromRoot.lastIndexOf('/definitions');\n }\n });\n\n var file, hash, pathFromRoot;\n inventory.forEach(function(i) {\n util.debug('Re-mapping $ref pointer \"%s\" at %s', i.$ref.$ref, i.pathFromRoot);\n\n if (!i.external) {\n // This $ref already resolves to the main JSON Schema file\n i.$ref.$ref = i.hash;\n }\n else if (i.file !== file || i.hash.indexOf(hash) !== 0) {\n // We've moved to a new file or new hash\n file = i.file;\n hash = i.hash;\n pathFromRoot = i.pathFromRoot;\n\n // This is the first $ref to point to this value, so dereference the value.\n // Any other $refs that point to the same value will point to this $ref instead\n i.$ref = i.parent[i.key] = util.dereference(i.$ref, i.value);\n\n if (i.circular) {\n // This $ref points to itself\n i.$ref.$ref = i.pathFromRoot;\n }\n }\n else {\n // This $ref points to the same value as the prevous $ref\n i.$ref.$ref = Pointer.join(pathFromRoot, Pointer.parse(i.hash));\n }\n\n util.debug(' new value: %s', (i.$ref && i.$ref.$ref) ? i.$ref.$ref : '[object Object]');\n });\n}\n", "'use strict';\n\nvar $Ref = require('./ref'),\n Pointer = require('./pointer'),\n util = require('./util'),\n ono = require('ono'),\n url = require('url');\n\nmodule.exports = dereference;\n\n/**\n * Crawls the JSON schema, finds all JSON references, and dereferences them.\n * This method mutates the JSON schema object, replacing JSON references with their resolved value.\n *\n * @param {$RefParser} parser\n * @param {$RefParserOptions} options\n */\nfunction dereference(parser, options) {\n util.debug('Dereferencing $ref pointers in %s', parser.$refs._basePath);\n parser.$refs.circular = false;\n crawl(parser.schema, parser.$refs._basePath, '#', [], parser.$refs, options);\n}\n\n/**\n * Recursively crawls the given value, and dereferences any JSON references.\n *\n * @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.\n * @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `obj` from the schema root\n * @param {object[]} parents - An array of the parent objects that have already been dereferenced\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {boolean} - Returns true if a circular reference was found\n */\nfunction crawl(obj, path, pathFromRoot, parents, $refs, options) {\n var isCircular = false;\n\n if (obj && typeof obj === 'object') {\n parents.push(obj);\n\n Object.keys(obj).forEach(function(key) {\n var keyPath = Pointer.join(path, key);\n var keyPathFromRoot = Pointer.join(pathFromRoot, key);\n var value = obj[key];\n var circular = false;\n\n if ($Ref.isAllowed$Ref(value, options)) {\n var dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, $refs, options);\n circular = dereferenced.circular;\n obj[key] = dereferenced.value;\n }\n else {\n if (parents.indexOf(value) === -1) {\n circular = crawl(value, keyPath, keyPathFromRoot, parents, $refs, options);\n }\n else {\n circular = foundCircularReference(keyPath, $refs, options);\n }\n }\n\n // Set the \"isCircular\" flag if this or any other property is circular\n isCircular = isCircular || circular;\n });\n\n parents.pop();\n }\n return isCircular;\n}\n\n/**\n * Dereferences the given JSON Reference, and then crawls the resulting value.\n *\n * @param {{$ref: string}} $ref - The JSON Reference to resolve\n * @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash\n * @param {string} pathFromRoot - The path of `$ref` from the schema root\n * @param {object[]} parents - An array of the parent objects that have already been dereferenced\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {object}\n */\nfunction dereference$Ref($ref, path, pathFromRoot, parents, $refs, options) {\n util.debug('Dereferencing $ref pointer \"%s\" at %s', $ref.$ref, path);\n\n var $refPath = url.resolve(path, $ref.$ref);\n var pointer = $refs._resolve($refPath, options);\n\n // Check for circular references\n var directCircular = pointer.circular;\n var circular = directCircular || parents.indexOf(pointer.value) !== -1;\n circular && foundCircularReference(path, $refs, options);\n\n // Dereference the JSON reference\n var dereferencedValue = util.dereference($ref, pointer.value);\n\n // Crawl the dereferenced value (unless it's circular)\n if (!circular) {\n // If the `crawl` method returns true, then dereferenced value is circular\n circular = crawl(dereferencedValue, pointer.path, pathFromRoot, parents, $refs, options);\n }\n\n if (circular && !directCircular && options.$refs.circular === 'ignore') {\n // The user has chosen to \"ignore\" circular references, so don't change the value\n dereferencedValue = $ref;\n }\n\n if (directCircular) {\n // The pointer is a DIRECT circular reference (i.e. it references itself).\n // So replace the $ref path with the absolute path from the JSON Schema root\n dereferencedValue.$ref = pathFromRoot;\n }\n\n return {\n circular: circular,\n value: dereferencedValue\n };\n}\n\n/**\n * Called when a circular reference is found.\n * It sets the {@link $Refs#circular} flag, and throws an error if options.$refs.circular is false.\n *\n * @param {string} keyPath - The JSON Reference path of the circular reference\n * @param {$Refs} $refs\n * @param {$RefParserOptions} options\n * @returns {boolean} - always returns true, to indicate that a circular reference was found\n */\nfunction foundCircularReference(keyPath, $refs, options) {\n $refs.circular = true;\n if (!options.$refs.circular) {\n throw ono.reference('Circular $ref pointer found at %s', keyPath);\n }\n return true;\n}\n", "'use strict';\n\nvar http = require('http'),\n https = require('https'),\n url = require('url'),\n util = require('./util'),\n Promise = require('./promise'),\n ono = require('ono');\n\nmodule.exports = download;\n\n/**\n * Downloads the given file.\n *\n * @param {Url|string} u - The url to download (can be a parsed {@link Url} object)\n * @param {$RefParserOptions} options\n * @param {number} [redirects] - The redirect URLs that have already been followed\n *\n * @returns {Promise}\n * The promise resolves with the raw downloaded data, or rejects if there is an HTTP error.\n */\nfunction download(u, options, redirects) {\n return new Promise(function(resolve, reject) {\n u = url.parse(u);\n redirects = redirects || [];\n redirects.push(u.href);\n\n get(u, options)\n .then(function(res) {\n if (res.statusCode >= 400) {\n throw ono({status: res.statusCode}, 'HTTP ERROR %d', res.statusCode);\n }\n else if (res.statusCode >= 300) {\n if (redirects.length > options.http.redirects) {\n reject(ono({status: res.statusCode}, 'Error downloading %s. \\nToo many redirects: \\n %s',\n redirects[0], redirects.join(' \\n ')));\n }\n else if (!res.headers.location) {\n throw ono({status: res.statusCode}, 'HTTP %d redirect with no location header', res.statusCode);\n }\n else {\n util.debug('HTTP %d redirect %s -> %s', res.statusCode, u.href, res.headers.location);\n var redirectTo = url.resolve(u, res.headers.location);\n download(redirectTo, options, redirects).then(resolve, reject);\n }\n }\n else if (res.statusCode === 204 && !options.allow.empty) {\n throw ono({status: 204}, 'HTTP 204 (No Content)');\n }\n else {\n resolve(res.body || new Buffer(0));\n }\n })\n .catch(function(err) {\n reject(ono(err, 'Error downloading', u.href));\n });\n });\n}\n\n/**\n * Sends an HTTP GET request.\n *\n * @param {Url} u - A parsed {@link Url} object\n * @param {$RefParserOptions} options\n *\n * @returns {Promise}\n * The promise resolves with the HTTP Response object.\n */\nfunction get(u, options) {\n return new Promise(function(resolve, reject) {\n util.debug('GET', u.href);\n\n var protocol = u.protocol === 'https:' ? https : http;\n var req = protocol.get({\n hostname: u.hostname,\n port: u.port,\n path: u.path,\n auth: u.auth,\n headers: options.http.headers,\n withCredentials: options.http.withCredentials\n });\n\n if (typeof req.setTimeout === 'function') {\n req.setTimeout(options.http.timeout);\n }\n\n req.on('timeout', function() {\n req.abort();\n });\n\n req.on('error', reject);\n\n req.once('response', function(res) {\n res.body = new Buffer(0);\n\n res.on('data', function(data) {\n res.body = Buffer.concat([res.body, new Buffer(data)]);\n });\n\n res.on('error', reject);\n\n res.on('end', function() {\n resolve(res);\n });\n });\n });\n}\n", "'use strict';\n\nvar Promise = require('./promise'),\n Options = require('./options'),\n $Refs = require('./refs'),\n $Ref = require('./ref'),\n read = require('./read'),\n resolve = require('./resolve'),\n bundle = require('./bundle'),\n dereference = require('./dereference'),\n util = require('./util'),\n url = require('url'),\n maybe = require('call-me-maybe'),\n ono = require('ono');\n\nmodule.exports = $RefParser;\nmodule.exports.YAML = require('./yaml');\n\n/**\n * This class parses a JSON schema, builds a map of its JSON references and their resolved values,\n * and provides methods for traversing, manipulating, and dereferencing those references.\n *\n * @constructor\n */\nfunction $RefParser() {\n /**\n * The parsed (and possibly dereferenced) JSON schema object\n *\n * @type {object}\n * @readonly\n */\n this.schema = null;\n\n /**\n * The resolved JSON references\n *\n * @type {$Refs}\n */\n this.$refs = new $Refs();\n}\n\n/**\n * Parses the given JSON schema.\n * This method does not resolve any JSON references.\n * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed\n * @param {function} [callback] - An error-first callback. The second parameter is the parsed JSON schema object.\n * @returns {Promise} - The returned promise resolves with the parsed JSON schema object.\n */\n$RefParser.parse = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().parse(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema.\n * This method does not resolve any JSON references.\n * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed\n * @param {function} [callback] - An error-first callback. The second parameter is the parsed JSON schema object.\n * @returns {Promise} - The returned promise resolves with the parsed JSON schema object.\n */\n$RefParser.prototype.parse = function(schema, options, callback) {\n var args = normalizeArgs(arguments);\n\n if (args.schema && typeof args.schema === 'object') {\n // The schema is an object, not a path/url\n this.schema = args.schema;\n this.$refs._basePath = '';\n var $ref = new $Ref(this.$refs, this.$refs._basePath);\n $ref.setValue(this.schema, args.options);\n\n return maybe(args.callback, Promise.resolve(this.schema));\n }\n\n if (!args.schema || typeof args.schema !== 'string') {\n var err = ono('Expected a file path, URL, or object. Got %s', args.schema);\n return maybe(args.callback, Promise.reject(err));\n }\n\n var me = this;\n\n // Resolve the absolute path of the schema\n args.schema = util.path.localPathToUrl(args.schema);\n args.schema = url.resolve(util.path.cwd(), args.schema);\n this.$refs._basePath = util.path.stripHash(args.schema);\n\n // Read the schema file/url\n return read(args.schema, this.$refs, args.options)\n .then(function(result) {\n var value = result.$ref.value;\n if (!value || typeof value !== 'object' || value instanceof Buffer) {\n throw ono.syntax('\"%s\" is not a valid JSON Schema', me.$refs._basePath);\n }\n else {\n me.schema = value;\n return maybe(args.callback, Promise.resolve(me.schema));\n }\n })\n .catch(function(e) {\n return maybe(args.callback, Promise.reject(e));\n });\n};\n\n/**\n * Parses the given JSON schema and resolves any JSON references, including references in\n * externally-referenced files.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed and resolved\n * @param {function} [callback]\n * - An error-first callback. The second parameter is a {@link $Refs} object containing the resolved JSON references\n *\n * @returns {Promise}\n * The returned promise resolves with a {@link $Refs} object containing the resolved JSON references\n */\n$RefParser.resolve = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().resolve(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema and resolves any JSON references, including references in\n * externally-referenced files.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed and resolved\n * @param {function} [callback]\n * - An error-first callback. The second parameter is a {@link $Refs} object containing the resolved JSON references\n *\n * @returns {Promise}\n * The returned promise resolves with a {@link $Refs} object containing the resolved JSON references\n */\n$RefParser.prototype.resolve = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.parse(args.schema, args.options)\n .then(function() {\n return resolve(me, args.options);\n })\n .then(function() {\n return maybe(args.callback, Promise.resolve(me.$refs));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and bundles all external references\n * into the main JSON schema. This produces a JSON schema that only has *internal* references,\n * not any *external* references.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the bundled JSON schema object\n * @returns {Promise} - The returned promise resolves with the bundled JSON schema object.\n */\n$RefParser.bundle = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().bundle(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and bundles all external references\n * into the main JSON schema. This produces a JSON schema that only has *internal* references,\n * not any *external* references.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the bundled JSON schema object\n * @returns {Promise} - The returned promise resolves with the bundled JSON schema object.\n */\n$RefParser.prototype.bundle = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.resolve(args.schema, args.options)\n .then(function() {\n bundle(me, args.options);\n return maybe(args.callback, Promise.resolve(me.schema));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and dereferences the JSON schema.\n * That is, all JSON references are replaced with their resolved values.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the dereferenced JSON schema object\n * @returns {Promise} - The returned promise resolves with the dereferenced JSON schema object.\n */\n$RefParser.dereference = function(schema, options, callback) {\n var Class = this; // eslint-disable-line consistent-this\n return new Class().dereference(schema, options, callback);\n};\n\n/**\n * Parses the given JSON schema, resolves any JSON references, and dereferences the JSON schema.\n * That is, all JSON references are replaced with their resolved values.\n *\n * @param {string|object} schema - The file path or URL of the JSON schema. Or a JSON schema object.\n * @param {$RefParserOptions} [options] - Options that determine how the schema is parsed, resolved, and dereferenced\n * @param {function} [callback] - An error-first callback. The second parameter is the dereferenced JSON schema object\n * @returns {Promise} - The returned promise resolves with the dereferenced JSON schema object.\n */\n$RefParser.prototype.dereference = function(schema, options, callback) {\n var me = this;\n var args = normalizeArgs(arguments);\n\n return this.resolve(args.schema, args.options)\n .then(function() {\n dereference(me, args.options);\n return maybe(args.callback, Promise.resolve(me.schema));\n })\n .catch(function(err) {\n return maybe(args.callback, Promise.reject(err));\n });\n};\n\n/**\n * Normalizes the given arguments, accounting for optional args.\n *\n * @param {Arguments} args\n * @returns {object}\n */\nfunction normalizeArgs(args) {\n var options = args[1], callback = args[2];\n if (typeof options === 'function') {\n callback = options;\n options = undefined;\n }\n if (!(options instanceof Options)) {\n options = new Options(options);\n }\n return {\n schema: args[0],\n options: options,\n callback: callback\n };\n}\n", diff --git a/lib/bundle.js b/lib/bundle.js index e4d7f680..0174adba 100644 --- a/lib/bundle.js +++ b/lib/bundle.js @@ -1,5 +1,5 @@ /** ! - * JSON Schema $Ref Parser v2.1.2 + * JSON Schema $Ref Parser v2.2.0 * * @link https://github.com/BigstickCarpet/json-schema-ref-parser * @license MIT diff --git a/package.json b/package.json index 06142aec..a2b09f0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "json-schema-ref-parser", - "version": "2.1.2", + "version": "2.2.0", "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers", "keywords": [ "json", diff --git a/tests/index.html b/tests/index.html index ce5baeea..fd198376 100644 --- a/tests/index.html +++ b/tests/index.html @@ -55,6 +55,7 @@ +