metal-orm 1.0.24 → 1.0.27
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/README.md +2 -0
- package/dist/decorators/index.cjs +91 -7
- package/dist/decorators/index.cjs.map +1 -1
- package/dist/decorators/index.d.cts +24 -7
- package/dist/decorators/index.d.ts +24 -7
- package/dist/decorators/index.js +91 -7
- package/dist/decorators/index.js.map +1 -1
- package/package.json +4 -1
- package/scripts/generate-entities.mjs +76 -6
- package/src/core/execution/executors/mssql-executor.ts +139 -0
- package/src/decorators/column.ts +38 -4
- package/src/decorators/decorator-metadata.ts +53 -0
- package/src/decorators/entity.ts +37 -4
- package/src/decorators/relations.ts +34 -4
- package/src/index.ts +5 -5
package/package.json
CHANGED
|
@@ -371,16 +371,86 @@ const renderEntityFile = (schema, options) => {
|
|
|
371
371
|
|
|
372
372
|
const relations = mapRelations(tables);
|
|
373
373
|
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
374
|
+
const usage = {
|
|
375
|
+
needsCol: false,
|
|
376
|
+
needsEntity: tables.length > 0,
|
|
377
|
+
needsColumnDecorator: false,
|
|
378
|
+
needsPrimaryKeyDecorator: false,
|
|
379
|
+
needsHasManyDecorator: false,
|
|
380
|
+
needsBelongsToDecorator: false,
|
|
381
|
+
needsBelongsToManyDecorator: false,
|
|
382
|
+
needsHasManyCollection: false,
|
|
383
|
+
needsManyToManyCollection: false
|
|
384
|
+
};
|
|
379
385
|
|
|
380
386
|
const lines = [];
|
|
381
387
|
lines.push('// AUTO-GENERATED by scripts/generate-entities.mjs');
|
|
382
388
|
lines.push('// Regenerate after schema changes.');
|
|
383
|
-
|
|
389
|
+
const imports = [];
|
|
390
|
+
|
|
391
|
+
for (const table of tables) {
|
|
392
|
+
for (const col of table.columns) {
|
|
393
|
+
usage.needsCol = true;
|
|
394
|
+
const rendered = renderColumnExpression(col, table.primaryKey);
|
|
395
|
+
if (rendered.decorator === 'PrimaryKey') {
|
|
396
|
+
usage.needsPrimaryKeyDecorator = true;
|
|
397
|
+
} else {
|
|
398
|
+
usage.needsColumnDecorator = true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const rels = relations.get(table.name) || [];
|
|
403
|
+
for (const rel of rels) {
|
|
404
|
+
if (rel.kind === 'hasMany') {
|
|
405
|
+
usage.needsHasManyDecorator = true;
|
|
406
|
+
usage.needsHasManyCollection = true;
|
|
407
|
+
}
|
|
408
|
+
if (rel.kind === 'belongsTo') {
|
|
409
|
+
usage.needsBelongsToDecorator = true;
|
|
410
|
+
}
|
|
411
|
+
if (rel.kind === 'belongsToMany') {
|
|
412
|
+
usage.needsBelongsToManyDecorator = true;
|
|
413
|
+
usage.needsManyToManyCollection = true;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (usage.needsCol) {
|
|
419
|
+
imports.push("import { col } from 'metal-orm';");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const decoratorSet = new Set(['bootstrapEntities', 'getTableDefFromEntity']);
|
|
423
|
+
if (usage.needsEntity) decoratorSet.add('Entity');
|
|
424
|
+
if (usage.needsColumnDecorator) decoratorSet.add('Column');
|
|
425
|
+
if (usage.needsPrimaryKeyDecorator) decoratorSet.add('PrimaryKey');
|
|
426
|
+
if (usage.needsHasManyDecorator) decoratorSet.add('HasMany');
|
|
427
|
+
if (usage.needsBelongsToDecorator) decoratorSet.add('BelongsTo');
|
|
428
|
+
if (usage.needsBelongsToManyDecorator) decoratorSet.add('BelongsToMany');
|
|
429
|
+
const decoratorOrder = [
|
|
430
|
+
'Entity',
|
|
431
|
+
'Column',
|
|
432
|
+
'PrimaryKey',
|
|
433
|
+
'HasMany',
|
|
434
|
+
'BelongsTo',
|
|
435
|
+
'BelongsToMany',
|
|
436
|
+
'bootstrapEntities',
|
|
437
|
+
'getTableDefFromEntity'
|
|
438
|
+
];
|
|
439
|
+
const decoratorImports = decoratorOrder.filter(name => decoratorSet.has(name));
|
|
440
|
+
if (decoratorImports.length) {
|
|
441
|
+
imports.push(`import { ${decoratorImports.join(', ')} } from 'metal-orm/decorators';`);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const ormTypes = [];
|
|
445
|
+
if (usage.needsHasManyCollection) ormTypes.push('HasManyCollection');
|
|
446
|
+
if (usage.needsManyToManyCollection) ormTypes.push('ManyToManyCollection');
|
|
447
|
+
if (ormTypes.length) {
|
|
448
|
+
imports.push(`import { ${ormTypes.join(', ')} } from 'metal-orm';`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (imports.length) {
|
|
452
|
+
lines.push(...imports, '');
|
|
453
|
+
}
|
|
384
454
|
|
|
385
455
|
for (const table of tables) {
|
|
386
456
|
const className = classNames.get(table.name);
|
|
@@ -37,3 +37,142 @@ export function createMssqlExecutor(
|
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Tedious integration helper (driver adapter)
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
export interface TediousColumn {
|
|
46
|
+
metadata: { colName: string };
|
|
47
|
+
value: unknown;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface TediousRequest {
|
|
51
|
+
addParameter(name: string, type: unknown, value: unknown): void;
|
|
52
|
+
on(event: 'row', listener: (columns: TediousColumn[]) => void): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TediousRequestCtor {
|
|
56
|
+
new (sql: string, callback: (err?: Error | null) => void): TediousRequest;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface TediousTypes {
|
|
60
|
+
NVarChar: unknown;
|
|
61
|
+
Int: unknown;
|
|
62
|
+
Float: unknown;
|
|
63
|
+
BigInt: unknown;
|
|
64
|
+
Bit: unknown;
|
|
65
|
+
DateTime: unknown;
|
|
66
|
+
VarBinary: unknown;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TediousModule {
|
|
71
|
+
Request: TediousRequestCtor;
|
|
72
|
+
TYPES: TediousTypes;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface TediousConnectionLike {
|
|
76
|
+
execSql(request: TediousRequest): void;
|
|
77
|
+
beginTransaction?(cb: (err?: Error | null) => void): void;
|
|
78
|
+
commitTransaction?(cb: (err?: Error | null) => void): void;
|
|
79
|
+
rollbackTransaction?(cb: (err?: Error | null) => void): void;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface CreateTediousClientOptions {
|
|
83
|
+
inferType?(value: unknown, TYPES: TediousTypes): unknown;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const defaultInferType = (value: unknown, TYPES: TediousTypes): unknown => {
|
|
87
|
+
if (value === null || value === undefined) return TYPES.NVarChar;
|
|
88
|
+
if (typeof value === 'number') {
|
|
89
|
+
return Number.isInteger(value) ? TYPES.Int : TYPES.Float;
|
|
90
|
+
}
|
|
91
|
+
if (typeof value === 'bigint') return TYPES.BigInt;
|
|
92
|
+
if (typeof value === 'boolean') return TYPES.Bit;
|
|
93
|
+
if (value instanceof Date) return TYPES.DateTime;
|
|
94
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
|
|
95
|
+
return TYPES.VarBinary;
|
|
96
|
+
}
|
|
97
|
+
return TYPES.NVarChar;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export function createTediousMssqlClient(
|
|
101
|
+
connection: TediousConnectionLike,
|
|
102
|
+
{ Request, TYPES }: TediousModule,
|
|
103
|
+
options?: CreateTediousClientOptions
|
|
104
|
+
): MssqlClientLike {
|
|
105
|
+
const inferType = options?.inferType ?? defaultInferType;
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
async query(sql: string, params: unknown[] = []) {
|
|
109
|
+
const rows = await new Promise<Array<Record<string, unknown>>>(
|
|
110
|
+
(resolve, reject) => {
|
|
111
|
+
const collected: Record<string, unknown>[] = [];
|
|
112
|
+
|
|
113
|
+
const request = new Request(sql, err => {
|
|
114
|
+
if (err) return reject(err);
|
|
115
|
+
resolve(collected);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
params.forEach((value, idx) => {
|
|
119
|
+
const sqlType = inferType(value, TYPES);
|
|
120
|
+
request.addParameter(
|
|
121
|
+
`p${idx + 1}`,
|
|
122
|
+
sqlType,
|
|
123
|
+
value as unknown
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
request.on('row', cols => {
|
|
128
|
+
const row: Record<string, unknown> = {};
|
|
129
|
+
for (const col of cols) {
|
|
130
|
+
row[col.metadata.colName] = col.value;
|
|
131
|
+
}
|
|
132
|
+
collected.push(row);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
connection.execSql(request);
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
return { recordset: rows };
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
beginTransaction: connection.beginTransaction
|
|
143
|
+
? () =>
|
|
144
|
+
new Promise<void>((resolve, reject) => {
|
|
145
|
+
connection.beginTransaction!(err =>
|
|
146
|
+
err ? reject(err) : resolve()
|
|
147
|
+
);
|
|
148
|
+
})
|
|
149
|
+
: undefined,
|
|
150
|
+
|
|
151
|
+
commit: connection.commitTransaction
|
|
152
|
+
? () =>
|
|
153
|
+
new Promise<void>((resolve, reject) => {
|
|
154
|
+
connection.commitTransaction!(err =>
|
|
155
|
+
err ? reject(err) : resolve()
|
|
156
|
+
);
|
|
157
|
+
})
|
|
158
|
+
: undefined,
|
|
159
|
+
|
|
160
|
+
rollback: connection.rollbackTransaction
|
|
161
|
+
? () =>
|
|
162
|
+
new Promise<void>((resolve, reject) => {
|
|
163
|
+
connection.rollbackTransaction!(err =>
|
|
164
|
+
err ? reject(err) : resolve()
|
|
165
|
+
);
|
|
166
|
+
})
|
|
167
|
+
: undefined,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function createTediousExecutor(
|
|
172
|
+
connection: TediousConnectionLike,
|
|
173
|
+
module: TediousModule,
|
|
174
|
+
options?: CreateTediousClientOptions
|
|
175
|
+
): DbExecutor {
|
|
176
|
+
const client = createTediousMssqlClient(connection, module, options);
|
|
177
|
+
return createMssqlExecutor(client);
|
|
178
|
+
}
|
package/src/decorators/column.ts
CHANGED
|
@@ -5,6 +5,13 @@ import {
|
|
|
5
5
|
ColumnDefLike,
|
|
6
6
|
ensureEntityMetadata
|
|
7
7
|
} from '../orm/entity-metadata.js';
|
|
8
|
+
import {
|
|
9
|
+
DualModePropertyDecorator,
|
|
10
|
+
getOrCreateMetadataBag,
|
|
11
|
+
isStandardDecoratorContext,
|
|
12
|
+
registerInitializer,
|
|
13
|
+
StandardDecoratorContext
|
|
14
|
+
} from './decorator-metadata.js';
|
|
8
15
|
|
|
9
16
|
export interface ColumnOptions {
|
|
10
17
|
type: ColumnType;
|
|
@@ -66,18 +73,45 @@ const registerColumn = (ctor: EntityConstructor, propertyName: string, column: C
|
|
|
66
73
|
addColumnMetadata(ctor, propertyName, column);
|
|
67
74
|
};
|
|
68
75
|
|
|
76
|
+
const registerColumnFromContext = (
|
|
77
|
+
context: StandardDecoratorContext,
|
|
78
|
+
column: ColumnDefLike
|
|
79
|
+
): void => {
|
|
80
|
+
if (!context.name) {
|
|
81
|
+
throw new Error('Column decorator requires a property name');
|
|
82
|
+
}
|
|
83
|
+
const propertyName = normalizePropertyName(context.name);
|
|
84
|
+
const bag = getOrCreateMetadataBag(context);
|
|
85
|
+
if (!bag.columns.some(entry => entry.propertyName === propertyName)) {
|
|
86
|
+
bag.columns.push({ propertyName, column: { ...column } });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
registerInitializer(context, function () {
|
|
90
|
+
const ctor = resolveConstructor(this);
|
|
91
|
+
if (!ctor) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
registerColumn(ctor, propertyName, column);
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
69
98
|
export function Column(definition: ColumnInput) {
|
|
70
99
|
const normalized = normalizeColumnInput(definition);
|
|
71
|
-
const decorator = (
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
const decorator: DualModePropertyDecorator = (targetOrValue, propertyKeyOrContext) => {
|
|
101
|
+
if (isStandardDecoratorContext(propertyKeyOrContext)) {
|
|
102
|
+
registerColumnFromContext(propertyKeyOrContext, normalized);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const propertyName = normalizePropertyName(propertyKeyOrContext);
|
|
107
|
+
const ctor = resolveConstructor(targetOrValue);
|
|
74
108
|
if (!ctor) {
|
|
75
109
|
throw new Error('Unable to resolve constructor when registering column metadata');
|
|
76
110
|
}
|
|
77
111
|
registerColumn(ctor, propertyName, { ...normalized });
|
|
78
112
|
};
|
|
79
113
|
|
|
80
|
-
return decorator
|
|
114
|
+
return decorator;
|
|
81
115
|
}
|
|
82
116
|
|
|
83
117
|
export function PrimaryKey(definition: ColumnInput) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ColumnDefLike, RelationMetadata } from '../orm/entity-metadata.js';
|
|
2
|
+
|
|
3
|
+
export interface StandardDecoratorContext {
|
|
4
|
+
kind: string;
|
|
5
|
+
name?: string | symbol;
|
|
6
|
+
metadata?: Record<PropertyKey, unknown>;
|
|
7
|
+
addInitializer?(initializer: (this: unknown) => void): void;
|
|
8
|
+
static?: boolean;
|
|
9
|
+
private?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DualModePropertyDecorator {
|
|
13
|
+
(target: object, propertyKey: string | symbol): void;
|
|
14
|
+
(value: unknown, context: StandardDecoratorContext): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DualModeClassDecorator {
|
|
18
|
+
<TFunction extends Function>(value: TFunction): void | TFunction;
|
|
19
|
+
<TFunction extends Function>(value: TFunction, context: StandardDecoratorContext): void | TFunction;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DecoratorMetadataBag {
|
|
23
|
+
columns: Array<{ propertyName: string; column: ColumnDefLike }>;
|
|
24
|
+
relations: Array<{ propertyName: string; relation: RelationMetadata }>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const METADATA_KEY = 'metal-orm:decorators';
|
|
28
|
+
|
|
29
|
+
export const isStandardDecoratorContext = (value: unknown): value is StandardDecoratorContext => {
|
|
30
|
+
return typeof value === 'object' && value !== null && 'kind' in (value as any);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getOrCreateMetadataBag = (context: StandardDecoratorContext): DecoratorMetadataBag => {
|
|
34
|
+
const metadata = context.metadata || (context.metadata = {} as Record<PropertyKey, unknown>);
|
|
35
|
+
const existing = metadata[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
36
|
+
if (existing) {
|
|
37
|
+
return existing;
|
|
38
|
+
}
|
|
39
|
+
const bag: DecoratorMetadataBag = { columns: [], relations: [] };
|
|
40
|
+
metadata[METADATA_KEY] = bag;
|
|
41
|
+
return bag;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const readMetadataBag = (context: StandardDecoratorContext): DecoratorMetadataBag | undefined => {
|
|
45
|
+
return context.metadata?.[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const registerInitializer = (
|
|
49
|
+
context: StandardDecoratorContext,
|
|
50
|
+
initializer: (this: unknown) => void
|
|
51
|
+
): void => {
|
|
52
|
+
context.addInitializer?.(initializer);
|
|
53
|
+
};
|
package/src/decorators/entity.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { TableHooks } from '../schema/table.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
addColumnMetadata,
|
|
4
|
+
addRelationMetadata,
|
|
5
|
+
EntityConstructor,
|
|
6
|
+
ensureEntityMetadata,
|
|
7
|
+
setEntityTableName
|
|
8
|
+
} from '../orm/entity-metadata.js';
|
|
9
|
+
import { DualModeClassDecorator, isStandardDecoratorContext, readMetadataBag } from './decorator-metadata.js';
|
|
3
10
|
|
|
4
11
|
export interface EntityOptions {
|
|
5
12
|
tableName?: string;
|
|
@@ -27,10 +34,36 @@ const deriveTableNameFromConstructor = (ctor: Function): string => {
|
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
export function Entity(options: EntityOptions = {}) {
|
|
30
|
-
const decorator
|
|
37
|
+
const decorator: DualModeClassDecorator = value => {
|
|
31
38
|
const tableName = options.tableName ?? deriveTableNameFromConstructor(value);
|
|
32
|
-
setEntityTableName(value, tableName, options.hooks);
|
|
39
|
+
setEntityTableName(value as EntityConstructor, tableName, options.hooks);
|
|
40
|
+
|
|
33
41
|
return value;
|
|
34
42
|
};
|
|
35
|
-
|
|
43
|
+
|
|
44
|
+
const decoratorWithContext: DualModeClassDecorator = (value, context?) => {
|
|
45
|
+
const ctor = value as EntityConstructor;
|
|
46
|
+
decorator(ctor);
|
|
47
|
+
|
|
48
|
+
if (context && isStandardDecoratorContext(context)) {
|
|
49
|
+
const bag = readMetadataBag(context);
|
|
50
|
+
if (bag) {
|
|
51
|
+
const meta = ensureEntityMetadata(ctor);
|
|
52
|
+
for (const entry of bag.columns) {
|
|
53
|
+
if (!meta.columns[entry.propertyName]) {
|
|
54
|
+
addColumnMetadata(ctor, entry.propertyName, { ...entry.column });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const entry of bag.relations) {
|
|
58
|
+
if (!meta.relations[entry.propertyName]) {
|
|
59
|
+
addRelationMetadata(ctor, entry.propertyName, entry.relation);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return ctor;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return decoratorWithContext;
|
|
36
69
|
}
|
|
@@ -5,6 +5,13 @@ import {
|
|
|
5
5
|
EntityOrTableTargetResolver,
|
|
6
6
|
RelationMetadata
|
|
7
7
|
} from '../orm/entity-metadata.js';
|
|
8
|
+
import {
|
|
9
|
+
DualModePropertyDecorator,
|
|
10
|
+
getOrCreateMetadataBag,
|
|
11
|
+
isStandardDecoratorContext,
|
|
12
|
+
registerInitializer,
|
|
13
|
+
StandardDecoratorContext
|
|
14
|
+
} from './decorator-metadata.js';
|
|
8
15
|
|
|
9
16
|
interface BaseRelationOptions {
|
|
10
17
|
target: EntityOrTableTargetResolver;
|
|
@@ -60,16 +67,39 @@ const registerRelation = (ctor: EntityConstructor, propertyName: string, metadat
|
|
|
60
67
|
const createFieldDecorator = (
|
|
61
68
|
metadataFactory: (propertyName: string) => RelationMetadata
|
|
62
69
|
) => {
|
|
63
|
-
const decorator = (
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
const decorator: DualModePropertyDecorator = (targetOrValue, propertyKeyOrContext) => {
|
|
71
|
+
if (isStandardDecoratorContext(propertyKeyOrContext)) {
|
|
72
|
+
const ctx = propertyKeyOrContext as StandardDecoratorContext;
|
|
73
|
+
if (!ctx.name) {
|
|
74
|
+
throw new Error('Relation decorator requires a property name');
|
|
75
|
+
}
|
|
76
|
+
const propertyName = normalizePropertyName(ctx.name);
|
|
77
|
+
const bag = getOrCreateMetadataBag(ctx);
|
|
78
|
+
const relationMetadata = metadataFactory(propertyName);
|
|
79
|
+
|
|
80
|
+
if (!bag.relations.some(entry => entry.propertyName === propertyName)) {
|
|
81
|
+
bag.relations.push({ propertyName, relation: relationMetadata });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
registerInitializer(ctx, function () {
|
|
85
|
+
const ctor = resolveConstructor(this);
|
|
86
|
+
if (!ctor) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
registerRelation(ctor, propertyName, relationMetadata);
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const propertyName = normalizePropertyName(propertyKeyOrContext);
|
|
95
|
+
const ctor = resolveConstructor(targetOrValue);
|
|
66
96
|
if (!ctor) {
|
|
67
97
|
throw new Error('Unable to resolve constructor when registering relation metadata');
|
|
68
98
|
}
|
|
69
99
|
registerRelation(ctor, propertyName, metadataFactory(propertyName));
|
|
70
100
|
};
|
|
71
101
|
|
|
72
|
-
return decorator
|
|
102
|
+
return decorator;
|
|
73
103
|
};
|
|
74
104
|
|
|
75
105
|
export function HasMany(options: HasManyOptions) {
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,11 @@ export * from './schema/table.js';
|
|
|
2
2
|
export * from './schema/column.js';
|
|
3
3
|
export * from './schema/relation.js';
|
|
4
4
|
export * from './schema/types.js';
|
|
5
|
-
export * from './query-builder/select.js';
|
|
6
|
-
export * from './query-builder/select-helpers.js';
|
|
7
|
-
export * from './query-builder/insert.js';
|
|
8
|
-
export * from './query-builder/update.js';
|
|
9
|
-
export * from './query-builder/delete.js';
|
|
5
|
+
export * from './query-builder/select.js';
|
|
6
|
+
export * from './query-builder/select-helpers.js';
|
|
7
|
+
export * from './query-builder/insert.js';
|
|
8
|
+
export * from './query-builder/update.js';
|
|
9
|
+
export * from './query-builder/delete.js';
|
|
10
10
|
export * from './core/ast/expression.js';
|
|
11
11
|
export * from './core/hydration/types.js';
|
|
12
12
|
export * from './core/dialect/mysql/index.js';
|