joist-codegen 2.3.0-next.65 → 2.3.0-next.67
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/build/EntityDbMetadata.cjs +6 -0
- package/build/EntityDbMetadata.cjs.map +1 -1
- package/build/EntityDbMetadata.d.cts +11 -0
- package/build/EntityDbMetadata.d.cts.map +1 -1
- package/build/EntityDbMetadata.d.mts +11 -0
- package/build/EntityDbMetadata.d.mts.map +1 -1
- package/build/EntityDbMetadata.js +6 -0
- package/build/EntityDbMetadata.js.map +1 -1
- package/build/generate.cjs +1 -0
- package/build/generate.cjs.map +1 -1
- package/build/generate.js +2 -1
- package/build/generate.js.map +1 -1
- package/build/generateEntityCodegenFile.cjs +7 -8
- package/build/generateEntityCodegenFile.cjs.map +1 -1
- package/build/generateEntityCodegenFile.d.cts.map +1 -1
- package/build/generateEntityCodegenFile.d.mts.map +1 -1
- package/build/generateEntityCodegenFile.js +7 -8
- package/build/generateEntityCodegenFile.js.map +1 -1
- package/build/generateMetadataFile.cjs +48 -61
- package/build/generateMetadataFile.cjs.map +1 -1
- package/build/generateMetadataFile.d.cts +3 -1
- package/build/generateMetadataFile.d.cts.map +1 -1
- package/build/generateMetadataFile.d.mts +3 -1
- package/build/generateMetadataFile.d.mts.map +1 -1
- package/build/generateMetadataFile.js +49 -63
- package/build/generateMetadataFile.js.map +1 -1
- package/build/symbols.cjs +10 -0
- package/build/symbols.cjs.map +1 -1
- package/build/symbols.d.cts +6 -1
- package/build/symbols.d.cts.map +1 -1
- package/build/symbols.d.mts +6 -1
- package/build/symbols.d.mts.map +1 -1
- package/build/symbols.js +6 -1
- package/build/symbols.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,21 +7,7 @@ let ts_poet = require("ts-poet");
|
|
|
7
7
|
//#region src/generateMetadataFile.ts
|
|
8
8
|
function generateMetadataFile(config, dbMeta, meta) {
|
|
9
9
|
const { entity, createdAt, updatedAt, deletedAt } = meta;
|
|
10
|
-
const fields = generateFields(config, meta);
|
|
11
|
-
const physical = meta.physicalMetadata ?? meta;
|
|
12
|
-
const sharedTable = meta.inheritanceType === "sti" && meta.baseClassName;
|
|
13
|
-
const storageFields = generateFields(config, physical, true);
|
|
14
|
-
const physicalFields = Object.fromEntries(Object.entries(storageFields).map(([name, field]) => [name, fields[name]?.toString() === field.toString() ? ts_poet.code`${entity.metaName}.fields[${require_utils.q(name)}]` : field]));
|
|
15
|
-
const columns = Object.fromEntries([
|
|
16
|
-
["id", "id"],
|
|
17
|
-
...[
|
|
18
|
-
...physical.primitives,
|
|
19
|
-
...physical.enums,
|
|
20
|
-
...physical.pgEnums,
|
|
21
|
-
...physical.manyToOnes
|
|
22
|
-
].map((field) => [field.columnName, field.fieldName]),
|
|
23
|
-
...physical.polymorphics.flatMap((field) => field.components.map((component) => [component.columnName, field.fieldName]))
|
|
24
|
-
]);
|
|
10
|
+
const fields = generateFields(config, dbMeta, meta, columnReference);
|
|
25
11
|
Object.values(fields).forEach((code) => code.asOneline());
|
|
26
12
|
const maybeBaseType = meta.baseClassName ? `"${meta.baseClassName}"` : void 0;
|
|
27
13
|
const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: "${meta.inheritanceType}",` : "";
|
|
@@ -49,7 +35,7 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
49
35
|
tableName: "${meta.tableName}",
|
|
50
36
|
supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},
|
|
51
37
|
fields: ${fields},
|
|
52
|
-
columns: {},
|
|
38
|
+
columns: ${meta.primaryKey.columnOwner.metaName}Columns,
|
|
53
39
|
allFields: {},
|
|
54
40
|
orderBy: ${require_utils.q(config.entities[meta.name]?.orderBy)},
|
|
55
41
|
timestampFields: ${maybeTimestampConfig},
|
|
@@ -59,14 +45,6 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
59
45
|
subTypes: [], ${maybeInsertionOrder} ${maybeUniqueBy}
|
|
60
46
|
};
|
|
61
47
|
|
|
62
|
-
${sharedTable ? "" : ts_poet.code`
|
|
63
|
-
${Object.entries(columns).map(([columnName, fieldName]) => {
|
|
64
|
-
const firstColumn = Object.keys(columns).find((name) => columns[name] === fieldName);
|
|
65
|
-
const field = firstColumn === columnName ? physicalFields[fieldName] : ts_poet.code`${entity.metaName}.columns[${require_utils.q(firstColumn)}].field`;
|
|
66
|
-
return ts_poet.code`${entity.metaName}.columns[${require_utils.q(columnName)}] = { fieldName: ${require_utils.q(fieldName)}, field: ${field} };`;
|
|
67
|
-
})}
|
|
68
|
-
`}
|
|
69
|
-
|
|
70
48
|
(${entity.typeForMetadataFile} as any).metadata = ${entity.metaName};
|
|
71
49
|
`;
|
|
72
50
|
}
|
|
@@ -81,8 +59,8 @@ function getUniqueBy(config, meta) {
|
|
|
81
59
|
return true;
|
|
82
60
|
});
|
|
83
61
|
}
|
|
84
|
-
/** Emits
|
|
85
|
-
function generateFields(config, dbMetadata,
|
|
62
|
+
/** Emits fields that bind the already-declared physical columns. */
|
|
63
|
+
function generateFields(config, dbMeta, dbMetadata, columnRef) {
|
|
86
64
|
const fields = {};
|
|
87
65
|
fields["id"] = ts_poet.code`
|
|
88
66
|
{
|
|
@@ -90,20 +68,20 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
90
68
|
fieldName: "id",
|
|
91
69
|
fieldIdName: undefined,
|
|
92
70
|
required: true,
|
|
93
|
-
serde: new ${require_symbols.
|
|
71
|
+
serde: new ${require_symbols.SimpleFieldSerde}("id", ${columnRef(dbMetadata.primaryKey, ts_poet.code`new ${require_symbols.KeySerde}("${dbMetadata.tagName}", "${dbMetadata.primaryKey.columnType}")`, columnArgs(dbMetadata.primaryKey, dbMetadata, ts_poet.code`() => ${dbMetadata.entity.metaName}`))}),
|
|
94
72
|
immutable: true,
|
|
95
73
|
}
|
|
96
74
|
`;
|
|
97
75
|
dbMetadata.primitives.forEach((p) => {
|
|
98
|
-
const { fieldName, derived,
|
|
99
|
-
const column =
|
|
76
|
+
const { fieldName, derived, columnType, superstruct, zodSchema, customSerde, isArray } = p;
|
|
77
|
+
const column = columnArgs(p, dbMetadata);
|
|
100
78
|
let serde;
|
|
101
|
-
if (customSerde) serde = isArray ? ts_poet.code`new ${require_symbols.CustomSerdeAdapter}(
|
|
102
|
-
else if (superstruct) serde = ts_poet.code`new ${require_symbols.SuperstructSerde}(
|
|
103
|
-
else if (zodSchema) serde = ts_poet.code`new ${require_symbols.ZodSerde}(
|
|
104
|
-
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? ts_poet.code`new ${require_symbols.DecimalToNumberSerde}(
|
|
105
|
-
else if (columnType === "jsonb") serde = ts_poet.code`new ${require_symbols.JsonSerde}(
|
|
106
|
-
else if (p.rawFieldType === "bigint") serde = isArray ? ts_poet.code`new ${require_symbols.BigIntSerde}(
|
|
79
|
+
if (customSerde) serde = isArray ? ts_poet.code`new ${require_symbols.CustomSerdeAdapter}( "${columnType}[]", ${customSerde}, true)` : ts_poet.code`new ${require_symbols.CustomSerdeAdapter}( "${columnType}", ${customSerde})`;
|
|
80
|
+
else if (superstruct) serde = ts_poet.code`new ${require_symbols.SuperstructSerde}( ${superstruct})`;
|
|
81
|
+
else if (zodSchema) serde = ts_poet.code`new ${require_symbols.ZodSerde}( ${zodSchema})`;
|
|
82
|
+
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? ts_poet.code`new ${require_symbols.DecimalToNumberSerde}(true)` : ts_poet.code`new ${require_symbols.DecimalToNumberSerde}()`;
|
|
83
|
+
else if (columnType === "jsonb") serde = ts_poet.code`new ${require_symbols.JsonSerde}()`;
|
|
84
|
+
else if (p.rawFieldType === "bigint") serde = isArray ? ts_poet.code`new ${require_symbols.BigIntSerde}(true)` : ts_poet.code`new ${require_symbols.BigIntSerde}()`;
|
|
107
85
|
else {
|
|
108
86
|
let serdeType;
|
|
109
87
|
if (columnType === "date") serdeType = config.temporal ? require_symbols.PlainDateSerde : require_symbols.DateSerde;
|
|
@@ -111,7 +89,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
111
89
|
else if (columnType === "timestamp with time zone") serdeType = config.temporal ? require_symbols.ZonedDateTimeSerde : require_symbols.DateSerde;
|
|
112
90
|
else if (columnType === "time without time zone") serdeType = config.temporal ? require_symbols.PlainTimeSerde : require_symbols.PrimitiveSerde;
|
|
113
91
|
else serdeType = require_symbols.PrimitiveSerde;
|
|
114
|
-
serde = isArray ? ts_poet.code`new ${serdeType}(
|
|
92
|
+
serde = isArray ? ts_poet.code`new ${serdeType}( "${columnType}[]", true)` : ts_poet.code`new ${serdeType}( "${columnType}")`;
|
|
115
93
|
}
|
|
116
94
|
const extras = columnType === "citext" ? ts_poet.code`citext: true,` : "";
|
|
117
95
|
fields[fieldName] = ts_poet.code`
|
|
@@ -123,7 +101,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
123
101
|
required: ${!derived && p.notNull},
|
|
124
102
|
protected: ${p.protected},
|
|
125
103
|
type: ${typeof p.rawFieldType === "string" ? `"${p.rawFieldType}"` : p.rawFieldType},
|
|
126
|
-
serde: ${serde},
|
|
104
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(p, serde, column)}),
|
|
127
105
|
immutable: false,
|
|
128
106
|
${p.lazy ? ts_poet.code`lazy: true,` : ""}
|
|
129
107
|
${extras}
|
|
@@ -132,7 +110,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
132
110
|
}`;
|
|
133
111
|
});
|
|
134
112
|
dbMetadata.pgEnums.forEach((p) => {
|
|
135
|
-
const {
|
|
113
|
+
const { fieldName, notNull, dbType } = p;
|
|
136
114
|
fields[fieldName] = ts_poet.code`
|
|
137
115
|
{
|
|
138
116
|
kind: "primitive",
|
|
@@ -142,16 +120,15 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
142
120
|
required: ${notNull},
|
|
143
121
|
protected: false,
|
|
144
122
|
type: "string",
|
|
145
|
-
serde: new ${require_symbols.
|
|
123
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(p, ts_poet.code`new ${require_symbols.PrimitiveSerde}("${dbType}")`, columnArgs(p, dbMetadata))}),
|
|
146
124
|
immutable: false,
|
|
147
125
|
${maybeDefault(p)}
|
|
148
126
|
}`;
|
|
149
127
|
});
|
|
150
128
|
dbMetadata.enums.forEach((field) => {
|
|
151
|
-
const { fieldName, enumDetailType, notNull, isArray,
|
|
129
|
+
const { fieldName, enumDetailType, notNull, isArray, columnType, derived } = field;
|
|
152
130
|
const serdeType = isArray ? require_symbols.EnumArrayFieldSerde : require_symbols.EnumFieldSerde;
|
|
153
131
|
const columnTypeWithArray = `${columnType}${isArray ? "[]" : ""}`;
|
|
154
|
-
const maybeIsNullable = isArray ? `, ${!notNull}` : "";
|
|
155
132
|
fields[fieldName] = ts_poet.code`
|
|
156
133
|
{
|
|
157
134
|
kind: "enum",
|
|
@@ -160,7 +137,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
160
137
|
required: ${notNull},
|
|
161
138
|
derived: ${!derived ? false : `"${derived}"`},
|
|
162
139
|
enumDetailType: ${enumDetailType},
|
|
163
|
-
serde: new ${
|
|
140
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(field, ts_poet.code`new ${serdeType}("${columnTypeWithArray}", ${enumDetailType})`, columnArgs(field, dbMetadata))}),
|
|
164
141
|
immutable: false,
|
|
165
142
|
${maybeDefault(field)}
|
|
166
143
|
}
|
|
@@ -169,6 +146,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
169
146
|
dbMetadata.manyToOnes.forEach((m2o) => {
|
|
170
147
|
const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;
|
|
171
148
|
const otherTagName = config.entities[otherEntity.name].tag;
|
|
149
|
+
const otherMetadata = (dbMetadata.physicalMetadata ?? dbMetadata).manyToOnes.find((field) => field.columnName === columnName)?.otherEntity.name === otherEntity.name ? ts_poet.code`${columnRef(m2o)}.idMetadata!` : ts_poet.code`() => ${otherEntity.metaName}`;
|
|
172
150
|
fields[fieldName] = ts_poet.code`
|
|
173
151
|
{
|
|
174
152
|
kind: "m2o",
|
|
@@ -176,9 +154,9 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
176
154
|
fieldIdName: "${fieldName}Id",
|
|
177
155
|
derived: ${!derived ? false : `"${derived}"`},
|
|
178
156
|
required: ${notNull},
|
|
179
|
-
otherMetadata:
|
|
157
|
+
otherMetadata: ${otherMetadata},
|
|
180
158
|
otherFieldName: "${otherFieldName}",
|
|
181
|
-
serde: new ${require_symbols.
|
|
159
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(m2o, ts_poet.code`new ${require_symbols.KeySerde}("${otherTagName}", "${dbType}")`, columnArgs(m2o, dbMetadata, ts_poet.code`() => ${otherEntity.metaName}`))}),
|
|
182
160
|
immutable: false,
|
|
183
161
|
${maybeDefault(m2o)}
|
|
184
162
|
}
|
|
@@ -274,28 +252,36 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
274
252
|
});
|
|
275
253
|
dbMetadata.polymorphics.forEach((p) => {
|
|
276
254
|
const { fieldName, notNull, components } = p;
|
|
255
|
+
components.forEach((component) => columnRef(component, ts_poet.code`new ${require_symbols.KeySerde}("${config.entities[component.otherEntity.name].tag}", "${dbMeta.entitiesByName[component.otherEntity.name].primaryKey.columnType}")`, ts_poet.code`true, false, false, false, false, () => ${component.otherEntity.metaName}`));
|
|
277
256
|
fields[fieldName] = ts_poet.code`
|
|
278
|
-
{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
components: [${components.map(({ otherFieldName, otherEntity, columnName }) => ts_poet.code`
|
|
284
|
-
{
|
|
285
|
-
otherMetadata: () => ${otherEntity.metaName},
|
|
286
|
-
otherFieldName: "${otherFieldName}",
|
|
287
|
-
columnName: "${columnName}",
|
|
288
|
-
},`)}],
|
|
289
|
-
serde: new ${require_symbols.PolymorphicKeySerde}(() => ${dbMetadata.entity.metaName}, "${fieldName}"${physical ? ts_poet.code`, ${require_utils.q(components[0].columnName)}` : ""}),
|
|
290
|
-
immutable: false,
|
|
291
|
-
}
|
|
257
|
+
${require_symbols.polymorphicField}("${fieldName}", ${notNull}, [${components.map((component) => {
|
|
258
|
+
const owner = dbMeta.entitiesByName[component.columnOwner.name];
|
|
259
|
+
const target = (owner.physicalMetadata ?? owner).polymorphics.flatMap((field) => field.components).find((c) => c.columnName === component.columnName).otherEntity.name === component.otherEntity.name ? "" : ts_poet.code`, () => ${component.otherEntity.metaName}`;
|
|
260
|
+
return ts_poet.code`new ${require_symbols.PolyComponent}(${columnRef(component)}, ${require_utils.q(component.otherFieldName)}${target}),`;
|
|
261
|
+
})}])
|
|
292
262
|
`;
|
|
293
263
|
});
|
|
294
264
|
return fields;
|
|
295
265
|
}
|
|
296
|
-
/** Emits constructor
|
|
297
|
-
function
|
|
298
|
-
|
|
266
|
+
/** Emits constructor arguments using codegen's existing column facts. */
|
|
267
|
+
function columnArgs(column, meta, idMetadata) {
|
|
268
|
+
const insertOptional = column === meta.createdAt || column === meta.updatedAt;
|
|
269
|
+
return ts_poet.code`${!column.columnNotNull}, ${column.columnDefault != null && !column.columnGenerated}, ${column.columnGenerated}, ${insertOptional}, true, ${idMetadata ?? "undefined"}`;
|
|
270
|
+
}
|
|
271
|
+
/** Declares all physical codecs before any domain metadata; ID targets remain lazy. */
|
|
272
|
+
function generateColumnDeclarations(config, dbMeta, meta) {
|
|
273
|
+
if (meta.inheritanceType === "sti" && meta.baseClassName) return ts_poet.code``;
|
|
274
|
+
const columns = {};
|
|
275
|
+
generateFields(config, dbMeta, meta.physicalMetadata ?? meta, (column, codec, args) => {
|
|
276
|
+
const name = column.columnName;
|
|
277
|
+
if (codec) columns[name] = ts_poet.code`new ${require_symbols.Column}(${require_utils.q(name)}, ${args}, ${codec})`.asOneline();
|
|
278
|
+
return ts_poet.code`${meta.entity.metaName}Columns[${require_utils.q(name)}]`;
|
|
279
|
+
});
|
|
280
|
+
return ts_poet.code`const ${meta.entity.metaName}Columns = ${columns} satisfies ${require_symbols.ColumnDescriptors};`;
|
|
281
|
+
}
|
|
282
|
+
/** Emits a direct reference to the single physical descriptor. */
|
|
283
|
+
function columnReference(column) {
|
|
284
|
+
return ts_poet.code`${column.columnOwner.metaName}Columns[${require_utils.q(column.columnName)}]`;
|
|
299
285
|
}
|
|
300
286
|
function maybeDefault(f) {
|
|
301
287
|
return f.hasConfigDefault ? ts_poet.code`default: "config",` : f.columnDefault != null ? ts_poet.code`default: "schema",` : "";
|
|
@@ -315,6 +301,7 @@ function isString(config, columnType) {
|
|
|
315
301
|
return require_utils.mapSimpleDbTypeToTypescriptType(config, columnType) === "string";
|
|
316
302
|
}
|
|
317
303
|
//#endregion
|
|
304
|
+
exports.generateColumnDeclarations = generateColumnDeclarations;
|
|
318
305
|
exports.generateMetadataFile = generateMetadataFile;
|
|
319
306
|
|
|
320
307
|
//# sourceMappingURL=generateMetadataFile.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateMetadataFile.cjs","names":["q","EntityMetadata","imp","KeySerde","CustomSerdeAdapter","SuperstructSerde","ZodSerde","DecimalToNumberSerde","JsonSerde","BigIntSerde","PlainDateSerde","DateSerde","PlainDateTimeSerde","ZonedDateTimeSerde","PlainTimeSerde","PrimitiveSerde","EnumArrayFieldSerde","EnumFieldSerde","PolymorphicKeySerde","mapSimpleDbTypeToTypescriptType"],"sources":["../src/generateMetadataFile.ts"],"sourcesContent":["import { type Code, type Import, code, imp } from \"ts-poet\";\n\nimport { type Config } from \"./config.ts\";\nimport {\n type DatabaseColumnType,\n type DbMetadata,\n type EntityDbMetadata,\n type OneToManyField,\n type PrimitiveField,\n} from \"./EntityDbMetadata.ts\";\nimport {\n BigIntSerde,\n CustomSerdeAdapter,\n DateSerde,\n DecimalToNumberSerde,\n EntityMetadata,\n EnumArrayFieldSerde,\n EnumFieldSerde,\n JsonSerde,\n KeySerde,\n PlainDateSerde,\n PlainDateTimeSerde,\n PlainTimeSerde,\n PolymorphicKeySerde,\n PrimitiveSerde,\n SuperstructSerde,\n ZodSerde,\n ZonedDateTimeSerde,\n} from \"./symbols.ts\";\nimport { mapSimpleDbTypeToTypescriptType, q } from \"./utils.ts\";\n\nexport function generateMetadataFile(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code {\n const { entity, createdAt, updatedAt, deletedAt } = meta;\n\n const fields = generateFields(config, meta);\n const physical = meta.physicalMetadata ?? meta;\n const sharedTable = meta.inheritanceType === \"sti\" && meta.baseClassName;\n const storageFields = generateFields(config, physical, true);\n // Reuse unchanged descriptors; only moved or specialized fields need separate storage metadata.\n const physicalFields = Object.fromEntries(\n Object.entries(storageFields).map(([name, field]) => [\n name,\n fields[name]?.toString() === field.toString() ? code`${entity.metaName}.fields[${q(name)}]` : field,\n ]),\n );\n const columns = Object.fromEntries<string>([\n [\"id\", \"id\"],\n ...[...physical.primitives, ...physical.enums, ...physical.pgEnums, ...physical.manyToOnes].map(\n (field) => [field.columnName, field.fieldName] as const,\n ),\n ...physical.polymorphics.flatMap((field) =>\n field.components.map((component) => [component.columnName, field.fieldName] as const),\n ),\n ]);\n\n Object.values(fields).forEach((code) => code.asOneline());\n\n const maybeBaseType = meta.baseClassName ? `\"${meta.baseClassName}\"` : undefined;\n // We want to put inheritanceType: sti/cti onto base classes as well\n const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: \"${meta.inheritanceType}\",` : \"\";\n const maybeStiColumn = meta.stiDiscriminatorField ? `stiDiscriminatorField: \"${meta.stiDiscriminatorField}\",` : \"\";\n const maybeStiValue = meta.stiDiscriminatorValue ? `stiDiscriminatorValue: ${meta.stiDiscriminatorValue},` : \"\";\n const maybeCtiAbstract = meta.abstract ? `ctiAbstract: ${meta.abstract},` : \"\";\n // Force subtype `timestampFields` to be `undefined` to ensure all runtime code is reading from the baseMeta values.\n // Force subtype `timestampFields` to be `undefined` to ensure all runtime code is reading from the baseMeta values.\n const maybeTimestampConfig = meta.baseClassName\n ? code`undefined`\n : code`\n {\n createdAt: ${q(createdAt?.fieldName)},\n updatedAt: ${q(updatedAt?.fieldName)},\n deletedAt: ${q(deletedAt?.fieldName)},\n }\n `;\n const maybeInsertionOrder = meta.nonDeferredFkOrder !== 0 ? `nonDeferredFkOrder: ${meta.nonDeferredFkOrder},` : ``;\n const uniqueBy = getUniqueBy(config, meta);\n const maybeUniqueBy = uniqueBy.length > 0 ? code`uniqueBy: ${JSON.stringify(uniqueBy)},` : code``;\n\n return code`\n export const ${entity.metaName}: ${EntityMetadata}<${entity.name}> = {\n cstr: ${entity.typeForMetadataFile},\n type: \"${entity.name}\",\n baseType: ${maybeBaseType}, ${maybeInheritanceType} ${maybeStiColumn} ${maybeStiValue} ${maybeCtiAbstract}\n idType: \"${config.idType ?? \"tagged-string\"}\",\n idDbType: \"${meta.primaryKey.columnType}\",\n tagName: \"${meta.tagName}\",\n tableName: \"${meta.tableName}\",\n supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},\n fields: ${fields},\n columns: {},\n allFields: {},\n orderBy: ${q(config.entities[meta.name]?.orderBy)},\n timestampFields: ${maybeTimestampConfig},\n config: ${entity.configConst},\n factory: ${imp(`new${entity.name}@./entities.ts`)},\n baseTypes: [],\n subTypes: [], ${maybeInsertionOrder} ${maybeUniqueBy}\n };\n\n ${\n sharedTable\n ? \"\"\n : code`\n ${Object.entries(columns).map(([columnName, fieldName]) => {\n const firstColumn = Object.keys(columns).find((name) => columns[name] === fieldName)!;\n const field =\n firstColumn === columnName\n ? physicalFields[fieldName]\n : code`${entity.metaName}.columns[${q(firstColumn)}].field`;\n return code`${entity.metaName}.columns[${q(columnName)}] = { fieldName: ${q(fieldName)}, field: ${field} };`;\n })}\n `\n }\n\n (${entity.typeForMetadataFile} as any).metadata = ${entity.metaName};\n `;\n}\n\n/** Returns configured identities plus conservative database-backed unique identities. */\nfunction getUniqueBy(config: Config, meta: EntityDbMetadata): string[][] {\n const uniqueBy = config.entities[meta.name]?.uniqueBy ?? [];\n const seen = new Set<string>();\n return [...uniqueBy, ...(meta.uniqueConstraints ?? [])].filter((fields) => {\n const key = fields.join(\"\\u0000\");\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/** Emits field descriptors; physical polymorphic serdes resolve the original storage components. */\nfunction generateFields(config: Config, dbMetadata: EntityDbMetadata, physical = false): Record<string, Code> {\n const fields: Record<string, Code> = {};\n\n fields[\"id\"] = code`\n {\n kind: \"primaryKey\",\n fieldName: \"id\",\n fieldIdName: undefined,\n required: true,\n serde: new ${KeySerde}(\"${dbMetadata.tagName}\", \"id\", \"id\", \"${dbMetadata.primaryKey.columnType}\", ${columnOptions(dbMetadata.primaryKey)}),\n immutable: true,\n }\n `;\n\n dbMetadata.primitives.forEach((p) => {\n const { fieldName, derived, columnName, columnType, superstruct, zodSchema, customSerde, isArray } = p;\n const column = columnOptions(p);\n let serde: Code;\n if (customSerde) {\n serde = isArray\n ? code`new ${CustomSerdeAdapter}(\"${fieldName}\", \"${columnName}\", \"${columnType}[]\", ${customSerde}, true, ${!p.notNull}, ${column})`\n : code`new ${CustomSerdeAdapter}(\"${fieldName}\", \"${columnName}\", \"${columnType}\", ${customSerde}, false, false, ${column})`;\n } else if (superstruct) {\n serde = code`new ${SuperstructSerde}(\"${fieldName}\", \"${columnName}\", ${superstruct}, ${column})`;\n } else if (zodSchema) {\n serde = code`new ${ZodSerde}(\"${fieldName}\", \"${columnName}\", ${zodSchema}, ${column})`;\n } else if (columnType === \"numeric\" || columnType === \"decimal\") {\n serde = isArray\n ? code`new ${DecimalToNumberSerde}(\"${fieldName}\", \"${columnName}\", true, ${!p.notNull}, ${column})`\n : code`new ${DecimalToNumberSerde}(\"${fieldName}\", \"${columnName}\", false, false, ${column})`;\n } else if (columnType === \"jsonb\") {\n serde = code`new ${JsonSerde}(\"${fieldName}\", \"${columnName}\", ${column})`;\n } else if (p.rawFieldType === \"bigint\") {\n serde = isArray\n ? code`new ${BigIntSerde}(\"${fieldName}\", \"${columnName}\", true, ${!p.notNull}, ${column})`\n : code`new ${BigIntSerde}(\"${fieldName}\", \"${columnName}\", false, false, ${column})`;\n } else {\n let serdeType: Import;\n if (columnType === \"date\") {\n serdeType = config.temporal ? PlainDateSerde : DateSerde;\n } else if (columnType === \"timestamp without time zone\") {\n serdeType = config.temporal ? PlainDateTimeSerde : DateSerde;\n } else if (columnType === \"timestamp with time zone\") {\n serdeType = config.temporal ? ZonedDateTimeSerde : DateSerde;\n } else if (columnType === \"time without time zone\") {\n serdeType = config.temporal ? PlainTimeSerde : PrimitiveSerde;\n } else {\n serdeType = PrimitiveSerde;\n }\n serde = isArray\n ? code`new ${serdeType}(\"${fieldName}\", \"${columnName}\", \"${columnType}[]\", true, ${!p.notNull}, ${column})`\n : code`new ${serdeType}(\"${fieldName}\", \"${columnName}\", \"${columnType}\", false, false, ${column})`;\n }\n const extras = columnType === \"citext\" ? code`citext: true,` : \"\";\n fields[fieldName] = code`\n {\n kind: \"primitive\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n derived: ${!derived ? false : `\"${derived}\"`},\n required: ${!derived && p.notNull},\n protected: ${p.protected},\n type: ${typeof p.rawFieldType === \"string\" ? `\"${p.rawFieldType}\"` : p.rawFieldType},\n serde: ${serde},\n immutable: false,\n ${p.lazy ? code`lazy: true,` : \"\"}\n ${extras}\n ${maybeDefault(p)}\n ${maybeSanitize(config, p)}\n }`;\n });\n\n // Treat native enums as primitives\n dbMetadata.pgEnums.forEach((p) => {\n const { columnName, fieldName, notNull, dbType } = p;\n fields[fieldName] = code`\n {\n kind: \"primitive\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n derived: false,\n required: ${notNull},\n protected: false,\n type: \"string\",\n serde: new ${PrimitiveSerde}(\"${fieldName}\", \"${columnName}\", \"${dbType}\", false, false, ${columnOptions(p)}),\n immutable: false,\n ${maybeDefault(p)}\n }`;\n });\n\n dbMetadata.enums.forEach((field) => {\n const { fieldName, enumDetailType, notNull, isArray, columnName, columnType, derived } = field;\n const serdeType = isArray ? EnumArrayFieldSerde : EnumFieldSerde;\n const columnTypeWithArray = `${columnType}${isArray ? \"[]\" : \"\"}`;\n const maybeIsNullable = isArray ? `, ${!notNull}` : \"\";\n fields[fieldName] = code`\n {\n kind: \"enum\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n required: ${notNull},\n derived: ${!derived ? false : `\"${derived}\"`},\n enumDetailType: ${enumDetailType},\n serde: new ${serdeType}(\"${fieldName}\", \"${columnName}\", \"${columnTypeWithArray}\"${maybeIsNullable}, ${enumDetailType}, ${columnOptions(field)}),\n immutable: false,\n ${maybeDefault(field)}\n }\n `;\n });\n\n dbMetadata.manyToOnes.forEach((m2o) => {\n const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;\n const otherTagName = config.entities[otherEntity.name].tag;\n fields[fieldName] = code`\n {\n kind: \"m2o\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${fieldName}Id\",\n derived: ${!derived ? false : `\"${derived}\"`},\n required: ${notNull},\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n serde: new ${KeySerde}(\"${otherTagName}\", \"${fieldName}\", \"${columnName}\", \"${dbType}\", ${columnOptions(m2o)}),\n immutable: false,\n ${maybeDefault(m2o)}\n }\n `;\n });\n\n dbMetadata.oneToManys.forEach((o2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, otherColumnName } = o2m;\n fields[fieldName] = code`\n {\n kind: \"o2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n ${maybeOrderBy(o2m)}\n ${maybeSoftDeletes(o2m)}\n }\n `;\n });\n\n dbMetadata.largeOneToManys.forEach((o2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, otherColumnName } = o2m;\n fields[fieldName] = code`\n {\n kind: \"lo2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n }\n `;\n });\n\n dbMetadata.manyToManys.forEach((m2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, derived } = m2m;\n fields[fieldName] = code`\n {\n kind: \"m2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n derived: ${derived === \"async\" ? `\"async\"` : derived === \"otherSide\" ? `\"otherSide\"` : \"false\"},\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n serde: undefined,\n immutable: false,\n joinTableName: \"${m2m.joinTableName}\",\n columnNames: [\"${m2m.columnName}\", \"${m2m.otherColumnName}\"],\n hasJoinTableId: ${m2m.hasJoinTableId},\n ${maybeSoftDeletes(m2m)}\n }\n `;\n });\n\n dbMetadata.manyToManyEnums.forEach((m2m) => {\n const { fieldName, enumDetailType } = m2m;\n fields[fieldName] = code`\n {\n kind: \"m2mEnum\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n required: false,\n derived: false,\n enumDetailType: ${enumDetailType},\n serde: undefined,\n immutable: false,\n joinTableName: \"${m2m.joinTableName}\",\n columnNames: [\"${m2m.columnName}\", \"${m2m.otherColumnName}\"],\n hasJoinTableId: ${m2m.hasJoinTableId},\n }\n `;\n });\n\n dbMetadata.oneToOnes.forEach((o2o) => {\n const { fieldName, otherEntity, otherFieldName, otherColumnName } = o2o;\n fields[fieldName] = code`\n {\n kind: \"o2o\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${fieldName}Id\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n }\n `;\n });\n\n dbMetadata.polymorphics.forEach((p) => {\n const { fieldName, notNull, components } = p;\n fields[fieldName] = code`\n {\n kind: \"poly\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${fieldName}Id\",\n required: ${notNull},\n components: [${components.map(\n ({ otherFieldName, otherEntity, columnName }) => code`\n {\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n columnName: \"${columnName}\",\n },`,\n )}],\n serde: new ${PolymorphicKeySerde}(() => ${dbMetadata.entity.metaName}, \"${fieldName}\"${physical ? code`, ${q(components[0].columnName)}` : \"\"}),\n immutable: false,\n }\n `;\n });\n\n return fields;\n}\n\n/** Emits constructor options using codegen's existing column facts. */\nfunction columnOptions(\n column: Pick<PrimitiveField, \"columnNotNull\" | \"columnGenerated\"> & Partial<Pick<PrimitiveField, \"columnDefault\">>,\n): Code {\n return code`{ sqlNullable: ${!column.columnNotNull}, hasDefault: ${column.columnDefault != null && !column.columnGenerated}, isGenerated: ${column.columnGenerated} }`;\n}\n\nfunction maybeDefault(f: { hasConfigDefault: boolean; columnDefault?: number | boolean | string | null }): Code | \"\" {\n return f.hasConfigDefault ? code`default: \"config\",` : f.columnDefault != null ? code`default: \"schema\",` : \"\";\n}\n\nfunction maybeOrderBy(f: OneToManyField): Code | \"\" {\n return f.orderBy ? code`orderBy: { field: \"${f.orderBy.field}\", direction: \"${f.orderBy.direction}\" },` : \"\";\n}\n\n/** Emits the `softDeletes` config, i.e. `softDeletes: \"include\",`, for relations that opt out of hiding soft-deletes. */\nfunction maybeSoftDeletes(f: { softDeletes: \"include\" | \"exclude\" | undefined }): Code | \"\" {\n return f.softDeletes ? code`softDeletes: \"${f.softDeletes}\",` : \"\";\n}\n\n/** We sanitize/cleanStringValue all varchars, unless opted out by the column default/arrays/custom serdes. */\nfunction maybeSanitize(\n config: Config,\n f: { columnType: DatabaseColumnType; columnDefault?: any; isArray: boolean; customSerde: any },\n): Code | \"\" {\n // Only strings need to maybe turn off their cleanStringValue sanitization, if the default=\"\" or its an array\n return isString(config, f.columnType) && (f.columnDefault === \"''\" || f.isArray || f.customSerde)\n ? code`sanitize: false,`\n : \"\";\n}\n\nfunction isString(config: Config, columnType: DatabaseColumnType): boolean {\n return mapSimpleDbTypeToTypescriptType(config, columnType) === \"string\";\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generateMetadataFile.cjs","names":["q","EntityMetadata","imp","SimpleFieldSerde","KeySerde","CustomSerdeAdapter","SuperstructSerde","ZodSerde","DecimalToNumberSerde","JsonSerde","BigIntSerde","PlainDateSerde","DateSerde","PlainDateTimeSerde","ZonedDateTimeSerde","PlainTimeSerde","PrimitiveSerde","EnumArrayFieldSerde","EnumFieldSerde","polymorphicField","PolyComponent","Column","ColumnDescriptors","mapSimpleDbTypeToTypescriptType"],"sources":["../src/generateMetadataFile.ts"],"sourcesContent":["import { type Code, type Import, code, imp } from \"ts-poet\";\n\nimport { type Config } from \"./config.ts\";\nimport {\n type DatabaseColumnType,\n type DbMetadata,\n type EntityDbMetadata,\n type OneToManyField,\n type PrimitiveField,\n} from \"./EntityDbMetadata.ts\";\nimport {\n BigIntSerde,\n Column,\n ColumnDescriptors,\n CustomSerdeAdapter,\n DateSerde,\n DecimalToNumberSerde,\n EntityMetadata,\n EnumArrayFieldSerde,\n EnumFieldSerde,\n JsonSerde,\n KeySerde,\n PlainDateSerde,\n PlainDateTimeSerde,\n PlainTimeSerde,\n PolyComponent,\n PrimitiveSerde,\n SimpleFieldSerde,\n SuperstructSerde,\n ZodSerde,\n ZonedDateTimeSerde,\n polymorphicField,\n} from \"./symbols.ts\";\nimport { mapSimpleDbTypeToTypescriptType, q } from \"./utils.ts\";\n\nexport function generateMetadataFile(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code {\n const { entity, createdAt, updatedAt, deletedAt } = meta;\n\n const fields = generateFields(config, dbMeta, meta, columnReference);\n\n Object.values(fields).forEach((code) => code.asOneline());\n\n const maybeBaseType = meta.baseClassName ? `\"${meta.baseClassName}\"` : undefined;\n // We want to put inheritanceType: sti/cti onto base classes as well\n const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: \"${meta.inheritanceType}\",` : \"\";\n const maybeStiColumn = meta.stiDiscriminatorField ? `stiDiscriminatorField: \"${meta.stiDiscriminatorField}\",` : \"\";\n const maybeStiValue = meta.stiDiscriminatorValue ? `stiDiscriminatorValue: ${meta.stiDiscriminatorValue},` : \"\";\n const maybeCtiAbstract = meta.abstract ? `ctiAbstract: ${meta.abstract},` : \"\";\n // Force subtype `timestampFields` to be `undefined` to ensure all runtime code is reading from the baseMeta values.\n // Force subtype `timestampFields` to be `undefined` to ensure all runtime code is reading from the baseMeta values.\n const maybeTimestampConfig = meta.baseClassName\n ? code`undefined`\n : code`\n {\n createdAt: ${q(createdAt?.fieldName)},\n updatedAt: ${q(updatedAt?.fieldName)},\n deletedAt: ${q(deletedAt?.fieldName)},\n }\n `;\n const maybeInsertionOrder = meta.nonDeferredFkOrder !== 0 ? `nonDeferredFkOrder: ${meta.nonDeferredFkOrder},` : ``;\n const uniqueBy = getUniqueBy(config, meta);\n const maybeUniqueBy = uniqueBy.length > 0 ? code`uniqueBy: ${JSON.stringify(uniqueBy)},` : code``;\n\n return code`\n export const ${entity.metaName}: ${EntityMetadata}<${entity.name}> = {\n cstr: ${entity.typeForMetadataFile},\n type: \"${entity.name}\",\n baseType: ${maybeBaseType}, ${maybeInheritanceType} ${maybeStiColumn} ${maybeStiValue} ${maybeCtiAbstract}\n idType: \"${config.idType ?? \"tagged-string\"}\",\n idDbType: \"${meta.primaryKey.columnType}\",\n tagName: \"${meta.tagName}\",\n tableName: \"${meta.tableName}\",\n supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},\n fields: ${fields},\n columns: ${meta.primaryKey.columnOwner.metaName}Columns,\n allFields: {},\n orderBy: ${q(config.entities[meta.name]?.orderBy)},\n timestampFields: ${maybeTimestampConfig},\n config: ${entity.configConst},\n factory: ${imp(`new${entity.name}@./entities.ts`)},\n baseTypes: [],\n subTypes: [], ${maybeInsertionOrder} ${maybeUniqueBy}\n };\n\n (${entity.typeForMetadataFile} as any).metadata = ${entity.metaName};\n `;\n}\n\n/** Returns configured identities plus conservative database-backed unique identities. */\nfunction getUniqueBy(config: Config, meta: EntityDbMetadata): string[][] {\n const uniqueBy = config.entities[meta.name]?.uniqueBy ?? [];\n const seen = new Set<string>();\n return [...uniqueBy, ...(meta.uniqueConstraints ?? [])].filter((fields) => {\n const key = fields.join(\"\\u0000\");\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/** Emits fields that bind the already-declared physical columns. */\nfunction generateFields(\n config: Config,\n dbMeta: DbMetadata,\n dbMetadata: EntityDbMetadata,\n columnRef: (column: Pick<PrimitiveField, \"columnName\" | \"columnOwner\">, codec?: Code, args?: Code) => Code,\n): Record<string, Code> {\n const fields: Record<string, Code> = {};\n\n fields[\"id\"] = code`\n {\n kind: \"primaryKey\",\n fieldName: \"id\",\n fieldIdName: undefined,\n required: true,\n serde: new ${SimpleFieldSerde}(\"id\", ${columnRef(dbMetadata.primaryKey, code`new ${KeySerde}(\"${dbMetadata.tagName}\", \"${dbMetadata.primaryKey.columnType}\")`, columnArgs(dbMetadata.primaryKey, dbMetadata, code`() => ${dbMetadata.entity.metaName}`))}),\n immutable: true,\n }\n `;\n\n dbMetadata.primitives.forEach((p) => {\n const { fieldName, derived, columnType, superstruct, zodSchema, customSerde, isArray } = p;\n const column = columnArgs(p, dbMetadata);\n let serde: Code;\n if (customSerde) {\n serde = isArray\n ? code`new ${CustomSerdeAdapter}( \"${columnType}[]\", ${customSerde}, true)`\n : code`new ${CustomSerdeAdapter}( \"${columnType}\", ${customSerde})`;\n } else if (superstruct) {\n serde = code`new ${SuperstructSerde}( ${superstruct})`;\n } else if (zodSchema) {\n serde = code`new ${ZodSerde}( ${zodSchema})`;\n } else if (columnType === \"numeric\" || columnType === \"decimal\") {\n serde = isArray ? code`new ${DecimalToNumberSerde}(true)` : code`new ${DecimalToNumberSerde}()`;\n } else if (columnType === \"jsonb\") {\n serde = code`new ${JsonSerde}()`;\n } else if (p.rawFieldType === \"bigint\") {\n serde = isArray ? code`new ${BigIntSerde}(true)` : code`new ${BigIntSerde}()`;\n } else {\n let serdeType: Import;\n if (columnType === \"date\") {\n serdeType = config.temporal ? PlainDateSerde : DateSerde;\n } else if (columnType === \"timestamp without time zone\") {\n serdeType = config.temporal ? PlainDateTimeSerde : DateSerde;\n } else if (columnType === \"timestamp with time zone\") {\n serdeType = config.temporal ? ZonedDateTimeSerde : DateSerde;\n } else if (columnType === \"time without time zone\") {\n serdeType = config.temporal ? PlainTimeSerde : PrimitiveSerde;\n } else {\n serdeType = PrimitiveSerde;\n }\n serde = isArray ? code`new ${serdeType}( \"${columnType}[]\", true)` : code`new ${serdeType}( \"${columnType}\")`;\n }\n const extras = columnType === \"citext\" ? code`citext: true,` : \"\";\n fields[fieldName] = code`\n {\n kind: \"primitive\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n derived: ${!derived ? false : `\"${derived}\"`},\n required: ${!derived && p.notNull},\n protected: ${p.protected},\n type: ${typeof p.rawFieldType === \"string\" ? `\"${p.rawFieldType}\"` : p.rawFieldType},\n serde: new ${SimpleFieldSerde}(\"${fieldName}\", ${columnRef(p, serde, column)}),\n immutable: false,\n ${p.lazy ? code`lazy: true,` : \"\"}\n ${extras}\n ${maybeDefault(p)}\n ${maybeSanitize(config, p)}\n }`;\n });\n\n // Treat native enums as primitives\n dbMetadata.pgEnums.forEach((p) => {\n const { fieldName, notNull, dbType } = p;\n fields[fieldName] = code`\n {\n kind: \"primitive\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n derived: false,\n required: ${notNull},\n protected: false,\n type: \"string\",\n serde: new ${SimpleFieldSerde}(\"${fieldName}\", ${columnRef(p, code`new ${PrimitiveSerde}(\"${dbType}\")`, columnArgs(p, dbMetadata))}),\n immutable: false,\n ${maybeDefault(p)}\n }`;\n });\n\n dbMetadata.enums.forEach((field) => {\n const { fieldName, enumDetailType, notNull, isArray, columnType, derived } = field;\n const serdeType = isArray ? EnumArrayFieldSerde : EnumFieldSerde;\n const columnTypeWithArray = `${columnType}${isArray ? \"[]\" : \"\"}`;\n fields[fieldName] = code`\n {\n kind: \"enum\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n required: ${notNull},\n derived: ${!derived ? false : `\"${derived}\"`},\n enumDetailType: ${enumDetailType},\n serde: new ${SimpleFieldSerde}(\"${fieldName}\", ${columnRef(field, code`new ${serdeType}(\"${columnTypeWithArray}\", ${enumDetailType})`, columnArgs(field, dbMetadata))}),\n immutable: false,\n ${maybeDefault(field)}\n }\n `;\n });\n\n dbMetadata.manyToOnes.forEach((m2o) => {\n const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;\n const otherTagName = config.entities[otherEntity.name].tag;\n const physical = (dbMetadata.physicalMetadata ?? dbMetadata).manyToOnes.find(\n (field) => field.columnName === columnName,\n );\n const otherMetadata =\n physical?.otherEntity.name === otherEntity.name\n ? code`${columnRef(m2o)}.idMetadata!`\n : code`() => ${otherEntity.metaName}`;\n fields[fieldName] = code`\n {\n kind: \"m2o\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${fieldName}Id\",\n derived: ${!derived ? false : `\"${derived}\"`},\n required: ${notNull},\n otherMetadata: ${otherMetadata},\n otherFieldName: \"${otherFieldName}\",\n serde: new ${SimpleFieldSerde}(\"${fieldName}\", ${columnRef(m2o, code`new ${KeySerde}(\"${otherTagName}\", \"${dbType}\")`, columnArgs(m2o, dbMetadata, code`() => ${otherEntity.metaName}`))}),\n immutable: false,\n ${maybeDefault(m2o)}\n }\n `;\n });\n\n dbMetadata.oneToManys.forEach((o2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, otherColumnName } = o2m;\n fields[fieldName] = code`\n {\n kind: \"o2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n ${maybeOrderBy(o2m)}\n ${maybeSoftDeletes(o2m)}\n }\n `;\n });\n\n dbMetadata.largeOneToManys.forEach((o2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, otherColumnName } = o2m;\n fields[fieldName] = code`\n {\n kind: \"lo2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n }\n `;\n });\n\n dbMetadata.manyToManys.forEach((m2m) => {\n const { fieldName, singularName, otherEntity, otherFieldName, derived } = m2m;\n fields[fieldName] = code`\n {\n kind: \"m2m\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${singularName}Ids\",\n required: false,\n derived: ${derived === \"async\" ? `\"async\"` : derived === \"otherSide\" ? `\"otherSide\"` : \"false\"},\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n serde: undefined,\n immutable: false,\n joinTableName: \"${m2m.joinTableName}\",\n columnNames: [\"${m2m.columnName}\", \"${m2m.otherColumnName}\"],\n hasJoinTableId: ${m2m.hasJoinTableId},\n ${maybeSoftDeletes(m2m)}\n }\n `;\n });\n\n dbMetadata.manyToManyEnums.forEach((m2m) => {\n const { fieldName, enumDetailType } = m2m;\n fields[fieldName] = code`\n {\n kind: \"m2mEnum\",\n fieldName: \"${fieldName}\",\n fieldIdName: undefined,\n required: false,\n derived: false,\n enumDetailType: ${enumDetailType},\n serde: undefined,\n immutable: false,\n joinTableName: \"${m2m.joinTableName}\",\n columnNames: [\"${m2m.columnName}\", \"${m2m.otherColumnName}\"],\n hasJoinTableId: ${m2m.hasJoinTableId},\n }\n `;\n });\n\n dbMetadata.oneToOnes.forEach((o2o) => {\n const { fieldName, otherEntity, otherFieldName, otherColumnName } = o2o;\n fields[fieldName] = code`\n {\n kind: \"o2o\",\n fieldName: \"${fieldName}\",\n fieldIdName: \"${fieldName}Id\",\n required: false,\n otherMetadata: () => ${otherEntity.metaName},\n otherFieldName: \"${otherFieldName}\",\n otherColumnName: \"${otherColumnName}\",\n serde: undefined,\n immutable: false,\n }\n `;\n });\n\n dbMetadata.polymorphics.forEach((p) => {\n const { fieldName, notNull, components } = p;\n components.forEach((component) =>\n columnRef(\n component,\n code`new ${KeySerde}(\"${config.entities[component.otherEntity.name].tag}\", \"${dbMeta.entitiesByName[component.otherEntity.name].primaryKey.columnType}\")`,\n code`true, false, false, false, false, () => ${component.otherEntity.metaName}`,\n ),\n );\n fields[fieldName] = code`\n ${polymorphicField}(\"${fieldName}\", ${notNull}, [${components.map((component) => {\n const owner = dbMeta.entitiesByName[component.columnOwner.name];\n const physical = (owner.physicalMetadata ?? owner).polymorphics\n .flatMap((field) => field.components)\n .find((c) => c.columnName === component.columnName)!;\n const target =\n physical.otherEntity.name === component.otherEntity.name\n ? \"\"\n : code`, () => ${component.otherEntity.metaName}`;\n return code`new ${PolyComponent}(${columnRef(component)}, ${q(component.otherFieldName)}${target}),`;\n })}])\n `;\n });\n\n return fields;\n}\n\n/** Emits constructor arguments using codegen's existing column facts. */\nfunction columnArgs(\n column: Pick<PrimitiveField, \"columnNotNull\" | \"columnGenerated\"> & Partial<Pick<PrimitiveField, \"columnDefault\">>,\n meta: EntityDbMetadata,\n idMetadata?: Code,\n): Code {\n const insertOptional = column === meta.createdAt || column === meta.updatedAt;\n return code`${!column.columnNotNull}, ${column.columnDefault != null && !column.columnGenerated}, ${column.columnGenerated}, ${insertOptional}, true, ${idMetadata ?? \"undefined\"}`;\n}\n\n/** Declares all physical codecs before any domain metadata; ID targets remain lazy. */\nexport function generateColumnDeclarations(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code {\n if (meta.inheritanceType === \"sti\" && meta.baseClassName) return code``;\n const columns: Record<string, Code> = {};\n generateFields(config, dbMeta, meta.physicalMetadata ?? meta, (column, codec, args) => {\n const name = column.columnName;\n if (codec) columns[name] = code`new ${Column}(${q(name)}, ${args}, ${codec})`.asOneline();\n return code`${meta.entity.metaName}Columns[${q(name)}]`;\n });\n return code`const ${meta.entity.metaName}Columns = ${columns} satisfies ${ColumnDescriptors};`;\n}\n\n/** Emits a direct reference to the single physical descriptor. */\nfunction columnReference(column: Pick<PrimitiveField, \"columnName\" | \"columnOwner\">): Code {\n return code`${column.columnOwner.metaName}Columns[${q(column.columnName)}]`;\n}\n\nfunction maybeDefault(f: { hasConfigDefault: boolean; columnDefault?: number | boolean | string | null }): Code | \"\" {\n return f.hasConfigDefault ? code`default: \"config\",` : f.columnDefault != null ? code`default: \"schema\",` : \"\";\n}\n\nfunction maybeOrderBy(f: OneToManyField): Code | \"\" {\n return f.orderBy ? code`orderBy: { field: \"${f.orderBy.field}\", direction: \"${f.orderBy.direction}\" },` : \"\";\n}\n\n/** Emits the `softDeletes` config, i.e. `softDeletes: \"include\",`, for relations that opt out of hiding soft-deletes. */\nfunction maybeSoftDeletes(f: { softDeletes: \"include\" | \"exclude\" | undefined }): Code | \"\" {\n return f.softDeletes ? code`softDeletes: \"${f.softDeletes}\",` : \"\";\n}\n\n/** We sanitize/cleanStringValue all varchars, unless opted out by the column default/arrays/custom serdes. */\nfunction maybeSanitize(\n config: Config,\n f: { columnType: DatabaseColumnType; columnDefault?: any; isArray: boolean; customSerde: any },\n): Code | \"\" {\n // Only strings need to maybe turn off their cleanStringValue sanitization, if the default=\"\" or its an array\n return isString(config, f.columnType) && (f.columnDefault === \"''\" || f.isArray || f.customSerde)\n ? code`sanitize: false,`\n : \"\";\n}\n\nfunction isString(config: Config, columnType: DatabaseColumnType): boolean {\n return mapSimpleDbTypeToTypescriptType(config, columnType) === \"string\";\n}\n"],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import { DbMetadata, EntityDbMetadata } from "./EntityDbMetadata.cjs";
|
|
|
3
3
|
import { Code } from "ts-poet";
|
|
4
4
|
//#region src/generateMetadataFile.d.ts
|
|
5
5
|
declare function generateMetadataFile(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code;
|
|
6
|
+
/** Declares all physical codecs before any domain metadata; ID targets remain lazy. */
|
|
7
|
+
declare function generateColumnDeclarations(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code;
|
|
6
8
|
//#endregion
|
|
7
|
-
export { generateMetadataFile };
|
|
9
|
+
export { generateColumnDeclarations, generateMetadataFile };
|
|
8
10
|
//# sourceMappingURL=generateMetadataFile.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateMetadataFile.d.cts","names":[],"sources":["../src/generateMetadataFile.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"generateMetadataFile.d.cts","names":[],"sources":["../src/generateMetadataFile.ts"],"mappings":";;;;iBAmCgB,qBAAqB,QAAQ,QAAQ,QAAQ,YAAY,MAAM,mBAAmB;;iBA2UlF,2BAA2B,QAAQ,QAAQ,QAAQ,YAAY,MAAM,mBAAmB"}
|
|
@@ -3,6 +3,8 @@ import { DbMetadata, EntityDbMetadata } from "./EntityDbMetadata.mjs";
|
|
|
3
3
|
import { Code } from "ts-poet";
|
|
4
4
|
//#region src/generateMetadataFile.d.ts
|
|
5
5
|
declare function generateMetadataFile(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code;
|
|
6
|
+
/** Declares all physical codecs before any domain metadata; ID targets remain lazy. */
|
|
7
|
+
declare function generateColumnDeclarations(config: Config, dbMeta: DbMetadata, meta: EntityDbMetadata): Code;
|
|
6
8
|
//#endregion
|
|
7
|
-
export { generateMetadataFile };
|
|
9
|
+
export { generateColumnDeclarations, generateMetadataFile };
|
|
8
10
|
//# sourceMappingURL=generateMetadataFile.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateMetadataFile.d.mts","names":[],"sources":["../src/generateMetadataFile.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"generateMetadataFile.d.mts","names":[],"sources":["../src/generateMetadataFile.ts"],"mappings":";;;;iBAmCgB,qBAAqB,QAAQ,QAAQ,QAAQ,YAAY,MAAM,mBAAmB;;iBA2UlF,2BAA2B,QAAQ,QAAQ,QAAQ,YAAY,MAAM,mBAAmB"}
|
|
@@ -1,26 +1,12 @@
|
|
|
1
1
|
import { mapSimpleDbTypeToTypescriptType, q } from "./utils.js";
|
|
2
2
|
import "./config.js";
|
|
3
|
-
import { BigIntSerde, CustomSerdeAdapter, DateSerde, DecimalToNumberSerde, EntityMetadata, EnumArrayFieldSerde, EnumFieldSerde, JsonSerde, KeySerde, PlainDateSerde, PlainDateTimeSerde, PlainTimeSerde,
|
|
3
|
+
import { BigIntSerde, Column, ColumnDescriptors, CustomSerdeAdapter, DateSerde, DecimalToNumberSerde, EntityMetadata, EnumArrayFieldSerde, EnumFieldSerde, JsonSerde, KeySerde, PlainDateSerde, PlainDateTimeSerde, PlainTimeSerde, PolyComponent, PrimitiveSerde, SimpleFieldSerde, SuperstructSerde, ZodSerde, ZonedDateTimeSerde, polymorphicField } from "./symbols.js";
|
|
4
4
|
import "./EntityDbMetadata.js";
|
|
5
5
|
import { code, imp } from "ts-poet";
|
|
6
6
|
//#region src/generateMetadataFile.ts
|
|
7
7
|
function generateMetadataFile(config, dbMeta, meta) {
|
|
8
8
|
const { entity, createdAt, updatedAt, deletedAt } = meta;
|
|
9
|
-
const fields = generateFields(config, meta);
|
|
10
|
-
const physical = meta.physicalMetadata ?? meta;
|
|
11
|
-
const sharedTable = meta.inheritanceType === "sti" && meta.baseClassName;
|
|
12
|
-
const storageFields = generateFields(config, physical, true);
|
|
13
|
-
const physicalFields = Object.fromEntries(Object.entries(storageFields).map(([name, field]) => [name, fields[name]?.toString() === field.toString() ? code`${entity.metaName}.fields[${q(name)}]` : field]));
|
|
14
|
-
const columns = Object.fromEntries([
|
|
15
|
-
["id", "id"],
|
|
16
|
-
...[
|
|
17
|
-
...physical.primitives,
|
|
18
|
-
...physical.enums,
|
|
19
|
-
...physical.pgEnums,
|
|
20
|
-
...physical.manyToOnes
|
|
21
|
-
].map((field) => [field.columnName, field.fieldName]),
|
|
22
|
-
...physical.polymorphics.flatMap((field) => field.components.map((component) => [component.columnName, field.fieldName]))
|
|
23
|
-
]);
|
|
9
|
+
const fields = generateFields(config, dbMeta, meta, columnReference);
|
|
24
10
|
Object.values(fields).forEach((code) => code.asOneline());
|
|
25
11
|
const maybeBaseType = meta.baseClassName ? `"${meta.baseClassName}"` : void 0;
|
|
26
12
|
const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: "${meta.inheritanceType}",` : "";
|
|
@@ -48,7 +34,7 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
48
34
|
tableName: "${meta.tableName}",
|
|
49
35
|
supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},
|
|
50
36
|
fields: ${fields},
|
|
51
|
-
columns: {},
|
|
37
|
+
columns: ${meta.primaryKey.columnOwner.metaName}Columns,
|
|
52
38
|
allFields: {},
|
|
53
39
|
orderBy: ${q(config.entities[meta.name]?.orderBy)},
|
|
54
40
|
timestampFields: ${maybeTimestampConfig},
|
|
@@ -58,14 +44,6 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
58
44
|
subTypes: [], ${maybeInsertionOrder} ${maybeUniqueBy}
|
|
59
45
|
};
|
|
60
46
|
|
|
61
|
-
${sharedTable ? "" : code`
|
|
62
|
-
${Object.entries(columns).map(([columnName, fieldName]) => {
|
|
63
|
-
const firstColumn = Object.keys(columns).find((name) => columns[name] === fieldName);
|
|
64
|
-
const field = firstColumn === columnName ? physicalFields[fieldName] : code`${entity.metaName}.columns[${q(firstColumn)}].field`;
|
|
65
|
-
return code`${entity.metaName}.columns[${q(columnName)}] = { fieldName: ${q(fieldName)}, field: ${field} };`;
|
|
66
|
-
})}
|
|
67
|
-
`}
|
|
68
|
-
|
|
69
47
|
(${entity.typeForMetadataFile} as any).metadata = ${entity.metaName};
|
|
70
48
|
`;
|
|
71
49
|
}
|
|
@@ -80,8 +58,8 @@ function getUniqueBy(config, meta) {
|
|
|
80
58
|
return true;
|
|
81
59
|
});
|
|
82
60
|
}
|
|
83
|
-
/** Emits
|
|
84
|
-
function generateFields(config, dbMetadata,
|
|
61
|
+
/** Emits fields that bind the already-declared physical columns. */
|
|
62
|
+
function generateFields(config, dbMeta, dbMetadata, columnRef) {
|
|
85
63
|
const fields = {};
|
|
86
64
|
fields["id"] = code`
|
|
87
65
|
{
|
|
@@ -89,20 +67,20 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
89
67
|
fieldName: "id",
|
|
90
68
|
fieldIdName: undefined,
|
|
91
69
|
required: true,
|
|
92
|
-
serde: new ${
|
|
70
|
+
serde: new ${SimpleFieldSerde}("id", ${columnRef(dbMetadata.primaryKey, code`new ${KeySerde}("${dbMetadata.tagName}", "${dbMetadata.primaryKey.columnType}")`, columnArgs(dbMetadata.primaryKey, dbMetadata, code`() => ${dbMetadata.entity.metaName}`))}),
|
|
93
71
|
immutable: true,
|
|
94
72
|
}
|
|
95
73
|
`;
|
|
96
74
|
dbMetadata.primitives.forEach((p) => {
|
|
97
|
-
const { fieldName, derived,
|
|
98
|
-
const column =
|
|
75
|
+
const { fieldName, derived, columnType, superstruct, zodSchema, customSerde, isArray } = p;
|
|
76
|
+
const column = columnArgs(p, dbMetadata);
|
|
99
77
|
let serde;
|
|
100
|
-
if (customSerde) serde = isArray ? code`new ${CustomSerdeAdapter}(
|
|
101
|
-
else if (superstruct) serde = code`new ${SuperstructSerde}(
|
|
102
|
-
else if (zodSchema) serde = code`new ${ZodSerde}(
|
|
103
|
-
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? code`new ${DecimalToNumberSerde}(
|
|
104
|
-
else if (columnType === "jsonb") serde = code`new ${JsonSerde}(
|
|
105
|
-
else if (p.rawFieldType === "bigint") serde = isArray ? code`new ${BigIntSerde}(
|
|
78
|
+
if (customSerde) serde = isArray ? code`new ${CustomSerdeAdapter}( "${columnType}[]", ${customSerde}, true)` : code`new ${CustomSerdeAdapter}( "${columnType}", ${customSerde})`;
|
|
79
|
+
else if (superstruct) serde = code`new ${SuperstructSerde}( ${superstruct})`;
|
|
80
|
+
else if (zodSchema) serde = code`new ${ZodSerde}( ${zodSchema})`;
|
|
81
|
+
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? code`new ${DecimalToNumberSerde}(true)` : code`new ${DecimalToNumberSerde}()`;
|
|
82
|
+
else if (columnType === "jsonb") serde = code`new ${JsonSerde}()`;
|
|
83
|
+
else if (p.rawFieldType === "bigint") serde = isArray ? code`new ${BigIntSerde}(true)` : code`new ${BigIntSerde}()`;
|
|
106
84
|
else {
|
|
107
85
|
let serdeType;
|
|
108
86
|
if (columnType === "date") serdeType = config.temporal ? PlainDateSerde : DateSerde;
|
|
@@ -110,7 +88,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
110
88
|
else if (columnType === "timestamp with time zone") serdeType = config.temporal ? ZonedDateTimeSerde : DateSerde;
|
|
111
89
|
else if (columnType === "time without time zone") serdeType = config.temporal ? PlainTimeSerde : PrimitiveSerde;
|
|
112
90
|
else serdeType = PrimitiveSerde;
|
|
113
|
-
serde = isArray ? code`new ${serdeType}(
|
|
91
|
+
serde = isArray ? code`new ${serdeType}( "${columnType}[]", true)` : code`new ${serdeType}( "${columnType}")`;
|
|
114
92
|
}
|
|
115
93
|
const extras = columnType === "citext" ? code`citext: true,` : "";
|
|
116
94
|
fields[fieldName] = code`
|
|
@@ -122,7 +100,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
122
100
|
required: ${!derived && p.notNull},
|
|
123
101
|
protected: ${p.protected},
|
|
124
102
|
type: ${typeof p.rawFieldType === "string" ? `"${p.rawFieldType}"` : p.rawFieldType},
|
|
125
|
-
serde: ${serde},
|
|
103
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(p, serde, column)}),
|
|
126
104
|
immutable: false,
|
|
127
105
|
${p.lazy ? code`lazy: true,` : ""}
|
|
128
106
|
${extras}
|
|
@@ -131,7 +109,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
131
109
|
}`;
|
|
132
110
|
});
|
|
133
111
|
dbMetadata.pgEnums.forEach((p) => {
|
|
134
|
-
const {
|
|
112
|
+
const { fieldName, notNull, dbType } = p;
|
|
135
113
|
fields[fieldName] = code`
|
|
136
114
|
{
|
|
137
115
|
kind: "primitive",
|
|
@@ -141,16 +119,15 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
141
119
|
required: ${notNull},
|
|
142
120
|
protected: false,
|
|
143
121
|
type: "string",
|
|
144
|
-
serde: new ${
|
|
122
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(p, code`new ${PrimitiveSerde}("${dbType}")`, columnArgs(p, dbMetadata))}),
|
|
145
123
|
immutable: false,
|
|
146
124
|
${maybeDefault(p)}
|
|
147
125
|
}`;
|
|
148
126
|
});
|
|
149
127
|
dbMetadata.enums.forEach((field) => {
|
|
150
|
-
const { fieldName, enumDetailType, notNull, isArray,
|
|
128
|
+
const { fieldName, enumDetailType, notNull, isArray, columnType, derived } = field;
|
|
151
129
|
const serdeType = isArray ? EnumArrayFieldSerde : EnumFieldSerde;
|
|
152
130
|
const columnTypeWithArray = `${columnType}${isArray ? "[]" : ""}`;
|
|
153
|
-
const maybeIsNullable = isArray ? `, ${!notNull}` : "";
|
|
154
131
|
fields[fieldName] = code`
|
|
155
132
|
{
|
|
156
133
|
kind: "enum",
|
|
@@ -159,7 +136,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
159
136
|
required: ${notNull},
|
|
160
137
|
derived: ${!derived ? false : `"${derived}"`},
|
|
161
138
|
enumDetailType: ${enumDetailType},
|
|
162
|
-
serde: new ${
|
|
139
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(field, code`new ${serdeType}("${columnTypeWithArray}", ${enumDetailType})`, columnArgs(field, dbMetadata))}),
|
|
163
140
|
immutable: false,
|
|
164
141
|
${maybeDefault(field)}
|
|
165
142
|
}
|
|
@@ -168,6 +145,7 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
168
145
|
dbMetadata.manyToOnes.forEach((m2o) => {
|
|
169
146
|
const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;
|
|
170
147
|
const otherTagName = config.entities[otherEntity.name].tag;
|
|
148
|
+
const otherMetadata = (dbMetadata.physicalMetadata ?? dbMetadata).manyToOnes.find((field) => field.columnName === columnName)?.otherEntity.name === otherEntity.name ? code`${columnRef(m2o)}.idMetadata!` : code`() => ${otherEntity.metaName}`;
|
|
171
149
|
fields[fieldName] = code`
|
|
172
150
|
{
|
|
173
151
|
kind: "m2o",
|
|
@@ -175,9 +153,9 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
175
153
|
fieldIdName: "${fieldName}Id",
|
|
176
154
|
derived: ${!derived ? false : `"${derived}"`},
|
|
177
155
|
required: ${notNull},
|
|
178
|
-
otherMetadata:
|
|
156
|
+
otherMetadata: ${otherMetadata},
|
|
179
157
|
otherFieldName: "${otherFieldName}",
|
|
180
|
-
serde: new ${
|
|
158
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(m2o, code`new ${KeySerde}("${otherTagName}", "${dbType}")`, columnArgs(m2o, dbMetadata, code`() => ${otherEntity.metaName}`))}),
|
|
181
159
|
immutable: false,
|
|
182
160
|
${maybeDefault(m2o)}
|
|
183
161
|
}
|
|
@@ -273,28 +251,36 @@ function generateFields(config, dbMetadata, physical = false) {
|
|
|
273
251
|
});
|
|
274
252
|
dbMetadata.polymorphics.forEach((p) => {
|
|
275
253
|
const { fieldName, notNull, components } = p;
|
|
254
|
+
components.forEach((component) => columnRef(component, code`new ${KeySerde}("${config.entities[component.otherEntity.name].tag}", "${dbMeta.entitiesByName[component.otherEntity.name].primaryKey.columnType}")`, code`true, false, false, false, false, () => ${component.otherEntity.metaName}`));
|
|
276
255
|
fields[fieldName] = code`
|
|
277
|
-
{
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
components: [${components.map(({ otherFieldName, otherEntity, columnName }) => code`
|
|
283
|
-
{
|
|
284
|
-
otherMetadata: () => ${otherEntity.metaName},
|
|
285
|
-
otherFieldName: "${otherFieldName}",
|
|
286
|
-
columnName: "${columnName}",
|
|
287
|
-
},`)}],
|
|
288
|
-
serde: new ${PolymorphicKeySerde}(() => ${dbMetadata.entity.metaName}, "${fieldName}"${physical ? code`, ${q(components[0].columnName)}` : ""}),
|
|
289
|
-
immutable: false,
|
|
290
|
-
}
|
|
256
|
+
${polymorphicField}("${fieldName}", ${notNull}, [${components.map((component) => {
|
|
257
|
+
const owner = dbMeta.entitiesByName[component.columnOwner.name];
|
|
258
|
+
const target = (owner.physicalMetadata ?? owner).polymorphics.flatMap((field) => field.components).find((c) => c.columnName === component.columnName).otherEntity.name === component.otherEntity.name ? "" : code`, () => ${component.otherEntity.metaName}`;
|
|
259
|
+
return code`new ${PolyComponent}(${columnRef(component)}, ${q(component.otherFieldName)}${target}),`;
|
|
260
|
+
})}])
|
|
291
261
|
`;
|
|
292
262
|
});
|
|
293
263
|
return fields;
|
|
294
264
|
}
|
|
295
|
-
/** Emits constructor
|
|
296
|
-
function
|
|
297
|
-
|
|
265
|
+
/** Emits constructor arguments using codegen's existing column facts. */
|
|
266
|
+
function columnArgs(column, meta, idMetadata) {
|
|
267
|
+
const insertOptional = column === meta.createdAt || column === meta.updatedAt;
|
|
268
|
+
return code`${!column.columnNotNull}, ${column.columnDefault != null && !column.columnGenerated}, ${column.columnGenerated}, ${insertOptional}, true, ${idMetadata ?? "undefined"}`;
|
|
269
|
+
}
|
|
270
|
+
/** Declares all physical codecs before any domain metadata; ID targets remain lazy. */
|
|
271
|
+
function generateColumnDeclarations(config, dbMeta, meta) {
|
|
272
|
+
if (meta.inheritanceType === "sti" && meta.baseClassName) return code``;
|
|
273
|
+
const columns = {};
|
|
274
|
+
generateFields(config, dbMeta, meta.physicalMetadata ?? meta, (column, codec, args) => {
|
|
275
|
+
const name = column.columnName;
|
|
276
|
+
if (codec) columns[name] = code`new ${Column}(${q(name)}, ${args}, ${codec})`.asOneline();
|
|
277
|
+
return code`${meta.entity.metaName}Columns[${q(name)}]`;
|
|
278
|
+
});
|
|
279
|
+
return code`const ${meta.entity.metaName}Columns = ${columns} satisfies ${ColumnDescriptors};`;
|
|
280
|
+
}
|
|
281
|
+
/** Emits a direct reference to the single physical descriptor. */
|
|
282
|
+
function columnReference(column) {
|
|
283
|
+
return code`${column.columnOwner.metaName}Columns[${q(column.columnName)}]`;
|
|
298
284
|
}
|
|
299
285
|
function maybeDefault(f) {
|
|
300
286
|
return f.hasConfigDefault ? code`default: "config",` : f.columnDefault != null ? code`default: "schema",` : "";
|
|
@@ -314,6 +300,6 @@ function isString(config, columnType) {
|
|
|
314
300
|
return mapSimpleDbTypeToTypescriptType(config, columnType) === "string";
|
|
315
301
|
}
|
|
316
302
|
//#endregion
|
|
317
|
-
export { generateMetadataFile };
|
|
303
|
+
export { generateColumnDeclarations, generateMetadataFile };
|
|
318
304
|
|
|
319
305
|
//# sourceMappingURL=generateMetadataFile.js.map
|