@kubb/adapter-oas 5.15.2 → 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 CHANGED
@@ -35,7 +35,7 @@ var compatibility = {
35
35
  "node": ">=22.22"
36
36
  };
37
37
  // package.json
38
- var version = "5.15.2";
38
+ var version = "5.15.4";
39
39
  // src/constants.ts
40
40
  /**
41
41
  * Default parser options applied when no explicit options are provided.
@@ -631,8 +631,10 @@ async function readSource(sourcePath) {
631
631
  async function resolveSource(sourcePath) {
632
632
  const data = await readSource(sourcePath);
633
633
  if (sourcePath.toLowerCase().endsWith(".md")) return data;
634
+ const pathname = urlRegExp.test(sourcePath) ? new URL(sourcePath).pathname : sourcePath;
634
635
  return parseYaml(data, {
635
636
  origin: sourcePath,
637
+ json: !/\.ya?ml$/i.test(pathname),
636
638
  help: "Fix the syntax at the reported line, or check that `input` points at the spec and not an HTML page."
637
639
  });
638
640
  }
@@ -640,11 +642,19 @@ async function resolveSource(sourcePath) {
640
642
  * Parses a YAML (or JSON) spec. A syntax error throws `KUBB_INVALID_DOCUMENT` naming `origin`,
641
643
  * with the parser message, which keeps the line and column.
642
644
  *
643
- * JSON is valid YAML, so one parser handles both. `js-yaml` parses about ten times faster than
644
- * `yaml`, and unlike `JSON.parse` it rejects duplicate keys instead of keeping the last one. Its
645
- * core schema keeps timestamps as strings and `<<` as a plain key, as `yaml` does for YAML 1.2.
645
+ * With `json` (the default), a document that starts with `{` or `[` goes through `JSON.parse`
646
+ * first, about ten times faster than `js-yaml` on a JSON spec. A duplicate key then keeps the last
647
+ * value, as every JSON parser does. YAML flow syntax also starts with `{`, so a parse failure falls
648
+ * through to YAML. Pass `json: false` for a source known to be YAML.
649
+ *
650
+ * `js-yaml` parses about ten times faster than `yaml`, and rejects duplicate keys instead of
651
+ * keeping the last one. Its core schema keeps timestamps as strings and `<<` as a plain key, as
652
+ * `yaml` does for YAML 1.2.
646
653
  */
647
- function parseYaml(data, { origin, help }) {
654
+ function parseYaml(data, { origin, help, json = true }) {
655
+ if (json && /^\s*[[{]/.test(data)) try {
656
+ return JSON.parse(data);
657
+ } catch {}
648
658
  try {
649
659
  const document = (0, js_yaml.load)(data, { schema: js_yaml.CORE_SCHEMA });
650
660
  if (document !== void 0) return document;
@@ -2249,6 +2259,34 @@ function getNumericConstraints(schema) {
2249
2259
  };
2250
2260
  }
2251
2261
  /**
2262
+ * Whether an enum value fits the schema's numeric bounds.
2263
+ */
2264
+ function isWithinBounds({ value, schema }) {
2265
+ if (typeof value !== "number") return true;
2266
+ const { min, max, exclusiveMinimum, exclusiveMaximum, multipleOf } = getNumericConstraints(schema);
2267
+ if (min !== void 0 && value < min) return false;
2268
+ if (max !== void 0 && value > max) return false;
2269
+ if (exclusiveMinimum !== void 0 && value <= exclusiveMinimum) return false;
2270
+ if (exclusiveMaximum !== void 0 && value >= exclusiveMaximum) return false;
2271
+ if (multipleOf !== void 0 && Math.abs(value / multipleOf - Math.round(value / multipleOf)) > 1e-9) return false;
2272
+ return true;
2273
+ }
2274
+ /**
2275
+ * Builds the test for which `enum` entries stay: not `null`, and within the numeric bounds. `enum` and the bounds
2276
+ * apply together, so a value outside them is never valid. Bounds that exclude every value are a spec error, so
2277
+ * they are ignored rather than leaving an empty enum.
2278
+ */
2279
+ function createEnumMemberFilter(schema) {
2280
+ const boundsApply = schema.enum.some((value) => value !== null && isWithinBounds({
2281
+ value,
2282
+ schema
2283
+ }));
2284
+ return (value) => value !== null && (!boundsApply || isWithinBounds({
2285
+ value,
2286
+ schema
2287
+ }));
2288
+ }
2289
+ /**
2252
2290
  * Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
2253
2291
  * and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
2254
2292
  */
@@ -2329,7 +2367,8 @@ function convertEnum({ schema, name, nullable, type, parse }) {
2329
2367
  name
2330
2368
  });
2331
2369
  const nullInEnum = schema.enum.includes(null);
2332
- const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
2370
+ const isMember = createEnumMemberFilter(schema);
2371
+ const filteredValues = schema.enum.filter(isMember);
2333
2372
  if (nullInEnum && filteredValues.length === 0) return createNullNode(schema, name);
2334
2373
  const enumNullable = nullable || nullInEnum || void 0;
2335
2374
  const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
@@ -2348,8 +2387,9 @@ function convertEnum({ schema, name, nullable, type, parse }) {
2348
2387
  primitive,
2349
2388
  enumValues: uniqueValues
2350
2389
  });
2351
- const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
2352
- const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
2390
+ const memberSlots = (list) => Array.isArray(list) ? list.filter((_, index) => isMember(schema.enum[index])) : void 0;
2391
+ const rawEnumNames = extensionKey ? memberSlots(schema[extensionKey]) : void 0;
2392
+ const rawEnumDescriptions = descriptionKey ? memberSlots(schema[descriptionKey]) : void 0;
2353
2393
  const seenNames = /* @__PURE__ */ new Set();
2354
2394
  return createNode(ctx, {
2355
2395
  type: "enum",
@@ -2367,6 +2407,25 @@ function convertEnum({ schema, name, nullable, type, parse }) {
2367
2407
  });
2368
2408
  }
2369
2409
  /**
2410
+ * Converts an `enum` with a handled `format` into a union of its literal values. A named enum node would rename
2411
+ * the exported type (`Status` becomes `StatusKey`), so the union keeps the name the format type had.
2412
+ */
2413
+ function convertFormattedEnum(context) {
2414
+ const { schema, nullable } = context;
2415
+ const values = [...new Set(schema.enum.filter(createEnumMemberFilter(schema)))];
2416
+ return createNode({
2417
+ ...context,
2418
+ nullable: nullable || schema.enum.includes(null) || void 0
2419
+ }, {
2420
+ type: "union",
2421
+ members: values.map((value) => _kubb_kit.ast.factory.createSchema({
2422
+ type: "enum",
2423
+ primitive: getPrimitiveType(typeof value),
2424
+ enumValues: [value]
2425
+ }))
2426
+ });
2427
+ }
2428
+ /**
2370
2429
  * Converts a `type: 'string'` schema into a `StringSchemaNode`.
2371
2430
  */
2372
2431
  function convertString(context) {
@@ -2543,6 +2602,24 @@ function convertArray({ schema, name, nullable, defaultValue, options, parse })
2543
2602
  }
2544
2603
  // src/emit/parseSchema.ts
2545
2604
  /**
2605
+ * Whether the `format` rule owns the schema: a handled format, and for a date format a `dateType` that is not `false`.
2606
+ */
2607
+ function matchesFormat({ schema, options }) {
2608
+ if (!schema.format) return false;
2609
+ if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") return resolveDateTypeValue(options.dateType, schema.format) !== false;
2610
+ return isHandledFormat(schema.format);
2611
+ }
2612
+ /**
2613
+ * Whether the format prints as a plain `string` or `number`, so narrowing it to literal values cannot break callers.
2614
+ * `Date`, `bigint` and `Blob` outputs keep the format.
2615
+ */
2616
+ function formatPrintsPlainType({ schema, options, type }) {
2617
+ const format = schema.format;
2618
+ if (format === "date-time" || format === "date" || format === "time") return resolveDateTypeValue(options.dateType, format) !== "date";
2619
+ if ((format === "int64" || format === "uint64") && type !== "string") return options.integerType !== "bigint";
2620
+ return formatMap[format] !== "blob";
2621
+ }
2622
+ /**
2546
2623
  * Ordered schema rule table. Order is significant: composition keywords (`not`, `$ref`, `allOf`,
2547
2624
  * `oneOf`/`anyOf`) take precedence over `const` (except a `$ref` with a sibling `const`, where the
2548
2625
  * `const` wins), which takes precedence over a genuine OAS 3.1 multi-type array (more than one
@@ -2580,11 +2657,11 @@ const schemaRules = [
2580
2657
  convert: convertMultiType
2581
2658
  },
2582
2659
  {
2583
- match: ({ schema, options }) => {
2584
- if (!schema.format) return false;
2585
- if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") return resolveDateTypeValue(options.dateType, schema.format) !== false;
2586
- return isHandledFormat(schema.format);
2587
- },
2660
+ match: (ctx) => ctx.type !== "array" && !!ctx.schema.enum?.some((value) => value !== null) && matchesFormat(ctx) && formatPrintsPlainType(ctx),
2661
+ convert: convertFormattedEnum
2662
+ },
2663
+ {
2664
+ match: matchesFormat,
2588
2665
  convert: convertFormat
2589
2666
  },
2590
2667
  {