@metaobjectsdev/codegen-ts 0.5.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/LICENSE +189 -0
- package/README.md +101 -0
- package/dist/column-mapper.d.ts +38 -0
- package/dist/column-mapper.d.ts.map +1 -0
- package/dist/column-mapper.js +205 -0
- package/dist/column-mapper.js.map +1 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.d.ts +2 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +47 -0
- package/dist/format.js.map +1 -0
- package/dist/generator.d.ts +44 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +17 -0
- package/dist/generator.js.map +1 -0
- package/dist/generators/barrel.d.ts +6 -0
- package/dist/generators/barrel.d.ts.map +1 -0
- package/dist/generators/barrel.js +17 -0
- package/dist/generators/barrel.js.map +1 -0
- package/dist/generators/entity-file.d.ts +8 -0
- package/dist/generators/entity-file.d.ts.map +1 -0
- package/dist/generators/entity-file.js +27 -0
- package/dist/generators/entity-file.js.map +1 -0
- package/dist/generators/index.d.ts +5 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +5 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/queries-file.d.ts +8 -0
- package/dist/generators/queries-file.d.ts.map +1 -0
- package/dist/generators/queries-file.js +26 -0
- package/dist/generators/queries-file.js.map +1 -0
- package/dist/generators/routes-file.d.ts +12 -0
- package/dist/generators/routes-file.d.ts.map +1 -0
- package/dist/generators/routes-file.js +30 -0
- package/dist/generators/routes-file.js.map +1 -0
- package/dist/import-path.d.ts +41 -0
- package/dist/import-path.d.ts.map +1 -0
- package/dist/import-path.js +95 -0
- package/dist/import-path.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/metaobjects-config.d.ts +56 -0
- package/dist/metaobjects-config.d.ts.map +1 -0
- package/dist/metaobjects-config.js +42 -0
- package/dist/metaobjects-config.js.map +1 -0
- package/dist/naming.d.ts +29 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +67 -0
- package/dist/naming.js.map +1 -0
- package/dist/overwrite-policy.d.ts +8 -0
- package/dist/overwrite-policy.d.ts.map +1 -0
- package/dist/overwrite-policy.js +23 -0
- package/dist/overwrite-policy.js.map +1 -0
- package/dist/pk-resolver.d.ts +18 -0
- package/dist/pk-resolver.d.ts.map +1 -0
- package/dist/pk-resolver.js +36 -0
- package/dist/pk-resolver.js.map +1 -0
- package/dist/projection/extract-view-spec.d.ts +18 -0
- package/dist/projection/extract-view-spec.d.ts.map +1 -0
- package/dist/projection/extract-view-spec.js +272 -0
- package/dist/projection/extract-view-spec.js.map +1 -0
- package/dist/projection/index.d.ts +5 -0
- package/dist/projection/index.d.ts.map +1 -0
- package/dist/projection/index.js +5 -0
- package/dist/projection/index.js.map +1 -0
- package/dist/projection/projection-detector.d.ts +4 -0
- package/dist/projection/projection-detector.d.ts.map +1 -0
- package/dist/projection/projection-detector.js +13 -0
- package/dist/projection/projection-detector.js.map +1 -0
- package/dist/projection/view-ddl-emit.d.ts +10 -0
- package/dist/projection/view-ddl-emit.d.ts.map +1 -0
- package/dist/projection/view-ddl-emit.js +47 -0
- package/dist/projection/view-ddl-emit.js.map +1 -0
- package/dist/projection/view-spec.d.ts +56 -0
- package/dist/projection/view-spec.d.ts.map +1 -0
- package/dist/projection/view-spec.js +2 -0
- package/dist/projection/view-spec.js.map +1 -0
- package/dist/relation-resolver.d.ts +21 -0
- package/dist/relation-resolver.d.ts.map +1 -0
- package/dist/relation-resolver.js +62 -0
- package/dist/relation-resolver.js.map +1 -0
- package/dist/render-context.d.ts +65 -0
- package/dist/render-context.d.ts.map +1 -0
- package/dist/render-context.js +28 -0
- package/dist/render-context.js.map +1 -0
- package/dist/runner.d.ts +17 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +135 -0
- package/dist/runner.js.map +1 -0
- package/dist/templates/barrel.d.ts +8 -0
- package/dist/templates/barrel.d.ts.map +1 -0
- package/dist/templates/barrel.js +12 -0
- package/dist/templates/barrel.js.map +1 -0
- package/dist/templates/drizzle-schema.d.ts +13 -0
- package/dist/templates/drizzle-schema.d.ts.map +1 -0
- package/dist/templates/drizzle-schema.js +251 -0
- package/dist/templates/drizzle-schema.js.map +1 -0
- package/dist/templates/entity-constants.d.ts +4 -0
- package/dist/templates/entity-constants.d.ts.map +1 -0
- package/dist/templates/entity-constants.js +215 -0
- package/dist/templates/entity-constants.js.map +1 -0
- package/dist/templates/entity-file.d.ts +4 -0
- package/dist/templates/entity-file.d.ts.map +1 -0
- package/dist/templates/entity-file.js +45 -0
- package/dist/templates/entity-file.js.map +1 -0
- package/dist/templates/field-meta.d.ts +24 -0
- package/dist/templates/field-meta.d.ts.map +1 -0
- package/dist/templates/field-meta.js +117 -0
- package/dist/templates/field-meta.js.map +1 -0
- package/dist/templates/filter-allowlist.d.ts +5 -0
- package/dist/templates/filter-allowlist.d.ts.map +1 -0
- package/dist/templates/filter-allowlist.js +86 -0
- package/dist/templates/filter-allowlist.js.map +1 -0
- package/dist/templates/filter-shared.d.ts +15 -0
- package/dist/templates/filter-shared.d.ts.map +1 -0
- package/dist/templates/filter-shared.js +30 -0
- package/dist/templates/filter-shared.js.map +1 -0
- package/dist/templates/filter-type.d.ts +4 -0
- package/dist/templates/filter-type.d.ts.map +1 -0
- package/dist/templates/filter-type.js +78 -0
- package/dist/templates/filter-type.js.map +1 -0
- package/dist/templates/inferred-types.d.ts +4 -0
- package/dist/templates/inferred-types.d.ts.map +1 -0
- package/dist/templates/inferred-types.js +14 -0
- package/dist/templates/inferred-types.js.map +1 -0
- package/dist/templates/projection-decl.d.ts +21 -0
- package/dist/templates/projection-decl.d.ts.map +1 -0
- package/dist/templates/projection-decl.js +116 -0
- package/dist/templates/projection-decl.js.map +1 -0
- package/dist/templates/queries-file.d.ts +4 -0
- package/dist/templates/queries-file.d.ts.map +1 -0
- package/dist/templates/queries-file.js +39 -0
- package/dist/templates/queries-file.js.map +1 -0
- package/dist/templates/queries.d.ts +9 -0
- package/dist/templates/queries.d.ts.map +1 -0
- package/dist/templates/queries.js +115 -0
- package/dist/templates/queries.js.map +1 -0
- package/dist/templates/relations-block.d.ts +9 -0
- package/dist/templates/relations-block.d.ts.map +1 -0
- package/dist/templates/relations-block.js +45 -0
- package/dist/templates/relations-block.js.map +1 -0
- package/dist/templates/routes-file.d.ts +4 -0
- package/dist/templates/routes-file.d.ts.map +1 -0
- package/dist/templates/routes-file.js +158 -0
- package/dist/templates/routes-file.js.map +1 -0
- package/dist/templates/zod-validators.d.ts +4 -0
- package/dist/templates/zod-validators.d.ts.map +1 -0
- package/dist/templates/zod-validators.js +129 -0
- package/dist/templates/zod-validators.js.map +1 -0
- package/package.json +59 -0
- package/src/column-mapper.ts +266 -0
- package/src/constants.ts +10 -0
- package/src/errors.ts +10 -0
- package/src/format.ts +50 -0
- package/src/generator.ts +73 -0
- package/src/generators/barrel.ts +28 -0
- package/src/generators/entity-file.ts +33 -0
- package/src/generators/index.ts +4 -0
- package/src/generators/queries-file.ts +32 -0
- package/src/generators/routes-file.ts +36 -0
- package/src/import-path.ts +153 -0
- package/src/index.ts +45 -0
- package/src/metaobjects-config.ts +95 -0
- package/src/naming.ts +84 -0
- package/src/overwrite-policy.ts +39 -0
- package/src/pk-resolver.ts +47 -0
- package/src/projection/extract-view-spec.ts +372 -0
- package/src/projection/index.ts +4 -0
- package/src/projection/projection-detector.ts +26 -0
- package/src/projection/view-ddl-emit.ts +66 -0
- package/src/projection/view-spec.ts +62 -0
- package/src/relation-resolver.ts +87 -0
- package/src/render-context.ts +93 -0
- package/src/runner.ts +178 -0
- package/src/templates/barrel.ts +23 -0
- package/src/templates/drizzle-schema.ts +286 -0
- package/src/templates/entity-constants.ts +248 -0
- package/src/templates/entity-file.ts +51 -0
- package/src/templates/field-meta.ts +150 -0
- package/src/templates/filter-allowlist.ts +104 -0
- package/src/templates/filter-shared.ts +30 -0
- package/src/templates/filter-type.ts +93 -0
- package/src/templates/inferred-types.ts +16 -0
- package/src/templates/projection-decl.ts +146 -0
- package/src/templates/queries-file.ts +56 -0
- package/src/templates/queries.ts +132 -0
- package/src/templates/relations-block.ts +65 -0
- package/src/templates/routes-file.ts +179 -0
- package/src/templates/zod-validators.ts +140 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// Drizzle schema template — emits a single sqliteTable() or pgTable() definition,
|
|
2
|
+
// with FK .references() on FK columns derived from relationship children,
|
|
3
|
+
// plus the relations() block auto-emitted at the end.
|
|
4
|
+
import { code, imp, joinCode } from "ts-poet";
|
|
5
|
+
import { MetaObject, MetaField } from "@metaobjectsdev/metadata";
|
|
6
|
+
import { IDENTITY_SUBTYPE_SECONDARY, FIELD_SUBTYPE_LONG, IDENTITY_ATTR_FIELDS, IDENTITY_ATTR_GENERATION, IDENTITY_ATTR_UNIQUE, GENERATION_INCREMENT, GENERATION_UUID, FIELD_ATTR_AUTO_SET, } from "@metaobjectsdev/metadata";
|
|
7
|
+
import {} from "../render-context.js";
|
|
8
|
+
import { crossEntitySpecifier } from "../import-path.js";
|
|
9
|
+
import { mapColumnType } from "../column-mapper.js";
|
|
10
|
+
import { tableNameFromEntity, variableNameFromEntity, columnNameFromField } from "../naming.js";
|
|
11
|
+
import { renderRelationsBlock } from "./relations-block.js";
|
|
12
|
+
/**
|
|
13
|
+
* Render the Drizzle table definition for one entity, including:
|
|
14
|
+
* - FK .references() on FK columns derived from relationship children
|
|
15
|
+
* - relations() block at the end of the section
|
|
16
|
+
*
|
|
17
|
+
* Returns a Code object so ts-poet can deduplicate imports when this composes
|
|
18
|
+
* with the rest of the entity file. Biome formatting runs after composition.
|
|
19
|
+
*/
|
|
20
|
+
export function renderDrizzleSchema(obj, ctx) {
|
|
21
|
+
const dialect = ctx.dialect;
|
|
22
|
+
const tableFn = dialect === "sqlite" ? "sqliteTable" : "pgTable";
|
|
23
|
+
const importModule = dialect === "sqlite" ? "drizzle-orm/sqlite-core" : "drizzle-orm/pg-core";
|
|
24
|
+
const tableFnSym = imp(`${tableFn}@${importModule}`);
|
|
25
|
+
const tableName = obj.dbTable ?? tableNameFromEntity(obj.name, ctx.columnNamingStrategy);
|
|
26
|
+
const varName = variableNameFromEntity(obj.name);
|
|
27
|
+
const primary = obj.primaryIdentity();
|
|
28
|
+
const rawPkFields = primary?.ownAttr(IDENTITY_ATTR_FIELDS);
|
|
29
|
+
const pkFieldsList = Array.isArray(rawPkFields)
|
|
30
|
+
? rawPkFields
|
|
31
|
+
: typeof rawPkFields === "string"
|
|
32
|
+
? rawPkFields.split(",").map((f) => f.trim()).filter(Boolean)
|
|
33
|
+
: [];
|
|
34
|
+
const pkFieldNames = new Set(pkFieldsList);
|
|
35
|
+
const pkGeneration = primary?.ownAttr(IDENTITY_ATTR_GENERATION);
|
|
36
|
+
const fkMap = buildFkMapForEntity(obj, ctx);
|
|
37
|
+
const isComposite = pkFieldNames.size > 1;
|
|
38
|
+
// Collect secondary identities and the field names that need .unique() on
|
|
39
|
+
// their column. Only single-column UNIQUE identities propagate .unique() to
|
|
40
|
+
// the column — non-unique indexes emit a separate index() callback entry
|
|
41
|
+
// (handled below) and must not stamp .unique() on the underlying column.
|
|
42
|
+
const secondaryIdentities = obj.secondaryIdentities();
|
|
43
|
+
const uniqueFieldNames = new Set();
|
|
44
|
+
for (const sec of secondaryIdentities) {
|
|
45
|
+
const uniqueAttr = sec.ownAttr(IDENTITY_ATTR_UNIQUE);
|
|
46
|
+
if (uniqueAttr === false)
|
|
47
|
+
continue; // explicit non-unique → don't mark column
|
|
48
|
+
const fields = sec.ownAttr(IDENTITY_ATTR_FIELDS);
|
|
49
|
+
if (!Array.isArray(fields) || fields.length !== 1)
|
|
50
|
+
continue; // multi-col uniques use a callback index, not a column flag
|
|
51
|
+
uniqueFieldNames.add(fields[0]);
|
|
52
|
+
}
|
|
53
|
+
const columnLines = [];
|
|
54
|
+
for (const child of obj.fields()) {
|
|
55
|
+
const isPk = pkFieldNames.has(child.name);
|
|
56
|
+
const isUnique = uniqueFieldNames.has(child.name) && !isPk;
|
|
57
|
+
const fkInfo = fkMap.get(child.name);
|
|
58
|
+
columnLines.push(renderColumn(child, ctx, isPk, pkGeneration, fkInfo, isComposite, isUnique, obj.package));
|
|
59
|
+
}
|
|
60
|
+
// Build all table callback entries
|
|
61
|
+
const callbackEntries = [];
|
|
62
|
+
if (isComposite && primary !== undefined) {
|
|
63
|
+
callbackEntries.push(buildCompositeKeyCallback(pkFieldNames, importModule));
|
|
64
|
+
}
|
|
65
|
+
for (const sec of secondaryIdentities) {
|
|
66
|
+
const fields = sec.ownAttr(IDENTITY_ATTR_FIELDS);
|
|
67
|
+
if (!Array.isArray(fields) || fields.length === 0)
|
|
68
|
+
continue;
|
|
69
|
+
const indexName = `idx_${tableName}_${fields.map((f) => columnNameFromField(f, ctx.columnNamingStrategy)).join("_")}`;
|
|
70
|
+
// @unique on the identity defaults to true (preserves back-compat with
|
|
71
|
+
// foundations fixtures that assumed secondary identities were always
|
|
72
|
+
// unique). Explicit @unique: false → ordinary non-unique index.
|
|
73
|
+
const uniqueAttr = sec.ownAttr(IDENTITY_ATTR_UNIQUE);
|
|
74
|
+
const isUnique = uniqueAttr !== false;
|
|
75
|
+
const indexFn = isUnique ? "uniqueIndex" : "index";
|
|
76
|
+
const indexSym = imp(`${indexFn}@${importModule}`);
|
|
77
|
+
// Use the callback param `table` (not the outer varName) so TS doesn't see
|
|
78
|
+
// the table referencing itself inside its own initializer (TS7022/TS7024).
|
|
79
|
+
const cols = fields.map((f) => `table.${f}`).join(", ");
|
|
80
|
+
callbackEntries.push(code `${indexSym}(${JSON.stringify(indexName)}).on(${cols})`);
|
|
81
|
+
}
|
|
82
|
+
let tableBlock;
|
|
83
|
+
if (callbackEntries.length > 0) {
|
|
84
|
+
tableBlock = code `
|
|
85
|
+
export const ${varName} = ${tableFnSym}(${JSON.stringify(tableName)}, {
|
|
86
|
+
${joinCode(columnLines, { on: ",\n", trim: false })}
|
|
87
|
+
}, (table) => [
|
|
88
|
+
${joinCode(callbackEntries, { on: ",\n ", trim: false })}
|
|
89
|
+
]);
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
tableBlock = code `
|
|
94
|
+
export const ${varName} = ${tableFnSym}(${JSON.stringify(tableName)}, {
|
|
95
|
+
${joinCode(columnLines, { on: ",\n", trim: false })}
|
|
96
|
+
});
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
// Emit the relations() block (returns null if no relations).
|
|
100
|
+
const relationsBlock = renderRelationsBlock(obj, ctx);
|
|
101
|
+
if (relationsBlock === null) {
|
|
102
|
+
return tableBlock;
|
|
103
|
+
}
|
|
104
|
+
return joinCode([tableBlock, relationsBlock], { on: "\n" });
|
|
105
|
+
}
|
|
106
|
+
/** Pre-pass: map fkFieldName → FkInfo for this entity's effective (own + inherited) identity.reference children. */
|
|
107
|
+
function buildFkMapForEntity(obj, ctx) {
|
|
108
|
+
const result = new Map();
|
|
109
|
+
for (const ref of obj.referenceIdentities()) {
|
|
110
|
+
// @enforce: false → logical-only reference. Skip the .references() emission;
|
|
111
|
+
// the column stays plain. Drizzle's relations() block (driven by
|
|
112
|
+
// relation-resolver) still includes the relationship for query navigation.
|
|
113
|
+
if (!ref.enforce)
|
|
114
|
+
continue;
|
|
115
|
+
const fkFieldNames = ref.fields;
|
|
116
|
+
if (fkFieldNames.length === 0)
|
|
117
|
+
continue;
|
|
118
|
+
const fkField = fkFieldNames[0];
|
|
119
|
+
const targetName = ref.targetEntity;
|
|
120
|
+
if (!targetName)
|
|
121
|
+
continue;
|
|
122
|
+
const targetObj = ctx.loadedRoot.findObject(targetName);
|
|
123
|
+
if (!targetObj)
|
|
124
|
+
continue;
|
|
125
|
+
const targetPkField = ref.resolvedTargetPkField(ctx.loadedRoot) ?? "id";
|
|
126
|
+
result.set(fkField, {
|
|
127
|
+
targetVarName: variableNameFromEntity(targetObj.name),
|
|
128
|
+
targetEntityName: targetObj.name,
|
|
129
|
+
targetPkField,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Build the `primaryKey({ columns: [table.f1, table.f2] })` Code expression
|
|
136
|
+
* for composite primary keys. Uses imp() so ts-poet tracks the import.
|
|
137
|
+
*/
|
|
138
|
+
function buildCompositeKeyCallback(pkFieldNames, importModule) {
|
|
139
|
+
const primaryKeySym = imp(`primaryKey@${importModule}`);
|
|
140
|
+
const columnRefs = Array.from(pkFieldNames)
|
|
141
|
+
.map((f) => `table.${f}`)
|
|
142
|
+
.join(", ");
|
|
143
|
+
return code `${primaryKeySym}({ columns: [${columnRefs}] })`;
|
|
144
|
+
}
|
|
145
|
+
/** Build a JS-style object literal string (not JSON.stringify which uses quoted keys). */
|
|
146
|
+
function inlineObjectLiteral(obj) {
|
|
147
|
+
const entries = Object.entries(obj).map(([k, v]) => `${k}: ${JSON.stringify(v)}`);
|
|
148
|
+
return `{ ${entries.join(", ")} }`;
|
|
149
|
+
}
|
|
150
|
+
/** Render one column line (field name + Drizzle column expression). */
|
|
151
|
+
function renderColumn(field, ctx, isPk, pkGeneration, fkInfo, isComposite, isUnique = false, entityPackage = undefined) {
|
|
152
|
+
const spec = mapColumnType(field, ctx.dialect, ctx.columnNamingStrategy);
|
|
153
|
+
const fnSym = imp(`${spec.fnName}@${spec.importModule}`);
|
|
154
|
+
const dbNameLit = JSON.stringify(spec.dbName);
|
|
155
|
+
let baseCall;
|
|
156
|
+
if (spec.fnOptions !== undefined && Object.keys(spec.fnOptions).length > 0) {
|
|
157
|
+
baseCall = code `${fnSym}(${dbNameLit}, ${inlineObjectLiteral(spec.fnOptions)})`;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
baseCall = code `${fnSym}(${dbNameLit})`;
|
|
161
|
+
}
|
|
162
|
+
let pkSuffix = "";
|
|
163
|
+
if (isPk) {
|
|
164
|
+
if (pkGeneration === GENERATION_INCREMENT) {
|
|
165
|
+
if (ctx.dialect === "sqlite") {
|
|
166
|
+
// Composite PKs don't use .primaryKey() per-column; table callback owns it.
|
|
167
|
+
pkSuffix = isComposite ? "" : ".primaryKey({ autoIncrement: true })";
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Postgres: bigserial for long (8-byte), serial for int (4-byte).
|
|
171
|
+
if (field.subType === FIELD_SUBTYPE_LONG) {
|
|
172
|
+
const bigserialSym = imp(`bigserial@${spec.importModule}`);
|
|
173
|
+
baseCall = code `${bigserialSym}(${dbNameLit}, { mode: "number" })`;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
const serialSym = imp(`serial@${spec.importModule}`);
|
|
177
|
+
baseCall = code `${serialSym}(${dbNameLit})`;
|
|
178
|
+
}
|
|
179
|
+
pkSuffix = isComposite ? "" : ".primaryKey()";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else if (pkGeneration === GENERATION_UUID) {
|
|
183
|
+
pkSuffix = isComposite
|
|
184
|
+
? ""
|
|
185
|
+
: ctx.dialect === "sqlite"
|
|
186
|
+
? ".primaryKey().$defaultFn(() => crypto.randomUUID())"
|
|
187
|
+
: ".primaryKey().defaultRandom()";
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// No generation: natural PK. Composite hands off to table callback.
|
|
191
|
+
pkSuffix = isComposite ? "" : ".primaryKey()";
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
let modifiersStr = pkSuffix;
|
|
195
|
+
// Append .unique() for secondary-identity fields (isPk guard already excluded PKs upstream).
|
|
196
|
+
if (isUnique)
|
|
197
|
+
modifiersStr += ".unique()";
|
|
198
|
+
for (const m of spec.modifiers) {
|
|
199
|
+
// Single-column PKs imply notNull/unique; avoid emitting them twice.
|
|
200
|
+
// Composite-PK columns are NOT declared with .primaryKey(), so they DO need .notNull().
|
|
201
|
+
if (isPk && !isComposite && (m === ".notNull()" || m === ".unique()"))
|
|
202
|
+
continue;
|
|
203
|
+
// Avoid double-emitting .unique() if it was already appended above.
|
|
204
|
+
if (isUnique && m === ".unique()")
|
|
205
|
+
continue;
|
|
206
|
+
modifiersStr += m;
|
|
207
|
+
}
|
|
208
|
+
// sqlDefaultSegment must be a Code segment (not a raw string) so ts-poet tracks
|
|
209
|
+
// the `sql` import via imp(); a raw `.default(sql`...`)` would leave `sql`
|
|
210
|
+
// unresolved in the generated file.
|
|
211
|
+
let sqlDefaultSegment = null;
|
|
212
|
+
if (spec.defaultExpr !== undefined && !isPk) {
|
|
213
|
+
if (spec.defaultExpr.kind === "now") {
|
|
214
|
+
if (ctx.dialect === "sqlite") {
|
|
215
|
+
const sqlSym = imp("sql@drizzle-orm");
|
|
216
|
+
sqlDefaultSegment = code `.default(${sqlSym}\`CURRENT_TIMESTAMP\`)`;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
modifiersStr += `.defaultNow()`;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (spec.defaultExpr.kind === "sqlExpr") {
|
|
223
|
+
const sqlSym = imp("sql@drizzle-orm");
|
|
224
|
+
// Raw SQL keyword/expression — emit as sql`<raw>` for both dialects.
|
|
225
|
+
sqlDefaultSegment = code `.default(${sqlSym}\`${spec.defaultExpr.raw}\`)`;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// literal
|
|
229
|
+
modifiersStr += `.default(${JSON.stringify(spec.defaultExpr.value)})`;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// FK .references() uses imp() so ts-poet tracks the cross-entity import.
|
|
233
|
+
let fkRefSegment = null;
|
|
234
|
+
if (fkInfo !== undefined && !isPk) {
|
|
235
|
+
const targetSpec = crossEntitySpecifier(ctx.outputLayout, entityPackage, ctx.packageOf.get(fkInfo.targetEntityName), fkInfo.targetEntityName, ctx.extStyle);
|
|
236
|
+
const targetVarSym = imp(`${fkInfo.targetVarName}@${targetSpec}`);
|
|
237
|
+
fkRefSegment = code `.references(() => ${targetVarSym}.${fkInfo.targetPkField})`;
|
|
238
|
+
}
|
|
239
|
+
// @autoSet fields: emit .$defaultFn(() => new Date().toISOString()) so Drizzle
|
|
240
|
+
// inserts stamp the server-side timestamp automatically. This means callers don't
|
|
241
|
+
// need to supply createdAt / updatedAt in INSERT calls — Drizzle fills them in.
|
|
242
|
+
const autoSet = field.ownAttr(FIELD_ATTR_AUTO_SET);
|
|
243
|
+
const autoSetSuffix = (autoSet === "onCreate" || autoSet === "onUpdate")
|
|
244
|
+
? `.$defaultFn(() => new Date().toISOString())`
|
|
245
|
+
: "";
|
|
246
|
+
const columnLine = code ` ${field.name}: ${baseCall}${modifiersStr}${autoSetSuffix}${sqlDefaultSegment ?? ""}${fkRefSegment ?? ""}`;
|
|
247
|
+
return spec.leadingComment !== undefined
|
|
248
|
+
? code ` // ${spec.leadingComment}\n${columnLine}`
|
|
249
|
+
: columnLine;
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=drizzle-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drizzle-schema.js","sourceRoot":"","sources":["../../src/templates/drizzle-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-constants.d.ts","sourceRoot":"","sources":["../../src/templates/entity-constants.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAa,MAAM,0BAA0B,CAAC;AA+KjE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,SAAK,GAAG,IAAI,CAwC3E"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Entity-constants template — emits an `<Entity>` const with all the
|
|
2
|
+
// metadata-derived strings consumers should use INSTEAD of magic strings.
|
|
3
|
+
//
|
|
4
|
+
// Shape (each non-$-prefixed key is a per-field object):
|
|
5
|
+
//
|
|
6
|
+
// export const Subscriber = {
|
|
7
|
+
// $entity: "Subscriber",
|
|
8
|
+
// $table: "subscribers",
|
|
9
|
+
// $path: "/subscribers",
|
|
10
|
+
//
|
|
11
|
+
// email: {
|
|
12
|
+
// name: "email",
|
|
13
|
+
// label: "Email Address", // from @label on the view, falls back to humanized field name
|
|
14
|
+
// view: "text", // MetaView subtype
|
|
15
|
+
// htmlType: "email", // optional; only when it maps to a real HTML input type
|
|
16
|
+
// placeholder: "you@example.com", // optional; only when @placeholder is set on the view
|
|
17
|
+
// helpText: "We never share this.", // optional; only when @helpText is set
|
|
18
|
+
// rules: { // optional; derived from validator children
|
|
19
|
+
// required: "Email is required",
|
|
20
|
+
// maxLength: { value: 255, message: "Must be 255 characters or fewer" },
|
|
21
|
+
// pattern: { value: /.../, message: "Invalid email" },
|
|
22
|
+
// },
|
|
23
|
+
// },
|
|
24
|
+
// // ...
|
|
25
|
+
// } as const;
|
|
26
|
+
//
|
|
27
|
+
// Consumers spread `form.input.email` from useEntityForm and never touch
|
|
28
|
+
// per-attribute access (placeholder, rules, etc.) by hand — the helper
|
|
29
|
+
// picks them up from this object automatically.
|
|
30
|
+
import { code } from "ts-poet";
|
|
31
|
+
import { MetaObject, MetaField } from "@metaobjectsdev/metadata";
|
|
32
|
+
import { VIEW_SUBTYPE_TEXT, VIEW_SUBTYPE_TEXTAREA, VIEW_SUBTYPE_NUMBER, VIEW_SUBTYPE_CHECKBOX, VIEW_SUBTYPE_DATE, VIEW_SUBTYPE_PASSWORD, VIEW_SUBTYPE_HIDDEN, VIEW_SUBTYPE_DROPDOWN, VIEW_SUBTYPE_RADIO, VALIDATOR_SUBTYPE_REQUIRED, VALIDATOR_SUBTYPE_LENGTH, VALIDATOR_SUBTYPE_REGEX, VALIDATOR_ATTR_MIN, VALIDATOR_ATTR_MAX, VALIDATOR_ATTR_PATTERN, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_REQUIRED, } from "@metaobjectsdev/metadata";
|
|
33
|
+
import { resolveTableName, pluralize, toSnakeCase } from "@metaobjectsdev/metadata";
|
|
34
|
+
import { inferViewKind, currencyMetaFor, labelFor } from "./field-meta.js";
|
|
35
|
+
/** Convert a camelCase or PascalCase field name to a human-friendly label. */
|
|
36
|
+
function humanize(s) {
|
|
37
|
+
return s
|
|
38
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
39
|
+
.replace(/_/g, " ")
|
|
40
|
+
.replace(/\b\w/g, (c) => c.toUpperCase())
|
|
41
|
+
.trim();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* REST resource path for an entity. Pluralized + snake_cased + lowercased.
|
|
45
|
+
* "Subscriber" → "/subscribers"
|
|
46
|
+
* "WorkoutEvent" → "/workout_events"
|
|
47
|
+
*/
|
|
48
|
+
function resourcePath(entity) {
|
|
49
|
+
const overrideAttr = entity.ownAttr("routePath");
|
|
50
|
+
if (typeof overrideAttr === "string" && overrideAttr.length > 0) {
|
|
51
|
+
return overrideAttr.startsWith("/") ? overrideAttr : `/${overrideAttr}`;
|
|
52
|
+
}
|
|
53
|
+
return `/${pluralize(toSnakeCase(entity.name))}`;
|
|
54
|
+
}
|
|
55
|
+
/** Resolve the view subtype: explicit `view` child (own or inherited) wins, else inferred from field subType. */
|
|
56
|
+
function resolveView(field) {
|
|
57
|
+
const viewChild = field.views()[0];
|
|
58
|
+
if (viewChild) {
|
|
59
|
+
return { view: viewChild.subType, viewNode: viewChild };
|
|
60
|
+
}
|
|
61
|
+
return { view: inferViewKind(field) };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map a MetaView subtype to a real HTML <input type=...> value. Returns
|
|
65
|
+
* undefined for views that don't map to <input> at all (textarea, dropdown,
|
|
66
|
+
* radio) — consumers render the right element type themselves.
|
|
67
|
+
*/
|
|
68
|
+
function htmlTypeFromView(view, override) {
|
|
69
|
+
if (typeof override === "string" && override.length > 0)
|
|
70
|
+
return override;
|
|
71
|
+
switch (view) {
|
|
72
|
+
case VIEW_SUBTYPE_TEXT:
|
|
73
|
+
return "text";
|
|
74
|
+
case VIEW_SUBTYPE_NUMBER:
|
|
75
|
+
return "number";
|
|
76
|
+
case VIEW_SUBTYPE_DATE:
|
|
77
|
+
return "date";
|
|
78
|
+
case VIEW_SUBTYPE_PASSWORD:
|
|
79
|
+
return "password";
|
|
80
|
+
case VIEW_SUBTYPE_CHECKBOX:
|
|
81
|
+
return "checkbox";
|
|
82
|
+
case VIEW_SUBTYPE_HIDDEN:
|
|
83
|
+
return "hidden";
|
|
84
|
+
case VIEW_SUBTYPE_RADIO:
|
|
85
|
+
return "radio";
|
|
86
|
+
case "month":
|
|
87
|
+
return "month";
|
|
88
|
+
case "email":
|
|
89
|
+
return "email";
|
|
90
|
+
case VIEW_SUBTYPE_TEXTAREA:
|
|
91
|
+
case VIEW_SUBTYPE_DROPDOWN:
|
|
92
|
+
return undefined;
|
|
93
|
+
default:
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build RHF rules JSON-ish code from a field's validator children plus
|
|
99
|
+
* field-level attrs (`@required`, `@maxLength`). Returns the code string
|
|
100
|
+
* (e.g. `{ required: "X", maxLength: { value: 255, message: "..." } }`)
|
|
101
|
+
* or undefined when there are no rules to emit.
|
|
102
|
+
*/
|
|
103
|
+
function renderFieldRules(field) {
|
|
104
|
+
const ruleParts = [];
|
|
105
|
+
let hasRequired = false;
|
|
106
|
+
let hasMaxLength = false;
|
|
107
|
+
for (const child of field.validators()) {
|
|
108
|
+
if (child.subType === VALIDATOR_SUBTYPE_REQUIRED) {
|
|
109
|
+
const msg = child.ownAttr("message") ?? `${humanize(field.name)} is required`;
|
|
110
|
+
ruleParts.push(`required: ${JSON.stringify(msg)}`);
|
|
111
|
+
hasRequired = true;
|
|
112
|
+
}
|
|
113
|
+
else if (child.subType === VALIDATOR_SUBTYPE_LENGTH) {
|
|
114
|
+
const min = child.ownAttr(VALIDATOR_ATTR_MIN);
|
|
115
|
+
const max = child.ownAttr(VALIDATOR_ATTR_MAX);
|
|
116
|
+
if (typeof min === "number") {
|
|
117
|
+
const msg = child.ownAttr("minMessage") ?? `Must be at least ${min} characters`;
|
|
118
|
+
ruleParts.push(`minLength: { value: ${min}, message: ${JSON.stringify(msg)} }`);
|
|
119
|
+
}
|
|
120
|
+
if (typeof max === "number") {
|
|
121
|
+
const msg = child.ownAttr("maxMessage") ?? `Must be ${max} characters or fewer`;
|
|
122
|
+
ruleParts.push(`maxLength: { value: ${max}, message: ${JSON.stringify(msg)} }`);
|
|
123
|
+
hasMaxLength = true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (child.subType === VALIDATOR_SUBTYPE_REGEX) {
|
|
127
|
+
const pattern = child.ownAttr(VALIDATOR_ATTR_PATTERN);
|
|
128
|
+
if (typeof pattern === "string") {
|
|
129
|
+
const msg = child.ownAttr("message") ?? "Invalid format";
|
|
130
|
+
// Emit as RegExp literal /.../ — `as const` preserves the value-ref.
|
|
131
|
+
// Forward-slash inside the pattern is escaped so the literal closes correctly.
|
|
132
|
+
const safe = pattern.replace(/\\/g, "\\\\").replace(/\//g, "\\/");
|
|
133
|
+
ruleParts.push(`pattern: { value: /${safe}/, message: ${JSON.stringify(msg)} }`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Field-level @required attr (if not already covered by validator).
|
|
138
|
+
if (!hasRequired && field.ownAttr(FIELD_ATTR_REQUIRED) === true) {
|
|
139
|
+
ruleParts.push(`required: ${JSON.stringify(`${humanize(field.name)} is required`)}`);
|
|
140
|
+
}
|
|
141
|
+
// Field-level @maxLength attr (if not already covered).
|
|
142
|
+
const maxLenAttr = field.ownAttr(FIELD_ATTR_MAX_LENGTH);
|
|
143
|
+
if (!hasMaxLength && typeof maxLenAttr === "number") {
|
|
144
|
+
ruleParts.push(`maxLength: { value: ${maxLenAttr}, message: ${JSON.stringify(`Must be ${maxLenAttr} characters or fewer`)} }`);
|
|
145
|
+
}
|
|
146
|
+
if (ruleParts.length === 0)
|
|
147
|
+
return undefined;
|
|
148
|
+
return `{ ${ruleParts.join(", ")} }`;
|
|
149
|
+
}
|
|
150
|
+
/** Build one nested field-object entry like `email: { name, label, ... },`. */
|
|
151
|
+
function renderFieldEntry(field) {
|
|
152
|
+
const { view, viewNode } = resolveView(field);
|
|
153
|
+
const label = labelFor(field);
|
|
154
|
+
const placeholder = viewNode?.ownAttr("placeholder");
|
|
155
|
+
const helpText = viewNode?.ownAttr("helpText");
|
|
156
|
+
const htmlType = htmlTypeFromView(view, viewNode?.ownAttr("htmlType"));
|
|
157
|
+
const rules = renderFieldRules(field);
|
|
158
|
+
const entries = [
|
|
159
|
+
`name: ${JSON.stringify(field.name)}`,
|
|
160
|
+
`label: ${JSON.stringify(label)}`,
|
|
161
|
+
`view: ${JSON.stringify(view)}`,
|
|
162
|
+
];
|
|
163
|
+
if (htmlType !== undefined)
|
|
164
|
+
entries.push(`htmlType: ${JSON.stringify(htmlType)}`);
|
|
165
|
+
if (placeholder !== undefined)
|
|
166
|
+
entries.push(`placeholder: ${JSON.stringify(placeholder)}`);
|
|
167
|
+
if (helpText !== undefined)
|
|
168
|
+
entries.push(`helpText: ${JSON.stringify(helpText)}`);
|
|
169
|
+
if (rules !== undefined)
|
|
170
|
+
entries.push(`rules: ${rules}`);
|
|
171
|
+
// Currency-specific keys: only emitted for currency-subtype fields.
|
|
172
|
+
const currencyMeta = currencyMetaFor(field);
|
|
173
|
+
if (currencyMeta !== null) {
|
|
174
|
+
entries.push(`currency: ${JSON.stringify(currencyMeta.currency)}`);
|
|
175
|
+
entries.push(`locale: ${JSON.stringify(currencyMeta.locale)}`);
|
|
176
|
+
}
|
|
177
|
+
return ` ${field.name}: {\n ${entries.join(",\n ")},\n }`;
|
|
178
|
+
}
|
|
179
|
+
export function renderEntityConstants(obj, apiPrefix = "") {
|
|
180
|
+
const entityName = obj.name;
|
|
181
|
+
const tableName = resolveTableName(obj);
|
|
182
|
+
const path = resourcePath(obj);
|
|
183
|
+
const fieldEntries = [];
|
|
184
|
+
// Use fields() so inherited fields (from extends:/super:) appear in constants.
|
|
185
|
+
for (const child of obj.fields()) {
|
|
186
|
+
fieldEntries.push(renderFieldEntry(child));
|
|
187
|
+
}
|
|
188
|
+
const body = [
|
|
189
|
+
` $entity: ${JSON.stringify(entityName)}`,
|
|
190
|
+
` $table: ${JSON.stringify(tableName)}`,
|
|
191
|
+
` $path: ${JSON.stringify(path)}`,
|
|
192
|
+
` $apiPrefix: ${JSON.stringify(apiPrefix)}`,
|
|
193
|
+
...fieldEntries,
|
|
194
|
+
].join(",\n");
|
|
195
|
+
return code `
|
|
196
|
+
/**
|
|
197
|
+
* Metadata constants for ${entityName}.
|
|
198
|
+
*
|
|
199
|
+
* Use these instead of magic strings so TS catches typos and refactors stay
|
|
200
|
+
* coherent. Each non-dollar-prefixed key is a per-field object carrying
|
|
201
|
+
* name, label, view, optional htmlType/placeholder/helpText, and the
|
|
202
|
+
* RHF-shaped validation rules derived from the field's validator children.
|
|
203
|
+
*
|
|
204
|
+
* Typical usage with the metaobjects React form helper:
|
|
205
|
+
*
|
|
206
|
+
* import { useEntityForm } from '@metaobjectsdev/react';
|
|
207
|
+
* const form = useEntityForm(${entityName}, ${entityName}InsertSchema);
|
|
208
|
+
* <input {...form.input.${fieldEntries[0]?.match(/^\s*(\w+):/)?.[1] ?? "fieldName"}} />
|
|
209
|
+
*/
|
|
210
|
+
export const ${entityName} = {
|
|
211
|
+
${body},
|
|
212
|
+
} as const;
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=entity-constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-constants.js","sourceRoot":"","sources":["../../src/templates/entity-constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-file.d.ts","sourceRoot":"","sources":["../../src/templates/entity-file.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAW1D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CA8B/E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Entity file composer — combines drizzle-schema, inferred-types, and zod-validators
|
|
2
|
+
// into one file with the @generated header. ts-poet deduplicates imports.
|
|
3
|
+
//
|
|
4
|
+
// Dispatch:
|
|
5
|
+
// isProjection(entity) → renderProjectionDecl (read-only: view declaration + Zod + filter sections)
|
|
6
|
+
// vanilla / write-through entity → Drizzle table path
|
|
7
|
+
import { joinCode } from "ts-poet";
|
|
8
|
+
import { renderDrizzleSchema } from "./drizzle-schema.js";
|
|
9
|
+
import { renderInferredTypes } from "./inferred-types.js";
|
|
10
|
+
import { renderZodValidators } from "./zod-validators.js";
|
|
11
|
+
import { renderEntityConstants } from "./entity-constants.js";
|
|
12
|
+
import { renderFilterAllowlist, renderSortAllowlist } from "./filter-allowlist.js";
|
|
13
|
+
import { renderFilterType } from "./filter-type.js";
|
|
14
|
+
import { GENERATED_HEADER } from "../constants.js";
|
|
15
|
+
import { isProjection } from "../projection/projection-detector.js";
|
|
16
|
+
import { renderProjectionDecl } from "./projection-decl.js";
|
|
17
|
+
export function renderEntityFile(entity, ctx) {
|
|
18
|
+
// --- Projection path (read-only: view-backed entity with no table source) ---
|
|
19
|
+
if (isProjection(entity)) {
|
|
20
|
+
return renderProjectionDecl(entity, ctx.loadedRoot, {
|
|
21
|
+
columnNamingStrategy: ctx.columnNamingStrategy,
|
|
22
|
+
dialect: ctx.dialect,
|
|
23
|
+
apiPrefix: ctx.apiPrefix,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// --- Vanilla / write-through entity path ---
|
|
27
|
+
const sections = [
|
|
28
|
+
renderDrizzleSchema(entity, ctx),
|
|
29
|
+
renderInferredTypes(entity),
|
|
30
|
+
renderZodValidators(entity),
|
|
31
|
+
renderEntityConstants(entity, ctx.apiPrefix),
|
|
32
|
+
renderFilterAllowlist(entity),
|
|
33
|
+
renderSortAllowlist(entity),
|
|
34
|
+
renderFilterType(entity),
|
|
35
|
+
];
|
|
36
|
+
// Render ts-poet body first (ts-poet hoists imp()-tracked imports to the top),
|
|
37
|
+
// then prepend the @generated header so it lands at line 1 — convention for
|
|
38
|
+
// generated files and what most tooling (overwrite-policy, IDEs) expects.
|
|
39
|
+
const body = joinCode(sections, { on: "\n" }).toString();
|
|
40
|
+
const header = `// ${GENERATED_HEADER} — DO NOT EDIT.\n` +
|
|
41
|
+
`// Source metadata: ${entity.name} (${entity.fqn()})\n` +
|
|
42
|
+
`// Customize via ${entity.name}.extra.ts in this directory.\n`;
|
|
43
|
+
return header + body;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=entity-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-file.js","sourceRoot":"","sources":["../../src/templates/entity-file.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,0EAA0E;AAC1E,EAAE;AACF,YAAY;AACZ,uGAAuG;AACvG,wDAAwD;AAExD,OAAO,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AAG9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,GAAkB;IACrE,+EAA+E;IAC/E,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE;YAClD,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;YAC9C,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IAED,8CAA8C;IAC9C,MAAM,QAAQ,GAAW;QACvB,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC;QAChC,mBAAmB,CAAC,MAAM,CAAC;QAC3B,mBAAmB,CAAC,MAAM,CAAC;QAC3B,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC;QAC5C,qBAAqB,CAAC,MAAM,CAAC;QAC7B,mBAAmB,CAAC,MAAM,CAAC;QAC3B,gBAAgB,CAAC,MAAM,CAAC;KACzB,CAAC;IAEF,+EAA+E;IAC/E,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzD,MAAM,MAAM,GACV,MAAM,gBAAgB,mBAAmB;QACzC,uBAAuB,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK;QACxD,oBAAoB,MAAM,CAAC,IAAI,gCAAgC,CAAC;IAClE,OAAO,MAAM,GAAG,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MetaField } from "@metaobjectsdev/metadata";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the cell-renderer key (view kind) for a field.
|
|
4
|
+
* Explicit view child wins; field subType determines default.
|
|
5
|
+
*/
|
|
6
|
+
export declare function inferViewKind(field: MetaField): string;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the Zod validator expression for a field's storage type.
|
|
9
|
+
*/
|
|
10
|
+
export declare function zodTypeFor(field: MetaField): string;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve currency code + locale for a currency-subtype field.
|
|
13
|
+
* Returns null for non-currency fields.
|
|
14
|
+
*/
|
|
15
|
+
export declare function currencyMetaFor(field: MetaField): {
|
|
16
|
+
currency: string;
|
|
17
|
+
locale: string;
|
|
18
|
+
} | null;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the human-readable label for a field.
|
|
21
|
+
* Uses @label attr on a view child if present; otherwise humanizes the field name.
|
|
22
|
+
*/
|
|
23
|
+
export declare function labelFor(field: MetaField): string;
|
|
24
|
+
//# sourceMappingURL=field-meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-meta.d.ts","sourceRoot":"","sources":["../../src/templates/field-meta.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AA8BrD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAMtD;AA6BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAwBnD;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS7F;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAMjD"}
|