joist-codegen 2.3.0-next.64 → 2.3.0-next.66
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 +2 -0
- package/build/EntityDbMetadata.d.cts.map +1 -1
- package/build/EntityDbMetadata.d.mts +2 -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 +13 -10
- 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 +13 -10
- package/build/generateEntityCodegenFile.js.map +1 -1
- package/build/generateMetadataFile.cjs +58 -44
- 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 +59 -46
- package/build/generateMetadataFile.js.map +1 -1
- package/build/inheritance.cjs +28 -0
- package/build/inheritance.cjs.map +1 -1
- package/build/inheritance.d.cts +1 -0
- package/build/inheritance.d.cts.map +1 -1
- package/build/inheritance.d.mts +1 -0
- package/build/inheritance.d.mts.map +1 -1
- package/build/inheritance.js +28 -0
- package/build/inheritance.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,7 +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);
|
|
10
|
+
const fields = generateFields(config, dbMeta, meta, (name) => columnReference(dbMeta, meta, name));
|
|
11
11
|
Object.values(fields).forEach((code) => code.asOneline());
|
|
12
12
|
const maybeBaseType = meta.baseClassName ? `"${meta.baseClassName}"` : void 0;
|
|
13
13
|
const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: "${meta.inheritanceType}",` : "";
|
|
@@ -35,16 +35,7 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
35
35
|
tableName: "${meta.tableName}",
|
|
36
36
|
supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},
|
|
37
37
|
fields: ${fields},
|
|
38
|
-
columns: ${
|
|
39
|
-
["id", { fieldName: "id" }],
|
|
40
|
-
...[
|
|
41
|
-
...meta.primitives,
|
|
42
|
-
...meta.enums,
|
|
43
|
-
...meta.pgEnums,
|
|
44
|
-
...meta.manyToOnes
|
|
45
|
-
].map((field) => [field.columnName, { fieldName: field.fieldName }]),
|
|
46
|
-
...meta.polymorphics.flatMap((field) => field.components.map((component) => [component.columnName, { fieldName: field.fieldName }]))
|
|
47
|
-
])},
|
|
38
|
+
columns: ${columnOwner(dbMeta, meta, "id").entity.metaName}Columns,
|
|
48
39
|
allFields: {},
|
|
49
40
|
orderBy: ${require_utils.q(config.entities[meta.name]?.orderBy)},
|
|
50
41
|
timestampFields: ${maybeTimestampConfig},
|
|
@@ -68,7 +59,8 @@ function getUniqueBy(config, meta) {
|
|
|
68
59
|
return true;
|
|
69
60
|
});
|
|
70
61
|
}
|
|
71
|
-
|
|
62
|
+
/** Emits fields that bind the already-declared physical columns. */
|
|
63
|
+
function generateFields(config, dbMeta, dbMetadata, columnRef) {
|
|
72
64
|
const fields = {};
|
|
73
65
|
fields["id"] = ts_poet.code`
|
|
74
66
|
{
|
|
@@ -76,20 +68,20 @@ function generateFields(config, dbMetadata) {
|
|
|
76
68
|
fieldName: "id",
|
|
77
69
|
fieldIdName: undefined,
|
|
78
70
|
required: true,
|
|
79
|
-
serde: new ${require_symbols.
|
|
71
|
+
serde: new ${require_symbols.SimpleFieldSerde}("id", ${columnRef("id", ts_poet.code`new ${require_symbols.KeySerde}("${dbMetadata.tagName}", "${dbMetadata.primaryKey.columnType}")`, columnArgs(dbMetadata.primaryKey, dbMetadata, ts_poet.code`() => ${dbMetadata.entity.metaName}`))}),
|
|
80
72
|
immutable: true,
|
|
81
73
|
}
|
|
82
74
|
`;
|
|
83
75
|
dbMetadata.primitives.forEach((p) => {
|
|
84
76
|
const { fieldName, derived, columnName, columnType, superstruct, zodSchema, customSerde, isArray } = p;
|
|
85
|
-
const column =
|
|
77
|
+
const column = columnArgs(p, dbMetadata);
|
|
86
78
|
let serde;
|
|
87
|
-
if (customSerde) serde = isArray ? ts_poet.code`new ${require_symbols.CustomSerdeAdapter}(
|
|
88
|
-
else if (superstruct) serde = ts_poet.code`new ${require_symbols.SuperstructSerde}(
|
|
89
|
-
else if (zodSchema) serde = ts_poet.code`new ${require_symbols.ZodSerde}(
|
|
90
|
-
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? ts_poet.code`new ${require_symbols.DecimalToNumberSerde}(
|
|
91
|
-
else if (columnType === "jsonb") serde = ts_poet.code`new ${require_symbols.JsonSerde}(
|
|
92
|
-
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}()`;
|
|
93
85
|
else {
|
|
94
86
|
let serdeType;
|
|
95
87
|
if (columnType === "date") serdeType = config.temporal ? require_symbols.PlainDateSerde : require_symbols.DateSerde;
|
|
@@ -97,7 +89,7 @@ function generateFields(config, dbMetadata) {
|
|
|
97
89
|
else if (columnType === "timestamp with time zone") serdeType = config.temporal ? require_symbols.ZonedDateTimeSerde : require_symbols.DateSerde;
|
|
98
90
|
else if (columnType === "time without time zone") serdeType = config.temporal ? require_symbols.PlainTimeSerde : require_symbols.PrimitiveSerde;
|
|
99
91
|
else serdeType = require_symbols.PrimitiveSerde;
|
|
100
|
-
serde = isArray ? ts_poet.code`new ${serdeType}(
|
|
92
|
+
serde = isArray ? ts_poet.code`new ${serdeType}( "${columnType}[]", true)` : ts_poet.code`new ${serdeType}( "${columnType}")`;
|
|
101
93
|
}
|
|
102
94
|
const extras = columnType === "citext" ? ts_poet.code`citext: true,` : "";
|
|
103
95
|
fields[fieldName] = ts_poet.code`
|
|
@@ -109,7 +101,7 @@ function generateFields(config, dbMetadata) {
|
|
|
109
101
|
required: ${!derived && p.notNull},
|
|
110
102
|
protected: ${p.protected},
|
|
111
103
|
type: ${typeof p.rawFieldType === "string" ? `"${p.rawFieldType}"` : p.rawFieldType},
|
|
112
|
-
serde: ${serde},
|
|
104
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, serde, column)}),
|
|
113
105
|
immutable: false,
|
|
114
106
|
${p.lazy ? ts_poet.code`lazy: true,` : ""}
|
|
115
107
|
${extras}
|
|
@@ -128,7 +120,7 @@ function generateFields(config, dbMetadata) {
|
|
|
128
120
|
required: ${notNull},
|
|
129
121
|
protected: false,
|
|
130
122
|
type: "string",
|
|
131
|
-
serde: new ${require_symbols.
|
|
123
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, ts_poet.code`new ${require_symbols.PrimitiveSerde}("${dbType}")`, columnArgs(p, dbMetadata))}),
|
|
132
124
|
immutable: false,
|
|
133
125
|
${maybeDefault(p)}
|
|
134
126
|
}`;
|
|
@@ -137,7 +129,6 @@ function generateFields(config, dbMetadata) {
|
|
|
137
129
|
const { fieldName, enumDetailType, notNull, isArray, columnName, columnType, derived } = field;
|
|
138
130
|
const serdeType = isArray ? require_symbols.EnumArrayFieldSerde : require_symbols.EnumFieldSerde;
|
|
139
131
|
const columnTypeWithArray = `${columnType}${isArray ? "[]" : ""}`;
|
|
140
|
-
const maybeIsNullable = isArray ? `, ${!notNull}` : "";
|
|
141
132
|
fields[fieldName] = ts_poet.code`
|
|
142
133
|
{
|
|
143
134
|
kind: "enum",
|
|
@@ -146,7 +137,7 @@ function generateFields(config, dbMetadata) {
|
|
|
146
137
|
required: ${notNull},
|
|
147
138
|
derived: ${!derived ? false : `"${derived}"`},
|
|
148
139
|
enumDetailType: ${enumDetailType},
|
|
149
|
-
serde: new ${
|
|
140
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, ts_poet.code`new ${serdeType}("${columnTypeWithArray}", ${enumDetailType})`, columnArgs(field, dbMetadata))}),
|
|
150
141
|
immutable: false,
|
|
151
142
|
${maybeDefault(field)}
|
|
152
143
|
}
|
|
@@ -155,6 +146,7 @@ function generateFields(config, dbMetadata) {
|
|
|
155
146
|
dbMetadata.manyToOnes.forEach((m2o) => {
|
|
156
147
|
const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;
|
|
157
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(columnName)}.idMetadata!` : ts_poet.code`() => ${otherEntity.metaName}`;
|
|
158
150
|
fields[fieldName] = ts_poet.code`
|
|
159
151
|
{
|
|
160
152
|
kind: "m2o",
|
|
@@ -162,9 +154,9 @@ function generateFields(config, dbMetadata) {
|
|
|
162
154
|
fieldIdName: "${fieldName}Id",
|
|
163
155
|
derived: ${!derived ? false : `"${derived}"`},
|
|
164
156
|
required: ${notNull},
|
|
165
|
-
otherMetadata:
|
|
157
|
+
otherMetadata: ${otherMetadata},
|
|
166
158
|
otherFieldName: "${otherFieldName}",
|
|
167
|
-
serde: new ${require_symbols.
|
|
159
|
+
serde: new ${require_symbols.SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, ts_poet.code`new ${require_symbols.KeySerde}("${otherTagName}", "${dbType}")`, columnArgs(m2o, dbMetadata, ts_poet.code`() => ${otherEntity.metaName}`))}),
|
|
168
160
|
immutable: false,
|
|
169
161
|
${maybeDefault(m2o)}
|
|
170
162
|
}
|
|
@@ -260,28 +252,49 @@ function generateFields(config, dbMetadata) {
|
|
|
260
252
|
});
|
|
261
253
|
dbMetadata.polymorphics.forEach((p) => {
|
|
262
254
|
const { fieldName, notNull, components } = p;
|
|
255
|
+
components.forEach((component) => columnRef(component.columnName, 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}`));
|
|
263
256
|
fields[fieldName] = ts_poet.code`
|
|
264
|
-
{
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
components: [${components.map(({ otherFieldName, otherEntity, columnName }) => ts_poet.code`
|
|
270
|
-
{
|
|
271
|
-
otherMetadata: () => ${otherEntity.metaName},
|
|
272
|
-
otherFieldName: "${otherFieldName}",
|
|
273
|
-
columnName: "${columnName}",
|
|
274
|
-
},`)}],
|
|
275
|
-
serde: new ${require_symbols.PolymorphicKeySerde}(() => ${dbMetadata.entity.metaName}, "${fieldName}"),
|
|
276
|
-
immutable: false,
|
|
277
|
-
}
|
|
257
|
+
${require_symbols.polymorphicField}("${fieldName}", ${notNull}, [${components.map((component) => {
|
|
258
|
+
const owner = columnOwner(dbMeta, dbMetadata, component.columnName);
|
|
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.columnName)}, ${require_utils.q(component.otherFieldName)}${target}),`;
|
|
261
|
+
})}])
|
|
278
262
|
`;
|
|
279
263
|
});
|
|
280
264
|
return fields;
|
|
281
265
|
}
|
|
282
|
-
/** Emits constructor
|
|
283
|
-
function
|
|
284
|
-
|
|
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, (name, codec, args) => {
|
|
276
|
+
if (codec) columns[name] = ts_poet.code`new ${require_symbols.Column}(${require_utils.q(name)}, ${args}, ${codec})`.asOneline();
|
|
277
|
+
return ts_poet.code`${meta.entity.metaName}Columns[${require_utils.q(name)}]`;
|
|
278
|
+
});
|
|
279
|
+
return ts_poet.code`const ${meta.entity.metaName}Columns = ${columns} satisfies ${require_symbols.ColumnDescriptors};`;
|
|
280
|
+
}
|
|
281
|
+
/** Locates a column's physical table without copying inherited columns into subtype tables. */
|
|
282
|
+
function columnOwner(dbMeta, meta, name) {
|
|
283
|
+
if (meta.inheritanceType === "sti" && meta.baseClassName) return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);
|
|
284
|
+
const physical = meta.physicalMetadata ?? meta;
|
|
285
|
+
if (name === "id" || [
|
|
286
|
+
...physical.primitives,
|
|
287
|
+
...physical.enums,
|
|
288
|
+
...physical.pgEnums,
|
|
289
|
+
...physical.manyToOnes,
|
|
290
|
+
...physical.polymorphics.flatMap((field) => field.components)
|
|
291
|
+
].some((field) => field.columnName === name)) return meta;
|
|
292
|
+
if (meta.baseClassName) return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);
|
|
293
|
+
throw new Error(`No physical column ${meta.name}.${name}`);
|
|
294
|
+
}
|
|
295
|
+
/** Emits a direct reference to the single physical descriptor. */
|
|
296
|
+
function columnReference(dbMeta, meta, name) {
|
|
297
|
+
return ts_poet.code`${columnOwner(dbMeta, meta, name).entity.metaName}Columns[${require_utils.q(name)}]`;
|
|
285
298
|
}
|
|
286
299
|
function maybeDefault(f) {
|
|
287
300
|
return f.hasConfigDefault ? ts_poet.code`default: "config",` : f.columnDefault != null ? ts_poet.code`default: "schema",` : "";
|
|
@@ -301,6 +314,7 @@ function isString(config, columnType) {
|
|
|
301
314
|
return require_utils.mapSimpleDbTypeToTypescriptType(config, columnType) === "string";
|
|
302
315
|
}
|
|
303
316
|
//#endregion
|
|
317
|
+
exports.generateColumnDeclarations = generateColumnDeclarations;
|
|
304
318
|
exports.generateMetadataFile = generateMetadataFile;
|
|
305
319
|
|
|
306
320
|
//# 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\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: ${Object.fromEntries([\n [\"id\", { fieldName: \"id\" }],\n ...[...meta.primitives, ...meta.enums, ...meta.pgEnums, ...meta.manyToOnes].map((field) => [\n field.columnName,\n { fieldName: field.fieldName },\n ]),\n ...meta.polymorphics.flatMap((field) =>\n field.components.map((component) => [component.columnName, { fieldName: field.fieldName }]),\n ),\n ])},\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\nfunction generateFields(config: Config, dbMetadata: EntityDbMetadata): 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}\"),\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, (name) => columnReference(dbMeta, meta, name));\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: ${columnOwner(dbMeta, meta, \"id\").entity.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: (name: string, 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(\"id\", 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, columnName, 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(columnName, 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 { 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 ${SimpleFieldSerde}(\"${fieldName}\", ${columnRef(columnName, 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, columnName, 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(columnName, 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(columnName)}.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(columnName, 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.columnName,\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 = columnOwner(dbMeta, dbMetadata, component.columnName);\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.columnName)}, ${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, (name, codec, args) => {\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/** Locates a column's physical table without copying inherited columns into subtype tables. */\nfunction columnOwner(dbMeta: DbMetadata, meta: EntityDbMetadata, name: string): EntityDbMetadata {\n if (meta.inheritanceType === \"sti\" && meta.baseClassName) {\n return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);\n }\n const physical = meta.physicalMetadata ?? meta;\n if (\n name === \"id\" ||\n [\n ...physical.primitives,\n ...physical.enums,\n ...physical.pgEnums,\n ...physical.manyToOnes,\n ...physical.polymorphics.flatMap((field) => field.components),\n ].some((field) => field.columnName === name)\n )\n return meta;\n if (meta.baseClassName) return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);\n throw new Error(`No physical column ${meta.name}.${name}`);\n}\n\n/** Emits a direct reference to the single physical descriptor. */\nfunction columnReference(dbMeta: DbMetadata, meta: EntityDbMetadata, name: string): Code {\n return code`${columnOwner(dbMeta, meta, name).entity.metaName}Columns[${q(name)}]`;\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,12 +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);
|
|
9
|
+
const fields = generateFields(config, dbMeta, meta, (name) => columnReference(dbMeta, meta, name));
|
|
10
10
|
Object.values(fields).forEach((code) => code.asOneline());
|
|
11
11
|
const maybeBaseType = meta.baseClassName ? `"${meta.baseClassName}"` : void 0;
|
|
12
12
|
const maybeInheritanceType = meta.inheritanceType ? `inheritanceType: "${meta.inheritanceType}",` : "";
|
|
@@ -34,16 +34,7 @@ function generateMetadataFile(config, dbMeta, meta) {
|
|
|
34
34
|
tableName: "${meta.tableName}",
|
|
35
35
|
supportsEmExecute: ${!meta.inheritanceType && meta.supportsEmExecute === true},
|
|
36
36
|
fields: ${fields},
|
|
37
|
-
columns: ${
|
|
38
|
-
["id", { fieldName: "id" }],
|
|
39
|
-
...[
|
|
40
|
-
...meta.primitives,
|
|
41
|
-
...meta.enums,
|
|
42
|
-
...meta.pgEnums,
|
|
43
|
-
...meta.manyToOnes
|
|
44
|
-
].map((field) => [field.columnName, { fieldName: field.fieldName }]),
|
|
45
|
-
...meta.polymorphics.flatMap((field) => field.components.map((component) => [component.columnName, { fieldName: field.fieldName }]))
|
|
46
|
-
])},
|
|
37
|
+
columns: ${columnOwner(dbMeta, meta, "id").entity.metaName}Columns,
|
|
47
38
|
allFields: {},
|
|
48
39
|
orderBy: ${q(config.entities[meta.name]?.orderBy)},
|
|
49
40
|
timestampFields: ${maybeTimestampConfig},
|
|
@@ -67,7 +58,8 @@ function getUniqueBy(config, meta) {
|
|
|
67
58
|
return true;
|
|
68
59
|
});
|
|
69
60
|
}
|
|
70
|
-
|
|
61
|
+
/** Emits fields that bind the already-declared physical columns. */
|
|
62
|
+
function generateFields(config, dbMeta, dbMetadata, columnRef) {
|
|
71
63
|
const fields = {};
|
|
72
64
|
fields["id"] = code`
|
|
73
65
|
{
|
|
@@ -75,20 +67,20 @@ function generateFields(config, dbMetadata) {
|
|
|
75
67
|
fieldName: "id",
|
|
76
68
|
fieldIdName: undefined,
|
|
77
69
|
required: true,
|
|
78
|
-
serde: new ${
|
|
70
|
+
serde: new ${SimpleFieldSerde}("id", ${columnRef("id", code`new ${KeySerde}("${dbMetadata.tagName}", "${dbMetadata.primaryKey.columnType}")`, columnArgs(dbMetadata.primaryKey, dbMetadata, code`() => ${dbMetadata.entity.metaName}`))}),
|
|
79
71
|
immutable: true,
|
|
80
72
|
}
|
|
81
73
|
`;
|
|
82
74
|
dbMetadata.primitives.forEach((p) => {
|
|
83
75
|
const { fieldName, derived, columnName, columnType, superstruct, zodSchema, customSerde, isArray } = p;
|
|
84
|
-
const column =
|
|
76
|
+
const column = columnArgs(p, dbMetadata);
|
|
85
77
|
let serde;
|
|
86
|
-
if (customSerde) serde = isArray ? code`new ${CustomSerdeAdapter}(
|
|
87
|
-
else if (superstruct) serde = code`new ${SuperstructSerde}(
|
|
88
|
-
else if (zodSchema) serde = code`new ${ZodSerde}(
|
|
89
|
-
else if (columnType === "numeric" || columnType === "decimal") serde = isArray ? code`new ${DecimalToNumberSerde}(
|
|
90
|
-
else if (columnType === "jsonb") serde = code`new ${JsonSerde}(
|
|
91
|
-
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}()`;
|
|
92
84
|
else {
|
|
93
85
|
let serdeType;
|
|
94
86
|
if (columnType === "date") serdeType = config.temporal ? PlainDateSerde : DateSerde;
|
|
@@ -96,7 +88,7 @@ function generateFields(config, dbMetadata) {
|
|
|
96
88
|
else if (columnType === "timestamp with time zone") serdeType = config.temporal ? ZonedDateTimeSerde : DateSerde;
|
|
97
89
|
else if (columnType === "time without time zone") serdeType = config.temporal ? PlainTimeSerde : PrimitiveSerde;
|
|
98
90
|
else serdeType = PrimitiveSerde;
|
|
99
|
-
serde = isArray ? code`new ${serdeType}(
|
|
91
|
+
serde = isArray ? code`new ${serdeType}( "${columnType}[]", true)` : code`new ${serdeType}( "${columnType}")`;
|
|
100
92
|
}
|
|
101
93
|
const extras = columnType === "citext" ? code`citext: true,` : "";
|
|
102
94
|
fields[fieldName] = code`
|
|
@@ -108,7 +100,7 @@ function generateFields(config, dbMetadata) {
|
|
|
108
100
|
required: ${!derived && p.notNull},
|
|
109
101
|
protected: ${p.protected},
|
|
110
102
|
type: ${typeof p.rawFieldType === "string" ? `"${p.rawFieldType}"` : p.rawFieldType},
|
|
111
|
-
serde: ${serde},
|
|
103
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, serde, column)}),
|
|
112
104
|
immutable: false,
|
|
113
105
|
${p.lazy ? code`lazy: true,` : ""}
|
|
114
106
|
${extras}
|
|
@@ -127,7 +119,7 @@ function generateFields(config, dbMetadata) {
|
|
|
127
119
|
required: ${notNull},
|
|
128
120
|
protected: false,
|
|
129
121
|
type: "string",
|
|
130
|
-
serde: new ${
|
|
122
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, code`new ${PrimitiveSerde}("${dbType}")`, columnArgs(p, dbMetadata))}),
|
|
131
123
|
immutable: false,
|
|
132
124
|
${maybeDefault(p)}
|
|
133
125
|
}`;
|
|
@@ -136,7 +128,6 @@ function generateFields(config, dbMetadata) {
|
|
|
136
128
|
const { fieldName, enumDetailType, notNull, isArray, columnName, columnType, derived } = field;
|
|
137
129
|
const serdeType = isArray ? EnumArrayFieldSerde : EnumFieldSerde;
|
|
138
130
|
const columnTypeWithArray = `${columnType}${isArray ? "[]" : ""}`;
|
|
139
|
-
const maybeIsNullable = isArray ? `, ${!notNull}` : "";
|
|
140
131
|
fields[fieldName] = code`
|
|
141
132
|
{
|
|
142
133
|
kind: "enum",
|
|
@@ -145,7 +136,7 @@ function generateFields(config, dbMetadata) {
|
|
|
145
136
|
required: ${notNull},
|
|
146
137
|
derived: ${!derived ? false : `"${derived}"`},
|
|
147
138
|
enumDetailType: ${enumDetailType},
|
|
148
|
-
serde: new ${
|
|
139
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, code`new ${serdeType}("${columnTypeWithArray}", ${enumDetailType})`, columnArgs(field, dbMetadata))}),
|
|
149
140
|
immutable: false,
|
|
150
141
|
${maybeDefault(field)}
|
|
151
142
|
}
|
|
@@ -154,6 +145,7 @@ function generateFields(config, dbMetadata) {
|
|
|
154
145
|
dbMetadata.manyToOnes.forEach((m2o) => {
|
|
155
146
|
const { fieldName, columnName, notNull, otherEntity, otherFieldName, derived, dbType } = m2o;
|
|
156
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(columnName)}.idMetadata!` : code`() => ${otherEntity.metaName}`;
|
|
157
149
|
fields[fieldName] = code`
|
|
158
150
|
{
|
|
159
151
|
kind: "m2o",
|
|
@@ -161,9 +153,9 @@ function generateFields(config, dbMetadata) {
|
|
|
161
153
|
fieldIdName: "${fieldName}Id",
|
|
162
154
|
derived: ${!derived ? false : `"${derived}"`},
|
|
163
155
|
required: ${notNull},
|
|
164
|
-
otherMetadata:
|
|
156
|
+
otherMetadata: ${otherMetadata},
|
|
165
157
|
otherFieldName: "${otherFieldName}",
|
|
166
|
-
serde: new ${
|
|
158
|
+
serde: new ${SimpleFieldSerde}("${fieldName}", ${columnRef(columnName, code`new ${KeySerde}("${otherTagName}", "${dbType}")`, columnArgs(m2o, dbMetadata, code`() => ${otherEntity.metaName}`))}),
|
|
167
159
|
immutable: false,
|
|
168
160
|
${maybeDefault(m2o)}
|
|
169
161
|
}
|
|
@@ -259,28 +251,49 @@ function generateFields(config, dbMetadata) {
|
|
|
259
251
|
});
|
|
260
252
|
dbMetadata.polymorphics.forEach((p) => {
|
|
261
253
|
const { fieldName, notNull, components } = p;
|
|
254
|
+
components.forEach((component) => columnRef(component.columnName, 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}`));
|
|
262
255
|
fields[fieldName] = code`
|
|
263
|
-
{
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
components: [${components.map(({ otherFieldName, otherEntity, columnName }) => code`
|
|
269
|
-
{
|
|
270
|
-
otherMetadata: () => ${otherEntity.metaName},
|
|
271
|
-
otherFieldName: "${otherFieldName}",
|
|
272
|
-
columnName: "${columnName}",
|
|
273
|
-
},`)}],
|
|
274
|
-
serde: new ${PolymorphicKeySerde}(() => ${dbMetadata.entity.metaName}, "${fieldName}"),
|
|
275
|
-
immutable: false,
|
|
276
|
-
}
|
|
256
|
+
${polymorphicField}("${fieldName}", ${notNull}, [${components.map((component) => {
|
|
257
|
+
const owner = columnOwner(dbMeta, dbMetadata, component.columnName);
|
|
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.columnName)}, ${q(component.otherFieldName)}${target}),`;
|
|
260
|
+
})}])
|
|
277
261
|
`;
|
|
278
262
|
});
|
|
279
263
|
return fields;
|
|
280
264
|
}
|
|
281
|
-
/** Emits constructor
|
|
282
|
-
function
|
|
283
|
-
|
|
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, (name, codec, args) => {
|
|
275
|
+
if (codec) columns[name] = code`new ${Column}(${q(name)}, ${args}, ${codec})`.asOneline();
|
|
276
|
+
return code`${meta.entity.metaName}Columns[${q(name)}]`;
|
|
277
|
+
});
|
|
278
|
+
return code`const ${meta.entity.metaName}Columns = ${columns} satisfies ${ColumnDescriptors};`;
|
|
279
|
+
}
|
|
280
|
+
/** Locates a column's physical table without copying inherited columns into subtype tables. */
|
|
281
|
+
function columnOwner(dbMeta, meta, name) {
|
|
282
|
+
if (meta.inheritanceType === "sti" && meta.baseClassName) return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);
|
|
283
|
+
const physical = meta.physicalMetadata ?? meta;
|
|
284
|
+
if (name === "id" || [
|
|
285
|
+
...physical.primitives,
|
|
286
|
+
...physical.enums,
|
|
287
|
+
...physical.pgEnums,
|
|
288
|
+
...physical.manyToOnes,
|
|
289
|
+
...physical.polymorphics.flatMap((field) => field.components)
|
|
290
|
+
].some((field) => field.columnName === name)) return meta;
|
|
291
|
+
if (meta.baseClassName) return columnOwner(dbMeta, dbMeta.entitiesByName[meta.baseClassName], name);
|
|
292
|
+
throw new Error(`No physical column ${meta.name}.${name}`);
|
|
293
|
+
}
|
|
294
|
+
/** Emits a direct reference to the single physical descriptor. */
|
|
295
|
+
function columnReference(dbMeta, meta, name) {
|
|
296
|
+
return code`${columnOwner(dbMeta, meta, name).entity.metaName}Columns[${q(name)}]`;
|
|
284
297
|
}
|
|
285
298
|
function maybeDefault(f) {
|
|
286
299
|
return f.hasConfigDefault ? code`default: "config",` : f.columnDefault != null ? code`default: "schema",` : "";
|
|
@@ -300,6 +313,6 @@ function isString(config, columnType) {
|
|
|
300
313
|
return mapSimpleDbTypeToTypescriptType(config, columnType) === "string";
|
|
301
314
|
}
|
|
302
315
|
//#endregion
|
|
303
|
-
export { generateMetadataFile };
|
|
316
|
+
export { generateColumnDeclarations, generateMetadataFile };
|
|
304
317
|
|
|
305
318
|
//# sourceMappingURL=generateMetadataFile.js.map
|