@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.js CHANGED
@@ -19,7 +19,7 @@ var compatibility = {
19
19
  "node": ">=22.22"
20
20
  };
21
21
  // package.json
22
- var version = "5.15.3";
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
- * JSON is valid YAML, so one parser handles both. `js-yaml` parses about ten times faster than
628
- * `yaml`, and unlike `JSON.parse` it rejects duplicate keys instead of keeping the last one. Its
629
- * core schema keeps timestamps as strings and `<<` as a plain key, as `yaml` does for YAML 1.2.
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 filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
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 rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
2336
- const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
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: ({ schema, options }) => {
2568
- if (!schema.format) return false;
2569
- if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") return resolveDateTypeValue(options.dateType, schema.format) !== false;
2570
- return isHandledFormat(schema.format);
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
  {