@kubb/adapter-oas 5.12.5 → 5.12.7

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.d.cts CHANGED
@@ -1081,6 +1081,10 @@ type SchemaObject$1 = {
1081
1081
  externalDocs?: unknown;
1082
1082
  xml?: unknown;
1083
1083
  $schema?: string;
1084
+ /** JSON Schema definitions that may be referenced from other schema locations. */
1085
+ $defs?: Record<string, SchemaObject$1>;
1086
+ /** Legacy draft-07 name for `$defs`. */
1087
+ definitions?: Record<string, SchemaObject$1>;
1084
1088
  deprecated?: boolean;
1085
1089
  example?: unknown;
1086
1090
  examples?: Array<unknown>;
package/dist/index.d.ts CHANGED
@@ -1081,6 +1081,10 @@ type SchemaObject$1 = {
1081
1081
  externalDocs?: unknown;
1082
1082
  xml?: unknown;
1083
1083
  $schema?: string;
1084
+ /** JSON Schema definitions that may be referenced from other schema locations. */
1085
+ $defs?: Record<string, SchemaObject$1>;
1086
+ /** Legacy draft-07 name for `$defs`. */
1087
+ definitions?: Record<string, SchemaObject$1>;
1084
1088
  deprecated?: boolean;
1085
1089
  example?: unknown;
1086
1090
  examples?: Array<unknown>;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var compatibility = {
14
14
  };
15
15
  //#endregion
16
16
  //#region package.json
17
- var version = "5.12.5";
17
+ var version = "5.12.7";
18
18
  //#endregion
19
19
  //#region src/constants.ts
20
20
  /**
@@ -99,24 +99,35 @@ const numericFormats = /* @__PURE__ */ new Set([
99
99
  /**
100
100
  * Static map from OAS `format` strings to Kubb `SchemaType` values.
101
101
  *
102
- * Only formats whose AST type differs from the OAS `type` field appear here.
102
+ * Lists formats whose AST type differs from the OAS `type` field, plus string formats that
103
+ * `KUBB_UNSUPPORTED_FORMAT` should not flag.
103
104
  * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled
104
- * separately in the parser. `ipv4` and `ipv6` map to their own dedicated schema types. `hostname`
105
- * and `idn-hostname` map to `'url'` as the closest generic string-format type.
105
+ * separately in the parser. `ipv4` and `ipv6` map to their own dedicated schema types.
106
+ * `uri-reference`, `iri`, `iri-reference`, `hostname` and `idn-hostname` map to `'string'`: a relative
107
+ * reference, a Unicode IRI or a bare host name is not a URL, so a `'url'` validator would reject valid
108
+ * values. `base64url`, `jwt`, `ulid`, `iban` and `duration` map to `'string'` because plugins check
109
+ * them by `format`.
106
110
  */
107
111
  const formatMap = {
108
112
  uuid: "uuid",
109
113
  email: "email",
110
114
  "idn-email": "email",
111
115
  uri: "url",
112
- "uri-reference": "url",
116
+ "uri-reference": "string",
117
+ iri: "string",
118
+ "iri-reference": "string",
113
119
  url: "url",
114
120
  ipv4: "ipv4",
115
121
  ipv6: "ipv6",
116
- hostname: "url",
117
- "idn-hostname": "url",
122
+ hostname: "string",
123
+ "idn-hostname": "string",
118
124
  binary: "blob",
119
125
  byte: "blob",
126
+ base64url: "string",
127
+ jwt: "string",
128
+ ulid: "string",
129
+ iban: "string",
130
+ duration: "string",
120
131
  int32: "integer",
121
132
  float: "number",
122
133
  double: "number"
@@ -708,23 +719,73 @@ function extractSchemaFromContent(content, preferredContentType) {
708
719
  /**
709
720
  * Walks a schema tree and collects the names of all `#/components/schemas/<name>` `$ref`s.
710
721
  */
711
- function* collectRefs(schema) {
722
+ function* collectRefs(schema, renames) {
712
723
  if (Array.isArray(schema)) {
713
- for (const item of schema) yield* collectRefs(item);
724
+ for (const item of schema) yield* collectRefs(item, renames);
714
725
  return;
715
726
  }
716
727
  if (schema && typeof schema === "object") for (const key in schema) {
717
728
  const value = schema[key];
718
729
  if (!(key === "$ref" && typeof value === "string")) {
719
- yield* collectRefs(value);
730
+ yield* collectRefs(value, renames);
720
731
  continue;
721
732
  }
722
733
  if (value.startsWith("#/components/schemas/")) {
723
- const name = value.slice(21);
734
+ const name = renames.get(value) ?? value.slice(21);
724
735
  if (name) yield name;
725
736
  }
726
737
  }
727
738
  }
739
+ const schemaChildKeywords = [
740
+ "additionalProperties",
741
+ "allOf",
742
+ "anyOf",
743
+ "contains",
744
+ "contentSchema",
745
+ "else",
746
+ "if",
747
+ "items",
748
+ "not",
749
+ "oneOf",
750
+ "patternProperties",
751
+ "prefixItems",
752
+ "properties",
753
+ "propertyNames",
754
+ "then"
755
+ ];
756
+ /** Collects definitions only from schema locations, never from examples/defaults or arbitrary data. */
757
+ function* collectNestedDefinitions(schema, pointer, name) {
758
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) return;
759
+ const value = schema;
760
+ for (const keyword of ["$defs", "definitions"]) {
761
+ const definitions = value[keyword];
762
+ if (!definitions || typeof definitions !== "object" || Array.isArray(definitions)) continue;
763
+ for (const [key, definition] of Object.entries(definitions)) {
764
+ if (!definition || typeof definition !== "object" || Array.isArray(definition)) continue;
765
+ const definitionPointer = `${pointer}/${keyword}/${escapePointerToken(key)}`;
766
+ const nestedName = `${name}_${key}`;
767
+ yield {
768
+ schema: definition,
769
+ pointer: definitionPointer,
770
+ originalName: nestedName
771
+ };
772
+ yield* collectNestedDefinitions(definition, definitionPointer, nestedName);
773
+ }
774
+ }
775
+ for (const keyword of schemaChildKeywords) {
776
+ const child = value[keyword];
777
+ if (!child || typeof child !== "object") continue;
778
+ if (Array.isArray(child)) {
779
+ for (const [index, item] of child.entries()) yield* collectNestedDefinitions(item, `${pointer}/${keyword}/${index}`, name);
780
+ continue;
781
+ }
782
+ if (keyword === "properties" || keyword === "patternProperties") {
783
+ for (const [key, item] of Object.entries(child)) yield* collectNestedDefinitions(item, `${pointer}/${keyword}/${escapePointerToken(key)}`, name);
784
+ continue;
785
+ }
786
+ yield* collectNestedDefinitions(child, `${pointer}/${keyword}`, name);
787
+ }
788
+ }
728
789
  /**
729
790
  * Returns a copy of `schemas` topologically sorted by `$ref` dependency.
730
791
  *
@@ -737,9 +798,9 @@ function* collectRefs(schema) {
737
798
  * // Pet appears before Order when Order.$ref points at Pet
738
799
  * ```
739
800
  */
740
- function sortSchemas(schemas) {
801
+ function sortSchemas(schemas, renames) {
741
802
  const deps = /* @__PURE__ */ new Map();
742
- for (const [name, schema] of Object.entries(schemas)) deps.set(name, [...new Set(collectRefs(schema))]);
803
+ for (const [name, schema] of Object.entries(schemas)) deps.set(name, [...new Set(collectRefs(schema, renames))]);
743
804
  const sorted = [];
744
805
  const visited = /* @__PURE__ */ new Set();
745
806
  function visit(name, stack) {
@@ -782,16 +843,25 @@ function getSchemas(document, { contentType }, refs) {
782
843
  const resolved = refs.resolve(schema.$ref);
783
844
  return resolved && !isReference(resolved) ? resolved : schema;
784
845
  }
785
- const candidates = [...Object.entries(components?.schemas ?? {}).map(([name, schema]) => ({
786
- schema: resolveSchemaRef(schema),
787
- source: "schemas",
788
- originalName: name
789
- })), ...["responses", "requestBodies"].flatMap((source) => Object.entries(components?.[source] ?? {}).flatMap(([name, item]) => {
846
+ const candidates = [...Object.entries(components?.schemas ?? {}).flatMap(([name, schema]) => {
847
+ const pointer = `#/components/schemas/${escapePointerToken(name)}`;
848
+ return [{
849
+ schema: resolveSchemaRef(schema),
850
+ source: "schemas",
851
+ originalName: name,
852
+ pointer
853
+ }, ...[...collectNestedDefinitions(schema, pointer, name)].map((nested) => ({
854
+ ...nested,
855
+ source: "schemas",
856
+ nested: true
857
+ }))];
858
+ }), ...["responses", "requestBodies"].flatMap((source) => Object.entries(components?.[source] ?? {}).flatMap(([name, item]) => {
790
859
  const schema = extractSchemaFromContent(item.content, contentType);
791
860
  return schema ? [{
792
861
  schema: resolveSchemaRef(schema),
793
862
  source,
794
- originalName: name
863
+ originalName: name,
864
+ pointer: `#/components/${source}/${escapePointerToken(name)}`
795
865
  }] : [];
796
866
  }))];
797
867
  const normalizedNames = /* @__PURE__ */ new Map();
@@ -810,11 +880,11 @@ function getSchemas(document, { contentType }, refs) {
810
880
  const suffix = isSingle ? "" : hasMultipleSources ? semanticSuffixes[item.source] : index ? String(index + 1) : "";
811
881
  const uniqueName = item.originalName + suffix;
812
882
  schemas[uniqueName] = item.schema;
813
- if (suffix) renames.set(`#/components/${item.source}/${item.originalName}`, uniqueName);
883
+ if (suffix || item.nested) renames.set(item.pointer, uniqueName);
814
884
  });
815
885
  }
816
886
  return {
817
- schemas: sortSchemas(schemas),
887
+ schemas: sortSchemas(schemas, renames),
818
888
  renames
819
889
  };
820
890
  }
@@ -1746,6 +1816,10 @@ function convertFormat(context) {
1746
1816
  });
1747
1817
  }
1748
1818
  const specialType = formatMap[schema.format];
1819
+ if (specialType === "string") {
1820
+ if (type === "integer" || type === "number") return convertNumeric(context, type);
1821
+ return convertString(context);
1822
+ }
1749
1823
  const isNumeric = specialType === "number" || specialType === "integer";
1750
1824
  return createNode(context, {
1751
1825
  primitive: isNumeric ? specialType : "string",