@hey-api/json-schema-ref-parser 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/__tests__/bundle.test.js +31 -4
- package/dist/lib/__tests__/index.test.js +16 -16
- package/dist/lib/__tests__/pointer.test.d.ts +1 -0
- package/dist/lib/__tests__/pointer.test.js +27 -0
- package/dist/lib/bundle.js +5 -4
- package/lib/__tests__/bundle.test.ts +40 -6
- package/lib/__tests__/index.test.ts +22 -20
- package/lib/__tests__/pointer.test.ts +26 -0
- package/lib/__tests__/spec/multiple-refs.json +34 -0
- package/lib/__tests__/spec/openapi-paths-ref.json +46 -0
- package/lib/__tests__/spec/path-parameter.json +12 -0
- package/lib/bundle.ts +7 -10
- package/package.json +2 -1
|
@@ -3,14 +3,41 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
7
|
const vitest_1 = require("vitest");
|
|
8
8
|
const __1 = require("..");
|
|
9
|
-
(0, vitest_1.describe)(
|
|
10
|
-
(0, vitest_1.it)(
|
|
9
|
+
(0, vitest_1.describe)("bundle", () => {
|
|
10
|
+
(0, vitest_1.it)("handles circular reference with description", async () => {
|
|
11
11
|
const refParser = new __1.$RefParser();
|
|
12
|
-
const pathOrUrlOrSchema =
|
|
12
|
+
const pathOrUrlOrSchema = path_1.default.resolve("lib", "__tests__", "spec", "circular-ref-with-description.json");
|
|
13
13
|
const schema = await refParser.bundle({ pathOrUrlOrSchema });
|
|
14
14
|
(0, vitest_1.expect)(schema).not.toBeUndefined();
|
|
15
15
|
});
|
|
16
|
+
(0, vitest_1.it)("bundles multiple references to the same file correctly", async () => {
|
|
17
|
+
const refParser = new __1.$RefParser();
|
|
18
|
+
const pathOrUrlOrSchema = path_1.default.resolve("lib", "__tests__", "spec", "multiple-refs.json");
|
|
19
|
+
const schema = (await refParser.bundle({ pathOrUrlOrSchema }));
|
|
20
|
+
// First reference should be fully resolved (no $ref)
|
|
21
|
+
(0, vitest_1.expect)(schema.paths["/test1/{pathId}"].get.parameters[0].name).toBe("pathId");
|
|
22
|
+
(0, vitest_1.expect)(schema.paths["/test1/{pathId}"].get.parameters[0].schema.type).toBe("string");
|
|
23
|
+
(0, vitest_1.expect)(schema.paths["/test1/{pathId}"].get.parameters[0].schema.format).toBe("uuid");
|
|
24
|
+
(0, vitest_1.expect)(schema.paths["/test1/{pathId}"].get.parameters[0].$ref).toBeUndefined();
|
|
25
|
+
// Second reference should be remapped to point to the first reference
|
|
26
|
+
(0, vitest_1.expect)(schema.paths["/test2/{pathId}"].get.parameters[0].$ref).toBe("#/paths/~1test1~1%7BpathId%7D/get/parameters/0");
|
|
27
|
+
// Both should effectively resolve to the same data
|
|
28
|
+
const firstParam = schema.paths["/test1/{pathId}"].get.parameters[0];
|
|
29
|
+
const secondParam = schema.paths["/test2/{pathId}"].get.parameters[0];
|
|
30
|
+
// The second parameter should resolve to the same data as the first
|
|
31
|
+
(0, vitest_1.expect)(secondParam.$ref).toBeDefined();
|
|
32
|
+
(0, vitest_1.expect)(firstParam).toEqual({
|
|
33
|
+
name: "pathId",
|
|
34
|
+
in: "path",
|
|
35
|
+
required: true,
|
|
36
|
+
schema: {
|
|
37
|
+
type: "string",
|
|
38
|
+
format: "uuid",
|
|
39
|
+
description: "Unique identifier for the path",
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
});
|
|
16
43
|
});
|
|
@@ -6,38 +6,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const node_path_1 = __importDefault(require("node:path"));
|
|
7
7
|
const vitest_1 = require("vitest");
|
|
8
8
|
const index_1 = require("../index");
|
|
9
|
-
(0, vitest_1.describe)(
|
|
10
|
-
(0, vitest_1.it)(
|
|
11
|
-
const pathOrUrlOrSchema =
|
|
9
|
+
(0, vitest_1.describe)("getResolvedInput", () => {
|
|
10
|
+
(0, vitest_1.it)("handles url", async () => {
|
|
11
|
+
const pathOrUrlOrSchema = "https://foo.com";
|
|
12
12
|
const resolvedInput = await (0, index_1.getResolvedInput)({ pathOrUrlOrSchema });
|
|
13
|
-
(0, vitest_1.expect)(resolvedInput.type).toBe(
|
|
13
|
+
(0, vitest_1.expect)(resolvedInput.type).toBe("url");
|
|
14
14
|
(0, vitest_1.expect)(resolvedInput.schema).toBeUndefined();
|
|
15
|
-
(0, vitest_1.expect)(resolvedInput.path).toBe(
|
|
15
|
+
(0, vitest_1.expect)(resolvedInput.path).toBe("https://foo.com/");
|
|
16
16
|
});
|
|
17
|
-
(0, vitest_1.it)(
|
|
18
|
-
const pathOrUrlOrSchema =
|
|
17
|
+
(0, vitest_1.it)("handles file", async () => {
|
|
18
|
+
const pathOrUrlOrSchema = "./path/to/openapi.json";
|
|
19
19
|
const resolvedInput = await (0, index_1.getResolvedInput)({ pathOrUrlOrSchema });
|
|
20
|
-
(0, vitest_1.expect)(resolvedInput.type).toBe(
|
|
20
|
+
(0, vitest_1.expect)(resolvedInput.type).toBe("file");
|
|
21
21
|
(0, vitest_1.expect)(resolvedInput.schema).toBeUndefined();
|
|
22
|
-
(0, vitest_1.expect)(resolvedInput.path).toBe(node_path_1.default.resolve(
|
|
22
|
+
(0, vitest_1.expect)(node_path_1.default.normalize(resolvedInput.path).toLowerCase()).toBe(node_path_1.default.normalize(node_path_1.default.resolve("./path/to/openapi.json")).toLowerCase());
|
|
23
23
|
});
|
|
24
|
-
(0, vitest_1.it)(
|
|
24
|
+
(0, vitest_1.it)("handles raw spec", async () => {
|
|
25
25
|
const pathOrUrlOrSchema = {
|
|
26
26
|
info: {
|
|
27
|
-
version:
|
|
27
|
+
version: "1.0.0",
|
|
28
28
|
},
|
|
29
|
-
openapi:
|
|
29
|
+
openapi: "3.1.0",
|
|
30
30
|
paths: {},
|
|
31
31
|
};
|
|
32
32
|
const resolvedInput = await (0, index_1.getResolvedInput)({ pathOrUrlOrSchema });
|
|
33
|
-
(0, vitest_1.expect)(resolvedInput.type).toBe(
|
|
33
|
+
(0, vitest_1.expect)(resolvedInput.type).toBe("json");
|
|
34
34
|
(0, vitest_1.expect)(resolvedInput.schema).toEqual({
|
|
35
35
|
info: {
|
|
36
|
-
version:
|
|
36
|
+
version: "1.0.0",
|
|
37
37
|
},
|
|
38
|
-
openapi:
|
|
38
|
+
openapi: "3.1.0",
|
|
39
39
|
paths: {},
|
|
40
40
|
});
|
|
41
|
-
(0, vitest_1.expect)(resolvedInput.path).toBe(
|
|
41
|
+
(0, vitest_1.expect)(resolvedInput.path).toBe("");
|
|
42
42
|
});
|
|
43
43
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const __1 = require("..");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
(0, vitest_1.describe)("pointer", () => {
|
|
10
|
+
(0, vitest_1.it)("inlines internal JSON Pointer refs under #/paths/ for OpenAPI bundling", async () => {
|
|
11
|
+
const refParser = new __1.$RefParser();
|
|
12
|
+
const pathOrUrlOrSchema = path_1.default.resolve("lib", "__tests__", "spec", "openapi-paths-ref.json");
|
|
13
|
+
const schema = (await refParser.bundle({ pathOrUrlOrSchema }));
|
|
14
|
+
// The GET endpoint should have its schema defined inline
|
|
15
|
+
const getSchema = schema.paths["/foo"].get.responses["200"].content["application/json"].schema;
|
|
16
|
+
(0, vitest_1.expect)(getSchema.$ref).toBeUndefined();
|
|
17
|
+
(0, vitest_1.expect)(getSchema.type).toBe("object");
|
|
18
|
+
(0, vitest_1.expect)(getSchema.properties.bar.type).toBe("string");
|
|
19
|
+
// The POST endpoint should have its schema inlined (copied) instead of a $ref
|
|
20
|
+
const postSchema = schema.paths["/foo"].post.responses["200"].content["application/json"].schema;
|
|
21
|
+
(0, vitest_1.expect)(postSchema.$ref).toBeUndefined();
|
|
22
|
+
(0, vitest_1.expect)(postSchema.type).toBe("object");
|
|
23
|
+
(0, vitest_1.expect)(postSchema.properties.bar.type).toBe("string");
|
|
24
|
+
// Both schemas should be identical objects
|
|
25
|
+
(0, vitest_1.expect)(postSchema).toEqual(getSchema);
|
|
26
|
+
});
|
|
27
|
+
});
|
package/dist/lib/bundle.js
CHANGED
|
@@ -74,9 +74,10 @@ const inventory$Ref = ({ $refKey, $refParent, $refs, indirections, inventory, op
|
|
|
74
74
|
const external = file !== $refs._root$Ref.path;
|
|
75
75
|
const extended = ref_js_1.default.isExtended$Ref($ref);
|
|
76
76
|
indirections += pointer.indirections;
|
|
77
|
+
// Check if this exact location (parent + key + pathFromRoot) has already been inventoried
|
|
77
78
|
const existingEntry = findInInventory(inventory, $refParent, $refKey);
|
|
78
|
-
if (existingEntry) {
|
|
79
|
-
// This
|
|
79
|
+
if (existingEntry && existingEntry.pathFromRoot === pathFromRoot) {
|
|
80
|
+
// This exact location has already been inventoried, so we don't need to process it again
|
|
80
81
|
if (depth < existingEntry.depth || indirections < existingEntry.indirections) {
|
|
81
82
|
removeFromInventory(inventory, existingEntry);
|
|
82
83
|
}
|
|
@@ -248,7 +249,7 @@ function remap(inventory) {
|
|
|
248
249
|
let file, hash, pathFromRoot;
|
|
249
250
|
for (const entry of inventory) {
|
|
250
251
|
// console.log('Re-mapping $ref pointer "%s" at %s', entry.$ref.$ref, entry.pathFromRoot);
|
|
251
|
-
if (!entry.external) {
|
|
252
|
+
if (!entry.external && !entry.hash?.startsWith("#/paths/")) {
|
|
252
253
|
// This $ref already resolves to the main JSON Schema file
|
|
253
254
|
entry.$ref.$ref = entry.hash;
|
|
254
255
|
}
|
|
@@ -312,7 +313,7 @@ const bundle = (parser, options) => {
|
|
|
312
313
|
const inventory = [];
|
|
313
314
|
crawl({
|
|
314
315
|
parent: parser,
|
|
315
|
-
key:
|
|
316
|
+
key: "schema",
|
|
316
317
|
path: parser.$refs._root$Ref.path + "#",
|
|
317
318
|
pathFromRoot: "#",
|
|
318
319
|
indirections: 0,
|
|
@@ -1,14 +1,48 @@
|
|
|
1
|
-
import path from
|
|
1
|
+
import path from "path";
|
|
2
2
|
|
|
3
|
-
import { describe, expect, it } from
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
|
-
import { $RefParser } from
|
|
5
|
+
import { $RefParser } from "..";
|
|
6
6
|
|
|
7
|
-
describe(
|
|
8
|
-
it(
|
|
7
|
+
describe("bundle", () => {
|
|
8
|
+
it("handles circular reference with description", async () => {
|
|
9
9
|
const refParser = new $RefParser();
|
|
10
|
-
const pathOrUrlOrSchema = path.resolve(
|
|
10
|
+
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "circular-ref-with-description.json");
|
|
11
11
|
const schema = await refParser.bundle({ pathOrUrlOrSchema });
|
|
12
12
|
expect(schema).not.toBeUndefined();
|
|
13
13
|
});
|
|
14
|
+
|
|
15
|
+
it("bundles multiple references to the same file correctly", async () => {
|
|
16
|
+
const refParser = new $RefParser();
|
|
17
|
+
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "multiple-refs.json");
|
|
18
|
+
const schema = (await refParser.bundle({ pathOrUrlOrSchema })) as any;
|
|
19
|
+
|
|
20
|
+
// First reference should be fully resolved (no $ref)
|
|
21
|
+
expect(schema.paths["/test1/{pathId}"].get.parameters[0].name).toBe("pathId");
|
|
22
|
+
expect(schema.paths["/test1/{pathId}"].get.parameters[0].schema.type).toBe("string");
|
|
23
|
+
expect(schema.paths["/test1/{pathId}"].get.parameters[0].schema.format).toBe("uuid");
|
|
24
|
+
expect(schema.paths["/test1/{pathId}"].get.parameters[0].$ref).toBeUndefined();
|
|
25
|
+
|
|
26
|
+
// Second reference should be remapped to point to the first reference
|
|
27
|
+
expect(schema.paths["/test2/{pathId}"].get.parameters[0].$ref).toBe(
|
|
28
|
+
"#/paths/~1test1~1%7BpathId%7D/get/parameters/0",
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// Both should effectively resolve to the same data
|
|
32
|
+
const firstParam = schema.paths["/test1/{pathId}"].get.parameters[0];
|
|
33
|
+
const secondParam = schema.paths["/test2/{pathId}"].get.parameters[0];
|
|
34
|
+
|
|
35
|
+
// The second parameter should resolve to the same data as the first
|
|
36
|
+
expect(secondParam.$ref).toBeDefined();
|
|
37
|
+
expect(firstParam).toEqual({
|
|
38
|
+
name: "pathId",
|
|
39
|
+
in: "path",
|
|
40
|
+
required: true,
|
|
41
|
+
schema: {
|
|
42
|
+
type: "string",
|
|
43
|
+
format: "uuid",
|
|
44
|
+
description: "Unique identifier for the path",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
});
|
|
14
48
|
});
|
|
@@ -1,43 +1,45 @@
|
|
|
1
|
-
import path from
|
|
1
|
+
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
import { describe, expect, it } from
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
|
-
import { getResolvedInput } from
|
|
5
|
+
import { getResolvedInput } from "../index";
|
|
6
6
|
|
|
7
|
-
describe(
|
|
8
|
-
it(
|
|
9
|
-
const pathOrUrlOrSchema =
|
|
7
|
+
describe("getResolvedInput", () => {
|
|
8
|
+
it("handles url", async () => {
|
|
9
|
+
const pathOrUrlOrSchema = "https://foo.com";
|
|
10
10
|
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
|
|
11
|
-
expect(resolvedInput.type).toBe(
|
|
11
|
+
expect(resolvedInput.type).toBe("url");
|
|
12
12
|
expect(resolvedInput.schema).toBeUndefined();
|
|
13
|
-
expect(resolvedInput.path).toBe(
|
|
13
|
+
expect(resolvedInput.path).toBe("https://foo.com/");
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
it(
|
|
17
|
-
const pathOrUrlOrSchema =
|
|
16
|
+
it("handles file", async () => {
|
|
17
|
+
const pathOrUrlOrSchema = "./path/to/openapi.json";
|
|
18
18
|
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
|
|
19
|
-
expect(resolvedInput.type).toBe(
|
|
19
|
+
expect(resolvedInput.type).toBe("file");
|
|
20
20
|
expect(resolvedInput.schema).toBeUndefined();
|
|
21
|
-
expect(resolvedInput.path).
|
|
21
|
+
expect(path.normalize(resolvedInput.path).toLowerCase()).toBe(
|
|
22
|
+
path.normalize(path.resolve("./path/to/openapi.json")).toLowerCase(),
|
|
23
|
+
);
|
|
22
24
|
});
|
|
23
25
|
|
|
24
|
-
it(
|
|
25
|
-
const pathOrUrlOrSchema =
|
|
26
|
+
it("handles raw spec", async () => {
|
|
27
|
+
const pathOrUrlOrSchema = {
|
|
26
28
|
info: {
|
|
27
|
-
version:
|
|
29
|
+
version: "1.0.0",
|
|
28
30
|
},
|
|
29
|
-
openapi:
|
|
31
|
+
openapi: "3.1.0",
|
|
30
32
|
paths: {},
|
|
31
33
|
};
|
|
32
34
|
const resolvedInput = await getResolvedInput({ pathOrUrlOrSchema });
|
|
33
|
-
expect(resolvedInput.type).toBe(
|
|
35
|
+
expect(resolvedInput.type).toBe("json");
|
|
34
36
|
expect(resolvedInput.schema).toEqual({
|
|
35
37
|
info: {
|
|
36
|
-
version:
|
|
38
|
+
version: "1.0.0",
|
|
37
39
|
},
|
|
38
|
-
openapi:
|
|
40
|
+
openapi: "3.1.0",
|
|
39
41
|
paths: {},
|
|
40
42
|
});
|
|
41
|
-
expect(resolvedInput.path).toBe(
|
|
43
|
+
expect(resolvedInput.path).toBe("");
|
|
42
44
|
});
|
|
43
45
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { $RefParser } from "..";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
describe("pointer", () => {
|
|
6
|
+
it("inlines internal JSON Pointer refs under #/paths/ for OpenAPI bundling", async () => {
|
|
7
|
+
const refParser = new $RefParser();
|
|
8
|
+
const pathOrUrlOrSchema = path.resolve("lib", "__tests__", "spec", "openapi-paths-ref.json");
|
|
9
|
+
const schema = (await refParser.bundle({ pathOrUrlOrSchema })) as any;
|
|
10
|
+
|
|
11
|
+
// The GET endpoint should have its schema defined inline
|
|
12
|
+
const getSchema = schema.paths["/foo"].get.responses["200"].content["application/json"].schema;
|
|
13
|
+
expect(getSchema.$ref).toBeUndefined();
|
|
14
|
+
expect(getSchema.type).toBe("object");
|
|
15
|
+
expect(getSchema.properties.bar.type).toBe("string");
|
|
16
|
+
|
|
17
|
+
// The POST endpoint should have its schema inlined (copied) instead of a $ref
|
|
18
|
+
const postSchema = schema.paths["/foo"].post.responses["200"].content["application/json"].schema;
|
|
19
|
+
expect(postSchema.$ref).toBeUndefined();
|
|
20
|
+
expect(postSchema.type).toBe("object");
|
|
21
|
+
expect(postSchema.properties.bar.type).toBe("string");
|
|
22
|
+
|
|
23
|
+
// Both schemas should be identical objects
|
|
24
|
+
expect(postSchema).toEqual(getSchema);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paths": {
|
|
3
|
+
"/test1/{pathId}": {
|
|
4
|
+
"get": {
|
|
5
|
+
"summary": "First endpoint using the same pathId schema",
|
|
6
|
+
"parameters": [
|
|
7
|
+
{
|
|
8
|
+
"$ref": "path-parameter.json#/pathId"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"responses": {
|
|
12
|
+
"200": {
|
|
13
|
+
"description": "Test 1 response"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"/test2/{pathId}": {
|
|
19
|
+
"get": {
|
|
20
|
+
"summary": "Second endpoint using the same pathId schema",
|
|
21
|
+
"parameters": [
|
|
22
|
+
{
|
|
23
|
+
"$ref": "path-parameter.json#/pathId"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"responses": {
|
|
27
|
+
"200": {
|
|
28
|
+
"description": "Test 2 response"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.1.0",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "Sample API",
|
|
5
|
+
"version": "1.0.0"
|
|
6
|
+
},
|
|
7
|
+
"paths": {
|
|
8
|
+
"/foo": {
|
|
9
|
+
"get": {
|
|
10
|
+
"summary": "Get foo",
|
|
11
|
+
"responses": {
|
|
12
|
+
"200": {
|
|
13
|
+
"description": "OK",
|
|
14
|
+
"content": {
|
|
15
|
+
"application/json": {
|
|
16
|
+
"schema": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"bar": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"post": {
|
|
30
|
+
"summary": "Create foo",
|
|
31
|
+
"responses": {
|
|
32
|
+
"200": {
|
|
33
|
+
"description": "OK",
|
|
34
|
+
"content": {
|
|
35
|
+
"application/json": {
|
|
36
|
+
"schema": {
|
|
37
|
+
"$ref": "#/paths/~1foo/get/responses/200/content/application~1json/schema"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/lib/bundle.ts
CHANGED
|
@@ -94,9 +94,10 @@ const inventory$Ref = <S extends object = JSONSchema>({
|
|
|
94
94
|
const extended = $Ref.isExtended$Ref($ref);
|
|
95
95
|
indirections += pointer.indirections;
|
|
96
96
|
|
|
97
|
+
// Check if this exact location (parent + key + pathFromRoot) has already been inventoried
|
|
97
98
|
const existingEntry = findInInventory(inventory, $refParent, $refKey);
|
|
98
|
-
if (existingEntry) {
|
|
99
|
-
// This
|
|
99
|
+
if (existingEntry && existingEntry.pathFromRoot === pathFromRoot) {
|
|
100
|
+
// This exact location has already been inventoried, so we don't need to process it again
|
|
100
101
|
if (depth < existingEntry.depth || indirections < existingEntry.indirections) {
|
|
101
102
|
removeFromInventory(inventory, existingEntry);
|
|
102
103
|
} else {
|
|
@@ -172,7 +173,7 @@ const crawl = <S extends object = JSONSchema>({
|
|
|
172
173
|
pathFromRoot: string;
|
|
173
174
|
}) => {
|
|
174
175
|
const obj = key === null ? parent : parent[key as keyof typeof parent];
|
|
175
|
-
|
|
176
|
+
|
|
176
177
|
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
|
|
177
178
|
if ($Ref.isAllowed$Ref(obj)) {
|
|
178
179
|
inventory$Ref({
|
|
@@ -299,7 +300,7 @@ function remap(inventory: InventoryEntry[]) {
|
|
|
299
300
|
for (const entry of inventory) {
|
|
300
301
|
// console.log('Re-mapping $ref pointer "%s" at %s', entry.$ref.$ref, entry.pathFromRoot);
|
|
301
302
|
|
|
302
|
-
if (!entry.external) {
|
|
303
|
+
if (!entry.external && !entry.hash?.startsWith("#/paths/")) {
|
|
303
304
|
// This $ref already resolves to the main JSON Schema file
|
|
304
305
|
entry.$ref.$ref = entry.hash;
|
|
305
306
|
} else if (entry.file === file && entry.hash === hash) {
|
|
@@ -359,17 +360,13 @@ function removeFromInventory(inventory: InventoryEntry[], entry: any) {
|
|
|
359
360
|
* @param parser
|
|
360
361
|
* @param options
|
|
361
362
|
*/
|
|
362
|
-
export const bundle = (
|
|
363
|
-
parser: $RefParser,
|
|
364
|
-
options: ParserOptions,
|
|
365
|
-
) => {
|
|
363
|
+
export const bundle = (parser: $RefParser, options: ParserOptions) => {
|
|
366
364
|
// console.log('Bundling $ref pointers in %s', parser.$refs._root$Ref.path);
|
|
367
|
-
|
|
368
365
|
// Build an inventory of all $ref pointers in the JSON Schema
|
|
369
366
|
const inventory: InventoryEntry[] = [];
|
|
370
367
|
crawl<JSONSchema>({
|
|
371
368
|
parent: parser,
|
|
372
|
-
key:
|
|
369
|
+
key: "schema",
|
|
373
370
|
path: parser.$refs._root$Ref.path + "#",
|
|
374
371
|
pathFromRoot: "#",
|
|
375
372
|
indirections: 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hey-api/json-schema-ref-parser",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
|
|
5
5
|
"homepage": "https://heyapi.dev/",
|
|
6
6
|
"repository": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "rimraf dist && tsc",
|
|
45
|
+
"dev": "rimraf dist && tsc --watch",
|
|
45
46
|
"lint": "eslint lib",
|
|
46
47
|
"prepublishOnly": "yarn build",
|
|
47
48
|
"prettier": "prettier --write \"**/*.+(js|jsx|ts|tsx|har||json|css|md)\"",
|