@tstdl/base 0.93.1 → 0.93.2
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/audit/audit.model.d.ts +101 -6
- package/audit/audit.model.js +138 -4
- package/audit/auditor.d.ts +106 -30
- package/audit/auditor.js +80 -2
- package/audit/drizzle/0000_tiny_the_captain.sql +25 -0
- package/audit/drizzle/meta/0000_snapshot.json +188 -0
- package/audit/drizzle/meta/_journal.json +13 -0
- package/audit/drizzle.config.d.ts +2 -0
- package/audit/drizzle.config.js +11 -0
- package/audit/module.d.ts +22 -0
- package/audit/module.js +34 -0
- package/audit/schemas.d.ts +6 -0
- package/audit/schemas.js +8 -0
- package/authentication/models/index.d.ts +0 -1
- package/authentication/models/index.js +0 -1
- package/authentication/server/drizzle.config.js +1 -1
- package/authentication/server/index.d.ts +1 -0
- package/authentication/server/index.js +1 -0
- package/authentication/{models → server}/schemas.d.ts +2 -2
- package/authentication/{models → server}/schemas.js +2 -2
- package/orm/entity.d.ts +6 -0
- package/orm/entity.js +14 -0
- package/orm/server/drizzle/schema-converter.ts +408 -0
- package/package.json +5 -16
- package/orm/server/drizzle/index.js +0 -1
- package/orm/server/drizzle/schema-converter.d.ts +0 -15
- package/orm/server/drizzle/schema-converter.js +0 -300
- /package/orm/server/drizzle/{index.d.ts → index.ts} +0 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { toCamelCase, toSnakeCase } from 'drizzle-orm/casing';
|
|
2
|
+
import { boolean, check, doublePrecision, foreignKey, index, integer, jsonb, pgSchema, primaryKey, text, unique, uniqueIndex, uuid, type ExtraConfigColumn, type PgColumn, type PgColumnBuilder, type PgEnum, type PgSchema, type PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
3
|
+
|
|
4
|
+
import { MultiKeyMap } from '#/data-structures/multi-key-map.js';
|
|
5
|
+
import { tryGetEnumName } from '#/enumeration/enumeration.js';
|
|
6
|
+
import { NotSupportedError } from '#/errors/not-supported.error.js';
|
|
7
|
+
import { JsonPath } from '#/json-path/json-path.js';
|
|
8
|
+
import { reflectionRegistry, type TypeMetadata } from '#/reflection/registry.js';
|
|
9
|
+
import { ArraySchema, BooleanSchema, DefaultSchema, EnumerationSchema, getObjectSchema, NullableSchema, NumberSchema, ObjectSchema, OptionalSchema, StringSchema, Uint8ArraySchema, type Record, type Schema } from '#/schema/index.js';
|
|
10
|
+
import type { AbstractConstructor, Enumeration, EnumerationObject, Type } from '#/types/index.js';
|
|
11
|
+
import { compareByValueSelectionToOrder, orderRest } from '#/utils/comparison.js';
|
|
12
|
+
import { decodeText, encodeUtf8 } from '#/utils/encoding.js';
|
|
13
|
+
import { enumValues } from '#/utils/enum.js';
|
|
14
|
+
import { memoize, memoizeSingle } from '#/utils/function/memoize.js';
|
|
15
|
+
import { compileDereferencer } from '#/utils/object/dereference.js';
|
|
16
|
+
import { fromEntries, objectEntries } from '#/utils/object/object.js';
|
|
17
|
+
import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNullOrUndefined, isNull, isString, isUndefined } from '#/utils/type-guards.js';
|
|
18
|
+
import { bytea, numericDate, timestamp } from '../../data-types/index.js';
|
|
19
|
+
import type { IndexReflectionData, OrmColumnReflectionData, OrmTableReflectionData } from '../../decorators.js';
|
|
20
|
+
import type { EntityType } from '../../entity.js';
|
|
21
|
+
import { JsonSchema } from '../../schemas/json.js';
|
|
22
|
+
import { NumericDateSchema } from '../../schemas/numeric-date.js';
|
|
23
|
+
import { TimestampSchema } from '../../schemas/timestamp.js';
|
|
24
|
+
import { UuidSchema } from '../../schemas/uuid.js';
|
|
25
|
+
import { decryptBytes, encryptBytes } from '../encryption.js';
|
|
26
|
+
import { convertQuery } from '../query-converter.js';
|
|
27
|
+
import type { BuildTypeOptions, ColumnDefinition, ColumnDefinitionsMap, PgTableFromType, TransformContext } from '../types.js';
|
|
28
|
+
|
|
29
|
+
type ConverterContext = { type: AbstractConstructor, property: string };
|
|
30
|
+
|
|
31
|
+
const getDbSchema = memoizeSingle(pgSchema);
|
|
32
|
+
|
|
33
|
+
export const getDrizzleTableFromType = memoize(_getDrizzleTableFromType);
|
|
34
|
+
|
|
35
|
+
const columnDefinitionsSymbol = Symbol('columnDefinitions');
|
|
36
|
+
const columnDefinitionsMapSymbol = Symbol('columnDefinitionsMap');
|
|
37
|
+
|
|
38
|
+
export function getColumnDefinitions(table: PgTableWithColumns<any>): ColumnDefinition[] {
|
|
39
|
+
return (table as PgTableWithColumns<any> & { [columnDefinitionsSymbol]: ColumnDefinition[] })[columnDefinitionsSymbol];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getColumnDefinitionsMap(table: PgTableWithColumns<any>): ColumnDefinitionsMap {
|
|
43
|
+
return (table as PgTableWithColumns<any> & { [columnDefinitionsMapSymbol]: ColumnDefinitionsMap })[columnDefinitionsMapSymbol];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function _getDrizzleTableFromType<T extends EntityType, S extends string>(type: T, fallbackSchemaName?: S): PgTableFromType<T, S> {
|
|
47
|
+
const metadata = reflectionRegistry.getMetadata(type);
|
|
48
|
+
assertDefined(metadata, `Type ${type.name} does not have reflection metadata.`);
|
|
49
|
+
|
|
50
|
+
const tableReflectionDatas: OrmTableReflectionData[] = [];
|
|
51
|
+
|
|
52
|
+
for (let currentMetadata: TypeMetadata | undefined = metadata; isNotNullOrUndefined(currentMetadata?.parent); currentMetadata = reflectionRegistry.getMetadata(currentMetadata.parent)) {
|
|
53
|
+
const tableReflectionData = currentMetadata.data.tryGet<OrmTableReflectionData>('orm');
|
|
54
|
+
|
|
55
|
+
if (isDefined(tableReflectionData)) {
|
|
56
|
+
tableReflectionDatas.push(tableReflectionData);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const mergedTableReflectionData = tableReflectionDatas.reduceRight((merged, data) => ({ ...merged, ...data }), {});
|
|
61
|
+
|
|
62
|
+
const tableReflectionData = tableReflectionDatas[0];
|
|
63
|
+
const schema = assertDefinedPass(mergedTableReflectionData.schema ?? fallbackSchemaName, 'Table schema not provided');
|
|
64
|
+
const tableName = tableReflectionData?.name ?? getDefaultTableName(type);
|
|
65
|
+
|
|
66
|
+
const dbSchema = getDbSchema(schema);
|
|
67
|
+
const columnDefinitions = getPostgresColumnEntries(type, dbSchema, tableName);
|
|
68
|
+
const columnDefinitionsMap = new Map(columnDefinitions.map((column) => [column.objectPath.path, column]));
|
|
69
|
+
|
|
70
|
+
function getColumn(table: Record<string, ExtraConfigColumn>, propertyName: string): ExtraConfigColumn {
|
|
71
|
+
return assertDefinedPass(table[propertyName], `Property "${propertyName}" does not exist on ${type.name}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function buildIndex(table: Record<string, ExtraConfigColumn>, data: IndexReflectionData, columnName?: string) {
|
|
75
|
+
const columns = (data.columns ?? [columnName]).map((columnValue) => {
|
|
76
|
+
assertDefined(columnValue, 'Missing column name for index.');
|
|
77
|
+
|
|
78
|
+
const [columnName, columnOrder] = isString(columnValue) ? [columnValue] as const : columnValue;
|
|
79
|
+
const order = columnOrder ?? data.order ?? 'asc';
|
|
80
|
+
|
|
81
|
+
let column = getColumn(table, columnName);
|
|
82
|
+
column = column[order]() as ExtraConfigColumn;
|
|
83
|
+
|
|
84
|
+
if (data.options?.nulls == 'first') {
|
|
85
|
+
column = column.nullsFirst() as ExtraConfigColumn;
|
|
86
|
+
}
|
|
87
|
+
else if (data.options?.nulls == 'last') {
|
|
88
|
+
column = column.nullsLast() as ExtraConfigColumn;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return column;
|
|
92
|
+
}) as [ExtraConfigColumn, ...ExtraConfigColumn[]];
|
|
93
|
+
|
|
94
|
+
const indexFn = (data.options?.unique == true) ? uniqueIndex : index;
|
|
95
|
+
|
|
96
|
+
let builder = indexFn(data.options?.name ?? getIndexName(tableName, columns, { naming: data.options?.naming })).using(data.options?.using ?? 'btree', ...columns);
|
|
97
|
+
|
|
98
|
+
if (isDefined(data.options?.where)) {
|
|
99
|
+
const query = convertQuery(data.options.where(table as PgTableWithColumns<any> as PgTableFromType<EntityType<any>>), table as PgTableWithColumns<any> as PgTableFromType, columnDefinitionsMap);
|
|
100
|
+
builder = builder.where(query.inlineParams());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return builder;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function buildPrimaryKey(table: Record<string, ExtraConfigColumn>) {
|
|
107
|
+
const columns = primaryKeyColumnDefinitions.map((columnDefinition) => getColumn(table, columnDefinition.name)) as unknown as [PgColumn, ...PgColumn[]];
|
|
108
|
+
|
|
109
|
+
return primaryKey({
|
|
110
|
+
name: mergedTableReflectionData.compundPrimaryKeyName ?? getPrimaryKeyName(tableName, columns, { naming: mergedTableReflectionData.compundPrimaryKeyNaming }),
|
|
111
|
+
columns,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const primaryKeyColumnDefinitions = columnDefinitions.filter((columnDefinition) => columnDefinition.reflectionData?.primaryKey == true);
|
|
116
|
+
|
|
117
|
+
const skipPrimaryKey = primaryKeyColumnDefinitions.length > 1;
|
|
118
|
+
const columnEntries = columnDefinitions.map((entry) => [entry.name, entry.buildType({ skipPrimaryKey })]);
|
|
119
|
+
|
|
120
|
+
const drizzleSchema = dbSchema.table(
|
|
121
|
+
tableName,
|
|
122
|
+
fromEntries(columnEntries) as any,
|
|
123
|
+
(table) => [
|
|
124
|
+
...(
|
|
125
|
+
(primaryKeyColumnDefinitions.length > 1)
|
|
126
|
+
? [buildPrimaryKey(table)]
|
|
127
|
+
: []
|
|
128
|
+
),
|
|
129
|
+
...(
|
|
130
|
+
columnDefinitions.map((columnDefinition) => {
|
|
131
|
+
const indexData = columnDefinition.reflectionData?.index;
|
|
132
|
+
|
|
133
|
+
if (isUndefined(indexData)) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return buildIndex(table, indexData, columnDefinition.name);
|
|
138
|
+
}).filter(isDefined)
|
|
139
|
+
),
|
|
140
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => {
|
|
141
|
+
return tableReflectionData.foreignKeys?.map((foreignKeyData) => {
|
|
142
|
+
const foreignTable = getDrizzleTableFromType(foreignKeyData.target(), dbSchema.schemaName);
|
|
143
|
+
|
|
144
|
+
return foreignKey({
|
|
145
|
+
name: foreignKeyData.options?.name ?? getForeignKeyName(tableName, foreignKeyData.columns, { naming: foreignKeyData.options?.naming }),
|
|
146
|
+
columns: foreignKeyData.columns.map((column) => getColumn(table, column)) as [ExtraConfigColumn, ...ExtraConfigColumn[]],
|
|
147
|
+
foreignColumns: foreignKeyData.foreignColumns.map((column) => getColumn(foreignTable as any as Record<string, ExtraConfigColumn>, column)) as [ExtraConfigColumn, ...ExtraConfigColumn[]],
|
|
148
|
+
});
|
|
149
|
+
}) ?? [];
|
|
150
|
+
}),
|
|
151
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.unique).filter(isDefined).map((data) => {
|
|
152
|
+
const columns = data.columns?.map((column) => getColumn(table, column)) as [ExtraConfigColumn, ...ExtraConfigColumn[]];
|
|
153
|
+
|
|
154
|
+
let constraint = unique(data.options?.name ?? getUniqueName(tableName, columns, { naming: data.options?.naming })).on(...columns);
|
|
155
|
+
|
|
156
|
+
if (data.options?.nulls == 'not distinct') {
|
|
157
|
+
constraint = constraint.nullsNotDistinct();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return constraint;
|
|
161
|
+
}),
|
|
162
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.index).filter(isDefined).map((data) => buildIndex(table, data)),
|
|
163
|
+
...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.checks).filter(isDefined).map((data) => check(data.name, data.builder(table as PgTableWithColumns<any> as PgTableFromType<EntityType<any>>))),
|
|
164
|
+
]
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
(drizzleSchema as Record)[columnDefinitionsSymbol] = columnDefinitions;
|
|
168
|
+
(drizzleSchema as Record)[columnDefinitionsMapSymbol] = columnDefinitionsMap;
|
|
169
|
+
|
|
170
|
+
return drizzleSchema as any as PgTableFromType<T, S>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function getPostgresColumnEntries(type: AbstractConstructor, dbSchema: PgSchema, tableName: string, path = new JsonPath({ dollar: false }), prefix: string = ''): ColumnDefinition[] {
|
|
174
|
+
const metadata = reflectionRegistry.getMetadata(type);
|
|
175
|
+
assertDefined(metadata, `Type ${type.name} does not have reflection metadata (path: ${path.toString()}).`);
|
|
176
|
+
|
|
177
|
+
const objectSchema = getObjectSchema<Record<string>>(type);
|
|
178
|
+
|
|
179
|
+
const entries = objectEntries(objectSchema.properties).toSorted(compareByValueSelectionToOrder(['id', orderRest, 'metadata'], (item) => item[0])).flatMap(([property, schema]): ColumnDefinition[] => {
|
|
180
|
+
const columnReflectionData = metadata.properties.get(property)?.data.tryGet<OrmColumnReflectionData>('orm');
|
|
181
|
+
const columnName = columnReflectionData?.name ?? toSnakeCase(property);
|
|
182
|
+
|
|
183
|
+
if ((schema instanceof ObjectSchema) && !(schema instanceof JsonSchema)) {
|
|
184
|
+
const propertyMetadata = reflectionRegistry.getMetadata(type)?.properties.get(property);
|
|
185
|
+
assertDefined(propertyMetadata, `Property "${property}" of type "${type.name}" does not have reflection metadata (path: ${path.toString()}).`);
|
|
186
|
+
|
|
187
|
+
const propertyPrefix = columnReflectionData?.embedded?.prefix;
|
|
188
|
+
const nestedPrefix = [prefix, isNull(propertyPrefix) ? '' : propertyPrefix ?? `${columnName}_`].join('');
|
|
189
|
+
|
|
190
|
+
return getPostgresColumnEntries(columnReflectionData?.embedded?.type ?? propertyMetadata.type, dbSchema, tableName, path.add(property), nestedPrefix);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const objectPath = path.add(property);
|
|
194
|
+
|
|
195
|
+
const encrypted = columnReflectionData?.encrypted == true;
|
|
196
|
+
|
|
197
|
+
const toDatabase = encrypted
|
|
198
|
+
? async (value: unknown, context: TransformContext) => {
|
|
199
|
+
const bytes = encodeUtf8(value as string);
|
|
200
|
+
return await encryptBytes(bytes, context.encryptionKey!);
|
|
201
|
+
}
|
|
202
|
+
: (value: unknown) => value;
|
|
203
|
+
|
|
204
|
+
const fromDatabase = encrypted
|
|
205
|
+
? async (value: unknown, context: TransformContext) => {
|
|
206
|
+
const decrypted = await decryptBytes(value as Uint8Array, context.encryptionKey!);
|
|
207
|
+
return decodeText(decrypted);
|
|
208
|
+
}
|
|
209
|
+
: (value: unknown) => value;
|
|
210
|
+
|
|
211
|
+
const prefixedColumnName = [prefix, columnName].join('');
|
|
212
|
+
|
|
213
|
+
return [{
|
|
214
|
+
name: toCamelCase(prefixedColumnName),
|
|
215
|
+
objectPath,
|
|
216
|
+
reflectionData: columnReflectionData,
|
|
217
|
+
buildType: (options: BuildTypeOptions) => getPostgresColumn(tableName, toSnakeCase(prefixedColumnName), dbSchema, schema, columnReflectionData ?? {}, options, { type, property }),
|
|
218
|
+
dereferenceObjectPath: compileDereferencer(objectPath, { optional: true }),
|
|
219
|
+
toDatabase,
|
|
220
|
+
fromDatabase,
|
|
221
|
+
}];
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return entries;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function getPostgresColumn(tableName: string, columnName: string, dbSchema: PgSchema, propertySchema: Schema, reflectionData: OrmColumnReflectionData, options: BuildTypeOptions, context: ConverterContext): PgColumnBuilder<any, any, any, any> {
|
|
228
|
+
let nullable = false;
|
|
229
|
+
let array = false;
|
|
230
|
+
|
|
231
|
+
let baseSchema = propertySchema;
|
|
232
|
+
while (true) {
|
|
233
|
+
if ((baseSchema instanceof NullableSchema) || (baseSchema instanceof OptionalSchema)) {
|
|
234
|
+
nullable = true;
|
|
235
|
+
baseSchema = baseSchema.schema;
|
|
236
|
+
}
|
|
237
|
+
else if (baseSchema instanceof ArraySchema) {
|
|
238
|
+
array = true;
|
|
239
|
+
baseSchema = baseSchema.itemSchema;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let column = getPostgresBaseColumn(columnName, dbSchema, baseSchema, reflectionData, context);
|
|
247
|
+
|
|
248
|
+
if (array) {
|
|
249
|
+
column = column.array();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!nullable) {
|
|
253
|
+
column = column.notNull();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (isDefined(reflectionData.unique)) {
|
|
257
|
+
column = column.unique(reflectionData.unique.options?.name ?? getUniqueName(tableName, [columnName], { naming: reflectionData.unique.options?.naming }), isString(reflectionData.unique.options?.nulls) ? { nulls: reflectionData.unique.options.nulls } : undefined);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if ((reflectionData.primaryKey == true) && (options.skipPrimaryKey != true)) {
|
|
261
|
+
column = column.primaryKey();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
for (const { target, targetColumn } of reflectionData.references ?? []) {
|
|
265
|
+
column = column.references(() => {
|
|
266
|
+
const targetTable = getDrizzleTableFromType(target(), dbSchema.schemaName);
|
|
267
|
+
return targetTable[(targetColumn ?? 'id') as keyof PgTableFromType] as PgColumn;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (isDefined(reflectionData.references)) {
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return column;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getPostgresBaseColumn(columnName: string, dbSchema: PgSchema, schema: Schema, reflectionData: OrmColumnReflectionData, context: ConverterContext): PgColumnBuilder<any, any, any, any> {
|
|
278
|
+
if (schema instanceof DefaultSchema) {
|
|
279
|
+
const column = getPostgresBaseColumn(columnName, dbSchema, schema.schema, reflectionData, context);
|
|
280
|
+
return column.default(schema.defaultValue);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (reflectionData.encrypted) {
|
|
284
|
+
return bytea(columnName);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (schema instanceof UuidSchema) {
|
|
288
|
+
let column = uuid(columnName);
|
|
289
|
+
|
|
290
|
+
if (schema.defaultRandom) {
|
|
291
|
+
column = column.defaultRandom();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return column;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (schema instanceof TimestampSchema) {
|
|
298
|
+
return timestamp(columnName);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (schema instanceof NumericDateSchema) {
|
|
302
|
+
return numericDate(columnName);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (schema instanceof NumberSchema) {
|
|
306
|
+
return schema.integer
|
|
307
|
+
? integer(columnName)
|
|
308
|
+
: doublePrecision(columnName);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (schema instanceof StringSchema) {
|
|
312
|
+
return text(columnName);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (schema instanceof BooleanSchema) {
|
|
316
|
+
return boolean(columnName);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (schema instanceof EnumerationSchema) {
|
|
320
|
+
const pgEnum = getPgEnum(dbSchema, schema.enumeration, context);
|
|
321
|
+
return pgEnum(columnName);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (schema instanceof JsonSchema) {
|
|
325
|
+
return jsonb(columnName);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (schema instanceof Uint8ArraySchema) {
|
|
329
|
+
return bytea(columnName);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
throw new NotSupportedError(`Schema "${schema.constructor.name}" not supported on type "${context.type.name}" for property "${context.property}"`);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const enumNames = new Map<Enumeration, string>();
|
|
336
|
+
const enums = new MultiKeyMap<[string, Enumeration], PgEnum<[string, ...string[]]>>();
|
|
337
|
+
|
|
338
|
+
export function registerEnum(enumeration: Enumeration, name: string): void {
|
|
339
|
+
enumNames.set(enumeration, toSnakeCase(name));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function getPgEnum(schema: string | PgSchema, enumeration: Enumeration, context?: ConverterContext): PgEnum<[string, ...string[]]> {
|
|
343
|
+
const dbSchema = isString(schema) ? getDbSchema(schema) : schema;
|
|
344
|
+
const enumName = enumNames.get(enumeration) ?? tryGetEnumName(enumeration as EnumerationObject);
|
|
345
|
+
|
|
346
|
+
if (isUndefined(enumName)) {
|
|
347
|
+
const errorMessage = 'Enum is not registered. Please register it using `databaseSchema.getEnum(MyEnum)` before use.';
|
|
348
|
+
|
|
349
|
+
if (isDefined(context)) {
|
|
350
|
+
throw new Error(`${errorMessage} (type: ${context.type.name}, property: ${context.property})`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
throw new Error(errorMessage);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const values = (isArray(enumeration) ? enumeration : enumValues(enumeration))
|
|
357
|
+
.map((value) => value.toString()) as [string, ...string[]];
|
|
358
|
+
|
|
359
|
+
const dbEnum = dbSchema.enum(toSnakeCase(enumName), values);
|
|
360
|
+
|
|
361
|
+
if (enums.has([dbSchema.schemaName, enumeration])) {
|
|
362
|
+
enums.set([dbSchema.schemaName, enumeration], dbEnum);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return dbEnum;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function getDefaultTableName(type: Type & Partial<Pick<EntityType, 'entityName'>>): string {
|
|
369
|
+
return toSnakeCase(isString(type.entityName) ? type.entityName : type.name.replace(/\d+$/u, ''));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function getPrimaryKeyName(tableName: string, columns: (string | PgColumn)[], options?: { naming?: 'abbreviated-table' }) {
|
|
373
|
+
return getIdentifier(tableName, columns, 'pk', options);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function getIndexName(tableName: string, columns: (string | PgColumn)[], options?: { naming?: 'abbreviated-table' }) {
|
|
377
|
+
return getIdentifier(tableName, columns, 'idx', options);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function getUniqueName(tableName: string, columns: (string | PgColumn)[], options?: { naming?: 'abbreviated-table' }) {
|
|
381
|
+
return getIdentifier(tableName, columns, 'unique', options);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function getForeignKeyName(tableName: string, columns: (string | PgColumn)[], options?: { naming?: 'abbreviated-table' }) {
|
|
385
|
+
return getIdentifier(tableName, columns, 'fkey', options);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function getIdentifier(tableName: string, columns: (string | PgColumn)[], suffix: string, options?: { naming?: 'abbreviated-table' }): string {
|
|
389
|
+
const identifier = `${getTablePrefix(tableName, options?.naming)}_${getColumnNames(columns).join('_')}_${suffix}`;
|
|
390
|
+
|
|
391
|
+
if (identifier.length > 63) {
|
|
392
|
+
if (options?.naming != 'abbreviated-table') {
|
|
393
|
+
return getIdentifier(tableName, columns, suffix, { naming: 'abbreviated-table' });
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
throw new Error(`Identifier "${identifier}" for table "${tableName}" is too long. Maximum length is 63 characters.`);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return identifier;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function getTablePrefix(tableName: string, naming?: 'abbreviated-table'): string {
|
|
403
|
+
return (naming == 'abbreviated-table') ? tableName.split('_').map((part) => part[0]).join('') : tableName;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function getColumnNames(columns: (string | PgColumn)[]): string[] {
|
|
407
|
+
return columns.map((column) => isString(column) ? column : column.name);
|
|
408
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.2",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -19,24 +19,12 @@
|
|
|
19
19
|
"tsc:watch": "tsc --watch",
|
|
20
20
|
"tsc-alias:watch": "tsc-alias --watch",
|
|
21
21
|
"cleanup:dist": "rm -vf dist/test* && rm -vrf dist/tools/",
|
|
22
|
-
"generate:migration": "
|
|
23
|
-
"generate:migration:document-management": "drizzle-kit generate --config dist/document-management/server/drizzle.config.js",
|
|
24
|
-
"generate:migration:authentication": "drizzle-kit generate --config dist/authentication/server/drizzle.config.js",
|
|
25
|
-
"generate:migration:mail": "drizzle-kit generate --config dist/mail/drizzle.config.js",
|
|
26
|
-
"generate:migration:queue": "drizzle-kit generate --config dist/queue/postgres/drizzle.config.js",
|
|
27
|
-
"generate:migration:key-value-store": "drizzle-kit generate --config dist/key-value-store/postgres/drizzle.config.js",
|
|
28
|
-
"generate:migration:lock": "drizzle-kit generate --config dist/lock/postgres/drizzle.config.js",
|
|
22
|
+
"generate:migration": "./scripts/manage-orm.sh generate",
|
|
29
23
|
"generate:readmes": "deno run --allow-run=code2prompt --allow-read --allow-write=source --allow-net=generativelanguage.googleapis.com --allow-env=GEMINI_API_KEY generate-readmes.ts",
|
|
30
24
|
"generate:readmes:new-only": "npm run generate:readmes -- --skip-existing",
|
|
31
25
|
"generate:llms.md": "npm run build:dts && npm run cleanup:dist && ./scripts/generate-llms-docs.sh",
|
|
32
26
|
"generate:context7-docs": "npm run build:dts && npm run cleanup:dist && ./scripts/generate-context7-docs.sh",
|
|
33
|
-
"copy:orm": "
|
|
34
|
-
"copy:orm:document-management": "rm -rf ./dist/document-management/server/drizzle && cp -r ./source/document-management/server/drizzle ./dist/document-management/server/",
|
|
35
|
-
"copy:orm:authentication": "rm -rf ./dist/authentication/server/drizzle && cp -r ./source/authentication/server/drizzle ./dist/authentication/server/",
|
|
36
|
-
"copy:orm:mail": "rm -rf ./dist/mail/drizzle && cp -r ./source/mail/drizzle ./dist/mail/",
|
|
37
|
-
"copy:orm:queue": "rm -rf ./dist/queue/postgres/drizzle && cp -r ./source/queue/postgres/drizzle ./dist/queue/postgres/",
|
|
38
|
-
"copy:orm:key-value-store": "rm -rf ./dist/key-value-store/postgres/drizzle && cp -r ./source/key-value-store/postgres/drizzle ./dist/key-value-store/postgres/",
|
|
39
|
-
"copy:orm:lock": "rm -rf ./dist/lock/postgres/drizzle && cp -r ./source/lock/postgres/drizzle ./dist/lock/postgres/"
|
|
27
|
+
"copy:orm": "./scripts/manage-orm.sh copy"
|
|
40
28
|
},
|
|
41
29
|
"exports": {
|
|
42
30
|
"./tsconfig.json": "./tsconfig.json",
|
|
@@ -52,6 +40,7 @@
|
|
|
52
40
|
"./api/client": "./api/client/index.js",
|
|
53
41
|
"./api/server": "./api/server/index.js",
|
|
54
42
|
"./application": "./application/index.js",
|
|
43
|
+
"./audit": "./audit/index.js",
|
|
55
44
|
"./authentication": "./authentication/index.js",
|
|
56
45
|
"./authentication/server": "./authentication/server/index.js",
|
|
57
46
|
"./browser": "./browser/index.js",
|
|
@@ -145,7 +134,7 @@
|
|
|
145
134
|
"peerDependencies": {
|
|
146
135
|
"@google-cloud/storage": "^7.17",
|
|
147
136
|
"@google/genai": "^1.19",
|
|
148
|
-
"@tstdl/angular": "^0.
|
|
137
|
+
"@tstdl/angular": "^0.93",
|
|
149
138
|
"@zxcvbn-ts/core": "^3.0",
|
|
150
139
|
"@zxcvbn-ts/language-common": "^3.0",
|
|
151
140
|
"@zxcvbn-ts/language-de": "^3.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './schema-converter.js';
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type PgEnum, type PgSchema, type PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
2
|
-
import type { AbstractConstructor, Enumeration } from '../../../types/index.js';
|
|
3
|
-
import type { EntityType } from '../../entity.js';
|
|
4
|
-
import type { ColumnDefinition, ColumnDefinitionsMap, PgTableFromType } from '../types.js';
|
|
5
|
-
type ConverterContext = {
|
|
6
|
-
type: AbstractConstructor;
|
|
7
|
-
property: string;
|
|
8
|
-
};
|
|
9
|
-
export declare const getDrizzleTableFromType: typeof _getDrizzleTableFromType;
|
|
10
|
-
export declare function getColumnDefinitions(table: PgTableWithColumns<any>): ColumnDefinition[];
|
|
11
|
-
export declare function getColumnDefinitionsMap(table: PgTableWithColumns<any>): ColumnDefinitionsMap;
|
|
12
|
-
export declare function _getDrizzleTableFromType<T extends EntityType, S extends string>(type: T, fallbackSchemaName?: S): PgTableFromType<T, S>;
|
|
13
|
-
export declare function registerEnum(enumeration: Enumeration, name: string): void;
|
|
14
|
-
export declare function getPgEnum(schema: string | PgSchema, enumeration: Enumeration, context?: ConverterContext): PgEnum<[string, ...string[]]>;
|
|
15
|
-
export {};
|