@githolon/dsl 0.101.3 → 0.101.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/dsl",
3
- "version": "0.101.3",
3
+ "version": "0.101.4",
4
4
  "type": "module",
5
5
  "description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -2365,6 +2365,7 @@ async function main(): Promise<void> {
2365
2365
  // Exec the bin DIRECTLY (not via `node`): esbuild's postinstall replaces the
2366
2366
  // JS shim with the platform-native binary, which only an exec can run.
2367
2367
  const esbuildBin = path.join(path.dirname(esbuildPkgJson), esbuildBinRel ?? "bin/esbuild");
2368
+ const esbuildMod = (await import(pathToFileURL(path.join(path.dirname(esbuildPkgJson), "lib", "main.js")).href)) as typeof import("esbuild");
2368
2369
 
2369
2370
  const canonicalizeEngineJavascript = (source: string): string => {
2370
2371
  // esbuild includes module labels derived from the package's install topology in
@@ -2391,7 +2392,6 @@ async function main(): Promise<void> {
2391
2392
  // package as the binary) so a resolve-plugin can stub zod's locale barrel to en-only —
2392
2393
  // the CLI binary has no plugin surface. Same bundle options + minify; deterministic
2393
2394
  // (pinned esbuild version, deterministic minifier).
2394
- const esbuildMod = (await import(pathToFileURL(path.join(path.dirname(esbuildPkgJson), "lib", "main.js")).href)) as typeof import("esbuild");
2395
2395
  const localeStripToEn = {
2396
2396
  name: "nomos-zod-locales-en-only",
2397
2397
  setup(build: import("esbuild").PluginBuild) {
@@ -2778,7 +2778,13 @@ async function main(): Promise<void> {
2778
2778
  // ── 5. the typed TS client (#10 — the web sibling of codegen_dart), with the
2779
2779
  // deployed law's content hash baked in (emitted AFTER the package is hashed) ──
2780
2780
  const clientPath = path.join(outDir, `${cfg.name}.client.ts`);
2781
- writeFileSync(clientPath, generateTsClient(presentationDomainModules, { packageName: cfg.name, domainHash, interface: packageInterface, compat: nomosCompat }), "utf8");
2781
+ const clientSource = generateTsClient(presentationDomainModules, { packageName: cfg.name, domainHash, interface: packageInterface, compat: nomosCompat });
2782
+ try {
2783
+ await esbuildMod.transform(clientSource, { loader: "ts", format: "esm", target: "es2020", logLevel: "silent" });
2784
+ } catch (e) {
2785
+ fail(`generated TypeScript client is not syntactically valid — this is a Nomos codegen bug: ${(e as Error).message}`);
2786
+ }
2787
+ writeFileSync(clientPath, clientSource, "utf8");
2782
2788
 
2783
2789
  // ── 6. the typed Dart frontend (opt-in; the Flutter sibling of step 5, emitted
2784
2790
  // after the package hash like the TS client) ──
package/src/zod_lazy.ts CHANGED
@@ -26,12 +26,22 @@ export function zodUnwrapLazy(zt: z.ZodTypeAny): z.ZodTypeAny {
26
26
  }
27
27
 
28
28
  const capFirst = (s: string): string => (s.length === 0 ? s : s[0]!.toUpperCase() + s.slice(1));
29
- const camelize = (s: string): string => s.replace(/[_\s-]+(\w)/g, (_m, c: string) => c.toUpperCase());
29
+
30
+ /** Turn one structural path component into a valid TS/Dart identifier component.
31
+ * `*` is the record-value marker, not tenant vocabulary, so name it `Value`. */
32
+ function typeNamePart(segment: string): string {
33
+ if (segment === "*") return "Value";
34
+ const words = segment.split(/[^A-Za-z0-9]+/).filter(Boolean);
35
+ const joined = words.map(capFirst).join("") || "Field";
36
+ return /^[A-Za-z]/.test(joined) ? joined : `N${joined}`;
37
+ }
30
38
 
31
39
  /**
32
40
  * A PascalCase type name from a payload path (`saveTree.root` → `SaveTreeRoot`), array markers
33
- * dropped. The SAME base the TS and Dart recursive-type synthesizers use so a recursive type's
34
- * TS alias and Dart class agree in the common case.
41
+ * dropped and record wildcards named `Value` (`saveJson.data.*` → `SaveJsonDataValue`). The SAME
42
+ * base the TS and Dart recursive-type synthesizers use so a recursive type's TS alias and Dart
43
+ * class agree in the common case. Every segment is sanitized here because schema object keys may
44
+ * contain punctuation even though generated language identifiers may not.
35
45
  */
36
46
  export function recursiveTypeBaseName(path: string): string {
37
47
  return (
@@ -39,7 +49,7 @@ export function recursiveTypeBaseName(path: string): string {
39
49
  .replace(/\[\]/g, "")
40
50
  .split(/[.]/)
41
51
  .filter(Boolean)
42
- .map((s) => capFirst(camelize(s)))
52
+ .map(typeNamePart)
43
53
  .join("") || "Recursive"
44
54
  );
45
55
  }