@kubb/adapter-oas 5.15.3 → 5.15.4
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 +90 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +90 -13
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var compatibility = {
|
|
|
19
19
|
"node": ">=22.22"
|
|
20
20
|
};
|
|
21
21
|
// package.json
|
|
22
|
-
var version = "5.15.
|
|
22
|
+
var version = "5.15.4";
|
|
23
23
|
// src/constants.ts
|
|
24
24
|
/**
|
|
25
25
|
* Default parser options applied when no explicit options are provided.
|
|
@@ -615,8 +615,10 @@ async function readSource(sourcePath) {
|
|
|
615
615
|
async function resolveSource(sourcePath) {
|
|
616
616
|
const data = await readSource(sourcePath);
|
|
617
617
|
if (sourcePath.toLowerCase().endsWith(".md")) return data;
|
|
618
|
+
const pathname = urlRegExp.test(sourcePath) ? new URL(sourcePath).pathname : sourcePath;
|
|
618
619
|
return parseYaml(data, {
|
|
619
620
|
origin: sourcePath,
|
|
621
|
+
json: !/\.ya?ml$/i.test(pathname),
|
|
620
622
|
help: "Fix the syntax at the reported line, or check that `input` points at the spec and not an HTML page."
|
|
621
623
|
});
|
|
622
624
|
}
|
|
@@ -624,11 +626,19 @@ async function resolveSource(sourcePath) {
|
|
|
624
626
|
* Parses a YAML (or JSON) spec. A syntax error throws `KUBB_INVALID_DOCUMENT` naming `origin`,
|
|
625
627
|
* with the parser message, which keeps the line and column.
|
|
626
628
|
*
|
|
627
|
-
*
|
|
628
|
-
* `yaml
|
|
629
|
-
*
|
|
629
|
+
* With `json` (the default), a document that starts with `{` or `[` goes through `JSON.parse`
|
|
630
|
+
* first, about ten times faster than `js-yaml` on a JSON spec. A duplicate key then keeps the last
|
|
631
|
+
* value, as every JSON parser does. YAML flow syntax also starts with `{`, so a parse failure falls
|
|
632
|
+
* through to YAML. Pass `json: false` for a source known to be YAML.
|
|
633
|
+
*
|
|
634
|
+
* `js-yaml` parses about ten times faster than `yaml`, and rejects duplicate keys instead of
|
|
635
|
+
* keeping the last one. Its core schema keeps timestamps as strings and `<<` as a plain key, as
|
|
636
|
+
* `yaml` does for YAML 1.2.
|
|
630
637
|
*/
|
|
631
|
-
function parseYaml(data, { origin, help }) {
|
|
638
|
+
function parseYaml(data, { origin, help, json = true }) {
|
|
639
|
+
if (json && /^\s*[[{]/.test(data)) try {
|
|
640
|
+
return JSON.parse(data);
|
|
641
|
+
} catch {}
|
|
632
642
|
try {
|
|
633
643
|
const document = load(data, { schema: CORE_SCHEMA });
|
|
634
644
|
if (document !== void 0) return document;
|
|
@@ -2233,6 +2243,34 @@ function getNumericConstraints(schema) {
|
|
|
2233
2243
|
};
|
|
2234
2244
|
}
|
|
2235
2245
|
/**
|
|
2246
|
+
* Whether an enum value fits the schema's numeric bounds.
|
|
2247
|
+
*/
|
|
2248
|
+
function isWithinBounds({ value, schema }) {
|
|
2249
|
+
if (typeof value !== "number") return true;
|
|
2250
|
+
const { min, max, exclusiveMinimum, exclusiveMaximum, multipleOf } = getNumericConstraints(schema);
|
|
2251
|
+
if (min !== void 0 && value < min) return false;
|
|
2252
|
+
if (max !== void 0 && value > max) return false;
|
|
2253
|
+
if (exclusiveMinimum !== void 0 && value <= exclusiveMinimum) return false;
|
|
2254
|
+
if (exclusiveMaximum !== void 0 && value >= exclusiveMaximum) return false;
|
|
2255
|
+
if (multipleOf !== void 0 && Math.abs(value / multipleOf - Math.round(value / multipleOf)) > 1e-9) return false;
|
|
2256
|
+
return true;
|
|
2257
|
+
}
|
|
2258
|
+
/**
|
|
2259
|
+
* Builds the test for which `enum` entries stay: not `null`, and within the numeric bounds. `enum` and the bounds
|
|
2260
|
+
* apply together, so a value outside them is never valid. Bounds that exclude every value are a spec error, so
|
|
2261
|
+
* they are ignored rather than leaving an empty enum.
|
|
2262
|
+
*/
|
|
2263
|
+
function createEnumMemberFilter(schema) {
|
|
2264
|
+
const boundsApply = schema.enum.some((value) => value !== null && isWithinBounds({
|
|
2265
|
+
value,
|
|
2266
|
+
schema
|
|
2267
|
+
}));
|
|
2268
|
+
return (value) => value !== null && (!boundsApply || isWithinBounds({
|
|
2269
|
+
value,
|
|
2270
|
+
schema
|
|
2271
|
+
}));
|
|
2272
|
+
}
|
|
2273
|
+
/**
|
|
2236
2274
|
* Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
|
|
2237
2275
|
* and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
|
|
2238
2276
|
*/
|
|
@@ -2313,7 +2351,8 @@ function convertEnum({ schema, name, nullable, type, parse }) {
|
|
|
2313
2351
|
name
|
|
2314
2352
|
});
|
|
2315
2353
|
const nullInEnum = schema.enum.includes(null);
|
|
2316
|
-
const
|
|
2354
|
+
const isMember = createEnumMemberFilter(schema);
|
|
2355
|
+
const filteredValues = schema.enum.filter(isMember);
|
|
2317
2356
|
if (nullInEnum && filteredValues.length === 0) return createNullNode(schema, name);
|
|
2318
2357
|
const enumNullable = nullable || nullInEnum || void 0;
|
|
2319
2358
|
const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
|
|
@@ -2332,8 +2371,9 @@ function convertEnum({ schema, name, nullable, type, parse }) {
|
|
|
2332
2371
|
primitive,
|
|
2333
2372
|
enumValues: uniqueValues
|
|
2334
2373
|
});
|
|
2335
|
-
const
|
|
2336
|
-
const
|
|
2374
|
+
const memberSlots = (list) => Array.isArray(list) ? list.filter((_, index) => isMember(schema.enum[index])) : void 0;
|
|
2375
|
+
const rawEnumNames = extensionKey ? memberSlots(schema[extensionKey]) : void 0;
|
|
2376
|
+
const rawEnumDescriptions = descriptionKey ? memberSlots(schema[descriptionKey]) : void 0;
|
|
2337
2377
|
const seenNames = /* @__PURE__ */ new Set();
|
|
2338
2378
|
return createNode(ctx, {
|
|
2339
2379
|
type: "enum",
|
|
@@ -2351,6 +2391,25 @@ function convertEnum({ schema, name, nullable, type, parse }) {
|
|
|
2351
2391
|
});
|
|
2352
2392
|
}
|
|
2353
2393
|
/**
|
|
2394
|
+
* Converts an `enum` with a handled `format` into a union of its literal values. A named enum node would rename
|
|
2395
|
+
* the exported type (`Status` becomes `StatusKey`), so the union keeps the name the format type had.
|
|
2396
|
+
*/
|
|
2397
|
+
function convertFormattedEnum(context) {
|
|
2398
|
+
const { schema, nullable } = context;
|
|
2399
|
+
const values = [...new Set(schema.enum.filter(createEnumMemberFilter(schema)))];
|
|
2400
|
+
return createNode({
|
|
2401
|
+
...context,
|
|
2402
|
+
nullable: nullable || schema.enum.includes(null) || void 0
|
|
2403
|
+
}, {
|
|
2404
|
+
type: "union",
|
|
2405
|
+
members: values.map((value) => ast.factory.createSchema({
|
|
2406
|
+
type: "enum",
|
|
2407
|
+
primitive: getPrimitiveType(typeof value),
|
|
2408
|
+
enumValues: [value]
|
|
2409
|
+
}))
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2354
2413
|
* Converts a `type: 'string'` schema into a `StringSchemaNode`.
|
|
2355
2414
|
*/
|
|
2356
2415
|
function convertString(context) {
|
|
@@ -2527,6 +2586,24 @@ function convertArray({ schema, name, nullable, defaultValue, options, parse })
|
|
|
2527
2586
|
}
|
|
2528
2587
|
// src/emit/parseSchema.ts
|
|
2529
2588
|
/**
|
|
2589
|
+
* Whether the `format` rule owns the schema: a handled format, and for a date format a `dateType` that is not `false`.
|
|
2590
|
+
*/
|
|
2591
|
+
function matchesFormat({ schema, options }) {
|
|
2592
|
+
if (!schema.format) return false;
|
|
2593
|
+
if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") return resolveDateTypeValue(options.dateType, schema.format) !== false;
|
|
2594
|
+
return isHandledFormat(schema.format);
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Whether the format prints as a plain `string` or `number`, so narrowing it to literal values cannot break callers.
|
|
2598
|
+
* `Date`, `bigint` and `Blob` outputs keep the format.
|
|
2599
|
+
*/
|
|
2600
|
+
function formatPrintsPlainType({ schema, options, type }) {
|
|
2601
|
+
const format = schema.format;
|
|
2602
|
+
if (format === "date-time" || format === "date" || format === "time") return resolveDateTypeValue(options.dateType, format) !== "date";
|
|
2603
|
+
if ((format === "int64" || format === "uint64") && type !== "string") return options.integerType !== "bigint";
|
|
2604
|
+
return formatMap[format] !== "blob";
|
|
2605
|
+
}
|
|
2606
|
+
/**
|
|
2530
2607
|
* Ordered schema rule table. Order is significant: composition keywords (`not`, `$ref`, `allOf`,
|
|
2531
2608
|
* `oneOf`/`anyOf`) take precedence over `const` (except a `$ref` with a sibling `const`, where the
|
|
2532
2609
|
* `const` wins), which takes precedence over a genuine OAS 3.1 multi-type array (more than one
|
|
@@ -2564,11 +2641,11 @@ const schemaRules = [
|
|
|
2564
2641
|
convert: convertMultiType
|
|
2565
2642
|
},
|
|
2566
2643
|
{
|
|
2567
|
-
match: (
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2644
|
+
match: (ctx) => ctx.type !== "array" && !!ctx.schema.enum?.some((value) => value !== null) && matchesFormat(ctx) && formatPrintsPlainType(ctx),
|
|
2645
|
+
convert: convertFormattedEnum
|
|
2646
|
+
},
|
|
2647
|
+
{
|
|
2648
|
+
match: matchesFormat,
|
|
2572
2649
|
convert: convertFormat
|
|
2573
2650
|
},
|
|
2574
2651
|
{
|