metal-orm 1.0.43 → 1.0.44
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 +173 -30
- package/dist/index.cjs +896 -476
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1146 -275
- package/dist/index.d.ts +1146 -275
- package/dist/index.js +896 -474
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/adapters.ts +8 -2
- package/src/core/ast/builders.ts +105 -81
- package/src/core/ast/expression-builders.ts +430 -390
- package/src/core/ast/expression-visitor.ts +47 -8
- package/src/core/ast/helpers.ts +23 -0
- package/src/core/ast/join-node.ts +17 -1
- package/src/core/ddl/dialects/base-schema-dialect.ts +7 -1
- package/src/core/ddl/dialects/index.ts +1 -0
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -0
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -0
- package/src/core/ddl/introspect/catalogs/index.ts +1 -0
- package/src/core/ddl/introspect/catalogs/postgres.ts +2 -0
- package/src/core/ddl/introspect/context.ts +6 -0
- package/src/core/ddl/introspect/functions/postgres.ts +13 -0
- package/src/core/ddl/introspect/mssql.ts +11 -0
- package/src/core/ddl/introspect/mysql.ts +2 -0
- package/src/core/ddl/introspect/postgres.ts +14 -0
- package/src/core/ddl/introspect/registry.ts +14 -0
- package/src/core/ddl/introspect/run-select.ts +13 -0
- package/src/core/ddl/introspect/sqlite.ts +22 -0
- package/src/core/ddl/introspect/utils.ts +18 -0
- package/src/core/ddl/naming-strategy.ts +6 -0
- package/src/core/ddl/schema-dialect.ts +19 -6
- package/src/core/ddl/schema-diff.ts +22 -0
- package/src/core/ddl/schema-generator.ts +22 -0
- package/src/core/ddl/schema-plan-executor.ts +6 -0
- package/src/core/ddl/schema-types.ts +6 -0
- package/src/core/dialect/abstract.ts +2 -2
- package/src/core/execution/pooling/pool.ts +12 -7
- package/src/core/functions/datetime.ts +57 -33
- package/src/core/functions/numeric.ts +95 -30
- package/src/core/functions/standard-strategy.ts +35 -0
- package/src/core/functions/text.ts +83 -22
- package/src/core/functions/types.ts +23 -8
- package/src/decorators/bootstrap.ts +16 -4
- package/src/decorators/column.ts +17 -0
- package/src/decorators/decorator-metadata.ts +27 -0
- package/src/decorators/entity.ts +8 -0
- package/src/decorators/index.ts +3 -0
- package/src/decorators/relations.ts +32 -0
- package/src/orm/als.ts +34 -9
- package/src/orm/entity-context.ts +54 -0
- package/src/orm/entity-metadata.ts +122 -9
- package/src/orm/execute.ts +15 -0
- package/src/orm/lazy-batch.ts +68 -98
- package/src/orm/relations/has-many.ts +44 -0
- package/src/query/index.ts +74 -0
- package/src/query/target.ts +46 -0
- package/src/query-builder/delete-query-state.ts +30 -0
- package/src/query-builder/delete.ts +64 -19
- package/src/query-builder/hydration-manager.ts +46 -0
- package/src/query-builder/insert-query-state.ts +30 -0
- package/src/query-builder/insert.ts +46 -2
- package/src/query-builder/query-ast-service.ts +5 -0
- package/src/query-builder/query-resolution.ts +78 -0
- package/src/query-builder/raw-column-parser.ts +5 -0
- package/src/query-builder/relation-alias.ts +7 -0
- package/src/query-builder/relation-conditions.ts +61 -48
- package/src/query-builder/relation-service.ts +68 -63
- package/src/query-builder/relation-utils.ts +3 -0
- package/src/query-builder/select/cte-facet.ts +40 -0
- package/src/query-builder/select/from-facet.ts +80 -0
- package/src/query-builder/select/join-facet.ts +62 -0
- package/src/query-builder/select/predicate-facet.ts +103 -0
- package/src/query-builder/select/projection-facet.ts +69 -0
- package/src/query-builder/select/relation-facet.ts +81 -0
- package/src/query-builder/select/setop-facet.ts +36 -0
- package/src/query-builder/select-helpers.ts +13 -0
- package/src/query-builder/select-query-builder-deps.ts +19 -1
- package/src/query-builder/select-query-state.ts +2 -1
- package/src/query-builder/select.ts +795 -1163
- package/src/query-builder/update-query-state.ts +52 -0
- package/src/query-builder/update.ts +69 -19
- package/src/schema/table-guards.ts +31 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { FunctionStrategy, FunctionRenderer, FunctionRenderContext } from './types.js';
|
|
2
2
|
import { LiteralNode, OperandNode, isOperandNode } from '../ast/expression.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Standard implementation of FunctionStrategy for ANSI SQL functions.
|
|
6
|
+
*/
|
|
4
7
|
export class StandardFunctionStrategy implements FunctionStrategy {
|
|
5
8
|
protected renderers: Map<string, FunctionRenderer> = new Map();
|
|
6
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new StandardFunctionStrategy and registers standard functions.
|
|
12
|
+
*/
|
|
7
13
|
constructor() {
|
|
8
14
|
this.registerStandard();
|
|
9
15
|
}
|
|
@@ -44,14 +50,27 @@ export class StandardFunctionStrategy implements FunctionStrategy {
|
|
|
44
50
|
this.add('GROUP_CONCAT', ctx => this.renderGroupConcat(ctx));
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Registers a renderer for a function name.
|
|
55
|
+
* @param name - The function name.
|
|
56
|
+
* @param renderer - The renderer function.
|
|
57
|
+
*/
|
|
47
58
|
protected add(name: string, renderer: FunctionRenderer) {
|
|
48
59
|
this.renderers.set(name, renderer);
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @inheritDoc
|
|
64
|
+
*/
|
|
51
65
|
getRenderer(name: string): FunctionRenderer | undefined {
|
|
52
66
|
return this.renderers.get(name);
|
|
53
67
|
}
|
|
54
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Renders the GROUP_CONCAT function with optional ORDER BY and SEPARATOR.
|
|
71
|
+
* @param ctx - The function render context.
|
|
72
|
+
* @returns The rendered SQL string.
|
|
73
|
+
*/
|
|
55
74
|
private renderGroupConcat(ctx: FunctionRenderContext): string {
|
|
56
75
|
const arg = ctx.compiledArgs[0];
|
|
57
76
|
const orderClause = this.buildOrderByExpression(ctx);
|
|
@@ -60,6 +79,11 @@ export class StandardFunctionStrategy implements FunctionStrategy {
|
|
|
60
79
|
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
61
80
|
}
|
|
62
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Builds the ORDER BY clause for functions like GROUP_CONCAT.
|
|
84
|
+
* @param ctx - The function render context.
|
|
85
|
+
* @returns The ORDER BY SQL clause or empty string.
|
|
86
|
+
*/
|
|
63
87
|
protected buildOrderByExpression(ctx: FunctionRenderContext): string {
|
|
64
88
|
const orderBy = ctx.node.orderBy;
|
|
65
89
|
if (!orderBy || orderBy.length === 0) {
|
|
@@ -78,6 +102,11 @@ export class StandardFunctionStrategy implements FunctionStrategy {
|
|
|
78
102
|
return `ORDER BY ${parts.join(', ')}`;
|
|
79
103
|
}
|
|
80
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Formats the SEPARATOR clause for GROUP_CONCAT.
|
|
107
|
+
* @param ctx - The function render context.
|
|
108
|
+
* @returns The SEPARATOR SQL clause or empty string.
|
|
109
|
+
*/
|
|
81
110
|
protected formatGroupConcatSeparator(ctx: FunctionRenderContext): string {
|
|
82
111
|
if (!ctx.node.separator) {
|
|
83
112
|
return '';
|
|
@@ -85,10 +114,16 @@ export class StandardFunctionStrategy implements FunctionStrategy {
|
|
|
85
114
|
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
86
115
|
}
|
|
87
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Gets the separator operand for GROUP_CONCAT, defaulting to comma.
|
|
119
|
+
* @param ctx - The function render context.
|
|
120
|
+
* @returns The separator operand.
|
|
121
|
+
*/
|
|
88
122
|
protected getGroupConcatSeparatorOperand(ctx: FunctionRenderContext): OperandNode {
|
|
89
123
|
return ctx.node.separator ?? StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
90
124
|
}
|
|
91
125
|
|
|
126
|
+
/** Default separator for GROUP_CONCAT, a comma. */
|
|
92
127
|
protected static readonly DEFAULT_GROUP_CONCAT_SEPARATOR: LiteralNode = {
|
|
93
128
|
type: 'Literal',
|
|
94
129
|
value: ','
|
|
@@ -23,22 +23,30 @@ const fn = (key: string, args: OperandInput[]): FunctionNode => ({
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Converts a string to lowercase.
|
|
27
|
+
* @param value - The string value.
|
|
28
|
+
* @returns A FunctionNode representing the LOWER SQL function.
|
|
27
29
|
*/
|
|
28
30
|
export const lower = (value: OperandInput): FunctionNode => fn('LOWER', [value]);
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
33
|
+
* Converts a string to uppercase.
|
|
34
|
+
* @param value - The string value.
|
|
35
|
+
* @returns A FunctionNode representing the UPPER SQL function.
|
|
32
36
|
*/
|
|
33
37
|
export const upper = (value: OperandInput): FunctionNode => fn('UPPER', [value]);
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
|
-
*
|
|
40
|
+
* Returns the ASCII code of the first character of a string.
|
|
41
|
+
* @param value - The string value.
|
|
42
|
+
* @returns A FunctionNode representing the ASCII SQL function.
|
|
37
43
|
*/
|
|
38
44
|
export const ascii = (value: OperandInput): FunctionNode => fn('ASCII', [value]);
|
|
39
45
|
|
|
40
46
|
/**
|
|
41
|
-
*
|
|
47
|
+
* Returns a string from one or more ASCII codes.
|
|
48
|
+
* @param codes - The ASCII codes.
|
|
49
|
+
* @returns A FunctionNode representing the CHAR SQL function.
|
|
42
50
|
*/
|
|
43
51
|
export const char = (...codes: OperandInput[]): FunctionNode => {
|
|
44
52
|
if (codes.length === 0) throw new Error('char() expects at least 1 argument');
|
|
@@ -46,33 +54,46 @@ export const char = (...codes: OperandInput[]): FunctionNode => {
|
|
|
46
54
|
};
|
|
47
55
|
|
|
48
56
|
/**
|
|
49
|
-
*
|
|
57
|
+
* Returns the number of characters in a string.
|
|
58
|
+
* @param value - The string value.
|
|
59
|
+
* @returns A FunctionNode representing the CHAR_LENGTH SQL function.
|
|
50
60
|
*/
|
|
51
61
|
export const charLength = (value: OperandInput): FunctionNode => fn('CHAR_LENGTH', [value]);
|
|
52
62
|
|
|
53
63
|
/**
|
|
54
|
-
*
|
|
64
|
+
* Returns the length of a string in bytes or characters.
|
|
65
|
+
* @param value - The string value.
|
|
66
|
+
* @returns A FunctionNode representing the LENGTH SQL function.
|
|
55
67
|
*/
|
|
56
68
|
export const length = (value: OperandInput): FunctionNode => fn('LENGTH', [value]);
|
|
57
69
|
|
|
58
70
|
/**
|
|
59
|
-
*
|
|
71
|
+
* Removes leading and trailing whitespace or specified characters from a string.
|
|
72
|
+
* @param value - The string value.
|
|
73
|
+
* @param chars - The characters to trim (optional).
|
|
74
|
+
* @returns A FunctionNode representing the TRIM SQL function.
|
|
60
75
|
*/
|
|
61
76
|
export const trim = (value: OperandInput, chars?: OperandInput): FunctionNode =>
|
|
62
77
|
chars === undefined ? fn('TRIM', [value]) : fn('TRIM', [value, chars]);
|
|
63
78
|
|
|
64
79
|
/**
|
|
65
|
-
*
|
|
80
|
+
* Removes leading whitespace from a string.
|
|
81
|
+
* @param value - The string value.
|
|
82
|
+
* @returns A FunctionNode representing the LTRIM SQL function.
|
|
66
83
|
*/
|
|
67
84
|
export const ltrim = (value: OperandInput): FunctionNode => fn('LTRIM', [value]);
|
|
68
85
|
|
|
69
86
|
/**
|
|
70
|
-
*
|
|
87
|
+
* Removes trailing whitespace from a string.
|
|
88
|
+
* @param value - The string value.
|
|
89
|
+
* @returns A FunctionNode representing the RTRIM SQL function.
|
|
71
90
|
*/
|
|
72
91
|
export const rtrim = (value: OperandInput): FunctionNode => fn('RTRIM', [value]);
|
|
73
92
|
|
|
74
93
|
/**
|
|
75
|
-
*
|
|
94
|
+
* Concatenates two or more strings.
|
|
95
|
+
* @param args - The strings to concatenate.
|
|
96
|
+
* @returns A FunctionNode representing the CONCAT SQL function.
|
|
76
97
|
*/
|
|
77
98
|
export const concat = (...args: OperandInput[]): FunctionNode => {
|
|
78
99
|
if (args.length < 2) throw new Error('concat() expects at least 2 arguments');
|
|
@@ -80,7 +101,10 @@ export const concat = (...args: OperandInput[]): FunctionNode => {
|
|
|
80
101
|
};
|
|
81
102
|
|
|
82
103
|
/**
|
|
83
|
-
*
|
|
104
|
+
* Concatenates strings with a separator.
|
|
105
|
+
* @param separator - The separator string.
|
|
106
|
+
* @param args - The strings to concatenate.
|
|
107
|
+
* @returns A FunctionNode representing the CONCAT_WS SQL function.
|
|
84
108
|
*/
|
|
85
109
|
export const concatWs = (separator: OperandInput, ...args: OperandInput[]): FunctionNode => {
|
|
86
110
|
if (args.length < 1) throw new Error('concatWs() expects at least 2 arguments including the separator');
|
|
@@ -88,61 +112,98 @@ export const concatWs = (separator: OperandInput, ...args: OperandInput[]): Func
|
|
|
88
112
|
};
|
|
89
113
|
|
|
90
114
|
/**
|
|
91
|
-
*
|
|
115
|
+
* Extracts a substring from a string.
|
|
116
|
+
* @param value - The string value.
|
|
117
|
+
* @param start - The starting position.
|
|
118
|
+
* @param length - The length of the substring (optional).
|
|
119
|
+
* @returns A FunctionNode representing the SUBSTR SQL function.
|
|
92
120
|
*/
|
|
93
121
|
export const substr = (value: OperandInput, start: OperandInput, length?: OperandInput): FunctionNode =>
|
|
94
122
|
length === undefined ? fn('SUBSTR', [value, start]) : fn('SUBSTR', [value, start, length]);
|
|
95
123
|
|
|
96
124
|
/**
|
|
97
|
-
*
|
|
125
|
+
* Returns the leftmost characters of a string.
|
|
126
|
+
* @param value - The string value.
|
|
127
|
+
* @param len - The number of characters to return.
|
|
128
|
+
* @returns A FunctionNode representing the LEFT SQL function.
|
|
98
129
|
*/
|
|
99
130
|
export const left = (value: OperandInput, len: OperandInput): FunctionNode => fn('LEFT', [value, len]);
|
|
100
131
|
|
|
101
132
|
/**
|
|
102
|
-
*
|
|
133
|
+
* Returns the rightmost characters of a string.
|
|
134
|
+
* @param value - The string value.
|
|
135
|
+
* @param len - The number of characters to return.
|
|
136
|
+
* @returns A FunctionNode representing the RIGHT SQL function.
|
|
103
137
|
*/
|
|
104
138
|
export const right = (value: OperandInput, len: OperandInput): FunctionNode => fn('RIGHT', [value, len]);
|
|
105
139
|
|
|
106
140
|
/**
|
|
107
|
-
*
|
|
141
|
+
* Returns the position of a substring in a string.
|
|
142
|
+
* @param substring - The substring to search for.
|
|
143
|
+
* @param value - The string to search in.
|
|
144
|
+
* @returns A FunctionNode representing the POSITION SQL function.
|
|
108
145
|
*/
|
|
109
146
|
export const position = (substring: OperandInput, value: OperandInput): FunctionNode => fn('POSITION', [substring, value]);
|
|
110
147
|
|
|
111
148
|
/**
|
|
112
|
-
*
|
|
149
|
+
* Returns the position of a substring in a string.
|
|
150
|
+
* @param value - The string to search in.
|
|
151
|
+
* @param substring - The substring to search for.
|
|
152
|
+
* @returns A FunctionNode representing the INSTR SQL function.
|
|
113
153
|
*/
|
|
114
154
|
export const instr = (value: OperandInput, substring: OperandInput): FunctionNode => fn('INSTR', [value, substring]);
|
|
115
155
|
|
|
116
156
|
/**
|
|
117
|
-
*
|
|
157
|
+
* Returns the position of a substring in a string, optionally starting from a position.
|
|
158
|
+
* @param substring - The substring to search for.
|
|
159
|
+
* @param value - The string to search in.
|
|
160
|
+
* @param start - The starting position (optional).
|
|
161
|
+
* @returns A FunctionNode representing the LOCATE SQL function.
|
|
118
162
|
*/
|
|
119
163
|
export const locate = (substring: OperandInput, value: OperandInput, start?: OperandInput): FunctionNode =>
|
|
120
164
|
start === undefined ? fn('LOCATE', [substring, value]) : fn('LOCATE', [substring, value, start]);
|
|
121
165
|
|
|
122
166
|
/**
|
|
123
|
-
*
|
|
167
|
+
* Replaces occurrences of a substring in a string.
|
|
168
|
+
* @param value - The string to search in.
|
|
169
|
+
* @param search - The substring to replace.
|
|
170
|
+
* @param replacement - The replacement string.
|
|
171
|
+
* @returns A FunctionNode representing the REPLACE SQL function.
|
|
124
172
|
*/
|
|
125
173
|
export const replace = (value: OperandInput, search: OperandInput, replacement: OperandInput): FunctionNode =>
|
|
126
174
|
fn('REPLACE', [value, search, replacement]);
|
|
127
175
|
|
|
128
176
|
/**
|
|
129
|
-
*
|
|
177
|
+
* Repeats a string a specified number of times.
|
|
178
|
+
* @param value - The string to repeat.
|
|
179
|
+
* @param count - The number of times to repeat.
|
|
180
|
+
* @returns A FunctionNode representing the REPEAT SQL function.
|
|
130
181
|
*/
|
|
131
182
|
export const repeat = (value: OperandInput, count: OperandInput): FunctionNode => fn('REPEAT', [value, count]);
|
|
132
183
|
|
|
133
184
|
/**
|
|
134
|
-
*
|
|
185
|
+
* Left-pads a string to a certain length with another string.
|
|
186
|
+
* @param value - The string to pad.
|
|
187
|
+
* @param len - The length to pad to.
|
|
188
|
+
* @param pad - The padding string.
|
|
189
|
+
* @returns A FunctionNode representing the LPAD SQL function.
|
|
135
190
|
*/
|
|
136
191
|
export const lpad = (value: OperandInput, len: OperandInput, pad: OperandInput): FunctionNode =>
|
|
137
192
|
fn('LPAD', [value, len, pad]);
|
|
138
193
|
|
|
139
194
|
/**
|
|
140
|
-
*
|
|
195
|
+
* Right-pads a string to a certain length with another string.
|
|
196
|
+
* @param value - The string to pad.
|
|
197
|
+
* @param len - The length to pad to.
|
|
198
|
+
* @param pad - The padding string.
|
|
199
|
+
* @returns A FunctionNode representing the RPAD SQL function.
|
|
141
200
|
*/
|
|
142
201
|
export const rpad = (value: OperandInput, len: OperandInput, pad: OperandInput): FunctionNode =>
|
|
143
202
|
fn('RPAD', [value, len, pad]);
|
|
144
203
|
|
|
145
204
|
/**
|
|
146
|
-
*
|
|
205
|
+
* Returns a string consisting of a specified number of spaces.
|
|
206
|
+
* @param count - The number of spaces.
|
|
207
|
+
* @returns A FunctionNode representing the SPACE SQL function.
|
|
147
208
|
*/
|
|
148
209
|
export const space = (count: OperandInput): FunctionNode => fn('SPACE', [count]);
|
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
import { FunctionNode, OperandNode } from '../ast/expression.js';
|
|
2
|
-
|
|
3
|
-
export interface FunctionRenderContext {
|
|
4
|
-
node: FunctionNode;
|
|
5
|
-
compiledArgs: string[];
|
|
6
|
-
/** Helper to compile additional operands (e.g., separators or ORDER BY columns) */
|
|
7
|
-
compileOperand: (operand: OperandNode) => string;
|
|
8
|
-
}
|
|
1
|
+
import { FunctionNode, OperandNode } from '../ast/expression.js';
|
|
9
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Context provided to function renderers.
|
|
5
|
+
*/
|
|
6
|
+
export interface FunctionRenderContext {
|
|
7
|
+
/** The function node being rendered. */
|
|
8
|
+
node: FunctionNode;
|
|
9
|
+
/** The compiled arguments for the function. */
|
|
10
|
+
compiledArgs: string[];
|
|
11
|
+
/** Helper to compile additional operands (e.g., separators or ORDER BY columns). */
|
|
12
|
+
compileOperand: (operand: OperandNode) => string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A function that renders a SQL function call.
|
|
17
|
+
* @param ctx - The rendering context.
|
|
18
|
+
* @returns The rendered SQL string.
|
|
19
|
+
*/
|
|
10
20
|
export type FunctionRenderer = (ctx: FunctionRenderContext) => string;
|
|
11
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Strategy for rendering SQL functions in a specific dialect.
|
|
24
|
+
*/
|
|
12
25
|
export interface FunctionStrategy {
|
|
13
26
|
/**
|
|
14
27
|
* Returns a renderer for a specific function name (e.g. "DATE_ADD").
|
|
15
28
|
* Returns undefined if this dialect doesn't support the function.
|
|
29
|
+
* @param functionName - The name of the function.
|
|
30
|
+
* @returns The renderer function or undefined.
|
|
16
31
|
*/
|
|
17
32
|
getRenderer(functionName: string): FunctionRenderer | undefined;
|
|
18
33
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type RelationDef
|
|
9
9
|
} from '../schema/relation.js';
|
|
10
10
|
import { TableDef } from '../schema/table.js';
|
|
11
|
+
import { isTableDef } from '../schema/table-guards.js';
|
|
11
12
|
import {
|
|
12
13
|
buildTableDef,
|
|
13
14
|
EntityConstructor,
|
|
@@ -20,10 +21,6 @@ import {
|
|
|
20
21
|
|
|
21
22
|
import { tableRef, type TableRef } from '../schema/table.js';
|
|
22
23
|
|
|
23
|
-
const isTableDef = (value: unknown): value is TableDef => {
|
|
24
|
-
return typeof value === 'object' && value !== null && 'columns' in (value as TableDef);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
24
|
const unwrapTarget = (target: EntityOrTableTargetResolver): EntityOrTableTarget => {
|
|
28
25
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
29
26
|
if (typeof target === 'function' && (target as Function).prototype === undefined) {
|
|
@@ -104,6 +101,10 @@ const buildRelationDefinitions = (
|
|
|
104
101
|
return relations;
|
|
105
102
|
};
|
|
106
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Bootstraps all entities by building their table definitions and relations.
|
|
106
|
+
* @returns An array of table definitions for all bootstrapped entities.
|
|
107
|
+
*/
|
|
107
108
|
export const bootstrapEntities = (): TableDef[] => {
|
|
108
109
|
const metas = getAllEntityMetadata();
|
|
109
110
|
const tableMap = new Map<EntityConstructor, TableDef>();
|
|
@@ -122,6 +123,12 @@ export const bootstrapEntities = (): TableDef[] => {
|
|
|
122
123
|
return metas.map(meta => meta.table!) as TableDef[];
|
|
123
124
|
};
|
|
124
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Gets the table definition for a given entity constructor.
|
|
128
|
+
* Bootstraps entities if necessary.
|
|
129
|
+
* @param ctor - The entity constructor.
|
|
130
|
+
* @returns The table definition or undefined if not found.
|
|
131
|
+
*/
|
|
125
132
|
export const getTableDefFromEntity = <TTable extends TableDef = TableDef>(ctor: EntityConstructor): TTable | undefined => {
|
|
126
133
|
const meta = getEntityMetadata(ctor);
|
|
127
134
|
if (!meta) return undefined;
|
|
@@ -131,6 +138,11 @@ export const getTableDefFromEntity = <TTable extends TableDef = TableDef>(ctor:
|
|
|
131
138
|
return meta.table as TTable;
|
|
132
139
|
};
|
|
133
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Creates a select query builder for the given entity.
|
|
143
|
+
* @param ctor - The entity constructor.
|
|
144
|
+
* @returns A select query builder for the entity.
|
|
145
|
+
*/
|
|
134
146
|
export const selectFromEntity = <TTable extends TableDef = TableDef>(
|
|
135
147
|
ctor: EntityConstructor
|
|
136
148
|
): SelectQueryBuilder<unknown, TTable> => {
|
package/src/decorators/column.ts
CHANGED
|
@@ -12,6 +12,9 @@ import {
|
|
|
12
12
|
StandardDecoratorContext
|
|
13
13
|
} from './decorator-metadata.js';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Options for defining a column in an entity.
|
|
17
|
+
*/
|
|
15
18
|
export interface ColumnOptions {
|
|
16
19
|
type: ColumnType;
|
|
17
20
|
args?: ColumnDef['args'];
|
|
@@ -20,6 +23,9 @@ export interface ColumnOptions {
|
|
|
20
23
|
tsType?: ColumnDef['tsType'];
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Input type for column definitions, either as options object or direct ColumnDef.
|
|
28
|
+
*/
|
|
23
29
|
export type ColumnInput = ColumnOptions | ColumnDef;
|
|
24
30
|
|
|
25
31
|
const normalizeColumnInput = (input: ColumnInput): ColumnDefLike => {
|
|
@@ -89,6 +95,11 @@ const registerColumnFromContext = (
|
|
|
89
95
|
|
|
90
96
|
};
|
|
91
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Decorator to define a column on an entity property.
|
|
100
|
+
* @param definition - The column definition or options.
|
|
101
|
+
* @returns A property decorator that registers the column metadata.
|
|
102
|
+
*/
|
|
92
103
|
export function Column(definition: ColumnInput) {
|
|
93
104
|
const normalized = normalizeColumnInput(definition);
|
|
94
105
|
const decorator: DualModePropertyDecorator = (targetOrValue, propertyKeyOrContext) => {
|
|
@@ -108,6 +119,12 @@ export function Column(definition: ColumnInput) {
|
|
|
108
119
|
return decorator;
|
|
109
120
|
}
|
|
110
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Decorator to define a primary key column on an entity property.
|
|
124
|
+
* Sets the primary flag to true and delegates to Column decorator.
|
|
125
|
+
* @param definition - The column definition or options.
|
|
126
|
+
* @returns A property decorator that registers the primary key column metadata.
|
|
127
|
+
*/
|
|
111
128
|
export function PrimaryKey(definition: ColumnInput) {
|
|
112
129
|
const normalized = normalizeColumnInput(definition);
|
|
113
130
|
normalized.primary = true;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ColumnDefLike, RelationMetadata } from '../orm/entity-metadata.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Context object provided by standard decorators in newer TypeScript versions.
|
|
5
|
+
*/
|
|
3
6
|
export interface StandardDecoratorContext {
|
|
4
7
|
kind: string;
|
|
5
8
|
name?: string | symbol;
|
|
@@ -8,11 +11,17 @@ export interface StandardDecoratorContext {
|
|
|
8
11
|
private?: boolean;
|
|
9
12
|
}
|
|
10
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Dual-mode property decorator that supports both legacy and standard decorator syntax.
|
|
16
|
+
*/
|
|
11
17
|
export interface DualModePropertyDecorator {
|
|
12
18
|
(target: object, propertyKey: string | symbol): void;
|
|
13
19
|
(value: unknown, context: StandardDecoratorContext): void;
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Dual-mode class decorator that supports both legacy and standard decorator syntax.
|
|
24
|
+
*/
|
|
16
25
|
export interface DualModeClassDecorator {
|
|
17
26
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
18
27
|
<TFunction extends Function>(value: TFunction): void | TFunction;
|
|
@@ -20,6 +29,9 @@ export interface DualModeClassDecorator {
|
|
|
20
29
|
<TFunction extends Function>(value: TFunction, context: StandardDecoratorContext): void | TFunction;
|
|
21
30
|
}
|
|
22
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Bag for storing decorator metadata during the decoration phase.
|
|
34
|
+
*/
|
|
23
35
|
export interface DecoratorMetadataBag {
|
|
24
36
|
columns: Array<{ propertyName: string; column: ColumnDefLike }>;
|
|
25
37
|
relations: Array<{ propertyName: string; relation: RelationMetadata }>;
|
|
@@ -27,10 +39,20 @@ export interface DecoratorMetadataBag {
|
|
|
27
39
|
|
|
28
40
|
const METADATA_KEY = 'metal-orm:decorators';
|
|
29
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Checks if a value is a StandardDecoratorContext.
|
|
44
|
+
* @param value - The value to check.
|
|
45
|
+
* @returns True if the value is a StandardDecoratorContext.
|
|
46
|
+
*/
|
|
30
47
|
export const isStandardDecoratorContext = (value: unknown): value is StandardDecoratorContext => {
|
|
31
48
|
return typeof value === 'object' && value !== null && 'kind' in (value as object);
|
|
32
49
|
};
|
|
33
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Gets or creates a metadata bag for the given decorator context.
|
|
53
|
+
* @param context - The decorator context.
|
|
54
|
+
* @returns The metadata bag.
|
|
55
|
+
*/
|
|
34
56
|
export const getOrCreateMetadataBag = (context: StandardDecoratorContext): DecoratorMetadataBag => {
|
|
35
57
|
const metadata = context.metadata || (context.metadata = {} as Record<PropertyKey, unknown>);
|
|
36
58
|
const existing = metadata[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
@@ -42,6 +64,11 @@ export const getOrCreateMetadataBag = (context: StandardDecoratorContext): Decor
|
|
|
42
64
|
return bag;
|
|
43
65
|
};
|
|
44
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Reads the metadata bag from the given decorator context.
|
|
69
|
+
* @param context - The decorator context.
|
|
70
|
+
* @returns The metadata bag if present.
|
|
71
|
+
*/
|
|
45
72
|
export const readMetadataBag = (context: StandardDecoratorContext): DecoratorMetadataBag | undefined => {
|
|
46
73
|
return context.metadata?.[METADATA_KEY] as DecoratorMetadataBag | undefined;
|
|
47
74
|
};
|
package/src/decorators/entity.ts
CHANGED
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
} from '../orm/entity-metadata.js';
|
|
10
10
|
import { DualModeClassDecorator, isStandardDecoratorContext, readMetadataBag } from './decorator-metadata.js';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Options for defining an entity.
|
|
14
|
+
*/
|
|
12
15
|
export interface EntityOptions {
|
|
13
16
|
tableName?: string;
|
|
14
17
|
hooks?: TableHooks;
|
|
@@ -34,6 +37,11 @@ const deriveTableNameFromConstructor = (ctor: EntityConstructor<unknown>): strin
|
|
|
34
37
|
return normalized.endsWith('s') ? normalized : `${normalized}s`;
|
|
35
38
|
};
|
|
36
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Class decorator to mark a class as an entity and configure its table mapping.
|
|
42
|
+
* @param options - Configuration options for the entity.
|
|
43
|
+
* @returns A class decorator that registers the entity metadata.
|
|
44
|
+
*/
|
|
37
45
|
export function Entity(options: EntityOptions = {}) {
|
|
38
46
|
const decorator: DualModeClassDecorator = value => {
|
|
39
47
|
const tableName = options.tableName ?? deriveTableNameFromConstructor(value);
|
package/src/decorators/index.ts
CHANGED
|
@@ -18,18 +18,30 @@ interface BaseRelationOptions {
|
|
|
18
18
|
localKey?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Options for HasMany relation.
|
|
23
|
+
*/
|
|
21
24
|
export interface HasManyOptions extends BaseRelationOptions {
|
|
22
25
|
foreignKey: string;
|
|
23
26
|
}
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Options for HasOne relation.
|
|
30
|
+
*/
|
|
25
31
|
export interface HasOneOptions extends BaseRelationOptions {
|
|
26
32
|
foreignKey: string;
|
|
27
33
|
}
|
|
28
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Options for BelongsTo relation.
|
|
37
|
+
*/
|
|
29
38
|
export interface BelongsToOptions extends BaseRelationOptions {
|
|
30
39
|
foreignKey: string;
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Options for BelongsToMany relation.
|
|
44
|
+
*/
|
|
33
45
|
export interface BelongsToManyOptions {
|
|
34
46
|
target: EntityOrTableTargetResolver;
|
|
35
47
|
pivotTable: EntityOrTableTargetResolver;
|
|
@@ -93,6 +105,11 @@ const createFieldDecorator = (
|
|
|
93
105
|
return decorator;
|
|
94
106
|
};
|
|
95
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Decorator to define a HasMany relation on an entity property.
|
|
110
|
+
* @param options - The relation options.
|
|
111
|
+
* @returns A property decorator that registers the relation metadata.
|
|
112
|
+
*/
|
|
96
113
|
export function HasMany(options: HasManyOptions) {
|
|
97
114
|
return createFieldDecorator(propertyName => ({
|
|
98
115
|
kind: RelationKinds.HasMany,
|
|
@@ -104,6 +121,11 @@ export function HasMany(options: HasManyOptions) {
|
|
|
104
121
|
}));
|
|
105
122
|
}
|
|
106
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Decorator to define a HasOne relation on an entity property.
|
|
126
|
+
* @param options - The relation options.
|
|
127
|
+
* @returns A property decorator that registers the relation metadata.
|
|
128
|
+
*/
|
|
107
129
|
export function HasOne(options: HasOneOptions) {
|
|
108
130
|
return createFieldDecorator(propertyName => ({
|
|
109
131
|
kind: RelationKinds.HasOne,
|
|
@@ -115,6 +137,11 @@ export function HasOne(options: HasOneOptions) {
|
|
|
115
137
|
}));
|
|
116
138
|
}
|
|
117
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Decorator to define a BelongsTo relation on an entity property.
|
|
142
|
+
* @param options - The relation options.
|
|
143
|
+
* @returns A property decorator that registers the relation metadata.
|
|
144
|
+
*/
|
|
118
145
|
export function BelongsTo(options: BelongsToOptions) {
|
|
119
146
|
return createFieldDecorator(propertyName => ({
|
|
120
147
|
kind: RelationKinds.BelongsTo,
|
|
@@ -126,6 +153,11 @@ export function BelongsTo(options: BelongsToOptions) {
|
|
|
126
153
|
}));
|
|
127
154
|
}
|
|
128
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Decorator to define a BelongsToMany relation on an entity property.
|
|
158
|
+
* @param options - The relation options.
|
|
159
|
+
* @returns A property decorator that registers the relation metadata.
|
|
160
|
+
*/
|
|
129
161
|
export function BelongsToMany(options: BelongsToManyOptions) {
|
|
130
162
|
return createFieldDecorator(propertyName => ({
|
|
131
163
|
kind: RelationKinds.BelongsToMany,
|
package/src/orm/als.ts
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
// In a real Node environment: import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Browser-compatible implementation of AsyncLocalStorage
|
|
5
|
-
* Provides a simple in-memory store for browser environments
|
|
6
|
-
*
|
|
4
|
+
* Browser-compatible implementation of AsyncLocalStorage.
|
|
5
|
+
* Provides a simple in-memory store for browser environments while maintaining
|
|
6
|
+
* Node.js AsyncLocalStorage API compatibility.
|
|
7
|
+
*
|
|
8
|
+
* @template T Type of the data stored in the async context
|
|
7
9
|
*/
|
|
8
10
|
export class AsyncLocalStorage<T> {
|
|
9
11
|
private store: T | undefined;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
|
-
* Executes a callback
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Executes a callback function within a context containing the specified store value.
|
|
15
|
+
* The store value is only available during the callback's execution and is automatically
|
|
16
|
+
* cleared afterward.
|
|
17
|
+
*
|
|
18
|
+
* @param store - The context value to make available during callback execution
|
|
19
|
+
* @param callback - Function to execute with the store value available
|
|
20
|
+
* @returns Result of the callback function execution
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```
|
|
24
|
+
* const als = new AsyncLocalStorage<number>();
|
|
25
|
+
* als.run(42, () => {
|
|
26
|
+
* console.log(als.getStore()); // Outputs: 42
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
16
29
|
*/
|
|
17
30
|
run<R>(store: T, callback: () => R): R {
|
|
18
31
|
this.store = store;
|
|
@@ -24,8 +37,20 @@ export class AsyncLocalStorage<T> {
|
|
|
24
37
|
}
|
|
25
38
|
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
40
|
+
* Retrieves the current store value from the async context.
|
|
41
|
+
* Returns undefined if called outside of a `run()` callback execution.
|
|
42
|
+
*
|
|
43
|
+
* @returns Current store value or undefined if no context exists
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```
|
|
47
|
+
* const als = new AsyncLocalStorage<string>();
|
|
48
|
+
* console.log(als.getStore()); // Outputs: undefined
|
|
49
|
+
*
|
|
50
|
+
* als.run('hello', () => {
|
|
51
|
+
* console.log(als.getStore()); // Outputs: 'hello'
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
29
54
|
*/
|
|
30
55
|
getStore(): T | undefined {
|
|
31
56
|
return this.store;
|