@metaobjectsdev/codegen-ts 0.14.2 → 0.15.0-rc.1

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.
Files changed (154) hide show
  1. package/dist/column-mapper.d.ts.map +1 -1
  2. package/dist/column-mapper.js +36 -16
  3. package/dist/column-mapper.js.map +1 -1
  4. package/dist/generators/api-model.js +21 -13
  5. package/dist/generators/api-model.js.map +1 -1
  6. package/dist/generators/docs-data-builder.d.ts.map +1 -1
  7. package/dist/generators/docs-data-builder.js +27 -22
  8. package/dist/generators/docs-data-builder.js.map +1 -1
  9. package/dist/generators/docs-file.d.ts.map +1 -1
  10. package/dist/generators/docs-file.js +2 -1
  11. package/dist/generators/docs-file.js.map +1 -1
  12. package/dist/generators/extractor-file.d.ts.map +1 -1
  13. package/dist/generators/extractor-file.js +4 -2
  14. package/dist/generators/extractor-file.js.map +1 -1
  15. package/dist/generators/output-prompt-file.d.ts.map +1 -1
  16. package/dist/generators/output-prompt-file.js +5 -3
  17. package/dist/generators/output-prompt-file.js.map +1 -1
  18. package/dist/generators/render-helper-file.d.ts.map +1 -1
  19. package/dist/generators/render-helper-file.js +5 -3
  20. package/dist/generators/render-helper-file.js.map +1 -1
  21. package/dist/generators/routes-file-hono.d.ts.map +1 -1
  22. package/dist/generators/routes-file-hono.js +2 -1
  23. package/dist/generators/routes-file-hono.js.map +1 -1
  24. package/dist/generators/routes-file.d.ts.map +1 -1
  25. package/dist/generators/routes-file.js +3 -1
  26. package/dist/generators/routes-file.js.map +1 -1
  27. package/dist/generators/template-doc-builder.d.ts.map +1 -1
  28. package/dist/generators/template-doc-builder.js +14 -11
  29. package/dist/generators/template-doc-builder.js.map +1 -1
  30. package/dist/generators/trace-helper-file.d.ts.map +1 -1
  31. package/dist/generators/trace-helper-file.js +11 -5
  32. package/dist/generators/trace-helper-file.js.map +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/naming.d.ts +10 -0
  38. package/dist/naming.d.ts.map +1 -1
  39. package/dist/naming.js +47 -0
  40. package/dist/naming.js.map +1 -1
  41. package/dist/payload-codegen.d.ts.map +1 -1
  42. package/dist/payload-codegen.js +12 -9
  43. package/dist/payload-codegen.js.map +1 -1
  44. package/dist/projection/extract-view-spec.d.ts.map +1 -1
  45. package/dist/projection/extract-view-spec.js +26 -3
  46. package/dist/projection/extract-view-spec.js.map +1 -1
  47. package/dist/projection/projection-detector.d.ts.map +1 -1
  48. package/dist/projection/projection-detector.js +4 -0
  49. package/dist/projection/projection-detector.js.map +1 -1
  50. package/dist/relation-resolver.d.ts.map +1 -1
  51. package/dist/relation-resolver.js +20 -12
  52. package/dist/relation-resolver.js.map +1 -1
  53. package/dist/source-detect.d.ts.map +1 -1
  54. package/dist/source-detect.js +4 -1
  55. package/dist/source-detect.js.map +1 -1
  56. package/dist/template-codegen/template-data.js +1 -1
  57. package/dist/template-codegen/template-data.js.map +1 -1
  58. package/dist/templates/callable-file.d.ts.map +1 -1
  59. package/dist/templates/callable-file.js +8 -4
  60. package/dist/templates/callable-file.js.map +1 -1
  61. package/dist/templates/entity-constants.d.ts.map +1 -1
  62. package/dist/templates/entity-constants.js +15 -11
  63. package/dist/templates/entity-constants.js.map +1 -1
  64. package/dist/templates/entity-file.d.ts.map +1 -1
  65. package/dist/templates/entity-file.js +7 -2
  66. package/dist/templates/entity-file.js.map +1 -1
  67. package/dist/templates/extract-delegate-emitter.d.ts.map +1 -1
  68. package/dist/templates/extract-delegate-emitter.js +2 -1
  69. package/dist/templates/extract-delegate-emitter.js.map +1 -1
  70. package/dist/templates/extractor.d.ts.map +1 -1
  71. package/dist/templates/extractor.js +8 -4
  72. package/dist/templates/extractor.js.map +1 -1
  73. package/dist/templates/field-meta.d.ts.map +1 -1
  74. package/dist/templates/field-meta.js +22 -4
  75. package/dist/templates/field-meta.js.map +1 -1
  76. package/dist/templates/find-templates.d.ts.map +1 -1
  77. package/dist/templates/find-templates.js +3 -0
  78. package/dist/templates/find-templates.js.map +1 -1
  79. package/dist/templates/fr010-field-mapping.d.ts.map +1 -1
  80. package/dist/templates/fr010-field-mapping.js +5 -2
  81. package/dist/templates/fr010-field-mapping.js.map +1 -1
  82. package/dist/templates/inferred-types.d.ts.map +1 -1
  83. package/dist/templates/inferred-types.js +18 -14
  84. package/dist/templates/inferred-types.js.map +1 -1
  85. package/dist/templates/output-format-spec-emitter.js +7 -3
  86. package/dist/templates/output-format-spec-emitter.js.map +1 -1
  87. package/dist/templates/output-parser.d.ts.map +1 -1
  88. package/dist/templates/output-parser.js +9 -5
  89. package/dist/templates/output-parser.js.map +1 -1
  90. package/dist/templates/output-prompt.d.ts.map +1 -1
  91. package/dist/templates/output-prompt.js +8 -4
  92. package/dist/templates/output-prompt.js.map +1 -1
  93. package/dist/templates/projection-decl.d.ts.map +1 -1
  94. package/dist/templates/projection-decl.js +4 -1
  95. package/dist/templates/projection-decl.js.map +1 -1
  96. package/dist/templates/queries-file.d.ts.map +1 -1
  97. package/dist/templates/queries-file.js +12 -1
  98. package/dist/templates/queries-file.js.map +1 -1
  99. package/dist/templates/queries.d.ts +19 -1
  100. package/dist/templates/queries.d.ts.map +1 -1
  101. package/dist/templates/queries.js +49 -7
  102. package/dist/templates/queries.js.map +1 -1
  103. package/dist/templates/render-helper.d.ts.map +1 -1
  104. package/dist/templates/render-helper.js +17 -10
  105. package/dist/templates/render-helper.js.map +1 -1
  106. package/dist/templates/routes-file.js +2 -1
  107. package/dist/templates/routes-file.js.map +1 -1
  108. package/dist/templates/tph-discriminator.d.ts.map +1 -1
  109. package/dist/templates/tph-discriminator.js +7 -0
  110. package/dist/templates/tph-discriminator.js.map +1 -1
  111. package/dist/templates/zod-validators.d.ts.map +1 -1
  112. package/dist/templates/zod-validators.js +55 -15
  113. package/dist/templates/zod-validators.js.map +1 -1
  114. package/package.json +6 -6
  115. package/src/column-mapper.ts +37 -16
  116. package/src/generators/api-model.ts +21 -13
  117. package/src/generators/docs-data-builder.ts +27 -22
  118. package/src/generators/docs-file.ts +2 -1
  119. package/src/generators/extractor-file.ts +4 -2
  120. package/src/generators/output-prompt-file.ts +5 -3
  121. package/src/generators/render-helper-file.ts +5 -3
  122. package/src/generators/routes-file-hono.ts +2 -1
  123. package/src/generators/routes-file.ts +2 -1
  124. package/src/generators/template-doc-builder.ts +14 -11
  125. package/src/generators/trace-helper-file.ts +11 -5
  126. package/src/index.ts +2 -0
  127. package/src/naming.ts +51 -0
  128. package/src/payload-codegen.ts +12 -9
  129. package/src/projection/extract-view-spec.ts +26 -3
  130. package/src/projection/projection-detector.ts +4 -0
  131. package/src/reference/queries.ts +9 -0
  132. package/src/reference/routes.ts +2 -1
  133. package/src/relation-resolver.ts +20 -12
  134. package/src/source-detect.ts +4 -1
  135. package/src/template-codegen/template-data.ts +1 -1
  136. package/src/templates/callable-file.ts +8 -4
  137. package/src/templates/entity-constants.ts +15 -11
  138. package/src/templates/entity-file.ts +7 -2
  139. package/src/templates/extract-delegate-emitter.ts +2 -1
  140. package/src/templates/extractor.ts +8 -4
  141. package/src/templates/field-meta.ts +25 -3
  142. package/src/templates/find-templates.ts +3 -0
  143. package/src/templates/fr010-field-mapping.ts +6 -1
  144. package/src/templates/inferred-types.ts +19 -13
  145. package/src/templates/output-format-spec-emitter.ts +7 -3
  146. package/src/templates/output-parser.ts +9 -5
  147. package/src/templates/output-prompt.ts +8 -4
  148. package/src/templates/projection-decl.ts +4 -1
  149. package/src/templates/queries-file.ts +14 -0
  150. package/src/templates/queries.ts +68 -8
  151. package/src/templates/render-helper.ts +17 -10
  152. package/src/templates/routes-file.ts +2 -1
  153. package/src/templates/tph-discriminator.ts +7 -0
  154. package/src/templates/zod-validators.ts +56 -14
@@ -16,9 +16,11 @@ import {
16
16
  FIELD_SUBTYPE_BOOLEAN, FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT,
17
17
  FIELD_SUBTYPE_DATE, FIELD_SUBTYPE_TIME, FIELD_SUBTYPE_TIMESTAMP,
18
18
  FIELD_SUBTYPE_ENUM, FIELD_SUBTYPE_OBJECT, FIELD_SUBTYPE_MAP, FIELD_SUBTYPE_UUID,
19
+ FIELD_SUBTYPE_URI, FIELD_SUBTYPE_INET,
19
20
  VALIDATOR_SUBTYPE_REQUIRED, VALIDATOR_SUBTYPE_LENGTH, VALIDATOR_SUBTYPE_REGEX,
20
21
  VALIDATOR_SUBTYPE_NUMERIC, VALIDATOR_SUBTYPE_ARRAY,
21
22
  IDENTITY_ATTR_FIELDS, IDENTITY_ATTR_GENERATION,
23
+ FIELD_ATTR_STRING_FORMAT, STRING_FORMAT_EMAIL, STRING_FORMAT_HOSTNAME,
22
24
  FIELD_ATTR_REQUIRED, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_DEFAULT,
23
25
  FIELD_ATTR_AUTO_SET, FIELD_ATTR_OBJECT_REF, FIELD_ATTR_VALUE_TYPE, FIELD_ATTR_READ_ONLY,
24
26
  FIELD_ATTR_DB_COLUMN_TYPE, DB_COLUMN_TYPE_JSONB,
@@ -43,12 +45,16 @@ import { valueObjectModuleSpecifier } from "../import-path.js";
43
45
  * when the object is not a TPH subtype.
44
46
  */
45
47
  export function tphDiscriminatorPin(obj: MetaObject): { fieldName: string; value: string } | undefined {
48
+ // ADR-0039: own — super-resolution walk. A subtype declares its OWN
49
+ // @discriminatorValue (must not inherit one), and the base level is found by
50
+ // walking superResolved reading each level's OWN @discriminator.
46
51
  const value = obj.ownAttr(OBJECT_ATTR_DISCRIMINATOR_VALUE);
47
52
  if (typeof value !== "string" || value === "") return undefined;
48
53
 
49
54
  // Walk the extends chain to find the root carrying @discriminator.
50
55
  let cursor = obj.superResolved;
51
56
  while (cursor !== undefined) {
57
+ // ADR-0039: own — super-resolution walk; read each level's OWN @discriminator.
52
58
  const fieldName = cursor.ownAttr(OBJECT_ATTR_DISCRIMINATOR);
53
59
  if (typeof fieldName === "string" && fieldName !== "") {
54
60
  return { fieldName, value };
@@ -322,6 +328,17 @@ ${joinCode(updateFieldLines, { on: ",\n" })}
322
328
  `;
323
329
  }
324
330
 
331
+ /**
332
+ * ADR-0036/0037 Wave 3 — the CANONICAL hostname matcher for @stringFormat:
333
+ * hostname, emitted as a Zod `.regex(...)` literal. The matcher lives in codegen
334
+ * (NOT author validator.regex) so every port can replicate the SAME canonical
335
+ * form — cross-language regex engines diverge, so the byte-identical source of
336
+ * truth is this one expression. RFC 1123 labels: 1–63 chars each, alphanumeric
337
+ * + internal hyphens, dot-separated; total form anchored.
338
+ */
339
+ const HOSTNAME_REGEX_LITERAL =
340
+ "/^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/";
341
+
325
342
  /** Zod expression for a scalar value subtype (used for a field.map's @valueType). */
326
343
  function zodScalarFor(subType: string): string {
327
344
  if (subType === FIELD_SUBTYPE_INT || subType === FIELD_SUBTYPE_LONG || subType === FIELD_SUBTYPE_CURRENCY) return "z.number().int()";
@@ -342,7 +359,7 @@ function zodFieldExpr(field: MetaField, owner?: MetaObject, ctx?: RenderContext)
342
359
  // field.object below).
343
360
  if (field.attr(FIELD_ATTR_DB_COLUMN_TYPE) === DB_COLUMN_TYPE_JSONB) {
344
361
  let base: Code = code`z.unknown()`;
345
- if (field.isArray) base = code`z.array(${base})`;
362
+ if (field.resolvedIsArray()) base = code`z.array(${base})`;
346
363
  return appendValidatorChain(base, field);
347
364
  }
348
365
 
@@ -364,13 +381,13 @@ function zodFieldExpr(field: MetaField, owner?: MetaObject, ctx?: RenderContext)
364
381
  : `./${refBase}.js`;
365
382
  const refImp = imp(`${refBase}InsertSchema@${moduleSpec}`);
366
383
  let base: Code = code`${refImp}`;
367
- if (field.isArray) base = code`z.array(${base})`;
384
+ if (field.resolvedIsArray()) base = code`z.array(${base})`;
368
385
  return appendValidatorChain(base, field);
369
386
  }
370
387
  // No resolvable @objectRef — fall through to z.unknown(); downstream code
371
388
  // can still pass a value through but loses validation.
372
389
  let base: Code = code`z.unknown()`;
373
- if (field.isArray) base = code`z.array(${base})`;
390
+ if (field.resolvedIsArray()) base = code`z.array(${base})`;
374
391
  return appendValidatorChain(base, field);
375
392
  }
376
393
 
@@ -427,21 +444,44 @@ function zodFieldExpr(field: MetaField, owner?: MetaObject, ctx?: RenderContext)
427
444
  const spec = sharedEnumImportSpecifier(ctx, owner?.package);
428
445
  const sharedConst = imp(`${constName}@${spec}`);
429
446
  let base: Code = code`${sharedConst}`;
430
- if (field.isArray) base = code`z.array(${base})`;
447
+ if (field.resolvedIsArray()) base = code`z.array(${base})`;
431
448
  return appendValidatorChain(base, field);
432
449
  }
433
450
  }
434
451
  baseStr = zodEnumExpr(values);
435
452
  break;
436
453
  }
437
- case FIELD_SUBTYPE_STRING:
454
+ case FIELD_SUBTYPE_URI:
455
+ // ADR-0036/0037 Wave 3: a URI/URL string — codegen owns the canonical
456
+ // URL matcher (Zod .url()), never author regex.
457
+ baseStr = "z.string().url()";
458
+ break;
459
+ case FIELD_SUBTYPE_INET:
460
+ // ADR-0036/0037 Wave 3: an IP-address string (v4 or v6) — codegen owns
461
+ // the canonical IP matcher (Zod .ip() accepts both versions).
462
+ baseStr = "z.string().ip()";
463
+ break;
464
+ case FIELD_SUBTYPE_STRING: {
465
+ // ADR-0036/0037 Wave 3: @stringFormat narrows a plain string to a closed
466
+ // validated format. The canonical matcher per format lives HERE (codegen),
467
+ // not author validator.regex. The field stays a plain string.
468
+ const fmt = field.attr(FIELD_ATTR_STRING_FORMAT);
469
+ if (fmt === STRING_FORMAT_EMAIL) {
470
+ baseStr = "z.string().email()";
471
+ } else if (fmt === STRING_FORMAT_HOSTNAME) {
472
+ baseStr = `z.string().regex(${HOSTNAME_REGEX_LITERAL})`;
473
+ } else {
474
+ baseStr = "z.string()";
475
+ }
476
+ break;
477
+ }
438
478
  case FIELD_SUBTYPE_UUID:
439
479
  default:
440
480
  baseStr = "z.string()";
441
481
  break;
442
482
  }
443
483
 
444
- if (field.isArray) baseStr = `z.array(${baseStr})`;
484
+ if (field.resolvedIsArray()) baseStr = `z.array(${baseStr})`;
445
485
  return appendValidatorChain(code`${baseStr}`, field);
446
486
  }
447
487
 
@@ -480,25 +520,27 @@ function appendValidatorChain(base: Code, field: MetaField): Code {
480
520
  let arrMax: number | undefined;
481
521
  for (const child of field.validators()) {
482
522
  if (child.subType === VALIDATOR_SUBTYPE_REQUIRED) isRequired = true;
523
+ // ADR-0039: resolving — a validator may inherit @min/@max/@pattern via extends
524
+ // (matches Java attrInt's resolving getMetaAttr(attr)).
483
525
  if (child.subType === VALIDATOR_SUBTYPE_LENGTH) {
484
- const max = child.ownAttr(VALIDATOR_ATTR_MAX);
485
- const min = child.ownAttr(VALIDATOR_ATTR_MIN);
526
+ const max = child.attr(VALIDATOR_ATTR_MAX);
527
+ const min = child.attr(VALIDATOR_ATTR_MIN);
486
528
  if (typeof max === "number") maxLen = max;
487
529
  if (typeof min === "number") minLen = min;
488
530
  }
489
531
  if (child.subType === VALIDATOR_SUBTYPE_REGEX) {
490
- const p = child.ownAttr(VALIDATOR_ATTR_PATTERN);
532
+ const p = child.attr(VALIDATOR_ATTR_PATTERN);
491
533
  if (typeof p === "string") pattern = p;
492
534
  }
493
535
  if (child.subType === VALIDATOR_SUBTYPE_NUMERIC) {
494
- const max = child.ownAttr(VALIDATOR_ATTR_MAX);
495
- const min = child.ownAttr(VALIDATOR_ATTR_MIN);
536
+ const max = child.attr(VALIDATOR_ATTR_MAX);
537
+ const min = child.attr(VALIDATOR_ATTR_MIN);
496
538
  if (typeof max === "number") numMax = max;
497
539
  if (typeof min === "number") numMin = min;
498
540
  }
499
541
  if (child.subType === VALIDATOR_SUBTYPE_ARRAY) {
500
- const max = child.ownAttr(VALIDATOR_ATTR_MAX);
501
- const min = child.ownAttr(VALIDATOR_ATTR_MIN);
542
+ const max = child.attr(VALIDATOR_ATTR_MAX);
543
+ const min = child.attr(VALIDATOR_ATTR_MIN);
502
544
  if (typeof max === "number") arrMax = max;
503
545
  if (typeof min === "number") arrMin = min;
504
546
  }
@@ -513,7 +555,7 @@ function appendValidatorChain(base: Code, field: MetaField): Code {
513
555
 
514
556
  let chain: Code = base;
515
557
  // Array element-count bounds apply to the z.array(...) wrapper regardless of element type.
516
- if (field.isArray) {
558
+ if (field.resolvedIsArray()) {
517
559
  if (arrMin !== undefined) chain = code`${chain}.min(${arrMin})`;
518
560
  if (arrMax !== undefined) chain = code`${chain}.max(${arrMax})`;
519
561
  } else if (field.subType === FIELD_SUBTYPE_STRING && !isJsonbBag) {