metal-orm 1.1.11 → 1.1.16

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.
Files changed (182) hide show
  1. package/README.md +758 -769
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/package.json +100 -96
  5. package/scripts/generate-entities/schema.mjs +122 -122
  6. package/scripts/generate-entities/tree-detection.mjs +92 -92
  7. package/scripts/inflection/pt-br.mjs +468 -468
  8. package/scripts/run-eslint.mjs +33 -34
  9. package/scripts/show-sql-seed.sql +102 -0
  10. package/scripts/show-sql.mjs +321 -325
  11. package/src/codegen/naming-strategy.ts +54 -54
  12. package/src/codegen/typescript.ts +482 -482
  13. package/src/core/ast/adapters.ts +1 -1
  14. package/src/core/ast/builders.ts +123 -123
  15. package/src/core/ast/expression-builders.ts +745 -745
  16. package/src/core/ast/expression-nodes.ts +304 -304
  17. package/src/core/ast/expression-visitor.ts +212 -212
  18. package/src/core/ast/expression.ts +20 -20
  19. package/src/core/ast/helpers.ts +14 -14
  20. package/src/core/ast/join.ts +18 -18
  21. package/src/core/ast/query.ts +200 -200
  22. package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
  23. package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
  24. package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
  25. package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
  26. package/src/core/ddl/dialects/render-reference.test.ts +70 -70
  27. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
  28. package/src/core/ddl/introspect/catalogs/index.ts +5 -5
  29. package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
  30. package/src/core/ddl/introspect/context.ts +15 -15
  31. package/src/core/ddl/introspect/functions/postgres.ts +35 -35
  32. package/src/core/ddl/introspect/registry.ts +40 -40
  33. package/src/core/ddl/introspect/run-select.ts +35 -35
  34. package/src/core/ddl/introspect/utils.ts +56 -56
  35. package/src/core/ddl/naming-strategy.ts +16 -16
  36. package/src/core/ddl/schema-dialect.ts +56 -56
  37. package/src/core/ddl/schema-diff.ts +234 -234
  38. package/src/core/ddl/schema-generator.ts +1 -1
  39. package/src/core/ddl/schema-introspect.ts +25 -25
  40. package/src/core/ddl/sql-writing.ts +171 -171
  41. package/src/core/dialect/abstract.ts +541 -541
  42. package/src/core/dialect/base/cte-compiler.ts +33 -33
  43. package/src/core/dialect/base/function-table-formatter.ts +103 -103
  44. package/src/core/dialect/base/groupby-compiler.ts +21 -21
  45. package/src/core/dialect/base/join-compiler.ts +25 -25
  46. package/src/core/dialect/base/orderby-compiler.ts +35 -35
  47. package/src/core/dialect/base/pagination-strategy.ts +32 -32
  48. package/src/core/dialect/base/returning-strategy.ts +57 -57
  49. package/src/core/dialect/base/sql-dialect.ts +294 -294
  50. package/src/core/dialect/dialect-factory.ts +91 -91
  51. package/src/core/dialect/mssql/functions.ts +120 -120
  52. package/src/core/dialect/mssql/index.ts +317 -317
  53. package/src/core/dialect/mysql/functions.ts +103 -103
  54. package/src/core/dialect/mysql/index.ts +105 -105
  55. package/src/core/dialect/postgres/functions.ts +108 -108
  56. package/src/core/dialect/postgres/index.ts +91 -91
  57. package/src/core/dialect/sqlite/functions.ts +129 -129
  58. package/src/core/dialect/sqlite/index.ts +67 -67
  59. package/src/core/driver/database-driver.ts +19 -19
  60. package/src/core/driver/mssql-driver.ts +23 -23
  61. package/src/core/driver/mysql-driver.ts +23 -23
  62. package/src/core/driver/postgres-driver.ts +23 -23
  63. package/src/core/driver/sqlite-driver.ts +23 -23
  64. package/src/core/execution/db-executor.ts +92 -92
  65. package/src/core/execution/executors/better-sqlite3-executor.ts +90 -90
  66. package/src/core/execution/executors/mssql-executor.ts +184 -184
  67. package/src/core/execution/executors/mysql-executor.ts +88 -88
  68. package/src/core/execution/executors/postgres-executor.ts +26 -26
  69. package/src/core/execution/executors/sqlite-executor.ts +42 -42
  70. package/src/core/execution/pooling/pool-types.ts +30 -30
  71. package/src/core/execution/pooling/pool.ts +275 -275
  72. package/src/core/functions/array.ts +35 -35
  73. package/src/core/functions/control-flow.ts +79 -79
  74. package/src/core/functions/datetime.ts +237 -237
  75. package/src/core/functions/json.ts +70 -70
  76. package/src/core/functions/numeric.ts +297 -297
  77. package/src/core/functions/text.ts +334 -334
  78. package/src/core/functions/types.ts +33 -33
  79. package/src/core/hydration/types.ts +51 -51
  80. package/src/core/sql/sql-operator-config.ts +39 -39
  81. package/src/core/sql/sql.ts +152 -152
  82. package/src/decorators/column-decorator.ts +87 -87
  83. package/src/decorators/decorator-metadata.ts +143 -143
  84. package/src/decorators/entity.ts +93 -93
  85. package/src/decorators/index.ts +39 -39
  86. package/src/decorators/relations.ts +231 -231
  87. package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
  88. package/src/decorators/transformers/transformer-decorators.ts +134 -134
  89. package/src/decorators/transformers/transformer-executor.ts +171 -171
  90. package/src/decorators/transformers/transformer-metadata.ts +73 -73
  91. package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
  92. package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
  93. package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
  94. package/src/decorators/validators/country-validator-registry.ts +64 -64
  95. package/src/decorators/validators/country-validators-decorators.ts +203 -203
  96. package/src/decorators/validators/country-validators.ts +105 -105
  97. package/src/decorators/validators/validator-metadata.ts +59 -59
  98. package/src/dto/dto-types.ts +226 -226
  99. package/src/dto/filter-types.ts +141 -141
  100. package/src/dto/index.ts +95 -95
  101. package/src/dto/openapi/generators/base.ts +29 -29
  102. package/src/dto/openapi/generators/column.ts +37 -37
  103. package/src/dto/openapi/generators/dto.ts +91 -91
  104. package/src/dto/openapi/generators/filter.ts +75 -75
  105. package/src/dto/openapi/generators/nested-dto.ts +618 -618
  106. package/src/dto/openapi/generators/pagination.ts +111 -111
  107. package/src/dto/openapi/generators/relation-filter.ts +228 -228
  108. package/src/dto/openapi/index.ts +12 -12
  109. package/src/dto/openapi/types.ts +101 -101
  110. package/src/dto/openapi/utilities.ts +95 -95
  111. package/src/dto/pagination-utils.ts +150 -150
  112. package/src/dto/transform.ts +197 -197
  113. package/src/index.ts +86 -86
  114. package/src/orm/als.ts +58 -58
  115. package/src/orm/domain-event-bus.ts +119 -119
  116. package/src/orm/entity-context.ts +86 -86
  117. package/src/orm/entity-materializer.ts +159 -159
  118. package/src/orm/entity-meta.ts +97 -97
  119. package/src/orm/entity-registry.ts +39 -39
  120. package/src/orm/entity-relation-cache.ts +39 -39
  121. package/src/orm/execute.ts +194 -194
  122. package/src/orm/execution-context.ts +18 -18
  123. package/src/orm/hydration-context.ts +26 -26
  124. package/src/orm/hydration.ts +112 -112
  125. package/src/orm/identity-map.ts +61 -61
  126. package/src/orm/interceptor-pipeline.ts +16 -16
  127. package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
  128. package/src/orm/lazy-batch/belongs-to.ts +108 -108
  129. package/src/orm/lazy-batch/has-many.ts +69 -69
  130. package/src/orm/lazy-batch/has-one.ts +68 -68
  131. package/src/orm/lazy-batch/shared.ts +125 -125
  132. package/src/orm/orm-session.ts +620 -620
  133. package/src/orm/orm.ts +34 -34
  134. package/src/orm/pooled-executor-factory.ts +121 -121
  135. package/src/orm/query-logger.ts +40 -40
  136. package/src/orm/relation-change-processor.ts +420 -420
  137. package/src/orm/relations/belongs-to.ts +143 -143
  138. package/src/orm/relations/has-many.ts +204 -204
  139. package/src/orm/relations/has-one.ts +174 -174
  140. package/src/orm/relations/many-to-many.ts +288 -288
  141. package/src/orm/relations/morph-many.ts +156 -156
  142. package/src/orm/relations/morph-one.ts +151 -151
  143. package/src/orm/relations/morph-to.ts +162 -162
  144. package/src/orm/runtime-types.ts +92 -92
  145. package/src/orm/save-graph.ts +561 -561
  146. package/src/orm/transaction-runner.ts +24 -24
  147. package/src/orm/unit-of-work.ts +426 -426
  148. package/src/query/index.ts +69 -69
  149. package/src/query/target.ts +46 -46
  150. package/src/query-builder/column-selector.ts +81 -81
  151. package/src/query-builder/delete.ts +141 -141
  152. package/src/query-builder/insert-query-state.ts +149 -149
  153. package/src/query-builder/insert.ts +117 -117
  154. package/src/query-builder/query-ast-service.ts +287 -287
  155. package/src/query-builder/query-resolution.ts +78 -78
  156. package/src/query-builder/raw-column-parser.ts +38 -38
  157. package/src/query-builder/relation-filter-utils.ts +153 -153
  158. package/src/query-builder/relation-join-planner.ts +10 -10
  159. package/src/query-builder/relation-manager.ts +87 -87
  160. package/src/query-builder/relation-projection-helper.ts +102 -102
  161. package/src/query-builder/relation-types.ts +9 -9
  162. package/src/query-builder/relation-utils.ts +15 -15
  163. package/src/query-builder/select/cte-facet.ts +40 -40
  164. package/src/query-builder/select/from-facet.ts +80 -80
  165. package/src/query-builder/select/join-facet.ts +62 -62
  166. package/src/query-builder/select/predicate-facet.ts +104 -104
  167. package/src/query-builder/select/projection-facet.ts +70 -70
  168. package/src/query-builder/select/relation-facet.ts +81 -81
  169. package/src/query-builder/select/setop-facet.ts +36 -36
  170. package/src/query-builder/select-helpers.ts +1 -1
  171. package/src/query-builder/select-query-builder-deps.ts +130 -130
  172. package/src/query-builder/select-query-state.ts +207 -207
  173. package/src/query-builder/update.ts +151 -151
  174. package/src/schema/column-types.ts +322 -322
  175. package/src/schema/table-guards.ts +37 -37
  176. package/src/schema/table.ts +281 -281
  177. package/src/tree/index.ts +13 -13
  178. package/src/tree/nested-set-strategy.ts +545 -545
  179. package/src/tree/tree-decorator.ts +397 -397
  180. package/src/tree/tree-manager.ts +754 -754
  181. package/src/tree/tree-query.ts +427 -427
  182. package/src/tree/tree-types.ts +299 -299
@@ -1,334 +1,334 @@
1
- // Pure AST Builders - No Dialect Logic Here!
2
-
3
- import { ColumnDef } from '../../schema/column-types.js';
4
- import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
5
- import { FunctionNode, OperandNode, isOperandNode, TypedExpression, asType } from '../ast/expression.js';
6
-
7
- type OperandInput = OperandNode | ColumnDef | string | number | boolean | null;
8
-
9
- const isColumnDef = (val: unknown): val is ColumnDef => !!val && typeof val === 'object' && 'type' in val && 'name' in val;
10
-
11
- const toOperand = (input: OperandInput): OperandNode => {
12
- if (isOperandNode(input)) return input;
13
- if (isColumnDef(input)) return columnOperand(input);
14
-
15
- return valueToOperand(input);
16
- };
17
-
18
- const fn = (key: string, args: OperandInput[]): FunctionNode => ({
19
- type: 'Function',
20
- name: key,
21
- fn: key,
22
- args: args.map(toOperand)
23
- });
24
-
25
- const sfn = (key: string, args: OperandInput[]): TypedExpression<string> => asType<string>(fn(key, args));
26
- const nfn = (key: string, args: OperandInput[]): TypedExpression<number> => asType<number>(fn(key, args));
27
-
28
- /**
29
- * Converts a string to lowercase.
30
- *
31
- * @param value - The string value or column.
32
- * @returns A `TypedExpression<string>` representing the `LOWER` SQL function.
33
- *
34
- * @example
35
- * lower(users.email);
36
- */
37
- export const lower = (value: OperandInput): TypedExpression<string> => sfn('LOWER', [value]);
38
-
39
- /**
40
- * Converts a string to uppercase.
41
- *
42
- * @param value - The string value or column.
43
- * @returns A `TypedExpression<string>` representing the `UPPER` SQL function.
44
- *
45
- * @example
46
- * upper(users.firstName);
47
- */
48
- export const upper = (value: OperandInput): TypedExpression<string> => sfn('UPPER', [value]);
49
-
50
- /**
51
- * Returns the ASCII code of the first character of a string.
52
- *
53
- * @param value - The string value or column.
54
- * @returns A `TypedExpression<number>` representing the `ASCII` SQL function.
55
- *
56
- * @example
57
- * ascii(users.initial);
58
- */
59
- export const ascii = (value: OperandInput): TypedExpression<number> => nfn('ASCII', [value]);
60
-
61
- /**
62
- * Returns a string from one or more ASCII codes.
63
- *
64
- * @param codes - One or more ASCII codes.
65
- * @returns A `TypedExpression<string>` representing the `CHAR` SQL function.
66
- *
67
- * @example
68
- * char(65, 66, 67); // 'ABC'
69
- */
70
- export const char = (...codes: OperandInput[]): TypedExpression<string> => {
71
- if (codes.length === 0) throw new Error('char() expects at least 1 argument');
72
- return sfn('CHAR', codes);
73
- };
74
-
75
- /**
76
- * Returns the number of characters in a string.
77
- *
78
- * @param value - The string value or column.
79
- * @returns A `TypedExpression<number>` representing the `CHAR_LENGTH` SQL function.
80
- *
81
- * @example
82
- * charLength(users.bio);
83
- */
84
- export const charLength = (value: OperandInput): TypedExpression<number> => nfn('CHAR_LENGTH', [value]);
85
-
86
- /**
87
- * Returns the length of a string in bytes or characters.
88
- *
89
- * @param value - The string value or column.
90
- * @returns A `TypedExpression<number>` representing the `LENGTH` SQL function.
91
- *
92
- * @example
93
- * length(users.password);
94
- */
95
- export const length = (value: OperandInput): TypedExpression<number> => nfn('LENGTH', [value]);
96
-
97
- /**
98
- * Removes leading and trailing whitespace or specified characters from a string.
99
- *
100
- * @param value - The string value or column.
101
- * @param chars - Optional characters to trim.
102
- * @returns A `TypedExpression<string>` representing the `TRIM` SQL function.
103
- *
104
- * @example
105
- * trim(users.name);
106
- * trim(users.path, '/');
107
- */
108
- export const trim = (value: OperandInput, chars?: OperandInput): TypedExpression<string> =>
109
- chars === undefined ? sfn('TRIM', [value]) : sfn('TRIM', [value, chars]);
110
-
111
- /**
112
- * Removes leading whitespace from a string.
113
- *
114
- * @param value - The string value or column.
115
- * @returns A `TypedExpression<string>` representing the `LTRIM` SQL function.
116
- */
117
- export const ltrim = (value: OperandInput): TypedExpression<string> => sfn('LTRIM', [value]);
118
-
119
- /**
120
- * Removes trailing whitespace from a string.
121
- *
122
- * @param value - The string value or column.
123
- * @returns A `TypedExpression<string>` representing the `RTRIM` SQL function.
124
- */
125
- export const rtrim = (value: OperandInput): TypedExpression<string> => sfn('RTRIM', [value]);
126
-
127
- /**
128
- * Concatenates two or more strings.
129
- *
130
- * @param args - The strings or columns to concatenate.
131
- * @returns A `TypedExpression<string>` representing the `CONCAT` SQL function.
132
- *
133
- * @example
134
- * concat(users.firstName, ' ', users.lastName);
135
- */
136
- export const concat = (...args: OperandInput[]): TypedExpression<string> => {
137
- if (args.length < 2) throw new Error('concat() expects at least 2 arguments');
138
- return sfn('CONCAT', args);
139
- };
140
-
141
- /**
142
- * Concatenates strings with a separator.
143
- *
144
- * @param separator - The separator string.
145
- * @param args - The strings or columns to concatenate.
146
- * @returns A `TypedExpression<string>` representing the `CONCAT_WS` SQL function.
147
- *
148
- * @example
149
- * concatWs(', ', users.lastName, users.firstName);
150
- */
151
- export const concatWs = (separator: OperandInput, ...args: OperandInput[]): TypedExpression<string> => {
152
- if (args.length < 1) throw new Error('concatWs() expects at least 2 arguments including the separator');
153
- return sfn('CONCAT_WS', [separator, ...args]);
154
- };
155
-
156
- /**
157
- * Extracts a substring from a string.
158
- *
159
- * @param value - The input string or column.
160
- * @param start - The starting position (1-indexed).
161
- * @param length - Optional length of the substring.
162
- * @returns A `TypedExpression<string>` representing the `SUBSTR` SQL function.
163
- *
164
- * @example
165
- * substr(users.token, 1, 8);
166
- */
167
- export const substr = (value: OperandInput, start: OperandInput, length?: OperandInput): TypedExpression<string> =>
168
- length === undefined ? sfn('SUBSTR', [value, start]) : sfn('SUBSTR', [value, start, length]);
169
-
170
- /**
171
- * Returns the leftmost characters of a string.
172
- *
173
- * @param value - The string value or column.
174
- * @param len - Number of characters to return.
175
- * @returns A `TypedExpression<string>` representing the `LEFT` SQL function.
176
- */
177
- export const left = (value: OperandInput, len: OperandInput): TypedExpression<string> => sfn('LEFT', [value, len]);
178
-
179
- /**
180
- * Returns the rightmost characters of a string.
181
- *
182
- * @param value - The string value or column.
183
- * @param len - Number of characters to return.
184
- * @returns A `TypedExpression<string>` representing the `RIGHT` SQL function.
185
- */
186
- export const right = (value: OperandInput, len: OperandInput): TypedExpression<string> => sfn('RIGHT', [value, len]);
187
-
188
- /**
189
- * Returns the position of a substring in a string.
190
- *
191
- * @param substring - The substring to search for.
192
- * @param value - The string or column to search within.
193
- * @returns A `TypedExpression<number>` representing the `POSITION` SQL function.
194
- */
195
- export const position = (substring: OperandInput, value: OperandInput): TypedExpression<number> => nfn('POSITION', [substring, value]);
196
-
197
- /**
198
- * Returns the position of a substring in a string.
199
- *
200
- * @param value - The string or column to search within.
201
- * @param substring - The substring to search for.
202
- * @returns A `TypedExpression<number>` representing the `INSTR` SQL function.
203
- */
204
- export const instr = (value: OperandInput, substring: OperandInput): TypedExpression<number> => nfn('INSTR', [value, substring]);
205
-
206
- /**
207
- * Returns the position of a substring in a string, optionally starting from a position.
208
- *
209
- * @param substring - Substring to find.
210
- * @param value - String/column to search.
211
- * @param start - Optional starting position.
212
- * @returns A `TypedExpression<number>` representing the `LOCATE` SQL function.
213
- */
214
- export const locate = (substring: OperandInput, value: OperandInput, start?: OperandInput): TypedExpression<number> =>
215
- start === undefined ? nfn('LOCATE', [substring, value]) : nfn('LOCATE', [substring, value, start]);
216
-
217
- /**
218
- * Replaces occurrences of a substring in a string.
219
- *
220
- * @param value - The original string or column.
221
- * @param search - Substring to search for.
222
- * @param replacement - Replacement string.
223
- * @returns A `TypedExpression<string>` representing the `REPLACE` SQL function.
224
- *
225
- * @example
226
- * replace(users.email, 'old.com', 'new.com');
227
- */
228
- export const replace = (value: OperandInput, search: OperandInput, replacement: OperandInput): TypedExpression<string> =>
229
- sfn('REPLACE', [value, search, replacement]);
230
-
231
- /**
232
- * Repeats a string a specified number of times.
233
- *
234
- * @param value - The string to repeat.
235
- * @param count - How many times to repeat.
236
- * @returns A `TypedExpression<string>` representing the `REPEAT` SQL function.
237
- */
238
- export const repeat = (value: OperandInput, count: OperandInput): TypedExpression<string> => sfn('REPEAT', [value, count]);
239
-
240
- /**
241
- * Left-pads a string to a certain length with another string.
242
- *
243
- * @param value - The string/column to pad.
244
- * @param len - Target length.
245
- * @param pad - Padding string.
246
- * @returns A `TypedExpression<string>` representing the `LPAD` SQL function.
247
- */
248
- export const lpad = (value: OperandInput, len: OperandInput, pad: OperandInput): TypedExpression<string> =>
249
- sfn('LPAD', [value, len, pad]);
250
-
251
- /**
252
- * Right-pads a string to a certain length with another string.
253
- *
254
- * @param value - The string/column to pad.
255
- * @param len - Target length.
256
- * @param pad - Padding string.
257
- * @returns A `TypedExpression<string>` representing the `RPAD` SQL function.
258
- */
259
- export const rpad = (value: OperandInput, len: OperandInput, pad: OperandInput): TypedExpression<string> =>
260
- sfn('RPAD', [value, len, pad]);
261
-
262
- /**
263
- * Returns a string consisting of a specified number of spaces.
264
- *
265
- * @param count - Number of spaces.
266
- * @returns A `TypedExpression<string>` representing the `SPACE` SQL function.
267
- */
268
- export const space = (count: OperandInput): TypedExpression<string> => sfn('SPACE', [count]);
269
-
270
- /**
271
- * Reverses a string.
272
- *
273
- * @param value - The string value or column.
274
- * @returns A `TypedExpression<string>` representing the `REVERSE` SQL function.
275
- */
276
- export const reverse = (value: OperandInput): TypedExpression<string> => sfn('REVERSE', [value]);
277
-
278
- /**
279
- * Capitalizes the first letter of each word in a string.
280
- *
281
- * @param value - The string value or column.
282
- * @returns A `TypedExpression<string>` representing the `INITCAP` SQL function.
283
- */
284
- export const initcap = (value: OperandInput): TypedExpression<string> => sfn('INITCAP', [value]);
285
-
286
- /**
287
- * Returns the MD5 hash of a string.
288
- *
289
- * @param value - The string value or column.
290
- * @returns A `TypedExpression<string>` representing the `MD5` SQL function.
291
- */
292
- export const md5 = (value: OperandInput): TypedExpression<string> => sfn('MD5', [value]);
293
-
294
- /**
295
- * Returns the SHA-1 hash of a string.
296
- *
297
- * @param value - The string value or column.
298
- * @returns A `TypedExpression<string>` representing the `SHA1` SQL function.
299
- */
300
- export const sha1 = (value: OperandInput): TypedExpression<string> => sfn('SHA1', [value]);
301
-
302
- /**
303
- * Returns the SHA-2 hash of a string with a specified bit length.
304
- *
305
- * @param value - The input.
306
- * @param bits - Bit length (e.g., 256, 512).
307
- * @returns A `TypedExpression<string>` representing the `SHA2` SQL function.
308
- */
309
- export const sha2 = (value: OperandInput, bits: OperandInput): TypedExpression<string> => sfn('SHA2', [value, bits]);
310
-
311
- /**
312
- * Returns the length of a string in bits.
313
- *
314
- * @param value - String value or column.
315
- * @returns A `TypedExpression<number>` representing the `BIT_LENGTH` SQL function.
316
- */
317
- export const bitLength = (value: OperandInput): TypedExpression<number> => nfn('BIT_LENGTH', [value]);
318
-
319
- /**
320
- * Returns the length of a string in bytes.
321
- *
322
- * @param value - String value or column.
323
- * @returns A `TypedExpression<number>` representing the `OCTET_LENGTH` SQL function.
324
- */
325
- export const octetLength = (value: OperandInput): TypedExpression<number> => nfn('OCTET_LENGTH', [value]);
326
-
327
- /**
328
- * Returns a string from an ASCII code.
329
- *
330
- * @param code - ASCII code.
331
- * @returns A `TypedExpression<string>` representing the `CHR` SQL function.
332
- */
333
- export const chr = (code: OperandInput): TypedExpression<string> => sfn('CHR', [code]);
334
-
1
+ // Pure AST Builders - No Dialect Logic Here!
2
+
3
+ import { ColumnDef } from '../../schema/column-types.js';
4
+ import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
5
+ import { FunctionNode, OperandNode, isOperandNode, TypedExpression, asType } from '../ast/expression.js';
6
+
7
+ type OperandInput = OperandNode | ColumnDef | string | number | boolean | null;
8
+
9
+ const isColumnDef = (val: unknown): val is ColumnDef => !!val && typeof val === 'object' && 'type' in val && 'name' in val;
10
+
11
+ const toOperand = (input: OperandInput): OperandNode => {
12
+ if (isOperandNode(input)) return input;
13
+ if (isColumnDef(input)) return columnOperand(input);
14
+
15
+ return valueToOperand(input);
16
+ };
17
+
18
+ const fn = (key: string, args: OperandInput[]): FunctionNode => ({
19
+ type: 'Function',
20
+ name: key,
21
+ fn: key,
22
+ args: args.map(toOperand)
23
+ });
24
+
25
+ const sfn = (key: string, args: OperandInput[]): TypedExpression<string> => asType<string>(fn(key, args));
26
+ const nfn = (key: string, args: OperandInput[]): TypedExpression<number> => asType<number>(fn(key, args));
27
+
28
+ /**
29
+ * Converts a string to lowercase.
30
+ *
31
+ * @param value - The string value or column.
32
+ * @returns A `TypedExpression<string>` representing the `LOWER` SQL function.
33
+ *
34
+ * @example
35
+ * lower(users.email);
36
+ */
37
+ export const lower = (value: OperandInput): TypedExpression<string> => sfn('LOWER', [value]);
38
+
39
+ /**
40
+ * Converts a string to uppercase.
41
+ *
42
+ * @param value - The string value or column.
43
+ * @returns A `TypedExpression<string>` representing the `UPPER` SQL function.
44
+ *
45
+ * @example
46
+ * upper(users.firstName);
47
+ */
48
+ export const upper = (value: OperandInput): TypedExpression<string> => sfn('UPPER', [value]);
49
+
50
+ /**
51
+ * Returns the ASCII code of the first character of a string.
52
+ *
53
+ * @param value - The string value or column.
54
+ * @returns A `TypedExpression<number>` representing the `ASCII` SQL function.
55
+ *
56
+ * @example
57
+ * ascii(users.initial);
58
+ */
59
+ export const ascii = (value: OperandInput): TypedExpression<number> => nfn('ASCII', [value]);
60
+
61
+ /**
62
+ * Returns a string from one or more ASCII codes.
63
+ *
64
+ * @param codes - One or more ASCII codes.
65
+ * @returns A `TypedExpression<string>` representing the `CHAR` SQL function.
66
+ *
67
+ * @example
68
+ * char(65, 66, 67); // 'ABC'
69
+ */
70
+ export const char = (...codes: OperandInput[]): TypedExpression<string> => {
71
+ if (codes.length === 0) throw new Error('char() expects at least 1 argument');
72
+ return sfn('CHAR', codes);
73
+ };
74
+
75
+ /**
76
+ * Returns the number of characters in a string.
77
+ *
78
+ * @param value - The string value or column.
79
+ * @returns A `TypedExpression<number>` representing the `CHAR_LENGTH` SQL function.
80
+ *
81
+ * @example
82
+ * charLength(users.bio);
83
+ */
84
+ export const charLength = (value: OperandInput): TypedExpression<number> => nfn('CHAR_LENGTH', [value]);
85
+
86
+ /**
87
+ * Returns the length of a string in bytes or characters.
88
+ *
89
+ * @param value - The string value or column.
90
+ * @returns A `TypedExpression<number>` representing the `LENGTH` SQL function.
91
+ *
92
+ * @example
93
+ * length(users.password);
94
+ */
95
+ export const length = (value: OperandInput): TypedExpression<number> => nfn('LENGTH', [value]);
96
+
97
+ /**
98
+ * Removes leading and trailing whitespace or specified characters from a string.
99
+ *
100
+ * @param value - The string value or column.
101
+ * @param chars - Optional characters to trim.
102
+ * @returns A `TypedExpression<string>` representing the `TRIM` SQL function.
103
+ *
104
+ * @example
105
+ * trim(users.name);
106
+ * trim(users.path, '/');
107
+ */
108
+ export const trim = (value: OperandInput, chars?: OperandInput): TypedExpression<string> =>
109
+ chars === undefined ? sfn('TRIM', [value]) : sfn('TRIM', [value, chars]);
110
+
111
+ /**
112
+ * Removes leading whitespace from a string.
113
+ *
114
+ * @param value - The string value or column.
115
+ * @returns A `TypedExpression<string>` representing the `LTRIM` SQL function.
116
+ */
117
+ export const ltrim = (value: OperandInput): TypedExpression<string> => sfn('LTRIM', [value]);
118
+
119
+ /**
120
+ * Removes trailing whitespace from a string.
121
+ *
122
+ * @param value - The string value or column.
123
+ * @returns A `TypedExpression<string>` representing the `RTRIM` SQL function.
124
+ */
125
+ export const rtrim = (value: OperandInput): TypedExpression<string> => sfn('RTRIM', [value]);
126
+
127
+ /**
128
+ * Concatenates two or more strings.
129
+ *
130
+ * @param args - The strings or columns to concatenate.
131
+ * @returns A `TypedExpression<string>` representing the `CONCAT` SQL function.
132
+ *
133
+ * @example
134
+ * concat(users.firstName, ' ', users.lastName);
135
+ */
136
+ export const concat = (...args: OperandInput[]): TypedExpression<string> => {
137
+ if (args.length < 2) throw new Error('concat() expects at least 2 arguments');
138
+ return sfn('CONCAT', args);
139
+ };
140
+
141
+ /**
142
+ * Concatenates strings with a separator.
143
+ *
144
+ * @param separator - The separator string.
145
+ * @param args - The strings or columns to concatenate.
146
+ * @returns A `TypedExpression<string>` representing the `CONCAT_WS` SQL function.
147
+ *
148
+ * @example
149
+ * concatWs(', ', users.lastName, users.firstName);
150
+ */
151
+ export const concatWs = (separator: OperandInput, ...args: OperandInput[]): TypedExpression<string> => {
152
+ if (args.length < 1) throw new Error('concatWs() expects at least 2 arguments including the separator');
153
+ return sfn('CONCAT_WS', [separator, ...args]);
154
+ };
155
+
156
+ /**
157
+ * Extracts a substring from a string.
158
+ *
159
+ * @param value - The input string or column.
160
+ * @param start - The starting position (1-indexed).
161
+ * @param length - Optional length of the substring.
162
+ * @returns A `TypedExpression<string>` representing the `SUBSTR` SQL function.
163
+ *
164
+ * @example
165
+ * substr(users.token, 1, 8);
166
+ */
167
+ export const substr = (value: OperandInput, start: OperandInput, length?: OperandInput): TypedExpression<string> =>
168
+ length === undefined ? sfn('SUBSTR', [value, start]) : sfn('SUBSTR', [value, start, length]);
169
+
170
+ /**
171
+ * Returns the leftmost characters of a string.
172
+ *
173
+ * @param value - The string value or column.
174
+ * @param len - Number of characters to return.
175
+ * @returns A `TypedExpression<string>` representing the `LEFT` SQL function.
176
+ */
177
+ export const left = (value: OperandInput, len: OperandInput): TypedExpression<string> => sfn('LEFT', [value, len]);
178
+
179
+ /**
180
+ * Returns the rightmost characters of a string.
181
+ *
182
+ * @param value - The string value or column.
183
+ * @param len - Number of characters to return.
184
+ * @returns A `TypedExpression<string>` representing the `RIGHT` SQL function.
185
+ */
186
+ export const right = (value: OperandInput, len: OperandInput): TypedExpression<string> => sfn('RIGHT', [value, len]);
187
+
188
+ /**
189
+ * Returns the position of a substring in a string.
190
+ *
191
+ * @param substring - The substring to search for.
192
+ * @param value - The string or column to search within.
193
+ * @returns A `TypedExpression<number>` representing the `POSITION` SQL function.
194
+ */
195
+ export const position = (substring: OperandInput, value: OperandInput): TypedExpression<number> => nfn('POSITION', [substring, value]);
196
+
197
+ /**
198
+ * Returns the position of a substring in a string.
199
+ *
200
+ * @param value - The string or column to search within.
201
+ * @param substring - The substring to search for.
202
+ * @returns A `TypedExpression<number>` representing the `INSTR` SQL function.
203
+ */
204
+ export const instr = (value: OperandInput, substring: OperandInput): TypedExpression<number> => nfn('INSTR', [value, substring]);
205
+
206
+ /**
207
+ * Returns the position of a substring in a string, optionally starting from a position.
208
+ *
209
+ * @param substring - Substring to find.
210
+ * @param value - String/column to search.
211
+ * @param start - Optional starting position.
212
+ * @returns A `TypedExpression<number>` representing the `LOCATE` SQL function.
213
+ */
214
+ export const locate = (substring: OperandInput, value: OperandInput, start?: OperandInput): TypedExpression<number> =>
215
+ start === undefined ? nfn('LOCATE', [substring, value]) : nfn('LOCATE', [substring, value, start]);
216
+
217
+ /**
218
+ * Replaces occurrences of a substring in a string.
219
+ *
220
+ * @param value - The original string or column.
221
+ * @param search - Substring to search for.
222
+ * @param replacement - Replacement string.
223
+ * @returns A `TypedExpression<string>` representing the `REPLACE` SQL function.
224
+ *
225
+ * @example
226
+ * replace(users.email, 'old.com', 'new.com');
227
+ */
228
+ export const replace = (value: OperandInput, search: OperandInput, replacement: OperandInput): TypedExpression<string> =>
229
+ sfn('REPLACE', [value, search, replacement]);
230
+
231
+ /**
232
+ * Repeats a string a specified number of times.
233
+ *
234
+ * @param value - The string to repeat.
235
+ * @param count - How many times to repeat.
236
+ * @returns A `TypedExpression<string>` representing the `REPEAT` SQL function.
237
+ */
238
+ export const repeat = (value: OperandInput, count: OperandInput): TypedExpression<string> => sfn('REPEAT', [value, count]);
239
+
240
+ /**
241
+ * Left-pads a string to a certain length with another string.
242
+ *
243
+ * @param value - The string/column to pad.
244
+ * @param len - Target length.
245
+ * @param pad - Padding string.
246
+ * @returns A `TypedExpression<string>` representing the `LPAD` SQL function.
247
+ */
248
+ export const lpad = (value: OperandInput, len: OperandInput, pad: OperandInput): TypedExpression<string> =>
249
+ sfn('LPAD', [value, len, pad]);
250
+
251
+ /**
252
+ * Right-pads a string to a certain length with another string.
253
+ *
254
+ * @param value - The string/column to pad.
255
+ * @param len - Target length.
256
+ * @param pad - Padding string.
257
+ * @returns A `TypedExpression<string>` representing the `RPAD` SQL function.
258
+ */
259
+ export const rpad = (value: OperandInput, len: OperandInput, pad: OperandInput): TypedExpression<string> =>
260
+ sfn('RPAD', [value, len, pad]);
261
+
262
+ /**
263
+ * Returns a string consisting of a specified number of spaces.
264
+ *
265
+ * @param count - Number of spaces.
266
+ * @returns A `TypedExpression<string>` representing the `SPACE` SQL function.
267
+ */
268
+ export const space = (count: OperandInput): TypedExpression<string> => sfn('SPACE', [count]);
269
+
270
+ /**
271
+ * Reverses a string.
272
+ *
273
+ * @param value - The string value or column.
274
+ * @returns A `TypedExpression<string>` representing the `REVERSE` SQL function.
275
+ */
276
+ export const reverse = (value: OperandInput): TypedExpression<string> => sfn('REVERSE', [value]);
277
+
278
+ /**
279
+ * Capitalizes the first letter of each word in a string.
280
+ *
281
+ * @param value - The string value or column.
282
+ * @returns A `TypedExpression<string>` representing the `INITCAP` SQL function.
283
+ */
284
+ export const initcap = (value: OperandInput): TypedExpression<string> => sfn('INITCAP', [value]);
285
+
286
+ /**
287
+ * Returns the MD5 hash of a string.
288
+ *
289
+ * @param value - The string value or column.
290
+ * @returns A `TypedExpression<string>` representing the `MD5` SQL function.
291
+ */
292
+ export const md5 = (value: OperandInput): TypedExpression<string> => sfn('MD5', [value]);
293
+
294
+ /**
295
+ * Returns the SHA-1 hash of a string.
296
+ *
297
+ * @param value - The string value or column.
298
+ * @returns A `TypedExpression<string>` representing the `SHA1` SQL function.
299
+ */
300
+ export const sha1 = (value: OperandInput): TypedExpression<string> => sfn('SHA1', [value]);
301
+
302
+ /**
303
+ * Returns the SHA-2 hash of a string with a specified bit length.
304
+ *
305
+ * @param value - The input.
306
+ * @param bits - Bit length (e.g., 256, 512).
307
+ * @returns A `TypedExpression<string>` representing the `SHA2` SQL function.
308
+ */
309
+ export const sha2 = (value: OperandInput, bits: OperandInput): TypedExpression<string> => sfn('SHA2', [value, bits]);
310
+
311
+ /**
312
+ * Returns the length of a string in bits.
313
+ *
314
+ * @param value - String value or column.
315
+ * @returns A `TypedExpression<number>` representing the `BIT_LENGTH` SQL function.
316
+ */
317
+ export const bitLength = (value: OperandInput): TypedExpression<number> => nfn('BIT_LENGTH', [value]);
318
+
319
+ /**
320
+ * Returns the length of a string in bytes.
321
+ *
322
+ * @param value - String value or column.
323
+ * @returns A `TypedExpression<number>` representing the `OCTET_LENGTH` SQL function.
324
+ */
325
+ export const octetLength = (value: OperandInput): TypedExpression<number> => nfn('OCTET_LENGTH', [value]);
326
+
327
+ /**
328
+ * Returns a string from an ASCII code.
329
+ *
330
+ * @param code - ASCII code.
331
+ * @returns A `TypedExpression<string>` representing the `CHR` SQL function.
332
+ */
333
+ export const chr = (code: OperandInput): TypedExpression<string> => sfn('CHR', [code]);
334
+