@supalive/codegen 1.20.0 → 1.20.2
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/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-BG6JNyje.js → src-BHtJlw3J.js} +147 -21
- package/package.json +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as emit, c as loadSchemaEnums, i as resolveConfig, n as generateToDisk, o as extractClient, r as readEntryConfig, s as SchemaEnumRegistry, t as generate } from "./src-
|
|
1
|
+
import { a as emit, c as loadSchemaEnums, i as resolveConfig, n as generateToDisk, o as extractClient, r as readEntryConfig, s as SchemaEnumRegistry, t as generate } from "./src-BHtJlw3J.js";
|
|
2
2
|
export { SchemaEnumRegistry, emit, extractClient, generate, generateToDisk, loadSchemaEnums, readEntryConfig, resolveConfig };
|
|
@@ -186,7 +186,10 @@ function scanOutputSchemaNode(node) {
|
|
|
186
186
|
if (methods.has("default") || methods.has("catch") || methods.has("prefault")) meta.optional = true;
|
|
187
187
|
const description = topLevelZodDescription(init);
|
|
188
188
|
if (description) meta.description = description;
|
|
189
|
-
|
|
189
|
+
const enumMeta = topLevelEnumMeta(init);
|
|
190
|
+
if (enumMeta?.modelName) meta.modelName = enumMeta.modelName;
|
|
191
|
+
if (enumMeta?.values) meta.enumValues = enumMeta.values;
|
|
192
|
+
if (meta.numeric || meta.optional || meta.description || meta.modelName || meta.enumValues) fieldMeta.set(key, meta);
|
|
190
193
|
const nestedMeta = scanOutputSchemaNode(init);
|
|
191
194
|
if (nestedMeta) nested.set(key, nestedMeta);
|
|
192
195
|
}
|
|
@@ -348,7 +351,10 @@ function scanObjectSchema(schema) {
|
|
|
348
351
|
if (methods.has("default") || methods.has("catch") || methods.has("prefault")) meta.optional = true;
|
|
349
352
|
const description = topLevelZodDescription(init);
|
|
350
353
|
if (description) meta.description = description;
|
|
351
|
-
|
|
354
|
+
const enumMeta = topLevelEnumMeta(init);
|
|
355
|
+
if (enumMeta?.modelName) meta.modelName = enumMeta.modelName;
|
|
356
|
+
if (enumMeta?.values) meta.enumValues = enumMeta.values;
|
|
357
|
+
if (meta.numeric || meta.optional || meta.description || meta.modelName || meta.enumValues) map.set(key, meta);
|
|
352
358
|
}
|
|
353
359
|
return map;
|
|
354
360
|
}
|
|
@@ -387,6 +393,72 @@ function topLevelZodDescription(node) {
|
|
|
387
393
|
cur = expr.getExpression();
|
|
388
394
|
}
|
|
389
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* For a field whose init is a Zod enum, read the enum's wire values and the
|
|
398
|
+
* model name it provides via `.modelName("X")` / `.meta({ __genType: "X" })`.
|
|
399
|
+
* Works whether the enum is inlined in the field or referenced through a const
|
|
400
|
+
* (e.g. `ZodTenantBillingPlanType`), even when wrapped in `.meta({...})` /
|
|
401
|
+
* `.optional()` and defined through `z.lazy(() => ...)`. Returns `undefined`
|
|
402
|
+
* when the chain is not an enum, so object/array model names (which
|
|
403
|
+
* `scanOutputSchemaNode` already reads at the top level) are not captured.
|
|
404
|
+
*/
|
|
405
|
+
function topLevelEnumMeta(node) {
|
|
406
|
+
let modelName;
|
|
407
|
+
let isEnum = false;
|
|
408
|
+
const values = [];
|
|
409
|
+
const walk = (n) => {
|
|
410
|
+
if (!n) return;
|
|
411
|
+
if (Node.isIdentifier(n)) {
|
|
412
|
+
const init = resolveIdentifierInit(n);
|
|
413
|
+
if (init) walk(init);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (Node.isPropertyAccessExpression(n)) return;
|
|
417
|
+
if (!Node.isCallExpression(n)) return;
|
|
418
|
+
const expr = n.getExpression();
|
|
419
|
+
if (!Node.isPropertyAccessExpression(expr)) return;
|
|
420
|
+
const method = expr.getName();
|
|
421
|
+
if (method === "enum") {
|
|
422
|
+
isEnum = true;
|
|
423
|
+
const arg = n.getArguments()[0];
|
|
424
|
+
if (arg && Node.isArrayLiteralExpression(arg)) {
|
|
425
|
+
for (const el of arg.getElements()) if (Node.isStringLiteral(el)) values.push(el.getLiteralValue());
|
|
426
|
+
}
|
|
427
|
+
} else if (method === "modelName") {
|
|
428
|
+
const arg = n.getArguments()[0];
|
|
429
|
+
if (arg && Node.isStringLiteral(arg)) modelName = arg.getLiteralValue();
|
|
430
|
+
} else if (method === "meta") {
|
|
431
|
+
const arg = n.getArguments()[0];
|
|
432
|
+
if (arg && Node.isObjectLiteralExpression(arg)) {
|
|
433
|
+
const genType = arg.getProperty("__genType");
|
|
434
|
+
if (genType && Node.isPropertyAssignment(genType)) {
|
|
435
|
+
const init = genType.getInitializer();
|
|
436
|
+
if (init && Node.isStringLiteral(init)) modelName = init.getLiteralValue();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} else if (method === "lazy") {
|
|
440
|
+
const arg = n.getArguments()[0];
|
|
441
|
+
if (arg && Node.isArrowFunction(arg)) {
|
|
442
|
+
const body = arg.getBody();
|
|
443
|
+
if (Node.isCallExpression(body)) {
|
|
444
|
+
walk(body);
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
if (Node.isBlock(body)) {
|
|
448
|
+
for (const stmt of body.getStatements()) if (Node.isReturnStatement(stmt)) walk(stmt.getExpression());
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
walk(expr.getExpression());
|
|
454
|
+
};
|
|
455
|
+
walk(node);
|
|
456
|
+
if (!isEnum) return void 0;
|
|
457
|
+
return {
|
|
458
|
+
modelName,
|
|
459
|
+
values: values.length > 0 ? values : void 0
|
|
460
|
+
};
|
|
461
|
+
}
|
|
390
462
|
function findZodObjectLiteral(node) {
|
|
391
463
|
let cur = node;
|
|
392
464
|
while (cur && Node.isCallExpression(cur)) {
|
|
@@ -564,7 +636,7 @@ async function loadSchemaEnums(config) {
|
|
|
564
636
|
} catch {}
|
|
565
637
|
}
|
|
566
638
|
} catch (err) {
|
|
567
|
-
console.warn(`[supalive-codegen] Could not load schemaModule (${config.schemaModule}) for schema-aware enum names; falling back to structural names. ${err instanceof Error ? err.message : String(err)}`);
|
|
639
|
+
console.warn(`[supalive-codegen] Could not load schemaModule (${config.schemaModule}) for schema-aware enum names; falling back to structural names. Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
568
640
|
return SchemaEnumRegistry.empty();
|
|
569
641
|
}
|
|
570
642
|
}
|
|
@@ -672,6 +744,8 @@ var Extractor = class {
|
|
|
672
744
|
if (meta.numeric && (f.type.kind === "double" || f.type.kind === "int")) f.type = { kind: meta.numeric };
|
|
673
745
|
if (meta.optional) f.optional = true;
|
|
674
746
|
if (meta.description && !f.doc) f.doc = meta.description;
|
|
747
|
+
if (meta.modelName && f.type.kind === "enum") this.setEnumCustomName(f.type, meta.modelName);
|
|
748
|
+
else if (meta.modelName && meta.enumValues && f.type.kind === "string") this.upgradeStringToEnum(f, meta, argsType.name);
|
|
675
749
|
}
|
|
676
750
|
}
|
|
677
751
|
const ret = unwrapPromise(sig.getReturnType());
|
|
@@ -692,20 +766,24 @@ var Extractor = class {
|
|
|
692
766
|
/**
|
|
693
767
|
* Recursively apply output schema metadata to a DartType tree.
|
|
694
768
|
* Patches numeric types (int/bigint), renames models via __genType,
|
|
695
|
-
* and recurses into nested
|
|
769
|
+
* names enums from their `.modelName("X")`, and recurses into nested
|
|
770
|
+
* objects and lists.
|
|
696
771
|
*/
|
|
697
772
|
applyOutputMeta(dt, meta) {
|
|
698
|
-
if (meta.modelName
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
773
|
+
if (meta.modelName) {
|
|
774
|
+
if (dt.kind === "model") {
|
|
775
|
+
const existing = this.modelRegistry.get(dt.name);
|
|
776
|
+
if (existing && !this.modelRegistry.has(meta.modelName)) {
|
|
777
|
+
const renamed = {
|
|
778
|
+
...existing,
|
|
779
|
+
name: meta.modelName
|
|
780
|
+
};
|
|
781
|
+
this.modelRegistry.set(meta.modelName, renamed);
|
|
782
|
+
this.modelRegistry.delete(dt.name);
|
|
783
|
+
}
|
|
784
|
+
dt.name = meta.modelName;
|
|
785
|
+
} else if (dt.kind === "enum") this.setEnumCustomName(dt, meta.modelName);
|
|
786
|
+
else if (dt.kind === "list" && dt.element.kind === "enum") this.setEnumCustomName(dt.element, meta.modelName);
|
|
709
787
|
}
|
|
710
788
|
if (dt.kind === "model") {
|
|
711
789
|
const model = this.modelRegistry.get(dt.name);
|
|
@@ -715,6 +793,8 @@ var Extractor = class {
|
|
|
715
793
|
if (fMeta.numeric && (f.type.kind === "double" || f.type.kind === "int")) f.type = { kind: fMeta.numeric };
|
|
716
794
|
if (fMeta.optional) f.optional = true;
|
|
717
795
|
if (fMeta.description && !f.doc) f.doc = fMeta.description;
|
|
796
|
+
if (fMeta.modelName && f.type.kind === "enum") this.setEnumCustomName(f.type, fMeta.modelName);
|
|
797
|
+
else if (fMeta.modelName && fMeta.enumValues && f.type.kind === "string") this.upgradeStringToEnum(f, fMeta, dt.name);
|
|
718
798
|
}
|
|
719
799
|
const nestedMeta = meta.nested.get(f.jsonKey);
|
|
720
800
|
if (nestedMeta) this.applyOutputMeta(f.type, nestedMeta);
|
|
@@ -724,6 +804,26 @@ var Extractor = class {
|
|
|
724
804
|
if (elMeta) this.applyOutputMeta(dt.element, elMeta);
|
|
725
805
|
}
|
|
726
806
|
}
|
|
807
|
+
/** Give an enum a canonical name from `.modelName()` / `__genType`. */
|
|
808
|
+
setEnumCustomName(type, name) {
|
|
809
|
+
if (type.name === name) return;
|
|
810
|
+
const group = this.enumGroups.get(type.name);
|
|
811
|
+
if (group) group.customName = name;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* A field whose TS type widened to `String` but whose returns/args Zod schema
|
|
815
|
+
* declares an enum (e.g. a handler returning literal `plan` strings) is
|
|
816
|
+
* upgraded to the enum, named from the schema's `.modelName("X")`.
|
|
817
|
+
*/
|
|
818
|
+
upgradeStringToEnum(f, meta, stem) {
|
|
819
|
+
const type = this.registerEnum(meta.enumValues, {
|
|
820
|
+
hint: f.jsonKey,
|
|
821
|
+
field: f.jsonKey,
|
|
822
|
+
stem: cleanStem(stem)
|
|
823
|
+
});
|
|
824
|
+
this.setEnumCustomName(type, meta.modelName);
|
|
825
|
+
f.type = type;
|
|
826
|
+
}
|
|
727
827
|
walk(type, hint) {
|
|
728
828
|
const { core } = splitNullish(type);
|
|
729
829
|
if (core.length === 0) return { kind: "dynamic" };
|
|
@@ -909,19 +1009,45 @@ var Extractor = class {
|
|
|
909
1009
|
this.enumsFinalized = true;
|
|
910
1010
|
const used = new Set(this.modelRegistry.keys());
|
|
911
1011
|
const groups = [...this.enumGroups.values()];
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
1012
|
+
const namedOwners = /* @__PURE__ */ new Map();
|
|
1013
|
+
const assignNamed = (g, name) => {
|
|
1014
|
+
const owner = namedOwners.get(name);
|
|
1015
|
+
if (owner) {
|
|
1016
|
+
g.type.name = owner.type.name;
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
const finalName = used.has(name) ? this.ensureUnique(name, used) : name;
|
|
1020
|
+
used.add(finalName);
|
|
1021
|
+
g.type.name = finalName;
|
|
1022
|
+
namedOwners.set(name, g);
|
|
1023
|
+
this.pushEnumIR(finalName, g.values);
|
|
1024
|
+
};
|
|
1025
|
+
const customGroups = groups.filter((g) => g.customName).sort((a, b) => a.customName.localeCompare(b.customName));
|
|
1026
|
+
for (const g of customGroups) assignNamed(g, g.customName);
|
|
1027
|
+
const schemaGroups = groups.filter((g) => g.schemaName && !g.customName).sort((a, b) => a.schemaName.localeCompare(b.schemaName));
|
|
1028
|
+
for (const g of schemaGroups) assignNamed(g, g.schemaName);
|
|
1029
|
+
const namedByField = /* @__PURE__ */ new Map();
|
|
1030
|
+
for (const g of groups) {
|
|
1031
|
+
if (!g.customName && !g.schemaName || !g.field) continue;
|
|
1032
|
+
const arr = namedByField.get(g.field) ?? [];
|
|
1033
|
+
if (!arr.some((x) => x.type.name === g.type.name)) arr.push(g);
|
|
1034
|
+
namedByField.set(g.field, arr);
|
|
917
1035
|
}
|
|
918
|
-
const
|
|
1036
|
+
const sameValueSet = (a, b) => a.length === b.length && [...a].sort().join("\0") === [...b].sort().join("\0");
|
|
1037
|
+
const fallbackGroups = groups.filter((g) => !g.schemaName && !g.customName).sort((a, b) => fallbackBase(a).localeCompare(fallbackBase(b)));
|
|
919
1038
|
const baseCount = /* @__PURE__ */ new Map();
|
|
920
1039
|
for (const g of fallbackGroups) {
|
|
921
1040
|
const base = fallbackBase(g);
|
|
922
1041
|
baseCount.set(base, (baseCount.get(base) ?? 0) + 1);
|
|
923
1042
|
}
|
|
924
1043
|
for (const g of fallbackGroups) {
|
|
1044
|
+
if (g.field) {
|
|
1045
|
+
const matches = (namedByField.get(g.field) ?? []).filter((n) => sameValueSet(n.values, g.values));
|
|
1046
|
+
if (matches.length === 1) {
|
|
1047
|
+
g.type.name = matches[0].type.name;
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
925
1051
|
const base = fallbackBase(g);
|
|
926
1052
|
let name;
|
|
927
1053
|
if (baseCount.get(base) === 1 && !used.has(base)) name = base;
|