@scalar/openapi-parser 0.29.14 → 0.29.16
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/CHANGELOG.md +14 -0
- package/dist/utils/get-list-of-references.d.ts +2 -6
- package/dist/utils/get-list-of-references.d.ts.map +1 -1
- package/dist/utils/get-list-of-references.js +5 -22
- package/dist/utils/get-reference-targets.d.ts +14 -0
- package/dist/utils/get-reference-targets.d.ts.map +1 -0
- package/dist/utils/get-reference-targets.js +45 -0
- package/dist/utils/join/join.js +1 -1
- package/dist/utils/load/load.d.ts +1 -1
- package/dist/utils/load/load.d.ts.map +1 -1
- package/dist/utils/load/load.js +41 -25
- package/dist/utils/openapi/actions/details.d.ts +1 -1
- package/dist/utils/openapi/actions/details.js +2 -2
- package/dist/utils/openapi/actions/toJson.js +2 -2
- package/dist/utils/openapi/actions/toYaml.js +2 -2
- package/dist/utils/openapi/commands/dereferenceCommand.d.ts +1 -1
- package/dist/utils/openapi/commands/filterCommand.d.ts +2 -2
- package/dist/utils/openapi/commands/loadCommand.d.ts +183 -183
- package/dist/utils/openapi/commands/upgradeCommand.d.ts +2 -2
- package/dist/utils/openapi/commands/validateCommand.d.ts +2 -2
- package/dist/utils/openapi/openapi.d.ts +173 -173
- package/dist/utils/openapi/utils/workThroughQueue.js +5 -5
- package/dist/utils/reference-context.d.ts +7 -0
- package/dist/utils/reference-context.d.ts.map +1 -0
- package/dist/utils/reference-context.js +111 -0
- package/dist/utils/resolve-references.d.ts.map +1 -1
- package/dist/utils/resolve-references.js +16 -17
- package/package.json +9 -9
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { dereference } from '
|
|
2
|
-
import { filter } from '
|
|
3
|
-
import { load } from '
|
|
4
|
-
import { upgrade } from '
|
|
5
|
-
import { validate } from '
|
|
1
|
+
import { dereference } from '../../dereference.js';
|
|
2
|
+
import { filter } from '../../filter.js';
|
|
3
|
+
import { load } from '../../load/load.js';
|
|
4
|
+
import { upgrade } from '../../upgrade.js';
|
|
5
|
+
import { validate } from '../../validate.js';
|
|
6
6
|
/**
|
|
7
7
|
* Takes a queue of tasks and works through them
|
|
8
8
|
*/
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Distinguishes reference-bearing objects from name maps and opaque instance data. */
|
|
2
|
+
export type ReferenceContext = 'link' | 'linkMap' | 'discriminator' | 'object' | 'document' | 'components' | 'paths' | 'namedResponseMap' | 'schema' | 'response' | 'responseMap' | 'example' | 'objectMap' | 'schemaMap' | 'exampleMap' | 'callbackMap' | 'callback' | 'literal';
|
|
3
|
+
/** A map's names are data, even when a name happens to be an OpenAPI keyword. */
|
|
4
|
+
export declare const getChildReferenceContext: (context: ReferenceContext, key: string, value: unknown) => ReferenceContext;
|
|
5
|
+
/** Only objects in reference positions may interpret their own $ref field as a URI. */
|
|
6
|
+
export declare const canResolveReference: (context: ReferenceContext) => boolean;
|
|
7
|
+
//# sourceMappingURL=reference-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-context.d.ts","sourceRoot":"","sources":["../../src/utils/reference-context.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,SAAS,GACT,eAAe,GACf,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,OAAO,GACP,kBAAkB,GAClB,QAAQ,GACR,UAAU,GACV,aAAa,GACb,SAAS,GACT,WAAW,GACX,WAAW,GACX,YAAY,GACZ,aAAa,GACb,UAAU,GACV,SAAS,CAAA;AAkCb,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,GAAI,SAAS,gBAAgB,EAAE,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,gBAwEjG,CAAA;AAED,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,GAAI,SAAS,gBAAgB,KAAG,OAOxC,CAAA"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const schemaMaps = new Set(['properties', 'patternProperties', '$defs', 'definitions', 'dependentSchemas']);
|
|
2
|
+
const schemaArrays = new Set(['allOf', 'anyOf', 'oneOf', 'prefixItems']);
|
|
3
|
+
const schemaValues = new Set([
|
|
4
|
+
'schema',
|
|
5
|
+
'items',
|
|
6
|
+
'additionalItems',
|
|
7
|
+
'contains',
|
|
8
|
+
'additionalProperties',
|
|
9
|
+
'unevaluatedProperties',
|
|
10
|
+
'unevaluatedItems',
|
|
11
|
+
'propertyNames',
|
|
12
|
+
'not',
|
|
13
|
+
'if',
|
|
14
|
+
'then',
|
|
15
|
+
'else',
|
|
16
|
+
'contentSchema',
|
|
17
|
+
]);
|
|
18
|
+
const objectMaps = new Set([
|
|
19
|
+
'additionalOperations',
|
|
20
|
+
'webhooks',
|
|
21
|
+
'content',
|
|
22
|
+
'mediaTypes',
|
|
23
|
+
'headers',
|
|
24
|
+
'encoding',
|
|
25
|
+
'variables',
|
|
26
|
+
'parameters',
|
|
27
|
+
'requestBodies',
|
|
28
|
+
'securitySchemes',
|
|
29
|
+
'pathItems',
|
|
30
|
+
]);
|
|
31
|
+
const literalValues = new Set(['example', 'default', 'enum', 'const', 'dependentRequired']);
|
|
32
|
+
/** A map's names are data, even when a name happens to be an OpenAPI keyword. */
|
|
33
|
+
export const getChildReferenceContext = (context, key, value) => {
|
|
34
|
+
if (context === 'literal') {
|
|
35
|
+
return 'literal';
|
|
36
|
+
}
|
|
37
|
+
if (context === 'callbackMap') {
|
|
38
|
+
return 'callback';
|
|
39
|
+
}
|
|
40
|
+
if (context === 'callback') {
|
|
41
|
+
return 'object';
|
|
42
|
+
}
|
|
43
|
+
if (context === 'responseMap' || context === 'paths') {
|
|
44
|
+
// These objects allow extensions, unlike maps of arbitrary component names.
|
|
45
|
+
return key.startsWith('x-') ? 'literal' : context === 'paths' ? 'object' : 'response';
|
|
46
|
+
}
|
|
47
|
+
if (context === 'namedResponseMap') {
|
|
48
|
+
return 'response';
|
|
49
|
+
}
|
|
50
|
+
if (context === 'schemaMap') {
|
|
51
|
+
return 'schema';
|
|
52
|
+
}
|
|
53
|
+
if (context === 'objectMap') {
|
|
54
|
+
return 'object';
|
|
55
|
+
}
|
|
56
|
+
if (context === 'linkMap') {
|
|
57
|
+
return 'link';
|
|
58
|
+
}
|
|
59
|
+
if (context === 'exampleMap') {
|
|
60
|
+
return 'example';
|
|
61
|
+
}
|
|
62
|
+
if (key.startsWith('x-') ||
|
|
63
|
+
key === 'scopes' ||
|
|
64
|
+
(context === 'discriminator' && key === 'mapping') ||
|
|
65
|
+
(context === 'link' && (key === 'requestBody' || key === 'parameters'))) {
|
|
66
|
+
return 'literal';
|
|
67
|
+
}
|
|
68
|
+
if (key === 'links') {
|
|
69
|
+
return 'linkMap';
|
|
70
|
+
}
|
|
71
|
+
if (key === 'discriminator') {
|
|
72
|
+
return 'discriminator';
|
|
73
|
+
}
|
|
74
|
+
if (literalValues.has(key) || (context === 'example' && (key === 'value' || key === 'dataValue'))) {
|
|
75
|
+
return 'literal';
|
|
76
|
+
}
|
|
77
|
+
if (key === 'examples') {
|
|
78
|
+
// OpenAPI 2 response examples map media types directly to instance data.
|
|
79
|
+
return context === 'schema' || context === 'response' || Array.isArray(value) ? 'literal' : 'exampleMap';
|
|
80
|
+
}
|
|
81
|
+
if (schemaMaps.has(key) || schemaArrays.has(key) || key === 'schemas') {
|
|
82
|
+
return 'schemaMap';
|
|
83
|
+
}
|
|
84
|
+
if (schemaValues.has(key)) {
|
|
85
|
+
return Array.isArray(value) ? 'schemaMap' : 'schema';
|
|
86
|
+
}
|
|
87
|
+
if (key === 'components') {
|
|
88
|
+
return 'components';
|
|
89
|
+
}
|
|
90
|
+
if (key === 'paths') {
|
|
91
|
+
return 'paths';
|
|
92
|
+
}
|
|
93
|
+
if (key === 'responses') {
|
|
94
|
+
return context === 'components' || context === 'document' ? 'namedResponseMap' : 'responseMap';
|
|
95
|
+
}
|
|
96
|
+
if (key === 'callbacks') {
|
|
97
|
+
return 'callbackMap';
|
|
98
|
+
}
|
|
99
|
+
if (objectMaps.has(key)) {
|
|
100
|
+
return 'objectMap';
|
|
101
|
+
}
|
|
102
|
+
return 'object';
|
|
103
|
+
};
|
|
104
|
+
/** Only objects in reference positions may interpret their own $ref field as a URI. */
|
|
105
|
+
export const canResolveReference = (context) => context === 'document' ||
|
|
106
|
+
context === 'link' ||
|
|
107
|
+
context === 'object' ||
|
|
108
|
+
context === 'schema' ||
|
|
109
|
+
context === 'example' ||
|
|
110
|
+
context === 'callback' ||
|
|
111
|
+
context === 'response';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-references.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-references.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGnE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve-references.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-references.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGnE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAiBjG,KAAK,uBAAuB,GAAG;IAC7B,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,MAAM,EAAE,aAAa,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,GAAG;IAC1D;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,KAAK,IAAI,CAAA;CACxF,CAAA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAE/B,KAAK,EAAE,SAAS,GAAG,UAAU,EAE7B,OAAO,CAAC,EAAE,wBAAwB,EAElC,IAAI,CAAC,EAAE,eAAe,EAEtB,MAAM,GAAE,WAAW,EAAO,GACzB,uBAAuB,CAuCzB"}
|
|
@@ -3,6 +3,7 @@ import { ERRORS } from '../configuration/index.js';
|
|
|
3
3
|
import { getEntrypoint } from './get-entrypoint.js';
|
|
4
4
|
import { getSegmentsFromPath } from './get-segments-from-path.js';
|
|
5
5
|
import { makeFilesystem } from './make-filesystem.js';
|
|
6
|
+
import { canResolveReference, getChildReferenceContext } from './reference-context.js';
|
|
6
7
|
/**
|
|
7
8
|
* Takes a specification and resolves all references.
|
|
8
9
|
*/
|
|
@@ -34,7 +35,7 @@ errors = []) {
|
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
// Recursively resolve all references
|
|
37
|
-
dereference(finalInput, filesystem, file ?? entrypoint, new WeakSet(), errors, options);
|
|
38
|
+
dereference(finalInput, filesystem, file ?? entrypoint, new WeakSet(), errors, options, 'document');
|
|
38
39
|
// Remove duplicates (according to message) from errors
|
|
39
40
|
const uniqueErrors = errors.filter((error, index, self) => index === self.findIndex((t) => t.message === error.message && t.code === error.code));
|
|
40
41
|
// Return the resolved specification
|
|
@@ -51,15 +52,19 @@ function dereference(schema, filesystem, entrypoint,
|
|
|
51
52
|
// references to resolved object
|
|
52
53
|
resolvedSchemas,
|
|
53
54
|
// error output
|
|
54
|
-
errors, options) {
|
|
55
|
-
if (schema === null || resolvedSchemas.has(schema)) {
|
|
55
|
+
errors, options, context = 'object') {
|
|
56
|
+
if (context === 'literal' || schema === null || resolvedSchemas.has(schema)) {
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
resolvedSchemas.add(schema);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
// A fragment inherits the reference site's context, not its storage container's keys.
|
|
61
|
+
const resolveExternal = (externalFile, fragment) => {
|
|
62
|
+
const target = resolveUri(`#${fragment}`, options, externalFile, filesystem, resolveExternal, errors);
|
|
63
|
+
if (isObjectLike(target)) {
|
|
64
|
+
dereference(target, filesystem, externalFile, resolvedSchemas, errors, options, context);
|
|
65
|
+
}
|
|
66
|
+
return target;
|
|
67
|
+
};
|
|
63
68
|
/**
|
|
64
69
|
* Track seen $ref paths to detect self-referencing schemas.
|
|
65
70
|
*
|
|
@@ -73,7 +78,7 @@ errors, options) {
|
|
|
73
78
|
* Person: { type: 'object', properties: { friend: { $ref: '#/components/schemas/Person' } } }
|
|
74
79
|
*/
|
|
75
80
|
const processedRefs = new Set();
|
|
76
|
-
while (schema.$ref !== undefined) {
|
|
81
|
+
while (canResolveReference(context) && schema.$ref !== undefined) {
|
|
77
82
|
const selfReferenceDetected = processedRefs.has(schema.$ref);
|
|
78
83
|
if (selfReferenceDetected) {
|
|
79
84
|
errors.push({
|
|
@@ -103,9 +108,9 @@ errors, options) {
|
|
|
103
108
|
}
|
|
104
109
|
}
|
|
105
110
|
// Iterate over the whole object
|
|
106
|
-
for (const value of Object.
|
|
111
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
107
112
|
if (typeof value === 'object' && value !== null) {
|
|
108
|
-
dereference(value, filesystem, entrypoint, resolvedSchemas, errors, options);
|
|
113
|
+
dereference(value, filesystem, entrypoint, resolvedSchemas, errors, options, getChildReferenceContext(context, key, value));
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -153,13 +158,7 @@ resolve, errors) {
|
|
|
153
158
|
});
|
|
154
159
|
return undefined;
|
|
155
160
|
}
|
|
156
|
-
|
|
157
|
-
if (path === undefined) {
|
|
158
|
-
return externalReference.specification;
|
|
159
|
-
}
|
|
160
|
-
// $ref: 'other-file.yaml#/foo/bar'
|
|
161
|
-
// resolve refs first before accessing properties directly
|
|
162
|
-
return resolveUri(`#${path}`, options, resolve(externalReference), filesystem, resolve, errors);
|
|
161
|
+
return resolve(externalReference, path ?? '');
|
|
163
162
|
}
|
|
164
163
|
// Try to find the URI
|
|
165
164
|
try {
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"parser",
|
|
18
18
|
"typescript"
|
|
19
19
|
],
|
|
20
|
-
"version": "0.29.
|
|
20
|
+
"version": "0.29.16",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=22"
|
|
23
23
|
},
|
|
@@ -49,18 +49,18 @@
|
|
|
49
49
|
"sideEffects": false,
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@scalar/helpers": "0.16.4",
|
|
52
|
-
"@scalar/json-magic": "0.
|
|
52
|
+
"@scalar/json-magic": "0.17.0",
|
|
53
53
|
"@scalar/openapi-types": "0.9.8",
|
|
54
|
-
"@scalar/openapi-upgrader": "0.4.
|
|
55
|
-
"@scalar/openapi-validator": "0.1.
|
|
56
|
-
"@scalar/types": "0.
|
|
57
|
-
"yaml": "^2.9.
|
|
54
|
+
"@scalar/openapi-upgrader": "0.4.6",
|
|
55
|
+
"@scalar/openapi-validator": "0.1.14",
|
|
56
|
+
"@scalar/types": "0.25.0",
|
|
57
|
+
"yaml": "^2.9.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@apidevtools/swagger-parser": "
|
|
61
|
-
"@types/node": "^24.
|
|
60
|
+
"@apidevtools/swagger-parser": "13.1.0",
|
|
61
|
+
"@types/node": "^24.19.2",
|
|
62
62
|
"just-diff": "^6.0.2",
|
|
63
|
-
"vite": "8.
|
|
63
|
+
"vite": "8.3.4"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|