@json-schema-tools/dereferencer
Advanced tools
Comparing version 1.0.3 to 1.0.5
@@ -1,2 +0,2 @@ | ||
import { CoreSchemaMetaSchema } from "@json-schema-tools/meta-schema"; | ||
import { JSONMetaSchema } from "@json-schema-tools/meta-schema"; | ||
/** | ||
@@ -25,3 +25,3 @@ * Options that can be passed to the derefencer constructor. | ||
export declare class NonStringRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema); | ||
constructor(schema: JSONMetaSchema); | ||
} | ||
@@ -45,3 +45,3 @@ /** | ||
export declare class NonJsonRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema, nonJson: string); | ||
constructor(schema: JSONMetaSchema, nonJson: string); | ||
} | ||
@@ -64,3 +64,3 @@ /** | ||
export declare class InvalidJsonPointerRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema); | ||
constructor(schema: JSONMetaSchema); | ||
} | ||
@@ -86,3 +86,4 @@ /** | ||
/** | ||
* When instantiated, represents a fully configured dereferencer. | ||
* When instantiated, represents a fully configured dereferencer. When constructed, references are pulled out. | ||
* No references are fetched until .resolve is called. | ||
*/ | ||
@@ -92,4 +93,5 @@ export declare class Dereferencer { | ||
refs: string[]; | ||
private refCache; | ||
private schema; | ||
constructor(schema: CoreSchemaMetaSchema, options?: DereferencerOptions | undefined); | ||
constructor(schema: JSONMetaSchema, options?: DereferencerOptions | undefined); | ||
/** | ||
@@ -103,3 +105,3 @@ * Fetches the schemas for all the refs in the configured input schema(s) | ||
*/ | ||
resolve(): Promise<CoreSchemaMetaSchema>; | ||
resolve(): Promise<JSONMetaSchema>; | ||
private fetchRef; | ||
@@ -111,10 +113,3 @@ /** | ||
private collectRefs; | ||
/** | ||
* the guts | ||
* | ||
* At some point soon this should mainly just apply middleware that is available. | ||
* | ||
*/ | ||
private applyDeref; | ||
} | ||
export default Dereferencer; |
@@ -233,3 +233,4 @@ "use strict"; | ||
/** | ||
* When instantiated, represents a fully configured dereferencer. | ||
* When instantiated, represents a fully configured dereferencer. When constructed, references are pulled out. | ||
* No references are fetched until .resolve is called. | ||
*/ | ||
@@ -239,2 +240,3 @@ var Dereferencer = /** @class */ (function () { | ||
this.options = options; | ||
this.refCache = {}; | ||
this.schema = __assign({}, schema); // start by making a shallow copy. | ||
@@ -253,22 +255,27 @@ this.refs = this.collectRefs(); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var fetchedRefs, refMap; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, Promise.all(this.refs.map(function (ref) { | ||
return _this.fetchRef(ref).then(function (fetchedRef) { | ||
var _a; | ||
return (_a = {}, _a[ref] = fetchedRef, _a); | ||
}); | ||
}))]; | ||
var refMap, _i, _a, ref, _b, _c; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
refMap = {}; | ||
_i = 0, _a = this.refs; | ||
_d.label = 1; | ||
case 1: | ||
fetchedRefs = _a.sent(); | ||
refMap = {}; | ||
fetchedRefs.forEach(function (r) { refMap = __assign(__assign({}, refMap), r); }); | ||
return [2 /*return*/, traverse_1.default(this.schema, function (s) { | ||
if (s.$ref !== undefined) { | ||
return refMap[s.$ref]; | ||
} | ||
return s; | ||
})]; | ||
if (!(_i < _a.length)) return [3 /*break*/, 4]; | ||
ref = _a[_i]; | ||
_b = refMap; | ||
_c = ref; | ||
return [4 /*yield*/, this.fetchRef(ref)]; | ||
case 2: | ||
_b[_c] = _d.sent(); | ||
_d.label = 3; | ||
case 3: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 4: return [2 /*return*/, traverse_1.default(this.schema, function (s) { | ||
if (s.$ref !== undefined) { | ||
return refMap[s.$ref]; | ||
} | ||
return s; | ||
}, { mutable: true })]; | ||
} | ||
@@ -284,2 +291,5 @@ }); | ||
case 0: | ||
if (this.refCache[ref] !== undefined) { | ||
return [2 /*return*/, this.refCache[ref]]; | ||
} | ||
if (ref[0] === "#") { | ||
@@ -293,2 +303,3 @@ withoutHash = ref.replace("#", ""); | ||
} | ||
this.refCache[ref] = reffedSchema; | ||
return [2 /*return*/, Promise.resolve(reffedSchema)]; | ||
@@ -316,2 +327,3 @@ } | ||
// return it | ||
this.refCache[ref] = reffedSchema; | ||
return [2 /*return*/, reffedSchema]; | ||
@@ -336,2 +348,3 @@ case 3: | ||
reffedSchema = _c.sent(); | ||
this.refCache[ref] = reffedSchema; | ||
return [2 /*return*/, reffedSchema]; | ||
@@ -347,4 +360,4 @@ case 8: | ||
e_2 = _c.sent(); | ||
return [3 /*break*/, 12]; | ||
case 12: throw new Error("Unhandled ref"); | ||
throw new Error("Unhandled ref"); | ||
case 12: return [2 /*return*/]; | ||
} | ||
@@ -371,76 +384,2 @@ }); | ||
}; | ||
/** | ||
* the guts | ||
* | ||
* At some point soon this should mainly just apply middleware that is available. | ||
* | ||
*/ | ||
Dereferencer.prototype.applyDeref = function (schema) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var withoutHash, pointer, reffedSchema, fileContents, reffedSchema, fetchResult, reffedSchema, e_3, _a, _b, e_4; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (schema.$ref === undefined) { | ||
return [2 /*return*/, schema]; | ||
} | ||
if (typeof schema.$ref !== "string") { | ||
throw new NonStringRefError(schema); | ||
} | ||
// handle internal reference | ||
if (schema.$ref[0] === "#") { | ||
withoutHash = schema.$ref.replace("#", ""); | ||
try { | ||
pointer = json_pointer_1.default.parse(withoutHash); | ||
reffedSchema = pointer.eval(this.schema); | ||
return [2 /*return*/, reffedSchema]; | ||
} | ||
catch (e) { | ||
throw new InvalidJsonPointerRefError(schema); | ||
} | ||
} | ||
return [4 /*yield*/, fileExistsAndReadable(schema.$ref)]; | ||
case 1: | ||
if (!((_c.sent()) === true)) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, readFile(schema.$ref)]; | ||
case 2: | ||
fileContents = _c.sent(); | ||
reffedSchema = void 0; | ||
try { | ||
reffedSchema = JSON.parse(fileContents); | ||
} | ||
catch (e) { | ||
throw new NonJsonRefError(schema, fileContents); | ||
} | ||
// throw if not valid json schema | ||
// (todo when we have validator) | ||
// return it | ||
return [2 /*return*/, reffedSchema]; | ||
case 3: | ||
_c.trys.push([3, 10, , 11]); | ||
return [4 /*yield*/, node_fetch_1.default(schema.$ref)]; | ||
case 4: | ||
fetchResult = _c.sent(); | ||
_c.label = 5; | ||
case 5: | ||
_c.trys.push([5, 7, , 9]); | ||
return [4 /*yield*/, fetchResult.json()]; | ||
case 6: | ||
reffedSchema = _c.sent(); | ||
return [2 /*return*/, reffedSchema]; | ||
case 7: | ||
e_3 = _c.sent(); | ||
_a = NonJsonRefError.bind; | ||
_b = [void 0, schema]; | ||
return [4 /*yield*/, fetchResult.text()]; | ||
case 8: throw new (_a.apply(NonJsonRefError, _b.concat([_c.sent()])))(); | ||
case 9: return [3 /*break*/, 11]; | ||
case 10: | ||
e_4 = _c.sent(); | ||
return [3 /*break*/, 11]; | ||
case 11: return [2 /*return*/, schema]; | ||
} | ||
}); | ||
}); | ||
}; | ||
return Dereferencer; | ||
@@ -447,0 +386,0 @@ }()); |
@@ -66,3 +66,3 @@ "use strict"; | ||
props = dereffed.properties; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.jsonSchemaMetaSchema.type).toBeDefined(); | ||
@@ -91,5 +91,5 @@ expect(props.fromFile.type).toBeDefined(); | ||
props = dereffed.properties; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.bar); | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.baz).toBe(props.foo); | ||
expect(props.baz).toBe(props.bar); | ||
return [2 /*return*/]; | ||
@@ -116,5 +116,5 @@ } | ||
props = dereffed.properties; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.bar); | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.baz).toBe(props.foo); | ||
expect(props.baz).toBe(props.bar); | ||
expect(props.baz.type).toBe("string"); | ||
@@ -121,0 +121,0 @@ return [2 /*return*/]; |
@@ -0,1 +1,16 @@ | ||
## [1.0.5](https://github.com/json-schema-tools/dereferencer/compare/1.0.4...1.0.5) (2020-06-30) | ||
### Bug Fixes | ||
* update random shit ([6e11447](https://github.com/json-schema-tools/dereferencer/commit/6e11447593455f0d9118558fe89bfdd83b61ff87)) | ||
## [1.0.4](https://github.com/json-schema-tools/dereferencer/compare/1.0.3...1.0.4) (2020-06-30) | ||
### Bug Fixes | ||
* all systems go ([6d051ff](https://github.com/json-schema-tools/dereferencer/commit/6d051ff83a50e2603b61547643b2434d711006af)) | ||
* update deps ([4d7dbc7](https://github.com/json-schema-tools/dereferencer/commit/4d7dbc7d587e20b3358f564c98503d857f4daa0e)) | ||
## [1.0.3](https://github.com/json-schema-tools/dereferencer/compare/1.0.2...1.0.3) (2020-06-27) | ||
@@ -2,0 +17,0 @@ |
{ | ||
"name": "@json-schema-tools/dereferencer", | ||
"version": "1.0.3", | ||
"description": "", | ||
"version": "1.0.5", | ||
"description": "Dereference (aka parse refs) from JSON Schemas", | ||
"main": "build/index.js", | ||
@@ -14,6 +14,6 @@ "publishConfig": { | ||
}, | ||
"author": "", | ||
"author": "BelfordZ<belfordz66@gmail.com>", | ||
"license": "Apache-2.0", | ||
"devDependencies": { | ||
"@json-schema-tools/meta-schema": "^1.0.9", | ||
"@json-schema-tools/meta-schema": "^1.0.10", | ||
"@types/jest": "^24.0.13", | ||
@@ -30,5 +30,5 @@ "@types/node": "^12.12.17", | ||
"@json-schema-spec/json-pointer": "^0.1.2", | ||
"@json-schema-tools/traverse": "^1.1.0", | ||
"@json-schema-tools/traverse": "^1.2.0", | ||
"node-fetch": "^2.6.0" | ||
} | ||
} |
import Dereferencer from "./index"; | ||
import { ObjectWji6VXSR } from "@json-schema-tools/meta-schema"; | ||
import { Properties } from "@json-schema-tools/meta-schema"; | ||
@@ -22,4 +22,4 @@ describe("Dereferencer", () => { | ||
const dereffed = await dereferencer.resolve(); | ||
const props = dereffed.properties as ObjectWji6VXSR; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
const props = dereffed.properties as Properties; | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.jsonSchemaMetaSchema.type).toBeDefined(); | ||
@@ -39,6 +39,6 @@ expect(props.fromFile.type).toBeDefined(); | ||
const dereffed = await dereferencer.resolve(); | ||
const props = dereffed.properties as ObjectWji6VXSR; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.bar); | ||
const props = dereffed.properties as Properties; | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.baz).toBe(props.foo); | ||
expect(props.baz).toBe(props.bar); | ||
}); | ||
@@ -56,6 +56,6 @@ | ||
const dereffed = await dereferencer.resolve(); | ||
const props = dereffed.properties as ObjectWji6VXSR; | ||
expect(props.bar).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.foo); | ||
expect(props.baz).toStrictEqual(props.bar); | ||
const props = dereffed.properties as Properties; | ||
expect(props.bar).toBe(props.foo); | ||
expect(props.baz).toBe(props.foo); | ||
expect(props.baz).toBe(props.bar); | ||
expect(props.baz.type).toBe("string"); | ||
@@ -62,0 +62,0 @@ }); |
107
src/index.ts
@@ -1,2 +0,2 @@ | ||
import { CoreSchemaMetaSchema } from "@json-schema-tools/meta-schema"; | ||
import { JSONMetaSchema } from "@json-schema-tools/meta-schema"; | ||
import traverse from "@json-schema-tools/traverse"; | ||
@@ -52,3 +52,3 @@ import * as fs from "fs"; | ||
export class NonStringRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema) { | ||
constructor(schema: JSONMetaSchema) { | ||
let schemaString = ""; | ||
@@ -90,3 +90,3 @@ try { | ||
export class NonJsonRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema, nonJson: string) { | ||
constructor(schema: JSONMetaSchema, nonJson: string) { | ||
super( | ||
@@ -118,3 +118,3 @@ [ | ||
export class InvalidJsonPointerRefError extends Error { | ||
constructor(schema: CoreSchemaMetaSchema) { | ||
constructor(schema: JSONMetaSchema) { | ||
super( | ||
@@ -157,3 +157,4 @@ [ | ||
/** | ||
* When instantiated, represents a fully configured dereferencer. | ||
* When instantiated, represents a fully configured dereferencer. When constructed, references are pulled out. | ||
* No references are fetched until .resolve is called. | ||
*/ | ||
@@ -163,5 +164,6 @@ export class Dereferencer { | ||
public refs: string[]; | ||
private schema: CoreSchemaMetaSchema; | ||
private refCache: { [k: string]: JSONMetaSchema } = {}; | ||
private schema: JSONMetaSchema; | ||
constructor(schema: CoreSchemaMetaSchema, private options?: DereferencerOptions) { | ||
constructor(schema: JSONMetaSchema, private options?: DereferencerOptions) { | ||
this.schema = { ...schema }; // start by making a shallow copy. | ||
@@ -179,10 +181,8 @@ this.refs = this.collectRefs(); | ||
*/ | ||
public async resolve(): Promise<CoreSchemaMetaSchema> { | ||
const fetchedRefs = await Promise.all(this.refs.map((ref) => { | ||
return this.fetchRef(ref).then((fetchedRef) => ({ [ref]: fetchedRef })); | ||
})); | ||
public async resolve(): Promise<JSONMetaSchema> { | ||
const refMap: { [s: string]: JSONMetaSchema } = {}; | ||
for (const ref of this.refs) { | ||
refMap[ref] = await this.fetchRef(ref); | ||
} | ||
let refMap: { [s: string]: CoreSchemaMetaSchema } = {}; | ||
fetchedRefs.forEach((r) => { refMap = { ...refMap, ...r }; }); | ||
return traverse(this.schema, (s) => { | ||
@@ -193,6 +193,10 @@ if (s.$ref !== undefined) { | ||
return s; | ||
}); | ||
}, { mutable: true }); | ||
} | ||
private async fetchRef(ref: string): Promise<CoreSchemaMetaSchema> { | ||
private async fetchRef(ref: string): Promise<JSONMetaSchema> { | ||
if (this.refCache[ref] !== undefined) { | ||
return this.refCache[ref]; | ||
} | ||
if (ref[0] === "#") { | ||
@@ -208,2 +212,3 @@ const withoutHash = ref.replace("#", ""); | ||
this.refCache[ref] = reffedSchema; | ||
return Promise.resolve(reffedSchema); | ||
@@ -230,2 +235,3 @@ } catch (e) { | ||
// return it | ||
this.refCache[ref] = reffedSchema; | ||
return reffedSchema; | ||
@@ -244,2 +250,4 @@ } else if (["$", ".", "/"].indexOf(ref[0]) !== -1) { | ||
const reffedSchema = await fetchResult.json(); | ||
this.refCache[ref] = reffedSchema; | ||
return reffedSchema; | ||
@@ -249,5 +257,5 @@ } catch (e) { | ||
} | ||
} catch (e) { /* noop */ } | ||
throw new Error("Unhandled ref"); | ||
} catch (e) { | ||
throw new Error("Unhandled ref"); | ||
} | ||
} | ||
@@ -261,5 +269,9 @@ | ||
const refs: string[] = []; | ||
traverse(this.schema, (s) => { | ||
if (s.$ref && refs.indexOf(s.$ref) === -1) { | ||
if (typeof s.$ref !== "string") { throw new NonStringRefError(s); } | ||
if (typeof s.$ref !== "string") { | ||
throw new NonStringRefError(s); | ||
} | ||
refs.push(s.$ref); | ||
@@ -269,60 +281,7 @@ } | ||
}); | ||
return refs; | ||
} | ||
/** | ||
* the guts | ||
* | ||
* At some point soon this should mainly just apply middleware that is available. | ||
* | ||
*/ | ||
private async applyDeref(schema: CoreSchemaMetaSchema): Promise<CoreSchemaMetaSchema> { | ||
if (schema.$ref === undefined) { return schema; } | ||
if (typeof schema.$ref !== "string") { throw new NonStringRefError(schema); } | ||
// handle internal reference | ||
if (schema.$ref[0] === "#") { | ||
const withoutHash = schema.$ref.replace("#", ""); | ||
try { | ||
const pointer = Ptr.parse(withoutHash); | ||
const reffedSchema = pointer.eval(this.schema); | ||
return reffedSchema; | ||
} catch (e) { | ||
throw new InvalidJsonPointerRefError(schema); | ||
} | ||
} | ||
// handle file references | ||
if (await fileExistsAndReadable(schema.$ref) === true) { | ||
const fileContents = await readFile(schema.$ref); | ||
let reffedSchema; | ||
try { | ||
reffedSchema = JSON.parse(fileContents); | ||
} catch (e) { | ||
throw new NonJsonRefError(schema, fileContents); | ||
} | ||
// throw if not valid json schema | ||
// (todo when we have validator) | ||
// return it | ||
return reffedSchema; | ||
} | ||
// handle http/https uri references | ||
// this forms the base case. We use node-fetch (or injected fetch lib) and let r rip | ||
try { | ||
const fetchResult = await fetch(schema.$ref); | ||
try { | ||
const reffedSchema = await fetchResult.json(); | ||
return reffedSchema; | ||
} catch (e) { | ||
throw new NonJsonRefError(schema, await fetchResult.text()); | ||
} | ||
} catch (e) { /* noop */ } | ||
return schema; | ||
} | ||
} | ||
export default Dereferencer; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
1
79649
1012