@kubb/adapter-oas 5.0.0-beta.37 → 5.0.0-beta.39
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/index.cjs +221 -199
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +221 -199
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/adapter.ts +71 -28
- package/src/factory.ts +5 -5
- package/src/refs.ts +7 -4
- package/src/resolvers.ts +3 -3
- package/src/schemaDiagnostics.ts +25 -8
package/dist/index.js
CHANGED
|
@@ -1,13 +1,145 @@
|
|
|
1
1
|
import "./chunk-C0LytTxp.js";
|
|
2
|
-
import {
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { DiagnosticError, Diagnostics, ast, createAdapter, diagnosticCode } from "@kubb/core";
|
|
2
|
+
import { Diagnostics, ast, createAdapter } from "@kubb/core";
|
|
5
3
|
import BaseOas from "oas";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { access } from "node:fs/promises";
|
|
6
6
|
import { bundle, loadConfig } from "@redocly/openapi-core";
|
|
7
7
|
import OASNormalize from "oas-normalize";
|
|
8
8
|
import swagger2openapi from "swagger2openapi";
|
|
9
9
|
import { isRef } from "oas/types";
|
|
10
10
|
import { matchesMimeType } from "oas/utils";
|
|
11
|
+
//#region src/constants.ts
|
|
12
|
+
/**
|
|
13
|
+
* Default parser options applied when no explicit options are provided.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
|
|
18
|
+
*
|
|
19
|
+
* const parser = createOasParser(oas)
|
|
20
|
+
* const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_PARSER_OPTIONS = {
|
|
24
|
+
dateType: "string",
|
|
25
|
+
integerType: "bigint",
|
|
26
|
+
unknownType: "any",
|
|
27
|
+
emptySchemaType: "any",
|
|
28
|
+
enumSuffix: "enum"
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
|
|
32
|
+
*
|
|
33
|
+
* Used when building or parsing `$ref` strings.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
const SCHEMA_REF_PREFIX = "#/components/schemas/";
|
|
41
|
+
/**
|
|
42
|
+
* OpenAPI version string written into the stub document created during multi-spec merges.
|
|
43
|
+
*/
|
|
44
|
+
const MERGE_OPENAPI_VERSION = "3.0.0";
|
|
45
|
+
/**
|
|
46
|
+
* Fallback `info.title` placed in the stub document when merging multiple API files.
|
|
47
|
+
*/
|
|
48
|
+
const MERGE_DEFAULT_TITLE = "Merged API";
|
|
49
|
+
/**
|
|
50
|
+
* Fallback `info.version` placed in the stub document when merging multiple API files.
|
|
51
|
+
*/
|
|
52
|
+
const MERGE_DEFAULT_VERSION = "1.0.0";
|
|
53
|
+
/**
|
|
54
|
+
* Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
|
|
55
|
+
*
|
|
56
|
+
* A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
|
|
57
|
+
* intersection member rather than being merged into the parent.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { structuralKeys } from '@kubb/adapter-oas'
|
|
62
|
+
*
|
|
63
|
+
* const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
|
|
64
|
+
* // true when fragment has e.g. 'properties' or 'oneOf'
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
const structuralKeys = new Set([
|
|
68
|
+
"properties",
|
|
69
|
+
"items",
|
|
70
|
+
"additionalProperties",
|
|
71
|
+
"oneOf",
|
|
72
|
+
"anyOf",
|
|
73
|
+
"allOf",
|
|
74
|
+
"not"
|
|
75
|
+
]);
|
|
76
|
+
/**
|
|
77
|
+
* Static map from OAS `format` strings to Kubb `SchemaType` values.
|
|
78
|
+
*
|
|
79
|
+
* Only formats whose AST type differs from the OAS `type` field appear here.
|
|
80
|
+
* Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
|
|
81
|
+
* in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
|
|
82
|
+
* `idn-hostname` map to `'url'` as the closest generic string-format type.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { formatMap } from '@kubb/adapter-oas'
|
|
87
|
+
*
|
|
88
|
+
* formatMap['uuid'] // 'uuid'
|
|
89
|
+
* formatMap['binary'] // 'blob'
|
|
90
|
+
* formatMap['float'] // 'number'
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
/**
|
|
94
|
+
* Formats `convertFormat` maps to a dedicated type without going through `formatMap`:
|
|
95
|
+
* `int64` and the date/time family. Keep this in sync with the `convertFormat`
|
|
96
|
+
* special-cases in `parser.ts`. `isHandledFormat` reads it so the
|
|
97
|
+
* `KUBB_UNSUPPORTED_FORMAT` diagnostic and the parser agree on what is handled.
|
|
98
|
+
*/
|
|
99
|
+
const specialCasedFormats = new Set([
|
|
100
|
+
"int64",
|
|
101
|
+
"date-time",
|
|
102
|
+
"date",
|
|
103
|
+
"time"
|
|
104
|
+
]);
|
|
105
|
+
const formatMap = {
|
|
106
|
+
uuid: "uuid",
|
|
107
|
+
email: "email",
|
|
108
|
+
"idn-email": "email",
|
|
109
|
+
uri: "url",
|
|
110
|
+
"uri-reference": "url",
|
|
111
|
+
url: "url",
|
|
112
|
+
ipv4: "ipv4",
|
|
113
|
+
ipv6: "ipv6",
|
|
114
|
+
hostname: "url",
|
|
115
|
+
"idn-hostname": "url",
|
|
116
|
+
binary: "blob",
|
|
117
|
+
byte: "blob",
|
|
118
|
+
int32: "integer",
|
|
119
|
+
float: "number",
|
|
120
|
+
double: "number"
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* import { enumExtensionKeys } from '@kubb/adapter-oas'
|
|
128
|
+
*
|
|
129
|
+
* const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
133
|
+
/**
|
|
134
|
+
* Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
|
|
135
|
+
* Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
|
|
136
|
+
*/
|
|
137
|
+
const typeOptionMap = new Map([
|
|
138
|
+
["any", ast.schemaTypes.any],
|
|
139
|
+
["unknown", ast.schemaTypes.unknown],
|
|
140
|
+
["void", ast.schemaTypes.void]
|
|
141
|
+
]);
|
|
142
|
+
//#endregion
|
|
11
143
|
//#region ../../internals/utils/src/casing.ts
|
|
12
144
|
/**
|
|
13
145
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -123,30 +255,6 @@ function mergeDeep(target, source) {
|
|
|
123
255
|
return result;
|
|
124
256
|
}
|
|
125
257
|
//#endregion
|
|
126
|
-
//#region ../../internals/utils/src/promise.ts
|
|
127
|
-
/**
|
|
128
|
-
* Returns a wrapper that caches the result of the first invocation and replays
|
|
129
|
-
* it for every subsequent call, ignoring later arguments.
|
|
130
|
-
*
|
|
131
|
-
* Works for sync and async factories — for async, the cached value is the
|
|
132
|
-
* promise itself, so concurrent callers share one in-flight execution and
|
|
133
|
-
* cannot race each other.
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* ```ts
|
|
137
|
-
* const loadDocument = once(async (path: string) => parse(await readFile(path)))
|
|
138
|
-
* const a = loadDocument('./a.yaml') // parses
|
|
139
|
-
* const b = loadDocument('./b.yaml') // returns the cached promise from the first call
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
function once(factory) {
|
|
143
|
-
let cache;
|
|
144
|
-
return (...args) => {
|
|
145
|
-
if (!cache) cache = { value: factory(...args) };
|
|
146
|
-
return cache.value;
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
//#endregion
|
|
150
258
|
//#region ../../internals/utils/src/reserved.ts
|
|
151
259
|
/**
|
|
152
260
|
* JavaScript and Java reserved words.
|
|
@@ -397,138 +505,6 @@ var URLPath = class {
|
|
|
397
505
|
}
|
|
398
506
|
};
|
|
399
507
|
//#endregion
|
|
400
|
-
//#region src/constants.ts
|
|
401
|
-
/**
|
|
402
|
-
* Default parser options applied when no explicit options are provided.
|
|
403
|
-
*
|
|
404
|
-
* @example
|
|
405
|
-
* ```ts
|
|
406
|
-
* import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
|
|
407
|
-
*
|
|
408
|
-
* const parser = createOasParser(oas)
|
|
409
|
-
* const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
|
|
410
|
-
* ```
|
|
411
|
-
*/
|
|
412
|
-
const DEFAULT_PARSER_OPTIONS = {
|
|
413
|
-
dateType: "string",
|
|
414
|
-
integerType: "bigint",
|
|
415
|
-
unknownType: "any",
|
|
416
|
-
emptySchemaType: "any",
|
|
417
|
-
enumSuffix: "enum"
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
* JSON-Pointer prefix for schemas declared under `components.schemas` in an OpenAPI document.
|
|
421
|
-
*
|
|
422
|
-
* Used when building or parsing `$ref` strings.
|
|
423
|
-
*
|
|
424
|
-
* @example
|
|
425
|
-
* ```ts
|
|
426
|
-
* `${SCHEMA_REF_PREFIX}Pet` // '#/components/schemas/Pet'
|
|
427
|
-
* ```
|
|
428
|
-
*/
|
|
429
|
-
const SCHEMA_REF_PREFIX = "#/components/schemas/";
|
|
430
|
-
/**
|
|
431
|
-
* OpenAPI version string written into the stub document created during multi-spec merges.
|
|
432
|
-
*/
|
|
433
|
-
const MERGE_OPENAPI_VERSION = "3.0.0";
|
|
434
|
-
/**
|
|
435
|
-
* Fallback `info.title` placed in the stub document when merging multiple API files.
|
|
436
|
-
*/
|
|
437
|
-
const MERGE_DEFAULT_TITLE = "Merged API";
|
|
438
|
-
/**
|
|
439
|
-
* Fallback `info.version` placed in the stub document when merging multiple API files.
|
|
440
|
-
*/
|
|
441
|
-
const MERGE_DEFAULT_VERSION = "1.0.0";
|
|
442
|
-
/**
|
|
443
|
-
* Set of JSON Schema keywords that prevent a schema fragment from being inlined during `allOf` flattening.
|
|
444
|
-
*
|
|
445
|
-
* A fragment that contains any of these keys carries structural meaning of its own and must stay as a separate
|
|
446
|
-
* intersection member rather than being merged into the parent.
|
|
447
|
-
*
|
|
448
|
-
* @example
|
|
449
|
-
* ```ts
|
|
450
|
-
* import { structuralKeys } from '@kubb/adapter-oas'
|
|
451
|
-
*
|
|
452
|
-
* const isStructural = Object.keys(fragment).some((key) => structuralKeys.has(key))
|
|
453
|
-
* // true when fragment has e.g. 'properties' or 'oneOf'
|
|
454
|
-
* ```
|
|
455
|
-
*/
|
|
456
|
-
const structuralKeys = new Set([
|
|
457
|
-
"properties",
|
|
458
|
-
"items",
|
|
459
|
-
"additionalProperties",
|
|
460
|
-
"oneOf",
|
|
461
|
-
"anyOf",
|
|
462
|
-
"allOf",
|
|
463
|
-
"not"
|
|
464
|
-
]);
|
|
465
|
-
/**
|
|
466
|
-
* Static map from OAS `format` strings to Kubb `SchemaType` values.
|
|
467
|
-
*
|
|
468
|
-
* Only formats whose AST type differs from the OAS `type` field appear here.
|
|
469
|
-
* Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
|
|
470
|
-
* in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
|
|
471
|
-
* `idn-hostname` map to `'url'` as the closest generic string-format type.
|
|
472
|
-
*
|
|
473
|
-
* @example
|
|
474
|
-
* ```ts
|
|
475
|
-
* import { formatMap } from '@kubb/adapter-oas'
|
|
476
|
-
*
|
|
477
|
-
* formatMap['uuid'] // 'uuid'
|
|
478
|
-
* formatMap['binary'] // 'blob'
|
|
479
|
-
* formatMap['float'] // 'number'
|
|
480
|
-
* ```
|
|
481
|
-
*/
|
|
482
|
-
/**
|
|
483
|
-
* Formats `convertFormat` maps to a dedicated type without going through `formatMap`:
|
|
484
|
-
* `int64` and the date/time family. Keep this in sync with the `convertFormat`
|
|
485
|
-
* special-cases in `parser.ts`. `isHandledFormat` reads it so the
|
|
486
|
-
* `KUBB_UNSUPPORTED_FORMAT` diagnostic and the parser agree on what is handled.
|
|
487
|
-
*/
|
|
488
|
-
const specialCasedFormats = new Set([
|
|
489
|
-
"int64",
|
|
490
|
-
"date-time",
|
|
491
|
-
"date",
|
|
492
|
-
"time"
|
|
493
|
-
]);
|
|
494
|
-
const formatMap = {
|
|
495
|
-
uuid: "uuid",
|
|
496
|
-
email: "email",
|
|
497
|
-
"idn-email": "email",
|
|
498
|
-
uri: "url",
|
|
499
|
-
"uri-reference": "url",
|
|
500
|
-
url: "url",
|
|
501
|
-
ipv4: "ipv4",
|
|
502
|
-
ipv6: "ipv6",
|
|
503
|
-
hostname: "url",
|
|
504
|
-
"idn-hostname": "url",
|
|
505
|
-
binary: "blob",
|
|
506
|
-
byte: "blob",
|
|
507
|
-
int32: "integer",
|
|
508
|
-
float: "number",
|
|
509
|
-
double: "number"
|
|
510
|
-
};
|
|
511
|
-
/**
|
|
512
|
-
* Vendor extension keys that attach human-readable labels to enum values, checked in priority order.
|
|
513
|
-
*
|
|
514
|
-
* @example
|
|
515
|
-
* ```ts
|
|
516
|
-
* import { enumExtensionKeys } from '@kubb/adapter-oas'
|
|
517
|
-
*
|
|
518
|
-
* const key = enumExtensionKeys.find((k) => k in schema) // 'x-enumNames' | 'x-enum-varnames' | undefined
|
|
519
|
-
* ```
|
|
520
|
-
*/
|
|
521
|
-
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
522
|
-
/**
|
|
523
|
-
* Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
|
|
524
|
-
* Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
|
|
525
|
-
*/
|
|
526
|
-
const typeOptionMap = new Map([
|
|
527
|
-
["any", ast.schemaTypes.any],
|
|
528
|
-
["unknown", ast.schemaTypes.unknown],
|
|
529
|
-
["void", ast.schemaTypes.void]
|
|
530
|
-
]);
|
|
531
|
-
//#endregion
|
|
532
508
|
//#region src/guards.ts
|
|
533
509
|
/**
|
|
534
510
|
* Returns `true` when `doc` is a Swagger 2.0 document (no `openapi` key).
|
|
@@ -638,8 +614,8 @@ async function mergeDocuments(pathOrApi) {
|
|
|
638
614
|
enablePaths: false,
|
|
639
615
|
canBundle: false
|
|
640
616
|
})));
|
|
641
|
-
if (documents.length === 0) throw new
|
|
642
|
-
code:
|
|
617
|
+
if (documents.length === 0) throw new Diagnostics.Error({
|
|
618
|
+
code: Diagnostics.code.inputRequired,
|
|
643
619
|
severity: "error",
|
|
644
620
|
message: "No OAS documents were provided for merging.",
|
|
645
621
|
help: "Pass at least one path or document to `input.path`.",
|
|
@@ -688,8 +664,8 @@ async function parseFromConfig(source) {
|
|
|
688
664
|
*/
|
|
689
665
|
async function assertInputExists(input) {
|
|
690
666
|
if (new URLPath(input).isURL) return;
|
|
691
|
-
if (!await exists(input)) throw new
|
|
692
|
-
code:
|
|
667
|
+
if (!await exists(input)) throw new Diagnostics.Error({
|
|
668
|
+
code: Diagnostics.code.inputNotFound,
|
|
693
669
|
severity: "error",
|
|
694
670
|
message: `Cannot read the file set in \`input.path\` (or via \`kubb generate PATH\`): ${input}`,
|
|
695
671
|
help: "Check that the path exists and is readable, then set it in `input.path` or pass it as `kubb generate PATH`.",
|
|
@@ -743,7 +719,7 @@ function resolveRef(document, $ref) {
|
|
|
743
719
|
const current = $ref.split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document);
|
|
744
720
|
if (!current) {
|
|
745
721
|
const diagnostic = {
|
|
746
|
-
code:
|
|
722
|
+
code: Diagnostics.code.refNotFound,
|
|
747
723
|
severity: "error",
|
|
748
724
|
message: `Could not find a definition for ${origRef}.`,
|
|
749
725
|
help: "Add the schema under `components.schemas`, or fix the `$ref`. Run `kubb validate` to check the spec.",
|
|
@@ -753,7 +729,7 @@ function resolveRef(document, $ref) {
|
|
|
753
729
|
ref: origRef
|
|
754
730
|
}
|
|
755
731
|
};
|
|
756
|
-
Diagnostics.report(diagnostic);
|
|
732
|
+
if (!Diagnostics.report(diagnostic)) throw new Diagnostics.Error(diagnostic);
|
|
757
733
|
return null;
|
|
758
734
|
}
|
|
759
735
|
docCache.set($ref, current);
|
|
@@ -830,8 +806,8 @@ function resolveServerUrl(server, overrides) {
|
|
|
830
806
|
for (const [key, variable] of Object.entries(server.variables)) {
|
|
831
807
|
const value = overrides?.[key] ?? (variable.default != null ? String(variable.default) : void 0);
|
|
832
808
|
if (value === void 0) continue;
|
|
833
|
-
if (variable.enum?.length && !variable.enum.some((e) => String(e) === value)) throw new
|
|
834
|
-
code:
|
|
809
|
+
if (variable.enum?.length && !variable.enum.some((e) => String(e) === value)) throw new Diagnostics.Error({
|
|
810
|
+
code: Diagnostics.code.invalidServerVariable,
|
|
835
811
|
severity: "error",
|
|
836
812
|
message: `Invalid server variable value '${value}' for '${key}' when resolving ${server.url}. Valid values are: ${variable.enum.join(", ")}.`,
|
|
837
813
|
help: `Use one of the allowed enum values, or drop the enum on the '${key}' server variable.`,
|
|
@@ -2162,11 +2138,18 @@ function patchDiscriminatorNode(node, entry) {
|
|
|
2162
2138
|
* no-op outside one, and repeats are deduped by the build.
|
|
2163
2139
|
*/
|
|
2164
2140
|
function reportSchemaDiagnostics({ node, name }) {
|
|
2165
|
-
visit(node, `#/components/schemas/${name}`);
|
|
2141
|
+
visit(node, `#/components/schemas/${escapePointerToken(name)}`);
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* Escapes a single JSON pointer reference token per RFC 6901 (`~` → `~0`, `/` → `~1`), so a
|
|
2145
|
+
* property name with those characters maps to a distinct pointer instead of colliding in the dedupe.
|
|
2146
|
+
*/
|
|
2147
|
+
function escapePointerToken(token) {
|
|
2148
|
+
return token.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
2166
2149
|
}
|
|
2167
2150
|
function visit(node, pointer) {
|
|
2168
2151
|
if (node.deprecated) Diagnostics.report({
|
|
2169
|
-
code:
|
|
2152
|
+
code: Diagnostics.code.deprecated,
|
|
2170
2153
|
severity: "info",
|
|
2171
2154
|
message: "This schema is marked as deprecated.",
|
|
2172
2155
|
location: {
|
|
@@ -2175,7 +2158,7 @@ function visit(node, pointer) {
|
|
|
2175
2158
|
}
|
|
2176
2159
|
});
|
|
2177
2160
|
if (typeof node.format === "string" && !isHandledFormat(node.format)) Diagnostics.report({
|
|
2178
|
-
code:
|
|
2161
|
+
code: Diagnostics.code.unsupportedFormat,
|
|
2179
2162
|
severity: "warning",
|
|
2180
2163
|
message: `Kubb does not map the format "${node.format}" to a specific type, so it falls back to the base type.`,
|
|
2181
2164
|
help: `Use a format Kubb supports, or handle "${node.format}" with a custom parser or plugin.`,
|
|
@@ -2185,15 +2168,19 @@ function visit(node, pointer) {
|
|
|
2185
2168
|
}
|
|
2186
2169
|
});
|
|
2187
2170
|
if (node.type === "object") {
|
|
2188
|
-
for (const property of node.properties) visit(property.schema, `${pointer}/properties/${property.name}`);
|
|
2171
|
+
for (const property of node.properties) visit(property.schema, `${pointer}/properties/${escapePointerToken(property.name)}`);
|
|
2189
2172
|
if (node.additionalProperties && typeof node.additionalProperties === "object") visit(node.additionalProperties, `${pointer}/additionalProperties`);
|
|
2190
2173
|
return;
|
|
2191
2174
|
}
|
|
2192
|
-
if (node.type === "array"
|
|
2175
|
+
if (node.type === "array") {
|
|
2193
2176
|
for (const item of node.items ?? []) visit(item, `${pointer}/items`);
|
|
2194
2177
|
return;
|
|
2195
2178
|
}
|
|
2196
|
-
if (node.type === "
|
|
2179
|
+
if (node.type === "tuple") {
|
|
2180
|
+
for (const [index, item] of (node.items ?? []).entries()) visit(item, `${pointer}/items/${index}`);
|
|
2181
|
+
return;
|
|
2182
|
+
}
|
|
2183
|
+
if (node.type === "union" || node.type === "intersection") for (const [index, member] of (node.members ?? []).entries()) visit(member, `${pointer}/members/${index}`);
|
|
2197
2184
|
}
|
|
2198
2185
|
//#endregion
|
|
2199
2186
|
//#region src/stream.ts
|
|
@@ -2423,37 +2410,72 @@ const adapterOas = createAdapter((options) => {
|
|
|
2423
2410
|
};
|
|
2424
2411
|
let nameMapping = /* @__PURE__ */ new Map();
|
|
2425
2412
|
let parsedDocument = null;
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2413
|
+
const documentCache = /* @__PURE__ */ new WeakMap();
|
|
2414
|
+
const schemasCache = /* @__PURE__ */ new WeakMap();
|
|
2415
|
+
const baseOasCache = /* @__PURE__ */ new WeakMap();
|
|
2416
|
+
const schemaParserCache = /* @__PURE__ */ new WeakMap();
|
|
2417
|
+
const preScanCache = /* @__PURE__ */ new WeakMap();
|
|
2418
|
+
function ensureDocument(source) {
|
|
2419
|
+
const cached = documentCache.get(source);
|
|
2420
|
+
if (cached) return cached;
|
|
2421
|
+
const promise = (async () => {
|
|
2422
|
+
const fresh = await parseFromConfig(source);
|
|
2423
|
+
if (validate) await validateDocument(fresh);
|
|
2424
|
+
parsedDocument = fresh;
|
|
2425
|
+
return fresh;
|
|
2426
|
+
})();
|
|
2427
|
+
documentCache.set(source, promise);
|
|
2428
|
+
return promise;
|
|
2429
|
+
}
|
|
2430
|
+
function ensureSchemas(document) {
|
|
2431
|
+
const cached = schemasCache.get(document);
|
|
2432
|
+
if (cached) return cached;
|
|
2433
|
+
const promise = Promise.resolve().then(() => {
|
|
2434
|
+
const result = getSchemas(document, { contentType });
|
|
2435
|
+
nameMapping = result.nameMapping;
|
|
2436
|
+
return result.schemas;
|
|
2437
|
+
});
|
|
2438
|
+
schemasCache.set(document, promise);
|
|
2439
|
+
return promise;
|
|
2440
|
+
}
|
|
2441
|
+
function ensureBaseOas(document) {
|
|
2442
|
+
const cached = baseOasCache.get(document);
|
|
2443
|
+
if (cached) return cached;
|
|
2444
|
+
const baseOas = new BaseOas(document);
|
|
2445
|
+
baseOasCache.set(document, baseOas);
|
|
2446
|
+
return baseOas;
|
|
2447
|
+
}
|
|
2448
|
+
function ensureSchemaParser(document) {
|
|
2449
|
+
const cached = schemaParserCache.get(document);
|
|
2450
|
+
if (cached) return cached;
|
|
2451
|
+
const parser = createSchemaParser({
|
|
2452
|
+
document,
|
|
2453
|
+
contentType
|
|
2454
|
+
});
|
|
2455
|
+
schemaParserCache.set(document, parser);
|
|
2456
|
+
return parser;
|
|
2457
|
+
}
|
|
2458
|
+
function ensurePreScan(document, schemas, parseSchema, parseOperation, baseOas) {
|
|
2459
|
+
const cached = preScanCache.get(document);
|
|
2460
|
+
if (cached) return cached;
|
|
2461
|
+
const result = preScan({
|
|
2462
|
+
schemas,
|
|
2463
|
+
parseSchema,
|
|
2464
|
+
parseOperation,
|
|
2465
|
+
baseOas,
|
|
2466
|
+
parserOptions,
|
|
2467
|
+
discriminator,
|
|
2468
|
+
dedupe
|
|
2469
|
+
});
|
|
2470
|
+
preScanCache.set(document, result);
|
|
2471
|
+
return result;
|
|
2472
|
+
}
|
|
2451
2473
|
async function createStream(source) {
|
|
2452
2474
|
const document = await ensureDocument(source);
|
|
2453
2475
|
const schemas = await ensureSchemas(document);
|
|
2454
2476
|
const { parseSchema, parseOperation } = ensureSchemaParser(document);
|
|
2455
2477
|
const baseOas = ensureBaseOas(document);
|
|
2456
|
-
const { refAliasMap, enumNames, circularNames, discriminatorChildMap, dedupePlan } = ensurePreScan(schemas, parseSchema, parseOperation, baseOas);
|
|
2478
|
+
const { refAliasMap, enumNames, circularNames, discriminatorChildMap, dedupePlan } = ensurePreScan(document, schemas, parseSchema, parseOperation, baseOas);
|
|
2457
2479
|
return createInputStream({
|
|
2458
2480
|
schemas,
|
|
2459
2481
|
parseSchema,
|