@metaobjectsdev/codegen-ts 0.14.1 → 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.
- package/dist/column-mapper.d.ts.map +1 -1
- package/dist/column-mapper.js +36 -16
- package/dist/column-mapper.js.map +1 -1
- package/dist/generators/api-model.js +21 -13
- package/dist/generators/api-model.js.map +1 -1
- package/dist/generators/docs-data-builder.d.ts.map +1 -1
- package/dist/generators/docs-data-builder.js +27 -22
- package/dist/generators/docs-data-builder.js.map +1 -1
- package/dist/generators/docs-file.d.ts.map +1 -1
- package/dist/generators/docs-file.js +2 -1
- package/dist/generators/docs-file.js.map +1 -1
- package/dist/generators/extractor-file.d.ts.map +1 -1
- package/dist/generators/extractor-file.js +4 -2
- package/dist/generators/extractor-file.js.map +1 -1
- package/dist/generators/output-prompt-file.d.ts.map +1 -1
- package/dist/generators/output-prompt-file.js +5 -3
- package/dist/generators/output-prompt-file.js.map +1 -1
- package/dist/generators/render-helper-file.d.ts.map +1 -1
- package/dist/generators/render-helper-file.js +5 -3
- package/dist/generators/render-helper-file.js.map +1 -1
- package/dist/generators/routes-file-hono.d.ts.map +1 -1
- package/dist/generators/routes-file-hono.js +2 -1
- package/dist/generators/routes-file-hono.js.map +1 -1
- package/dist/generators/routes-file.d.ts.map +1 -1
- package/dist/generators/routes-file.js +3 -1
- package/dist/generators/routes-file.js.map +1 -1
- package/dist/generators/template-doc-builder.d.ts.map +1 -1
- package/dist/generators/template-doc-builder.js +14 -11
- package/dist/generators/template-doc-builder.js.map +1 -1
- package/dist/generators/trace-helper-file.d.ts.map +1 -1
- package/dist/generators/trace-helper-file.js +11 -5
- package/dist/generators/trace-helper-file.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/naming.d.ts +10 -0
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +47 -0
- package/dist/naming.js.map +1 -1
- package/dist/payload-codegen.d.ts.map +1 -1
- package/dist/payload-codegen.js +12 -9
- package/dist/payload-codegen.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts.map +1 -1
- package/dist/projection/extract-view-spec.js +26 -3
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/projection/projection-detector.d.ts.map +1 -1
- package/dist/projection/projection-detector.js +4 -0
- package/dist/projection/projection-detector.js.map +1 -1
- package/dist/relation-resolver.d.ts.map +1 -1
- package/dist/relation-resolver.js +20 -12
- package/dist/relation-resolver.js.map +1 -1
- package/dist/source-detect.d.ts.map +1 -1
- package/dist/source-detect.js +4 -1
- package/dist/source-detect.js.map +1 -1
- package/dist/template-codegen/template-data.js +1 -1
- package/dist/template-codegen/template-data.js.map +1 -1
- package/dist/templates/callable-file.d.ts.map +1 -1
- package/dist/templates/callable-file.js +8 -4
- package/dist/templates/callable-file.js.map +1 -1
- package/dist/templates/entity-constants.d.ts.map +1 -1
- package/dist/templates/entity-constants.js +15 -11
- package/dist/templates/entity-constants.js.map +1 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +7 -2
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/extract-delegate-emitter.d.ts.map +1 -1
- package/dist/templates/extract-delegate-emitter.js +2 -1
- package/dist/templates/extract-delegate-emitter.js.map +1 -1
- package/dist/templates/extractor.d.ts.map +1 -1
- package/dist/templates/extractor.js +8 -4
- package/dist/templates/extractor.js.map +1 -1
- package/dist/templates/field-meta.d.ts.map +1 -1
- package/dist/templates/field-meta.js +22 -4
- package/dist/templates/field-meta.js.map +1 -1
- package/dist/templates/find-templates.d.ts.map +1 -1
- package/dist/templates/find-templates.js +3 -0
- package/dist/templates/find-templates.js.map +1 -1
- package/dist/templates/fr010-field-mapping.d.ts.map +1 -1
- package/dist/templates/fr010-field-mapping.js +5 -2
- package/dist/templates/fr010-field-mapping.js.map +1 -1
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +18 -14
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/output-format-spec-emitter.js +7 -3
- package/dist/templates/output-format-spec-emitter.js.map +1 -1
- package/dist/templates/output-parser.d.ts.map +1 -1
- package/dist/templates/output-parser.js +9 -5
- package/dist/templates/output-parser.js.map +1 -1
- package/dist/templates/output-prompt.d.ts.map +1 -1
- package/dist/templates/output-prompt.js +8 -4
- package/dist/templates/output-prompt.js.map +1 -1
- package/dist/templates/projection-decl.d.ts.map +1 -1
- package/dist/templates/projection-decl.js +4 -1
- package/dist/templates/projection-decl.js.map +1 -1
- package/dist/templates/queries-file.d.ts.map +1 -1
- package/dist/templates/queries-file.js +12 -1
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/queries.d.ts +19 -1
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +49 -7
- package/dist/templates/queries.js.map +1 -1
- package/dist/templates/render-helper.d.ts.map +1 -1
- package/dist/templates/render-helper.js +17 -10
- package/dist/templates/render-helper.js.map +1 -1
- package/dist/templates/routes-file.js +2 -1
- package/dist/templates/routes-file.js.map +1 -1
- package/dist/templates/tph-discriminator.d.ts.map +1 -1
- package/dist/templates/tph-discriminator.js +7 -0
- package/dist/templates/tph-discriminator.js.map +1 -1
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +62 -16
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +6 -6
- package/src/column-mapper.ts +37 -16
- package/src/generators/api-model.ts +21 -13
- package/src/generators/docs-data-builder.ts +27 -22
- package/src/generators/docs-file.ts +2 -1
- package/src/generators/extractor-file.ts +4 -2
- package/src/generators/output-prompt-file.ts +5 -3
- package/src/generators/render-helper-file.ts +5 -3
- package/src/generators/routes-file-hono.ts +2 -1
- package/src/generators/routes-file.ts +2 -1
- package/src/generators/template-doc-builder.ts +14 -11
- package/src/generators/trace-helper-file.ts +11 -5
- package/src/index.ts +2 -0
- package/src/naming.ts +51 -0
- package/src/payload-codegen.ts +12 -9
- package/src/projection/extract-view-spec.ts +26 -3
- package/src/projection/projection-detector.ts +4 -0
- package/src/reference/queries.ts +9 -0
- package/src/reference/routes.ts +2 -1
- package/src/relation-resolver.ts +20 -12
- package/src/source-detect.ts +4 -1
- package/src/template-codegen/template-data.ts +1 -1
- package/src/templates/callable-file.ts +8 -4
- package/src/templates/entity-constants.ts +15 -11
- package/src/templates/entity-file.ts +7 -2
- package/src/templates/extract-delegate-emitter.ts +2 -1
- package/src/templates/extractor.ts +8 -4
- package/src/templates/field-meta.ts +25 -3
- package/src/templates/find-templates.ts +3 -0
- package/src/templates/fr010-field-mapping.ts +6 -1
- package/src/templates/inferred-types.ts +19 -13
- package/src/templates/output-format-spec-emitter.ts +7 -3
- package/src/templates/output-parser.ts +9 -5
- package/src/templates/output-prompt.ts +8 -4
- package/src/templates/projection-decl.ts +4 -1
- package/src/templates/queries-file.ts +14 -0
- package/src/templates/queries.ts +68 -8
- package/src/templates/render-helper.ts +17 -10
- package/src/templates/routes-file.ts +2 -1
- package/src/templates/tph-discriminator.ts +7 -0
- package/src/templates/zod-validators.ts +64 -15
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
484
|
+
if (field.resolvedIsArray()) baseStr = `z.array(${baseStr})`;
|
|
445
485
|
return appendValidatorChain(code`${baseStr}`, field);
|
|
446
486
|
}
|
|
447
487
|
|
|
@@ -480,36 +520,45 @@ 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.
|
|
485
|
-
const min = child.
|
|
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.
|
|
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.
|
|
495
|
-
const min = child.
|
|
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.
|
|
501
|
-
const min = child.
|
|
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
|
}
|
|
505
547
|
}
|
|
506
548
|
|
|
549
|
+
// A `field.string` + `@dbColumnType: jsonb` open bag has a `z.unknown()` base, so
|
|
550
|
+
// the string character-count validators (.min/.max/.regex) do NOT apply — chaining
|
|
551
|
+
// `.min(1)` for a required bag yields `z.unknown().min(1)`, a TS compile error.
|
|
552
|
+
// "Required" for an open bag means non-optional only (handled by the optional()
|
|
553
|
+
// logic below). A jsonb ARRAY still gets element-count bounds via the array branch.
|
|
554
|
+
const isJsonbBag = field.attr(FIELD_ATTR_DB_COLUMN_TYPE) === DB_COLUMN_TYPE_JSONB;
|
|
555
|
+
|
|
507
556
|
let chain: Code = base;
|
|
508
557
|
// Array element-count bounds apply to the z.array(...) wrapper regardless of element type.
|
|
509
|
-
if (field.
|
|
558
|
+
if (field.resolvedIsArray()) {
|
|
510
559
|
if (arrMin !== undefined) chain = code`${chain}.min(${arrMin})`;
|
|
511
560
|
if (arrMax !== undefined) chain = code`${chain}.max(${arrMax})`;
|
|
512
|
-
} else if (field.subType === FIELD_SUBTYPE_STRING) {
|
|
561
|
+
} else if (field.subType === FIELD_SUBTYPE_STRING && !isJsonbBag) {
|
|
513
562
|
if (minLen !== undefined) chain = code`${chain}.min(${minLen})`;
|
|
514
563
|
else if (isRequired) chain = code`${chain}.min(1)`;
|
|
515
564
|
if (maxLen !== undefined) chain = code`${chain}.max(${maxLen})`;
|