@kurotako/ir 0.2.0 → 0.3.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/CHANGELOG.md +38 -0
- package/dist/index.cjs +98 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +98 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @kurotako/ir
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9fe08b3: Add an `array` field type to the IR and bump the IR format to `'4'`.
|
|
8
|
+
|
|
9
|
+
- `@kurotako/ir`: new `{ kind: 'array', element: FieldType }` field type, so an
|
|
10
|
+
array-typed type alias, union variant or map value can be represented (the
|
|
11
|
+
boolean `Field.list` fast path stays as an optimisation for a plain
|
|
12
|
+
`property: { type: 'array', items: <scalar|ref> }`). Builders (`.array(...)`),
|
|
13
|
+
validation, reference traversal, cycle analysis and TypeScript-type helpers
|
|
14
|
+
recurse through it. The strict compatibility check now requires `irVersion` `'4'`.
|
|
15
|
+
- `@kurotako/gen-zod`: renders an array as `z.array(<element>)` and its TS type as
|
|
16
|
+
`<element>[]`.
|
|
17
|
+
- `@kurotako/gen-typescript`: renders an array as `<element>[]`, parenthesising a
|
|
18
|
+
union element.
|
|
19
|
+
- `@kurotako/gen-angular`: renders an array field as `FormControl<<element>[]>`
|
|
20
|
+
seeded with `[]`.
|
|
21
|
+
- `@kurotako/parser-openapi`: an array schema that is not a plain object property
|
|
22
|
+
(an array-typed response/component alias, a nested array, an array inside a
|
|
23
|
+
`oneOf`/`additionalProperties`) now maps to the `array` field type instead of
|
|
24
|
+
silently dropping the array wrapper. Nested arrays are supported.
|
|
25
|
+
- ecdb02c: Add the OpenAPI parser and IR typed maps.
|
|
26
|
+
|
|
27
|
+
- `@kurotako/ir`: adds the `{ kind: 'map', value: FieldType }`
|
|
28
|
+
field type and the optional `Entity.additionalProperties` slot. Builders,
|
|
29
|
+
validation, reference traversal, cycle analysis and TypeScript-type helpers
|
|
30
|
+
recurse through both.
|
|
31
|
+
- `@kurotako/gen-zod`: renders map values as `z.record(z.string(), value)` and an
|
|
32
|
+
entity catch-all as `.catchall(value)`.
|
|
33
|
+
- `@kurotako/gen-typescript`: renders map values as `Record<string, Value>` and an
|
|
34
|
+
entity catch-all as an index signature.
|
|
35
|
+
- `@kurotako/gen-angular`: renders a map field as `FormControl<Record<string, Value>>`
|
|
36
|
+
seeded with `{}`; entity-level catch-all values stay under the emitted Zod validator.
|
|
37
|
+
- `@kurotako/parser-openapi`: new package. Turns an OpenAPI 3.0/3.1 document (local
|
|
38
|
+
JSON/YAML or an unauthenticated HTTP(S) URL) into one `SourceIR`, mapping component
|
|
39
|
+
and inline operation schemas to deterministic entities, aliases, enums and typed maps.
|
|
40
|
+
|
|
3
41
|
## 0.2.0
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -144,6 +144,8 @@ var FieldTypeSchema = v.lazy(
|
|
|
144
144
|
v.object({ kind: v.literal("enum"), ref: v.string() }),
|
|
145
145
|
v.object({ kind: v.literal("unknown"), hint: v.optional(v.string()) }),
|
|
146
146
|
v.object({ kind: v.literal("ref"), ref: v.string() }),
|
|
147
|
+
v.object({ kind: v.literal("map"), value: FieldTypeSchema }),
|
|
148
|
+
v.object({ kind: v.literal("array"), element: FieldTypeSchema }),
|
|
147
149
|
v.object({
|
|
148
150
|
kind: v.literal("union"),
|
|
149
151
|
variants: v.array(FieldTypeSchema),
|
|
@@ -228,6 +230,7 @@ var CompositeUniqueSchema = v.object({
|
|
|
228
230
|
var EntitySchema = v.object({
|
|
229
231
|
name: v.string(),
|
|
230
232
|
fields: v.array(FieldSchema),
|
|
233
|
+
additionalProperties: v.optional(FieldTypeSchema),
|
|
231
234
|
relations: v.array(RelationSchema),
|
|
232
235
|
enums: v.optional(v.record(v.string(), EnumDefSchema)),
|
|
233
236
|
primaryKey: v.optional(v.array(v.string())),
|
|
@@ -253,7 +256,7 @@ var IrSchema = v.object({
|
|
|
253
256
|
var v2 = __toESM(require("valibot"), 1);
|
|
254
257
|
|
|
255
258
|
// src/version.ts
|
|
256
|
-
var IR_VERSION = "
|
|
259
|
+
var IR_VERSION = "4";
|
|
257
260
|
function isCompatible(irVersion) {
|
|
258
261
|
return irVersion === IR_VERSION;
|
|
259
262
|
}
|
|
@@ -351,6 +354,19 @@ function walkFieldType(type, path, entity, source, issues, info) {
|
|
|
351
354
|
}
|
|
352
355
|
return;
|
|
353
356
|
}
|
|
357
|
+
case "map":
|
|
358
|
+
walkFieldType(type.value, `${path}.value`, entity, source, issues, info);
|
|
359
|
+
return;
|
|
360
|
+
case "array":
|
|
361
|
+
walkFieldType(
|
|
362
|
+
type.element,
|
|
363
|
+
`${path}.element`,
|
|
364
|
+
entity,
|
|
365
|
+
source,
|
|
366
|
+
issues,
|
|
367
|
+
info
|
|
368
|
+
);
|
|
369
|
+
return;
|
|
354
370
|
case "union": {
|
|
355
371
|
if (type.variants.length < 2) {
|
|
356
372
|
pushIssue(
|
|
@@ -397,6 +413,10 @@ function collectRefs(type, out) {
|
|
|
397
413
|
for (const variant2 of type.variants) {
|
|
398
414
|
collectRefs(variant2, out);
|
|
399
415
|
}
|
|
416
|
+
} else if (type.kind === "map") {
|
|
417
|
+
collectRefs(type.value, out);
|
|
418
|
+
} else if (type.kind === "array") {
|
|
419
|
+
collectRefs(type.element, out);
|
|
400
420
|
}
|
|
401
421
|
}
|
|
402
422
|
function checkRefCycles(namespace, source, info) {
|
|
@@ -486,6 +506,16 @@ function checkSource(namespace, source, lookupEntity, isNamespacePresent, issues
|
|
|
486
506
|
checkConstraints(issues, `${fPath}.constraints`, field.constraints);
|
|
487
507
|
walkFieldType(field.type, fPath, entity, source, issues, info);
|
|
488
508
|
}
|
|
509
|
+
if (entity.additionalProperties !== void 0) {
|
|
510
|
+
walkFieldType(
|
|
511
|
+
entity.additionalProperties,
|
|
512
|
+
`${ePath}.additionalProperties`,
|
|
513
|
+
entity,
|
|
514
|
+
source,
|
|
515
|
+
issues,
|
|
516
|
+
info
|
|
517
|
+
);
|
|
518
|
+
}
|
|
489
519
|
for (const [localKey, def] of Object.entries(entity.enums ?? {})) {
|
|
490
520
|
if (def.name !== localKey) {
|
|
491
521
|
pushIssue(
|
|
@@ -736,6 +766,18 @@ var UnionBuilderImpl = class _UnionBuilderImpl {
|
|
|
736
766
|
}
|
|
737
767
|
return this;
|
|
738
768
|
}
|
|
769
|
+
map(build) {
|
|
770
|
+
const value = new TypeAliasBuilderImpl(this.#path, "map-value");
|
|
771
|
+
build(value);
|
|
772
|
+
this.#variants.push({ kind: "map", value: value.build().type });
|
|
773
|
+
return this;
|
|
774
|
+
}
|
|
775
|
+
array(build) {
|
|
776
|
+
const element = new TypeAliasBuilderImpl(this.#path, "array-element");
|
|
777
|
+
build(element);
|
|
778
|
+
this.#variants.push({ kind: "array", element: element.build().type });
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
739
781
|
unknown(hint) {
|
|
740
782
|
this.#variants.push(
|
|
741
783
|
hint === void 0 ? { kind: "unknown" } : { kind: "unknown", hint }
|
|
@@ -777,7 +819,7 @@ var UnionBuilderImpl = class _UnionBuilderImpl {
|
|
|
777
819
|
return type;
|
|
778
820
|
}
|
|
779
821
|
};
|
|
780
|
-
var TypeAliasBuilderImpl = class {
|
|
822
|
+
var TypeAliasBuilderImpl = class _TypeAliasBuilderImpl {
|
|
781
823
|
#path;
|
|
782
824
|
#name;
|
|
783
825
|
#type = { kind: "unknown" };
|
|
@@ -804,6 +846,18 @@ var TypeAliasBuilderImpl = class {
|
|
|
804
846
|
this.#type = nested.build();
|
|
805
847
|
return this;
|
|
806
848
|
}
|
|
849
|
+
map(build) {
|
|
850
|
+
const value = new _TypeAliasBuilderImpl(this.#path, "map-value");
|
|
851
|
+
build(value);
|
|
852
|
+
this.#type = { kind: "map", value: value.build().type };
|
|
853
|
+
return this;
|
|
854
|
+
}
|
|
855
|
+
array(build) {
|
|
856
|
+
const element = new _TypeAliasBuilderImpl(this.#path, "array-element");
|
|
857
|
+
build(element);
|
|
858
|
+
this.#type = { kind: "array", element: element.build().type };
|
|
859
|
+
return this;
|
|
860
|
+
}
|
|
807
861
|
unknown(hint) {
|
|
808
862
|
this.#type = hint === void 0 ? { kind: "unknown" } : { kind: "unknown", hint };
|
|
809
863
|
return this;
|
|
@@ -857,6 +911,18 @@ var FieldBuilderImpl = class {
|
|
|
857
911
|
this.#field.type = builder.build();
|
|
858
912
|
return this;
|
|
859
913
|
}
|
|
914
|
+
map(build) {
|
|
915
|
+
const value = new TypeAliasBuilderImpl(this.#path, "map-value");
|
|
916
|
+
build(value);
|
|
917
|
+
this.#field.type = { kind: "map", value: value.build().type };
|
|
918
|
+
return this;
|
|
919
|
+
}
|
|
920
|
+
array(build) {
|
|
921
|
+
const element = new TypeAliasBuilderImpl(this.#path, "array-element");
|
|
922
|
+
build(element);
|
|
923
|
+
this.#field.type = { kind: "array", element: element.build().type };
|
|
924
|
+
return this;
|
|
925
|
+
}
|
|
860
926
|
unknown(hint) {
|
|
861
927
|
this.#field.type = hint === void 0 ? { kind: "unknown" } : { kind: "unknown", hint };
|
|
862
928
|
return this;
|
|
@@ -1000,6 +1066,7 @@ var EntityBuilderImpl = class {
|
|
|
1000
1066
|
#uniques = [];
|
|
1001
1067
|
#doc;
|
|
1002
1068
|
#dbName;
|
|
1069
|
+
#additionalProperties;
|
|
1003
1070
|
constructor(namespace, name) {
|
|
1004
1071
|
this.#namespace = namespace;
|
|
1005
1072
|
this.#name = name;
|
|
@@ -1026,6 +1093,15 @@ var EntityBuilderImpl = class {
|
|
|
1026
1093
|
this.#fields.push(builder);
|
|
1027
1094
|
return this;
|
|
1028
1095
|
}
|
|
1096
|
+
additionalProperties(def) {
|
|
1097
|
+
const value = new TypeAliasBuilderImpl(
|
|
1098
|
+
`${this.#namespace}.${this.#name}.additionalProperties`,
|
|
1099
|
+
"additionalProperties"
|
|
1100
|
+
);
|
|
1101
|
+
def(value);
|
|
1102
|
+
this.#additionalProperties = value.build().type;
|
|
1103
|
+
return this;
|
|
1104
|
+
}
|
|
1029
1105
|
relation(name, def) {
|
|
1030
1106
|
const builder = new RelationBuilderImpl(name);
|
|
1031
1107
|
def(builder);
|
|
@@ -1091,6 +1167,9 @@ var EntityBuilderImpl = class {
|
|
|
1091
1167
|
if (this.#dbName !== void 0) {
|
|
1092
1168
|
entity.dbName = this.#dbName;
|
|
1093
1169
|
}
|
|
1170
|
+
if (this.#additionalProperties !== void 0) {
|
|
1171
|
+
entity.additionalProperties = this.#additionalProperties;
|
|
1172
|
+
}
|
|
1094
1173
|
return entity;
|
|
1095
1174
|
}
|
|
1096
1175
|
};
|
|
@@ -1209,6 +1288,10 @@ function collectRefNames(type, into = /* @__PURE__ */ new Set()) {
|
|
|
1209
1288
|
for (const variant2 of type.variants) {
|
|
1210
1289
|
collectRefNames(variant2, into);
|
|
1211
1290
|
}
|
|
1291
|
+
} else if (type.kind === "map") {
|
|
1292
|
+
collectRefNames(type.value, into);
|
|
1293
|
+
} else if (type.kind === "array") {
|
|
1294
|
+
collectRefNames(type.element, into);
|
|
1212
1295
|
}
|
|
1213
1296
|
return into;
|
|
1214
1297
|
}
|
|
@@ -1230,6 +1313,9 @@ function refCycleMembers(source) {
|
|
|
1230
1313
|
for (const field of entity.fields) {
|
|
1231
1314
|
collectRefNames(field.type, set);
|
|
1232
1315
|
}
|
|
1316
|
+
if (entity.additionalProperties !== void 0) {
|
|
1317
|
+
collectRefNames(entity.additionalProperties, set);
|
|
1318
|
+
}
|
|
1233
1319
|
}
|
|
1234
1320
|
const canReachSelf = (start) => {
|
|
1235
1321
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1270,6 +1356,10 @@ function fieldTypeKey(type) {
|
|
|
1270
1356
|
return `ref:${type.ref}`;
|
|
1271
1357
|
case "unknown":
|
|
1272
1358
|
return `unknown:${type.hint ?? ""}`;
|
|
1359
|
+
case "map":
|
|
1360
|
+
return `map:${fieldTypeKey(type.value)}`;
|
|
1361
|
+
case "array":
|
|
1362
|
+
return `array:${fieldTypeKey(type.element)}`;
|
|
1273
1363
|
case "union":
|
|
1274
1364
|
return `union:${flattenUnion(type).map(fieldTypeKey).join(",")}`;
|
|
1275
1365
|
}
|
|
@@ -1357,6 +1447,12 @@ function scalarTsType(type) {
|
|
|
1357
1447
|
return flattenUnion(type).map(
|
|
1358
1448
|
(variant2) => variant2.kind === "union" ? `(${scalarTsType(variant2)})` : scalarTsType(variant2)
|
|
1359
1449
|
).join(" | ");
|
|
1450
|
+
case "map":
|
|
1451
|
+
return `Record<string, ${scalarTsType(type.value)}>`;
|
|
1452
|
+
case "array": {
|
|
1453
|
+
const element = scalarTsType(type.element);
|
|
1454
|
+
return type.element.kind === "union" ? `(${element})[]` : `${element}[]`;
|
|
1455
|
+
}
|
|
1360
1456
|
}
|
|
1361
1457
|
}
|
|
1362
1458
|
function mapScalar(scalar) {
|