@ir-kit/schema 0.2.0

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ahmed Rowaihi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # `@ir-kit/schema`
2
+
3
+ Canonical JSON Schema 2020-12 IR shared across the OpenAPI and AsyncAPI codegen families. Source-agnostic — adapters fold hey-api's `IR.SchemaObject`, raw JSON Schema (any draft), and OpenAPI 3.0 `nullable` quirks into one shape so every emitter (`@ir-kit/openapi-{go,kotlin,swift,typescript}`, `@ir-kit/asyncapi-typescript`, `@ir-kit/k6-codegen`) reads the same model.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install @ir-kit/schema
9
+ # adapter from hey-api needs:
10
+ npm install @hey-api/shared
11
+ ```
12
+
13
+ ## Use
14
+
15
+ ```ts
16
+ import {
17
+ type Schema,
18
+ classifyUnion,
19
+ classifyObject,
20
+ classifyEnumLiterals,
21
+ extractEnumValues,
22
+ } from "@ir-kit/schema";
23
+
24
+ const schema: Schema = {
25
+ oneOf: [{ type: "string" }, { type: "null" }],
26
+ };
27
+
28
+ const shape = classifyUnion(schema);
29
+ // → { kind: "single", inner: { type: "string" }, nullable: true }
30
+ ```
31
+
32
+ ## Adapters
33
+
34
+ ```ts
35
+ import { fromHeyApi } from "@ir-kit/schema/adapters/heyapi";
36
+ import { fromJsonSchema } from "@ir-kit/schema/adapters/jsonschema";
37
+
38
+ const canonical = fromHeyApi(heyApiIrSchemaObject);
39
+ const fromAsync = fromJsonSchema(asyncSchema.json(), { dialect: "draft-07" });
40
+ const fromOas3 = fromJsonSchema(openapi30Schema); // `nullable: true` folded into type[]
41
+ ```
42
+
43
+ ## Scope
44
+
45
+ This is the **dialect**: types + classifiers + adapters. Per-target rendering (Go pointer vs Kotlin nullable, struct emission, enum identifier transforms) lives in each emitter package — see `@ir-kit/openapi`'s `SchemaToTypeOps<T,D>` interface.
46
+
47
+ Subset of JSON Schema 2020-12. Omitted (codegen can't bind cleanly): `$dynamicRef`, `$dynamicAnchor`, `unevaluatedProperties`, `unevaluatedItems`, `if`/`then`/`else`, `dependentSchemas`, `dependentRequired`, `contains`.
48
+
49
+ ## Status
50
+
51
+ `0.1.0` — first release. Consumers (`@ir-kit/openapi`, `@ir-kit/asyncapi-typescript`, `@ir-kit/k6-codegen`) migrate incrementally in follow-up changesets.
52
+
53
+ ## Repo
54
+
55
+ Source at [ir-kit/ir-kit](https://github.com/ir-kit/ir-kit/tree/main/packages/shared/schema).
@@ -0,0 +1,16 @@
1
+ import type { IR } from "@hey-api/shared";
2
+ import type { Schema } from "../types.js";
3
+ /**
4
+ * Adapt `IR.SchemaObject` (hey-api's normalized intermediate form) to
5
+ * canonical {@link Schema}.
6
+ *
7
+ * Normalizations:
8
+ * - `type:"enum"` + `items[].const` → `enum: [...]`
9
+ * - `type:"tuple"` → `type:"array"` + `prefixItems`
10
+ * - `type:"void"|"never"|"undefined"` → `type` left unset
11
+ * - `logicalOperator:"or"|"and"` → `oneOf` / `allOf`
12
+ * - untyped + items[] → `oneOf` (hey-api's implicit
13
+ * union convention)
14
+ */
15
+ export declare function fromHeyApi(s: IR.SchemaObject): Schema;
16
+ //# sourceMappingURL=heyapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heyapi.d.ts","sourceRoot":"","sources":["../../src/adapters/heyapi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,aAAa,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,CAsGrD"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Adapt `IR.SchemaObject` (hey-api's normalized intermediate form) to
3
+ * canonical {@link Schema}.
4
+ *
5
+ * Normalizations:
6
+ * - `type:"enum"` + `items[].const` → `enum: [...]`
7
+ * - `type:"tuple"` → `type:"array"` + `prefixItems`
8
+ * - `type:"void"|"never"|"undefined"` → `type` left unset
9
+ * - `logicalOperator:"or"|"and"` → `oneOf` / `allOf`
10
+ * - untyped + items[] → `oneOf` (hey-api's implicit
11
+ * union convention)
12
+ */
13
+ export function fromHeyApi(s) {
14
+ const out = {};
15
+ if (s.$ref) {
16
+ out.$ref = s.$ref;
17
+ }
18
+ else {
19
+ // hey-api's post-resolution marker for a generated symbol —
20
+ // express it canonically as a $ref into `#/components/schemas`.
21
+ const sym = s.symbolRef;
22
+ if (sym?.name)
23
+ out.$ref = `#/components/schemas/${sym.name}`;
24
+ }
25
+ if (s.title)
26
+ out.title = s.title;
27
+ if (s.description)
28
+ out.description = s.description;
29
+ if (s.deprecated !== undefined)
30
+ out.deprecated = s.deprecated;
31
+ if (s.default !== undefined)
32
+ out.default = s.default;
33
+ if (s.format)
34
+ out.format = s.format;
35
+ if (s.pattern)
36
+ out.pattern = s.pattern;
37
+ if (s.minLength !== undefined)
38
+ out.minLength = s.minLength;
39
+ if (s.maxLength !== undefined)
40
+ out.maxLength = s.maxLength;
41
+ if (s.minimum !== undefined)
42
+ out.minimum = s.minimum;
43
+ if (s.maximum !== undefined)
44
+ out.maximum = s.maximum;
45
+ if (typeof s.exclusiveMinimum === "number")
46
+ out.exclusiveMinimum = s.exclusiveMinimum;
47
+ if (typeof s.exclusiveMaximum === "number")
48
+ out.exclusiveMaximum = s.exclusiveMaximum;
49
+ if (s.const !== undefined)
50
+ out.const = s.const;
51
+ if (s.logicalOperator === "and" && Array.isArray(s.items)) {
52
+ out.allOf = s.items.map(fromHeyApi);
53
+ }
54
+ else if (s.logicalOperator === "or" && Array.isArray(s.items)) {
55
+ out.oneOf = s.items.map(fromHeyApi);
56
+ }
57
+ else if (!s.type && Array.isArray(s.items) && s.items.length > 0) {
58
+ out.oneOf = s.items.map(fromHeyApi);
59
+ }
60
+ if (s.properties) {
61
+ out.properties = {};
62
+ for (const [k, v] of Object.entries(s.properties)) {
63
+ out.properties[k] = fromHeyApi(v);
64
+ }
65
+ }
66
+ if (s.required && s.required.length > 0)
67
+ out.required = [...s.required];
68
+ if (s.additionalProperties !== undefined) {
69
+ const ap = s.additionalProperties;
70
+ if (typeof ap === "boolean") {
71
+ out.additionalProperties = ap;
72
+ }
73
+ else if (ap.type === "never" ||
74
+ ap.type === "void" ||
75
+ ap.type === "undefined") {
76
+ // hey-api represents `additionalProperties: false` as a never/void/
77
+ // undefined-typed schema after normalization — collapse back to
78
+ // the canonical boolean form so emitters can sealed-detect.
79
+ out.additionalProperties = false;
80
+ }
81
+ else {
82
+ out.additionalProperties = fromHeyApi(ap);
83
+ }
84
+ }
85
+ switch (s.type) {
86
+ case "enum": {
87
+ const values = (s.items ?? [])
88
+ .map((i) => i.const)
89
+ .filter((v) => typeof v === "string" ||
90
+ typeof v === "number" ||
91
+ typeof v === "boolean");
92
+ if (values.length > 0)
93
+ out.enum = values;
94
+ out.type = inferEnumType(values);
95
+ break;
96
+ }
97
+ case "tuple": {
98
+ out.type = "array";
99
+ if (Array.isArray(s.items) && s.items.length > 0) {
100
+ out.prefixItems = s.items.map(fromHeyApi);
101
+ }
102
+ break;
103
+ }
104
+ case "array": {
105
+ out.type = "array";
106
+ const elem = Array.isArray(s.items) ? s.items[0] : undefined;
107
+ if (elem)
108
+ out.items = fromHeyApi(elem);
109
+ break;
110
+ }
111
+ case "void":
112
+ case "never":
113
+ case "undefined":
114
+ break;
115
+ case "object":
116
+ case "string":
117
+ case "number":
118
+ case "integer":
119
+ case "boolean":
120
+ case "null":
121
+ out.type = s.type;
122
+ break;
123
+ }
124
+ return out;
125
+ }
126
+ function inferEnumType(values) {
127
+ if (values.every((v) => typeof v === "string"))
128
+ return "string";
129
+ if (values.every((v) => typeof v === "number" && Number.isInteger(v)))
130
+ return "integer";
131
+ if (values.every((v) => typeof v === "number"))
132
+ return "number";
133
+ if (values.every((v) => typeof v === "boolean"))
134
+ return "boolean";
135
+ return undefined;
136
+ }
137
+ //# sourceMappingURL=heyapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heyapi.js","sourceRoot":"","sources":["../../src/adapters/heyapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Schema } from "../types.js";
2
+ export type JsonSchemaDialect = "draft-04" | "draft-06" | "draft-07" | "2019-09" | "2020-12";
3
+ export interface FromJsonSchemaOptions {
4
+ /** Source dialect — drives normalization of legacy quirks (boolean
5
+ * `exclusiveMinimum`, array-form `items` as tuple, `definitions` →
6
+ * `$defs`). Defaults to `2020-12` (pass-through). */
7
+ dialect?: JsonSchemaDialect;
8
+ }
9
+ /**
10
+ * Adapt raw JSON Schema (any draft) → canonical {@link Schema}. Pure
11
+ * conversion: no validation, no ref resolution. Unknown keywords are
12
+ * dropped. OpenAPI 3.0's `nullable: true` is folded into the type
13
+ * array regardless of dialect (it's a common quirk).
14
+ */
15
+ export declare function fromJsonSchema(raw: unknown, opts?: FromJsonSchemaOptions): Schema;
16
+ //# sourceMappingURL=jsonschema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonschema.d.ts","sourceRoot":"","sources":["../../src/adapters/jsonschema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,aAAa,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,qBAAqB;IACpC;;0DAEsD;IACtD,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,IAAI,GAAE,qBAA0B,GAC/B,MAAM,CAwIR"}
@@ -0,0 +1,161 @@
1
+ const PRIMITIVE_TYPES = new Set([
2
+ "string",
3
+ "number",
4
+ "integer",
5
+ "boolean",
6
+ "null",
7
+ "object",
8
+ "array",
9
+ ]);
10
+ /**
11
+ * Adapt raw JSON Schema (any draft) → canonical {@link Schema}. Pure
12
+ * conversion: no validation, no ref resolution. Unknown keywords are
13
+ * dropped. OpenAPI 3.0's `nullable: true` is folded into the type
14
+ * array regardless of dialect (it's a common quirk).
15
+ */
16
+ export function fromJsonSchema(raw, opts = {}) {
17
+ if (typeof raw !== "object" || raw === null)
18
+ return {};
19
+ const r = raw;
20
+ const dialect = opts.dialect ?? "2020-12";
21
+ const out = {};
22
+ if (typeof r.$ref === "string")
23
+ out.$ref = r.$ref;
24
+ if (typeof r.title === "string")
25
+ out.title = r.title;
26
+ if (typeof r.description === "string")
27
+ out.description = r.description;
28
+ if (typeof r.deprecated === "boolean")
29
+ out.deprecated = r.deprecated;
30
+ if (typeof r.readOnly === "boolean")
31
+ out.readOnly = r.readOnly;
32
+ if (typeof r.writeOnly === "boolean")
33
+ out.writeOnly = r.writeOnly;
34
+ if (r.default !== undefined)
35
+ out.default = r.default;
36
+ if (typeof r.format === "string")
37
+ out.format = r.format;
38
+ if (typeof r.pattern === "string")
39
+ out.pattern = r.pattern;
40
+ if (typeof r.minLength === "number")
41
+ out.minLength = r.minLength;
42
+ if (typeof r.maxLength === "number")
43
+ out.maxLength = r.maxLength;
44
+ if (typeof r.minimum === "number")
45
+ out.minimum = r.minimum;
46
+ if (typeof r.maximum === "number")
47
+ out.maximum = r.maximum;
48
+ if (typeof r.multipleOf === "number")
49
+ out.multipleOf = r.multipleOf;
50
+ if (typeof r.minItems === "number")
51
+ out.minItems = r.minItems;
52
+ if (typeof r.maxItems === "number")
53
+ out.maxItems = r.maxItems;
54
+ if (typeof r.uniqueItems === "boolean")
55
+ out.uniqueItems = r.uniqueItems;
56
+ if (r.const !== undefined)
57
+ out.const = r.const;
58
+ if (Array.isArray(r.enum) && r.enum.length > 0)
59
+ out.enum = r.enum;
60
+ if (Array.isArray(r.examples))
61
+ out.examples = r.examples;
62
+ if (Array.isArray(r.required)) {
63
+ const req = r.required.filter((x) => typeof x === "string");
64
+ if (req.length > 0)
65
+ out.required = req;
66
+ }
67
+ if (dialect === "draft-04") {
68
+ if (r.exclusiveMinimum === true && typeof r.minimum === "number") {
69
+ out.exclusiveMinimum = r.minimum;
70
+ }
71
+ else if (typeof r.exclusiveMinimum === "number") {
72
+ out.exclusiveMinimum = r.exclusiveMinimum;
73
+ }
74
+ if (r.exclusiveMaximum === true && typeof r.maximum === "number") {
75
+ out.exclusiveMaximum = r.maximum;
76
+ }
77
+ else if (typeof r.exclusiveMaximum === "number") {
78
+ out.exclusiveMaximum = r.exclusiveMaximum;
79
+ }
80
+ }
81
+ else {
82
+ if (typeof r.exclusiveMinimum === "number")
83
+ out.exclusiveMinimum = r.exclusiveMinimum;
84
+ if (typeof r.exclusiveMaximum === "number")
85
+ out.exclusiveMaximum = r.exclusiveMaximum;
86
+ }
87
+ const nullable = r.nullable === true;
88
+ if (typeof r.type === "string" && isPrimitiveTag(r.type)) {
89
+ out.type = nullable && r.type !== "null" ? [r.type, "null"] : r.type;
90
+ }
91
+ else if (Array.isArray(r.type)) {
92
+ const tags = r.type.filter((t) => typeof t === "string" && isPrimitiveTag(t));
93
+ if (tags.length > 0) {
94
+ out.type = nullable && !tags.includes("null") ? [...tags, "null"] : tags;
95
+ }
96
+ }
97
+ else if (nullable) {
98
+ out.type = ["null"];
99
+ }
100
+ if (Array.isArray(r.oneOf))
101
+ out.oneOf = r.oneOf.map((b) => fromJsonSchema(b, opts));
102
+ if (Array.isArray(r.anyOf))
103
+ out.anyOf = r.anyOf.map((b) => fromJsonSchema(b, opts));
104
+ if (Array.isArray(r.allOf))
105
+ out.allOf = r.allOf.map((b) => fromJsonSchema(b, opts));
106
+ if (r.not && typeof r.not === "object")
107
+ out.not = fromJsonSchema(r.not, opts);
108
+ if (r.properties && typeof r.properties === "object") {
109
+ out.properties = {};
110
+ for (const [k, v] of Object.entries(r.properties)) {
111
+ out.properties[k] = fromJsonSchema(v, opts);
112
+ }
113
+ }
114
+ if (r.patternProperties && typeof r.patternProperties === "object") {
115
+ out.patternProperties = {};
116
+ for (const [k, v] of Object.entries(r.patternProperties)) {
117
+ out.patternProperties[k] = fromJsonSchema(v, opts);
118
+ }
119
+ }
120
+ if (typeof r.additionalProperties === "boolean") {
121
+ out.additionalProperties = r.additionalProperties;
122
+ }
123
+ else if (r.additionalProperties &&
124
+ typeof r.additionalProperties === "object") {
125
+ out.additionalProperties = fromJsonSchema(r.additionalProperties, opts);
126
+ }
127
+ if (r.propertyNames && typeof r.propertyNames === "object") {
128
+ out.propertyNames = fromJsonSchema(r.propertyNames, opts);
129
+ }
130
+ if (Array.isArray(r.items)) {
131
+ out.prefixItems = r.items.map((b) => fromJsonSchema(b, opts));
132
+ }
133
+ else if (r.items && typeof r.items === "object") {
134
+ out.items = fromJsonSchema(r.items, opts);
135
+ }
136
+ if (Array.isArray(r.prefixItems)) {
137
+ out.prefixItems = r.prefixItems.map((b) => fromJsonSchema(b, opts));
138
+ }
139
+ const defs = (r.$defs ?? r.definitions);
140
+ if (defs && typeof defs === "object") {
141
+ out.$defs = {};
142
+ for (const [k, v] of Object.entries(defs)) {
143
+ out.$defs[k] = fromJsonSchema(v, opts);
144
+ }
145
+ }
146
+ if (r.discriminator &&
147
+ typeof r.discriminator === "object" &&
148
+ typeof r.discriminator.propertyName ===
149
+ "string") {
150
+ const d = r.discriminator;
151
+ out.discriminator = {
152
+ propertyName: d.propertyName,
153
+ ...(d.mapping ? { mapping: d.mapping } : {}),
154
+ };
155
+ }
156
+ return out;
157
+ }
158
+ function isPrimitiveTag(t) {
159
+ return PRIMITIVE_TYPES.has(t);
160
+ }
161
+ //# sourceMappingURL=jsonschema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonschema.js","sourceRoot":"","sources":["../../src/adapters/jsonschema.ts"],"names":[],"mappings":"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"}
package/dist/enum.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { type Schema } from "./types.js";
2
+ export type EnumLiteral = string | number | boolean;
3
+ export type EnumKind = "string" | "integer";
4
+ /**
5
+ * Extract enum literals from a schema. Recognises both explicit
6
+ * `enum: [...]` and `oneOf`/`anyOf` of `{const}` branches. Returns
7
+ * `undefined` when neither shape is present.
8
+ */
9
+ export declare function extractEnumValues(schema: Schema): ReadonlyArray<unknown> | undefined;
10
+ /**
11
+ * Throws on mixed shapes. The `name` is woven into the error so the
12
+ * caller doesn't have to re-wrap.
13
+ */
14
+ export declare function classifyEnumLiterals(values: ReadonlyArray<unknown>, name: string): EnumKind;
15
+ export interface EnumEntryIdent<T extends string | number> {
16
+ identifier: string;
17
+ raw: T;
18
+ }
19
+ /**
20
+ * Throws if two raw values normalize to the same target identifier
21
+ * (otherwise the emitted source won't compile). `noun` preserves the
22
+ * per-target wording — Go/Kotlin say `entry name`, Swift says `case
23
+ * name`; tests pin the exact phrase.
24
+ */
25
+ export declare function assertNoEnumCollisions<T extends string | number>(schemaName: string, entries: Iterable<EnumEntryIdent<T>>, noun?: "entry name" | "case name"): void;
26
+ //# sourceMappingURL=enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum.d.ts","sourceRoot":"","sources":["../src/enum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACpD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,GACb,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAWpC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,EAC9B,IAAI,EAAE,MAAM,GACX,QAAQ,CAWV;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,CAAC,CAAC;CACR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAC9D,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EACpC,IAAI,GAAE,YAAY,GAAG,WAA0B,GAC9C,IAAI,CAiBN"}
package/dist/enum.js ADDED
@@ -0,0 +1,58 @@
1
+ import { isSchemaObject } from "./types.js";
2
+ /**
3
+ * Extract enum literals from a schema. Recognises both explicit
4
+ * `enum: [...]` and `oneOf`/`anyOf` of `{const}` branches. Returns
5
+ * `undefined` when neither shape is present.
6
+ */
7
+ export function extractEnumValues(schema) {
8
+ if (Array.isArray(schema.enum) && schema.enum.length > 0)
9
+ return schema.enum;
10
+ const branches = schema.oneOf ?? schema.anyOf;
11
+ if (!branches)
12
+ return undefined;
13
+ const consts = [];
14
+ for (const b of branches) {
15
+ if (!isSchemaObject(b))
16
+ return undefined;
17
+ if (Object.hasOwn(b, "const"))
18
+ consts.push(b.const);
19
+ else
20
+ return undefined;
21
+ }
22
+ return consts.length > 0 ? consts : undefined;
23
+ }
24
+ /**
25
+ * Throws on mixed shapes. The `name` is woven into the error so the
26
+ * caller doesn't have to re-wrap.
27
+ */
28
+ export function classifyEnumLiterals(values, name) {
29
+ const allStrings = values.every((v) => typeof v === "string");
30
+ const allIntegers = values.every((v) => typeof v === "number" && Number.isInteger(v));
31
+ if (!allStrings && !allIntegers) {
32
+ throw new Error(`Enum ${name}: members must all be strings or all integers; got ${JSON.stringify(values)}`);
33
+ }
34
+ return allIntegers ? "integer" : "string";
35
+ }
36
+ /**
37
+ * Throws if two raw values normalize to the same target identifier
38
+ * (otherwise the emitted source won't compile). `noun` preserves the
39
+ * per-target wording — Go/Kotlin say `entry name`, Swift says `case
40
+ * name`; tests pin the exact phrase.
41
+ */
42
+ export function assertNoEnumCollisions(schemaName, entries, noun = "entry name") {
43
+ const collisions = new Map();
44
+ for (const { identifier, raw } of entries) {
45
+ const list = collisions.get(identifier) ?? [];
46
+ list.push(raw);
47
+ collisions.set(identifier, list);
48
+ }
49
+ for (const [identifier, raws] of collisions) {
50
+ if (raws.length > 1) {
51
+ const formatted = raws
52
+ .map((r) => (typeof r === "string" ? `"${r}"` : String(r)))
53
+ .join(", ");
54
+ throw new Error(`Enum ${schemaName}: ${noun} "${identifier}" collides for raw values [${formatted}]`);
55
+ }
56
+ }
57
+ }
58
+ //# sourceMappingURL=enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum.js","sourceRoot":"","sources":["../src/enum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAe,MAAM,YAAY,CAAC;AAKzD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc;IAEd,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAC7E,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;IAC9C,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;;YAC/C,OAAO,SAAS,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAA8B,EAC9B,IAAY;IAEZ,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CACpD,CAAC;IACF,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,QAAQ,IAAI,sDAAsD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC5C,CAAC;AAOD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAkB,EAClB,OAAoC,EACpC,OAAmC,YAAY;IAE/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAe,CAAC;IAC1C,KAAK,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,KAAK,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,SAAS,GAAG,IAAI;iBACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC1D,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,KAAK,CACb,QAAQ,UAAU,KAAK,IAAI,KAAK,UAAU,8BAA8B,SAAS,GAAG,CACrF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { assertNoEnumCollisions, classifyEnumLiterals, type EnumEntryIdent, type EnumKind, type EnumLiteral, extractEnumValues, } from "./enum.js";
2
+ export { classifyObject, iterateObjectProperties, type ObjectProperty, type ObjectShape, } from "./object.js";
3
+ export { isPrimitive, isPrimitiveTag, primitiveTag, } from "./primitive.js";
4
+ export { refName } from "./ref.js";
5
+ export { isNullable, isRefOnly, isSchemaObject, type Schema, type SchemaDiscriminator, type SchemaOrBool, type SchemaPrimitiveType, typeList, } from "./types.js";
6
+ export { classifyUnion, isUnionShape, type UnionShape, } from "./union.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,cAAc,EACd,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EACL,UAAU,EACV,SAAS,EACT,cAAc,EACd,KAAK,MAAM,EACX,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { assertNoEnumCollisions, classifyEnumLiterals, extractEnumValues, } from "./enum.js";
2
+ export { classifyObject, iterateObjectProperties, } from "./object.js";
3
+ export { isPrimitive, isPrimitiveTag, primitiveTag, } from "./primitive.js";
4
+ export { refName } from "./ref.js";
5
+ export { isNullable, isRefOnly, isSchemaObject, typeList, } from "./types.js";
6
+ export { classifyUnion, isUnionShape, } from "./union.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EAIpB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,uBAAuB,GAGxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,cAAc,EACd,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EACL,UAAU,EACV,SAAS,EACT,cAAc,EAKd,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,aAAa,EACb,YAAY,GAEb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type Schema } from "./types.js";
2
+ /**
3
+ * Three-way object dispatch. Emitters render:
4
+ * - `named-struct` → synth name, emit struct/data-class, return ref
5
+ * - `map` → wrap value in target map (`map[string]V`, etc.)
6
+ * - `open-map` → same map, value is target `any`
7
+ */
8
+ export type ObjectShape = {
9
+ kind: "named-struct";
10
+ } | {
11
+ kind: "map";
12
+ valueSchema: Schema;
13
+ } | {
14
+ kind: "open-map";
15
+ };
16
+ export declare function classifyObject(schema: Schema): ObjectShape;
17
+ export interface ObjectProperty {
18
+ jsonKey: string;
19
+ schema: Schema;
20
+ required: boolean;
21
+ /** `string` + `format: "binary"`. Common enough across emitters
22
+ * (multipart-binary handling) to surface alongside the iteration. */
23
+ isBinary: boolean;
24
+ /** Pre-pascal'd segment ready to plug into `synthName(owner, [seg])`.
25
+ * All emitters synth identifiers from PascalCase pieces; computing
26
+ * once here keeps emitters narrow. */
27
+ propPathSegment: string;
28
+ }
29
+ export declare function iterateObjectProperties(schema: Schema): Generator<ObjectProperty>;
30
+ //# sourceMappingURL=object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAO1D;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB;0EACsE;IACtE,QAAQ,EAAE,OAAO,CAAC;IAClB;;2CAEuC;IACvC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAiB,uBAAuB,CACtC,MAAM,EAAE,MAAM,GACb,SAAS,CAAC,cAAc,CAAC,CAY3B"}
package/dist/object.js ADDED
@@ -0,0 +1,25 @@
1
+ import { pascal } from "@ir-kit/codegen-core";
2
+ import { isSchemaObject } from "./types.js";
3
+ export function classifyObject(schema) {
4
+ if (Object.keys(schema.properties ?? {}).length > 0)
5
+ return { kind: "named-struct" };
6
+ const ap = schema.additionalProperties;
7
+ if (ap && isSchemaObject(ap))
8
+ return { kind: "map", valueSchema: ap };
9
+ return { kind: "open-map" };
10
+ }
11
+ export function* iterateObjectProperties(schema) {
12
+ const required = new Set(schema.required ?? []);
13
+ for (const [jsonKey, propSchema] of Object.entries(schema.properties ?? {})) {
14
+ if (!isSchemaObject(propSchema))
15
+ continue;
16
+ yield {
17
+ jsonKey,
18
+ schema: propSchema,
19
+ required: required.has(jsonKey),
20
+ isBinary: propSchema.type === "string" && propSchema.format === "binary",
21
+ propPathSegment: pascal(jsonKey),
22
+ };
23
+ }
24
+ }
25
+ //# sourceMappingURL=object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.js","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAe,MAAM,YAAY,CAAC;AAazD,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;QACjD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,GAAG,MAAM,CAAC,oBAAoB,CAAC;IACvC,IAAI,EAAE,IAAI,cAAc,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAY,EAAE,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC9B,CAAC;AAeD,MAAM,SAAS,CAAC,CAAC,uBAAuB,CACtC,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAChD,KAAK,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;YAAE,SAAS;QAC1C,MAAM;YACJ,OAAO;YACP,MAAM,EAAE,UAAoB;YAC5B,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;YAC/B,QAAQ,EAAE,UAAU,CAAC,IAAI,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ;YACxE,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC;SACjC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Schema, SchemaPrimitiveType } from "./types.js";
2
+ export declare function isPrimitiveTag(t: SchemaPrimitiveType): boolean;
3
+ export declare function isPrimitive(schema: Schema): boolean;
4
+ /** Sole non-null primitive tag, or `undefined` if the schema is
5
+ * compound / multi-typed / null-only. */
6
+ export declare function primitiveTag(schema: Schema): SchemaPrimitiveType | undefined;
7
+ //# sourceMappingURL=primitive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitive.d.ts","sourceRoot":"","sources":["../src/primitive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAW9D,wBAAgB,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAE9D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;0CAC0C;AAC1C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAI5E"}
@@ -0,0 +1,24 @@
1
+ import { typeList } from "./types.js";
2
+ const PRIMITIVE_TAGS = new Set([
3
+ "string",
4
+ "number",
5
+ "integer",
6
+ "boolean",
7
+ "null",
8
+ ]);
9
+ export function isPrimitiveTag(t) {
10
+ return PRIMITIVE_TAGS.has(t);
11
+ }
12
+ export function isPrimitive(schema) {
13
+ const tags = typeList(schema).filter((t) => t !== "null");
14
+ return tags.length === 1 && isPrimitiveTag(tags[0]);
15
+ }
16
+ /** Sole non-null primitive tag, or `undefined` if the schema is
17
+ * compound / multi-typed / null-only. */
18
+ export function primitiveTag(schema) {
19
+ const tags = typeList(schema).filter((t) => t !== "null");
20
+ if (tags.length !== 1)
21
+ return undefined;
22
+ return isPrimitiveTag(tags[0]) ? tags[0] : undefined;
23
+ }
24
+ //# sourceMappingURL=primitive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitive.js","sourceRoot":"","sources":["../src/primitive.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAsB;IAClD,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,SAAS;IACT,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAAC,CAAsB;IACnD,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;AACvD,CAAC;AAED;0CAC0C;AAC1C,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;IAC1D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC"}
package/dist/ref.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Last `/`-separated segment of a JSON-pointer ref (with `~1`/`~0`
3
+ * decoded) — the conventional codegen "schema name". Handles both
4
+ * `#/$defs/X` (2020-12) and `#/components/schemas/X` (OpenAPI)
5
+ * uniformly. External / empty refs are returned untouched.
6
+ */
7
+ export declare function refName(ref: string): string;
8
+ //# sourceMappingURL=ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3C"}
package/dist/ref.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Last `/`-separated segment of a JSON-pointer ref (with `~1`/`~0`
3
+ * decoded) — the conventional codegen "schema name". Handles both
4
+ * `#/$defs/X` (2020-12) and `#/components/schemas/X` (OpenAPI)
5
+ * uniformly. External / empty refs are returned untouched.
6
+ */
7
+ export function refName(ref) {
8
+ if (!ref)
9
+ return ref;
10
+ const hashIdx = ref.lastIndexOf("#");
11
+ const fragment = hashIdx >= 0 ? ref.slice(hashIdx + 1) : ref;
12
+ const last = fragment.split("/").pop();
13
+ if (!last)
14
+ return ref;
15
+ return last.replace(/~1/g, "/").replace(/~0/g, "~");
16
+ }
17
+ //# sourceMappingURL=ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref.js","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC;IACtB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { JSONSchema, TypeName } from "json-schema-typed/draft-2020-12";
2
+ /**
3
+ * Canonical schema model — re-exports of the JSON Schema 2020-12
4
+ * typings from [`json-schema-typed`](https://www.npmjs.com/package/json-schema-typed).
5
+ * Adapters fold each spec family (hey-api's `IR.SchemaObject`, raw
6
+ * JSON Schema of any draft, OpenAPI 3.0 `nullable`) into this shape;
7
+ * emitters consume only this.
8
+ *
9
+ * We add one OpenAPI-only extension (`discriminator`) since it's
10
+ * common enough across the emitter surface to carry at the top level.
11
+ */
12
+ /** Primitive type tags. Sourced from the upstream `TypeName` enum so
13
+ * values stay in sync with the spec. */
14
+ export type SchemaPrimitiveType = `${TypeName}`;
15
+ /** OpenAPI-only — emitters use it for tagged-union dispatch. Not part
16
+ * of vanilla JSON Schema. */
17
+ export interface SchemaDiscriminator {
18
+ propertyName: string;
19
+ mapping?: Record<string, string>;
20
+ }
21
+ /**
22
+ * Canonical schema node. Structurally `JSONSchema.Interface` (the
23
+ * object form of `json-schema-typed`'s `JSONSchema` — i.e. the spec
24
+ * type with the `true`/`false` schema booleans excluded) plus our
25
+ * OpenAPI `discriminator` extension. Nested recursive fields
26
+ * (`properties`, `items`, `oneOf`, `additionalProperties`, etc.) still
27
+ * type to upstream `JSONSchema` (= `Interface | boolean`), per the
28
+ * spec — guard for `boolean` at use sites.
29
+ */
30
+ export type Schema = JSONSchema.Interface & {
31
+ discriminator?: SchemaDiscriminator;
32
+ };
33
+ /** A nested schema slot per the spec — either an object schema or the
34
+ * `true`/`false` boolean schema. Equivalent to upstream `JSONSchema`. */
35
+ export type SchemaOrBool = JSONSchema;
36
+ /** Narrowing helper: a nested `SchemaOrBool` slot is a real object schema. */
37
+ export declare function isSchemaObject(s: SchemaOrBool): s is JSONSchema.Interface;
38
+ export declare function isRefOnly(schema: Schema): schema is Schema & {
39
+ $ref: string;
40
+ };
41
+ /**
42
+ * Normalize `schema.type` to an array form for uniform handling.
43
+ * Returns `[]` for untyped schemas — those are typically composition
44
+ * shells whose `type` is implied by `oneOf` / `anyOf`.
45
+ */
46
+ export declare function typeList(schema: Schema): ReadonlyArray<SchemaPrimitiveType>;
47
+ /** True when the schema permits `null` — either via `type` containing
48
+ * `"null"` or via a `oneOf`/`anyOf` branch that is exactly
49
+ * `{ type: "null" }`. */
50
+ export declare function isNullable(schema: Schema): boolean;
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAE5E;;;;;;;;;GASG;AAEH;yCACyC;AACzC,MAAM,MAAM,mBAAmB,GAAG,GAAG,QAAQ,EAAE,CAAC;AAEhD;8BAC8B;AAC9B,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,GAAG;IAC1C,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC,CAAC;AAEF;0EAC0E;AAC1E,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,IAAI,UAAU,CAAC,SAAS,CAEzE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,mBAAmB,CAAC,CAK3E;AAED;;0BAE0B;AAC1B,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CASlD"}
package/dist/types.js ADDED
@@ -0,0 +1,33 @@
1
+ /** Narrowing helper: a nested `SchemaOrBool` slot is a real object schema. */
2
+ export function isSchemaObject(s) {
3
+ return typeof s === "object" && s !== null;
4
+ }
5
+ export function isRefOnly(schema) {
6
+ return typeof schema.$ref === "string";
7
+ }
8
+ /**
9
+ * Normalize `schema.type` to an array form for uniform handling.
10
+ * Returns `[]` for untyped schemas — those are typically composition
11
+ * shells whose `type` is implied by `oneOf` / `anyOf`.
12
+ */
13
+ export function typeList(schema) {
14
+ const t = schema.type;
15
+ if (t === undefined)
16
+ return [];
17
+ if (Array.isArray(t))
18
+ return t;
19
+ return [t];
20
+ }
21
+ /** True when the schema permits `null` — either via `type` containing
22
+ * `"null"` or via a `oneOf`/`anyOf` branch that is exactly
23
+ * `{ type: "null" }`. */
24
+ export function isNullable(schema) {
25
+ if (typeList(schema).includes("null"))
26
+ return true;
27
+ const branches = schema.oneOf ?? schema.anyOf;
28
+ if (!branches)
29
+ return false;
30
+ return branches.some((b) => isSchemaObject(b) &&
31
+ (b.type === "null" || (Array.isArray(b.type) && b.type.includes("null"))));
32
+ }
33
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAyCA,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,CAAe;IAC5C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAuC,CAAC;IACrE,OAAO,CAAC,CAAwB,CAAC,CAAC;AACpC,CAAC;AAED;;0BAE0B;AAC1B,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;IAC9C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,QAAQ,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,EAAE,CACJ,cAAc,CAAC,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { type Schema, type SchemaOrBool } from "./types.js";
2
+ /**
3
+ * Composition-shape outcomes. Each emitter renders per-target — Go
4
+ * pointer vs Kotlin nullable vs Swift optional, fallback to `any` vs
5
+ * `Any`. `nullable` is reported on `single`/`multi` but caller decides
6
+ * whether to apply it (Go drops, Kotlin/Swift wrap).
7
+ */
8
+ export type UnionShape = {
9
+ kind: "intersection-with-properties";
10
+ } | {
11
+ kind: "intersection-empty";
12
+ } | {
13
+ kind: "single";
14
+ inner: Schema;
15
+ nullable: boolean;
16
+ } | {
17
+ kind: "multi";
18
+ nullable: boolean;
19
+ };
20
+ export declare function classifyUnion(schema: Schema): UnionShape;
21
+ export declare function isUnionShape(schema: Schema): boolean;
22
+ export type { SchemaOrBool };
23
+ //# sourceMappingURL=union.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"union.d.ts","sourceRoot":"","sources":["../src/union.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,YAAY,EAElB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,8BAA8B,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzC,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAqCxD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAKpD;AAMD,YAAY,EAAE,YAAY,EAAE,CAAC"}
package/dist/union.js ADDED
@@ -0,0 +1,46 @@
1
+ import { isNullable, isSchemaObject, typeList, } from "./types.js";
2
+ export function classifyUnion(schema) {
3
+ if (schema.allOf && schema.allOf.length > 0) {
4
+ return schema.properties
5
+ ? { kind: "intersection-with-properties" }
6
+ : { kind: "intersection-empty" };
7
+ }
8
+ const branches = schema.oneOf ?? schema.anyOf;
9
+ if (branches && branches.length > 0) {
10
+ const objectBranches = branches.filter(isSchemaObject);
11
+ const nonNull = objectBranches.filter((b) => b.type !== "null" && !(Array.isArray(b.type) && onlyNull(b.type)));
12
+ const nullable = nonNull.length < branches.length ||
13
+ objectBranches.some((b) => isNullable(b));
14
+ if (nonNull.length === 1) {
15
+ return { kind: "single", inner: nonNull[0], nullable };
16
+ }
17
+ return { kind: "multi", nullable };
18
+ }
19
+ const types = typeList(schema);
20
+ const nonNullTypes = types.filter((t) => t !== "null");
21
+ if (types.length > 1) {
22
+ const nullable = isNullable(schema);
23
+ if (nonNullTypes.length === 1) {
24
+ return {
25
+ kind: "single",
26
+ inner: { ...schema, type: nonNullTypes[0] },
27
+ nullable,
28
+ };
29
+ }
30
+ return { kind: "multi", nullable };
31
+ }
32
+ return { kind: "multi", nullable: false };
33
+ }
34
+ export function isUnionShape(schema) {
35
+ if (schema.allOf && schema.allOf.length > 0)
36
+ return true;
37
+ if (schema.oneOf && schema.oneOf.length > 0)
38
+ return true;
39
+ if (schema.anyOf && schema.anyOf.length > 0)
40
+ return true;
41
+ return Array.isArray(schema.type) && schema.type.length > 1;
42
+ }
43
+ function onlyNull(t) {
44
+ return t.length === 1 && t[0] === "null";
45
+ }
46
+ //# sourceMappingURL=union.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"union.js","sourceRoot":"","sources":["../src/union.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@ir-kit/schema",
3
+ "version": "0.2.0",
4
+ "description": "Canonical JSON Schema 2020-12 IR shared across OpenAPI and AsyncAPI codegen families. Source-agnostic schema model + adapters from hey-api's IR.SchemaObject and @asyncapi/parser schemas.",
5
+ "keywords": [
6
+ "json-schema",
7
+ "json-schema-2020-12",
8
+ "ir",
9
+ "codegen",
10
+ "openapi",
11
+ "asyncapi"
12
+ ],
13
+ "homepage": "https://github.com/ir-kit/ir-kit/tree/main/packages/shared/schema",
14
+ "bugs": {
15
+ "url": "https://github.com/ir-kit/ir-kit/issues"
16
+ },
17
+ "license": "MIT",
18
+ "author": {
19
+ "name": "Ahmed Rowaihi",
20
+ "email": "ahmedrowaihi@gmail.com"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/ir-kit/ir-kit.git",
25
+ "directory": "packages/shared/schema"
26
+ },
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js"
35
+ },
36
+ "./adapters/heyapi": {
37
+ "types": "./dist/adapters/heyapi.d.ts",
38
+ "import": "./dist/adapters/heyapi.js"
39
+ },
40
+ "./adapters/jsonschema": {
41
+ "types": "./dist/adapters/jsonschema.d.ts",
42
+ "import": "./dist/adapters/jsonschema.js"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "README.md",
49
+ "LICENSE.md"
50
+ ],
51
+ "publishConfig": {
52
+ "access": "public",
53
+ "provenance": true
54
+ },
55
+ "peerDependencies": {
56
+ "@hey-api/shared": ">=0.3.0"
57
+ },
58
+ "peerDependenciesMeta": {
59
+ "@hey-api/shared": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "dependencies": {
64
+ "json-schema-typed": "^8.0.2",
65
+ "@ir-kit/codegen-core": "0.1.0"
66
+ },
67
+ "devDependencies": {
68
+ "@hey-api/shared": "^0.4.2",
69
+ "@types/node": "^22",
70
+ "vitest": "^4.0.0",
71
+ "@ir-kit/tsconfig": "0.0.0"
72
+ },
73
+ "engines": {
74
+ "node": ">=20.19.0"
75
+ },
76
+ "scripts": {
77
+ "build": "tsc -p tsconfig.build.json",
78
+ "dev": "tsc -p tsconfig.build.json --watch",
79
+ "typecheck": "tsc --noEmit",
80
+ "test": "vitest run --passWithNoTests"
81
+ }
82
+ }