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,222 +1,222 @@
1
- import { OrderingTerm, SelectQueryNode } from '../core/ast/query.js';
2
- import {
3
- ExpressionNode,
4
- OperandNode,
1
+ import { OrderingTerm, SelectQueryNode } from '../core/ast/query.js';
2
+ import {
3
+ ExpressionNode,
4
+ OperandNode,
5
5
  BinaryExpressionNode,
6
6
  LogicalExpressionNode,
7
7
  NotExpressionNode,
8
8
  InExpressionNode,
9
- NullExpressionNode,
10
- JsonPathNode,
11
- ExistsExpressionNode,
12
- BetweenExpressionNode,
13
- ScalarSubqueryNode,
14
- CaseExpressionNode,
15
- WindowFunctionNode,
16
- ArithmeticExpressionNode,
17
- ColumnNode,
18
- LiteralNode,
19
- FunctionNode,
20
- AliasRefNode,
21
- CastExpressionNode,
22
- CollateExpressionNode,
23
- ExpressionVisitor,
24
- OperandVisitor,
25
- visitExpression,
26
- visitOperand
27
- } from '../core/ast/expression.js';
28
- import { SQL_OPERATOR_REGISTRY } from '../core/sql/sql-operator-config.js';
29
- import { SqlOperator } from '../core/sql/sql.js';
30
- import { isRelationAlias } from '../query-builder/relation-alias.js';
31
- import { HydrationMetadata } from '../core/hydration/types.js';
32
- import { getJoinRelationName } from '../core/ast/join-metadata.js';
33
- import { NamingStrategy, DefaultNamingStrategy } from './naming-strategy.js';
34
-
35
- const assertNever = (value: never): never => {
36
- throw new Error(`Unhandled SQL operator: ${value}`);
37
- };
38
-
39
- /**
40
- * Generates TypeScript code from query AST nodes
41
- */
42
- type SelectionColumn =
43
- | ColumnNode
44
- | FunctionNode
45
- | ScalarSubqueryNode
46
- | CaseExpressionNode
47
- | WindowFunctionNode
48
- | CastExpressionNode;
49
-
50
- export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVisitor<string> {
51
- constructor(private namingStrategy: NamingStrategy = new DefaultNamingStrategy()) { }
52
-
53
- /**
54
- * Generates TypeScript code from a query AST
55
- * @param ast - Query AST to generate code from
56
- * @returns Generated TypeScript code
57
- */
58
- generate(ast: SelectQueryNode): string {
59
- const chainLines = this.buildSelectLines(ast);
60
- const lines = chainLines.map((line, index) => (index === 0 ? `const query = ${line}` : line));
61
- lines.push(';', '', 'await query.execute();');
62
- return lines.join('\n');
63
- }
64
-
65
- /**
66
- * Builds TypeScript method chain lines from query AST
67
- * @param ast - Query AST
68
- * @returns Array of TypeScript method chain lines
69
- */
70
- private buildSelectLines(ast: SelectQueryNode): string[] {
71
- const lines: string[] = [];
72
- const hydration = (ast.meta as HydrationMetadata | undefined)?.hydration;
73
- const hydratedRelations = new Set(hydration?.relations?.map(r => r.name) ?? []);
74
-
75
- const selections = ast.columns
76
- .filter((col): col is SelectionColumn => !(hydration && isRelationAlias(col.alias)))
77
- .map((col, index) => `${this.getSelectionKey(col, index)}: ${this.printOperand(col)}`);
78
-
79
- lines.push(`db.select({`);
80
- selections.forEach((sel, index) => {
81
- lines.push(` ${sel}${index < selections.length - 1 ? ',' : ''}`);
82
- });
83
- lines.push(`})`);
84
- lines.push(`.from(${this.namingStrategy.tableToSymbol(ast.from)})`);
85
-
86
- if (ast.distinct && ast.distinct.length) {
87
- const cols = ast.distinct.map(c => `${this.namingStrategy.tableToSymbol(c.table)}.${c.name}`).join(', ');
88
- lines.push(`.distinct(${cols})`);
89
- }
90
-
91
- ast.joins.forEach(join => {
92
- const relationName = getJoinRelationName(join);
93
- if (relationName && hydratedRelations.has(relationName)) {
94
- return;
95
- }
96
-
97
- if (relationName) {
98
- if (join.kind === 'INNER') {
99
- lines.push(`.joinRelation('${relationName}')`);
100
- } else {
101
- lines.push(`.joinRelation('${relationName}', '${join.kind}')`);
102
- }
103
- } else {
104
- const table = this.namingStrategy.tableToSymbol(join.table);
105
- const cond = this.printExpression(join.condition);
106
- let method = 'innerJoin';
107
- if (join.kind === 'LEFT') method = 'leftJoin';
108
- if (join.kind === 'RIGHT') method = 'rightJoin';
109
- lines.push(`.${method}(${table}, ${cond})`);
110
- }
111
- });
112
-
113
- if (hydration?.relations?.length) {
114
- hydration.relations.forEach(rel => {
115
- const options: string[] = [];
116
- if (rel.columns.length) options.push(`columns: [${rel.columns.map(c => `'${c}'`).join(', ')}]`);
117
- if (rel.aliasPrefix !== rel.name) options.push(`aliasPrefix: '${rel.aliasPrefix}'`);
118
- const opts = options.length ? `, { ${options.join(', ')} }` : '';
119
- lines.push(`.include('${rel.name}'${opts})`);
120
- });
121
- }
122
-
123
- if (ast.where) {
124
- lines.push(`.where(${this.printExpression(ast.where)})`);
125
- }
126
-
127
- if (ast.groupBy && ast.groupBy.length) {
128
- const cols = ast.groupBy.map(term => this.printOrderingTerm(term)).join(', ');
129
- lines.push(`.groupBy(${cols})`);
130
- }
131
-
132
- if (ast.having) {
133
- lines.push(`.having(${this.printExpression(ast.having)})`);
134
- }
135
-
136
- if (ast.orderBy && ast.orderBy.length) {
137
- ast.orderBy.forEach(o => {
138
- const term = this.printOrderingTerm(o.term);
139
- const opts: string[] = [`direction: '${o.direction}'`];
140
- if (o.nulls) opts.push(`nulls: '${o.nulls}'`);
141
- if (o.collation) opts.push(`collation: '${o.collation}'`);
142
- const hasOpts = opts.length > 1;
143
- if (hasOpts) {
144
- lines.push(`.orderBy(${term}, { ${opts.join(', ')} })`);
145
- } else {
146
- lines.push(`.orderBy(${term}, '${o.direction}')`);
147
- }
148
- });
149
- }
150
-
151
- if (ast.limit) lines.push(`.limit(${ast.limit})`);
152
- if (ast.offset) lines.push(`.offset(${ast.offset})`);
153
-
154
- return lines;
155
- }
156
-
157
- /**
158
- * Prints an expression node to TypeScript code
159
- * @param expr - Expression node to print
160
- * @returns TypeScript code representation
161
- */
162
- private printExpression(expr: ExpressionNode): string {
163
- return visitExpression(expr, this);
164
- }
165
-
166
- /**
167
- * Prints an operand node to TypeScript code
168
- * @param node - Operand node to print
169
- * @returns TypeScript code representation
170
- */
171
- private printOperand(node: OperandNode): string {
172
- return visitOperand(node, this);
173
- }
174
-
175
- /**
176
- * Prints an ordering term (operand/expression/alias) to TypeScript code.
177
- */
178
- private printOrderingTerm(term: OrderingTerm): string {
179
- if (!term || !('type' in term)) {
180
- throw new Error('Unsupported ordering term');
181
- }
182
-
183
- switch (term.type) {
184
- case 'Column':
185
- return `${this.namingStrategy.tableToSymbol(term.table)}.${term.name}`;
186
- case 'AliasRef':
187
- return this.visitAliasRef(term);
188
- case 'Literal':
189
- case 'Function':
190
- case 'JsonPath':
191
- case 'ScalarSubquery':
192
- case 'CaseExpression':
193
- case 'WindowFunction':
194
- case 'Cast':
195
- case 'Collate':
196
- return this.printOperand(term);
197
- default:
198
- return this.printExpression(term);
199
- }
200
- }
201
-
202
- private getSelectionKey(selection: SelectionColumn, index: number): string {
203
- if (selection.alias) {
204
- return selection.alias;
205
- }
206
- if (this.isNamedSelection(selection)) {
207
- return selection.name;
208
- }
209
- return `selection${index + 1}`;
210
- }
211
-
212
- private isNamedSelection(selection: SelectionColumn): selection is ColumnNode | FunctionNode | WindowFunctionNode {
213
- return 'name' in selection;
214
- }
215
-
216
- public visitBinaryExpression(binary: BinaryExpressionNode): string {
217
- return this.printBinaryExpression(binary);
218
- }
219
-
9
+ NullExpressionNode,
10
+ JsonPathNode,
11
+ ExistsExpressionNode,
12
+ BetweenExpressionNode,
13
+ ScalarSubqueryNode,
14
+ CaseExpressionNode,
15
+ WindowFunctionNode,
16
+ ArithmeticExpressionNode,
17
+ ColumnNode,
18
+ LiteralNode,
19
+ FunctionNode,
20
+ AliasRefNode,
21
+ CastExpressionNode,
22
+ CollateExpressionNode,
23
+ ExpressionVisitor,
24
+ OperandVisitor,
25
+ visitExpression,
26
+ visitOperand
27
+ } from '../core/ast/expression.js';
28
+ import { SQL_OPERATOR_REGISTRY } from '../core/sql/sql-operator-config.js';
29
+ import { SqlOperator } from '../core/sql/sql.js';
30
+ import { isRelationAlias } from '../query-builder/relation-alias.js';
31
+ import { HydrationMetadata } from '../core/hydration/types.js';
32
+ import { getJoinRelationName } from '../core/ast/join-metadata.js';
33
+ import { NamingStrategy, DefaultNamingStrategy } from './naming-strategy.js';
34
+
35
+ const assertNever = (value: never): never => {
36
+ throw new Error(`Unhandled SQL operator: ${value}`);
37
+ };
38
+
39
+ /**
40
+ * Generates TypeScript code from query AST nodes
41
+ */
42
+ type SelectionColumn =
43
+ | ColumnNode
44
+ | FunctionNode
45
+ | ScalarSubqueryNode
46
+ | CaseExpressionNode
47
+ | WindowFunctionNode
48
+ | CastExpressionNode;
49
+
50
+ export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVisitor<string> {
51
+ constructor(private namingStrategy: NamingStrategy = new DefaultNamingStrategy()) { }
52
+
53
+ /**
54
+ * Generates TypeScript code from a query AST
55
+ * @param ast - Query AST to generate code from
56
+ * @returns Generated TypeScript code
57
+ */
58
+ generate(ast: SelectQueryNode): string {
59
+ const chainLines = this.buildSelectLines(ast);
60
+ const lines = chainLines.map((line, index) => (index === 0 ? `const query = ${line}` : line));
61
+ lines.push(';', '', 'await query.execute();');
62
+ return lines.join('\n');
63
+ }
64
+
65
+ /**
66
+ * Builds TypeScript method chain lines from query AST
67
+ * @param ast - Query AST
68
+ * @returns Array of TypeScript method chain lines
69
+ */
70
+ private buildSelectLines(ast: SelectQueryNode): string[] {
71
+ const lines: string[] = [];
72
+ const hydration = (ast.meta as HydrationMetadata | undefined)?.hydration;
73
+ const hydratedRelations = new Set(hydration?.relations?.map(r => r.name) ?? []);
74
+
75
+ const selections = ast.columns
76
+ .filter((col): col is SelectionColumn => !(hydration && isRelationAlias(col.alias)))
77
+ .map((col, index) => `${this.getSelectionKey(col, index)}: ${this.printOperand(col)}`);
78
+
79
+ lines.push(`db.select({`);
80
+ selections.forEach((sel, index) => {
81
+ lines.push(` ${sel}${index < selections.length - 1 ? ',' : ''}`);
82
+ });
83
+ lines.push(`})`);
84
+ lines.push(`.from(${this.namingStrategy.tableToSymbol(ast.from)})`);
85
+
86
+ if (ast.distinct && ast.distinct.length) {
87
+ const cols = ast.distinct.map(c => `${this.namingStrategy.tableToSymbol(c.table)}.${c.name}`).join(', ');
88
+ lines.push(`.distinct(${cols})`);
89
+ }
90
+
91
+ ast.joins.forEach(join => {
92
+ const relationName = getJoinRelationName(join);
93
+ if (relationName && hydratedRelations.has(relationName)) {
94
+ return;
95
+ }
96
+
97
+ if (relationName) {
98
+ if (join.kind === 'INNER') {
99
+ lines.push(`.joinRelation('${relationName}')`);
100
+ } else {
101
+ lines.push(`.joinRelation('${relationName}', '${join.kind}')`);
102
+ }
103
+ } else {
104
+ const table = this.namingStrategy.tableToSymbol(join.table);
105
+ const cond = this.printExpression(join.condition);
106
+ let method = 'innerJoin';
107
+ if (join.kind === 'LEFT') method = 'leftJoin';
108
+ if (join.kind === 'RIGHT') method = 'rightJoin';
109
+ lines.push(`.${method}(${table}, ${cond})`);
110
+ }
111
+ });
112
+
113
+ if (hydration?.relations?.length) {
114
+ hydration.relations.forEach(rel => {
115
+ const options: string[] = [];
116
+ if (rel.columns.length) options.push(`columns: [${rel.columns.map(c => `'${c}'`).join(', ')}]`);
117
+ if (rel.aliasPrefix !== rel.name) options.push(`aliasPrefix: '${rel.aliasPrefix}'`);
118
+ const opts = options.length ? `, { ${options.join(', ')} }` : '';
119
+ lines.push(`.include('${rel.name}'${opts})`);
120
+ });
121
+ }
122
+
123
+ if (ast.where) {
124
+ lines.push(`.where(${this.printExpression(ast.where)})`);
125
+ }
126
+
127
+ if (ast.groupBy && ast.groupBy.length) {
128
+ const cols = ast.groupBy.map(term => this.printOrderingTerm(term)).join(', ');
129
+ lines.push(`.groupBy(${cols})`);
130
+ }
131
+
132
+ if (ast.having) {
133
+ lines.push(`.having(${this.printExpression(ast.having)})`);
134
+ }
135
+
136
+ if (ast.orderBy && ast.orderBy.length) {
137
+ ast.orderBy.forEach(o => {
138
+ const term = this.printOrderingTerm(o.term);
139
+ const opts: string[] = [`direction: '${o.direction}'`];
140
+ if (o.nulls) opts.push(`nulls: '${o.nulls}'`);
141
+ if (o.collation) opts.push(`collation: '${o.collation}'`);
142
+ const hasOpts = opts.length > 1;
143
+ if (hasOpts) {
144
+ lines.push(`.orderBy(${term}, { ${opts.join(', ')} })`);
145
+ } else {
146
+ lines.push(`.orderBy(${term}, '${o.direction}')`);
147
+ }
148
+ });
149
+ }
150
+
151
+ if (ast.limit) lines.push(`.limit(${ast.limit})`);
152
+ if (ast.offset) lines.push(`.offset(${ast.offset})`);
153
+
154
+ return lines;
155
+ }
156
+
157
+ /**
158
+ * Prints an expression node to TypeScript code
159
+ * @param expr - Expression node to print
160
+ * @returns TypeScript code representation
161
+ */
162
+ private printExpression(expr: ExpressionNode): string {
163
+ return visitExpression(expr, this);
164
+ }
165
+
166
+ /**
167
+ * Prints an operand node to TypeScript code
168
+ * @param node - Operand node to print
169
+ * @returns TypeScript code representation
170
+ */
171
+ private printOperand(node: OperandNode): string {
172
+ return visitOperand(node, this);
173
+ }
174
+
175
+ /**
176
+ * Prints an ordering term (operand/expression/alias) to TypeScript code.
177
+ */
178
+ private printOrderingTerm(term: OrderingTerm): string {
179
+ if (!term || !('type' in term)) {
180
+ throw new Error('Unsupported ordering term');
181
+ }
182
+
183
+ switch (term.type) {
184
+ case 'Column':
185
+ return `${this.namingStrategy.tableToSymbol(term.table)}.${term.name}`;
186
+ case 'AliasRef':
187
+ return this.visitAliasRef(term);
188
+ case 'Literal':
189
+ case 'Function':
190
+ case 'JsonPath':
191
+ case 'ScalarSubquery':
192
+ case 'CaseExpression':
193
+ case 'WindowFunction':
194
+ case 'Cast':
195
+ case 'Collate':
196
+ return this.printOperand(term);
197
+ default:
198
+ return this.printExpression(term);
199
+ }
200
+ }
201
+
202
+ private getSelectionKey(selection: SelectionColumn, index: number): string {
203
+ if (selection.alias) {
204
+ return selection.alias;
205
+ }
206
+ if (this.isNamedSelection(selection)) {
207
+ return selection.name;
208
+ }
209
+ return `selection${index + 1}`;
210
+ }
211
+
212
+ private isNamedSelection(selection: SelectionColumn): selection is ColumnNode | FunctionNode | WindowFunctionNode {
213
+ return 'name' in selection;
214
+ }
215
+
216
+ public visitBinaryExpression(binary: BinaryExpressionNode): string {
217
+ return this.printBinaryExpression(binary);
218
+ }
219
+
220
220
  public visitLogicalExpression(logical: LogicalExpressionNode): string {
221
221
  return this.printLogicalExpression(logical);
222
222
  }
@@ -228,84 +228,84 @@ export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVi
228
228
  public visitNullExpression(nullExpr: NullExpressionNode): string {
229
229
  return this.printNullExpression(nullExpr);
230
230
  }
231
-
232
- public visitInExpression(inExpr: InExpressionNode): string {
233
- return this.printInExpression(inExpr);
234
- }
235
-
236
- public visitExistsExpression(existsExpr: ExistsExpressionNode): string {
237
- return this.printExistsExpression(existsExpr);
238
- }
239
-
240
- public visitBetweenExpression(betweenExpr: BetweenExpressionNode): string {
241
- return this.printBetweenExpression(betweenExpr);
242
- }
243
-
244
- public visitArithmeticExpression(arithExpr: ArithmeticExpressionNode): string {
245
- return this.printArithmeticExpression(arithExpr);
246
- }
247
-
248
- public visitColumn(node: ColumnNode): string {
249
- return this.printColumnOperand(node);
250
- }
251
-
252
- public visitLiteral(node: LiteralNode): string {
253
- return this.printLiteralOperand(node);
254
- }
255
-
256
- public visitFunction(node: FunctionNode): string {
257
- return this.printFunctionOperand(node);
258
- }
259
-
260
- public visitJsonPath(node: JsonPathNode): string {
261
- return this.printJsonPathOperand(node);
262
- }
263
-
264
- public visitScalarSubquery(node: ScalarSubqueryNode): string {
265
- return this.printScalarSubqueryOperand(node);
266
- }
267
-
268
- public visitCaseExpression(node: CaseExpressionNode): string {
269
- return this.printCaseExpressionOperand(node);
270
- }
271
-
272
- public visitWindowFunction(node: WindowFunctionNode): string {
273
- return this.printWindowFunctionOperand(node);
274
- }
275
-
276
- public visitCast(node: CastExpressionNode): string {
277
- return this.printCastOperand(node);
278
- }
279
-
280
- public visitCollate(node: CollateExpressionNode): string {
281
- return this.printCollateOperand(node);
282
- }
283
-
284
- public visitAliasRef(node: AliasRefNode): string {
285
- return `aliasRef('${node.name}')`;
286
- }
287
-
288
- /**
289
- * Prints a binary expression to TypeScript code
290
- * @param binary - Binary expression node
291
- * @returns TypeScript code representation
292
- */
293
- private printBinaryExpression(binary: BinaryExpressionNode): string {
294
- const left = this.printOperand(binary.left);
295
- const right = this.printOperand(binary.right);
296
- const fn = this.mapOp(binary.operator);
297
- const args = [left, right];
298
- if (binary.escape) {
299
- args.push(this.printOperand(binary.escape));
300
- }
301
- return `${fn}(${args.join(', ')})`;
302
- }
303
-
304
- /**
305
- * Prints a logical expression to TypeScript code
306
- * @param logical - Logical expression node
307
- * @returns TypeScript code representation
308
- */
231
+
232
+ public visitInExpression(inExpr: InExpressionNode): string {
233
+ return this.printInExpression(inExpr);
234
+ }
235
+
236
+ public visitExistsExpression(existsExpr: ExistsExpressionNode): string {
237
+ return this.printExistsExpression(existsExpr);
238
+ }
239
+
240
+ public visitBetweenExpression(betweenExpr: BetweenExpressionNode): string {
241
+ return this.printBetweenExpression(betweenExpr);
242
+ }
243
+
244
+ public visitArithmeticExpression(arithExpr: ArithmeticExpressionNode): string {
245
+ return this.printArithmeticExpression(arithExpr);
246
+ }
247
+
248
+ public visitColumn(node: ColumnNode): string {
249
+ return this.printColumnOperand(node);
250
+ }
251
+
252
+ public visitLiteral(node: LiteralNode): string {
253
+ return this.printLiteralOperand(node);
254
+ }
255
+
256
+ public visitFunction(node: FunctionNode): string {
257
+ return this.printFunctionOperand(node);
258
+ }
259
+
260
+ public visitJsonPath(node: JsonPathNode): string {
261
+ return this.printJsonPathOperand(node);
262
+ }
263
+
264
+ public visitScalarSubquery(node: ScalarSubqueryNode): string {
265
+ return this.printScalarSubqueryOperand(node);
266
+ }
267
+
268
+ public visitCaseExpression(node: CaseExpressionNode): string {
269
+ return this.printCaseExpressionOperand(node);
270
+ }
271
+
272
+ public visitWindowFunction(node: WindowFunctionNode): string {
273
+ return this.printWindowFunctionOperand(node);
274
+ }
275
+
276
+ public visitCast(node: CastExpressionNode): string {
277
+ return this.printCastOperand(node);
278
+ }
279
+
280
+ public visitCollate(node: CollateExpressionNode): string {
281
+ return this.printCollateOperand(node);
282
+ }
283
+
284
+ public visitAliasRef(node: AliasRefNode): string {
285
+ return `aliasRef('${node.name}')`;
286
+ }
287
+
288
+ /**
289
+ * Prints a binary expression to TypeScript code
290
+ * @param binary - Binary expression node
291
+ * @returns TypeScript code representation
292
+ */
293
+ private printBinaryExpression(binary: BinaryExpressionNode): string {
294
+ const left = this.printOperand(binary.left);
295
+ const right = this.printOperand(binary.right);
296
+ const fn = this.mapOp(binary.operator);
297
+ const args = [left, right];
298
+ if (binary.escape) {
299
+ args.push(this.printOperand(binary.escape));
300
+ }
301
+ return `${fn}(${args.join(', ')})`;
302
+ }
303
+
304
+ /**
305
+ * Prints a logical expression to TypeScript code
306
+ * @param logical - Logical expression node
307
+ * @returns TypeScript code representation
308
+ */
309
309
  private printLogicalExpression(logical: LogicalExpressionNode): string {
310
310
  if (logical.operands.length === 0) return '';
311
311
  const parts = logical.operands.map(op => {
@@ -321,192 +321,192 @@ export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVi
321
321
 
322
322
  private printArithmeticExpression(expr: ArithmeticExpressionNode): string {
323
323
  const left = this.printOperand(expr.left);
324
- const right = this.printOperand(expr.right);
325
- return `${left} ${expr.operator} ${right}`;
326
- }
327
-
328
- /**
329
- * Prints an IN expression to TypeScript code
330
- * @param inExpr - IN expression node
331
- * @returns TypeScript code representation
332
- */
333
- private printInExpression(inExpr: InExpressionNode): string {
334
- const left = this.printOperand(inExpr.left);
335
- const fn = this.mapOp(inExpr.operator);
336
- if (Array.isArray(inExpr.right)) {
337
- const values = inExpr.right.map(v => this.printOperand(v)).join(', ');
338
- return `${fn}(${left}, [${values}])`;
339
- }
340
- const subquery = this.inlineChain(this.buildSelectLines(inExpr.right.query));
341
- return `${fn}(${left}, (${subquery}))`;
342
- }
343
-
344
- /**
345
- * Prints a null expression to TypeScript code
346
- * @param nullExpr - Null expression node
347
- * @returns TypeScript code representation
348
- */
349
- private printNullExpression(nullExpr: NullExpressionNode): string {
350
- const left = this.printOperand(nullExpr.left);
351
- const fn = this.mapOp(nullExpr.operator);
352
- return `${fn}(${left})`;
353
- }
354
-
355
- /**
356
- * Prints a BETWEEN expression to TypeScript code
357
- * @param betweenExpr - BETWEEN expression node
358
- * @returns TypeScript code representation
359
- */
360
- private printBetweenExpression(betweenExpr: BetweenExpressionNode): string {
361
- const left = this.printOperand(betweenExpr.left);
362
- const lower = this.printOperand(betweenExpr.lower);
363
- const upper = this.printOperand(betweenExpr.upper);
364
- return `${this.mapOp(betweenExpr.operator)}(${left}, ${lower}, ${upper})`;
365
- }
366
-
367
- /**
368
- * Prints an EXISTS expression to TypeScript code
369
- * @param existsExpr - EXISTS expression node
370
- * @returns TypeScript code representation
371
- */
372
- private printExistsExpression(existsExpr: ExistsExpressionNode): string {
373
- const subquery = this.inlineChain(this.buildSelectLines(existsExpr.subquery));
374
- return `${this.mapOp(existsExpr.operator)}(${subquery})`;
375
- }
376
-
377
- /**
378
- * Prints a column operand to TypeScript code
379
- * @param column - Column node
380
- * @returns TypeScript code representation
381
- */
382
- private printColumnOperand(column: ColumnNode): string {
383
- return `${this.namingStrategy.tableToSymbol(column.table)}.${column.name}`;
384
- }
385
-
386
- /**
387
- * Prints a literal operand to TypeScript code
388
- * @param literal - Literal node
389
- * @returns TypeScript code representation
390
- */
391
- private printLiteralOperand(literal: LiteralNode): string {
392
- if (literal.value === null) return 'null';
393
- return typeof literal.value === 'string' ? `'${literal.value}'` : String(literal.value);
394
- }
395
-
396
- /**
397
- * Prints a function operand to TypeScript code
398
- * @param fn - Function node
399
- * @returns TypeScript code representation
400
- */
401
- private printFunctionOperand(fn: FunctionNode): string {
402
- const args = fn.args.map(a => this.printOperand(a)).join(', ');
403
- return `${fn.name.toLowerCase()}(${args})`;
404
- }
405
-
406
- /**
407
- * Prints a JSON path operand to TypeScript code
408
- * @param json - JSON path node
409
- * @returns TypeScript code representation
410
- */
411
- private printJsonPathOperand(json: JsonPathNode): string {
412
- return `jsonPath(${this.namingStrategy.tableToSymbol(json.column.table)}.${json.column.name}, '${json.path}')`;
413
- }
414
-
415
- /**
416
- * Prints a scalar subquery operand to TypeScript code
417
- * @param node - Scalar subquery node
418
- * @returns TypeScript code representation
419
- */
420
- private printScalarSubqueryOperand(node: ScalarSubqueryNode): string {
421
- const subquery = this.inlineChain(this.buildSelectLines(node.query));
422
- return `(${subquery})`;
423
- }
424
-
425
- /**
426
- * Prints a CASE expression operand to TypeScript code
427
- * @param node - CASE expression node
428
- * @returns TypeScript code representation
429
- */
430
- private printCaseExpressionOperand(node: CaseExpressionNode): string {
431
- const clauses = node.conditions.map(
432
- condition =>
433
- `{ when: ${this.printExpression(condition.when)}, then: ${this.printOperand(condition.then)} }`
434
- );
435
- const elseValue = node.else ? `, ${this.printOperand(node.else)}` : '';
436
- return `caseWhen([${clauses.join(', ')}]${elseValue})`;
437
- }
438
-
439
- /**
440
- * Prints a window function operand to TypeScript code
441
- * @param node - Window function node
442
- * @returns TypeScript code representation
443
- */
444
- private printWindowFunctionOperand(node: WindowFunctionNode): string {
445
- let result = `${node.name}(`;
446
- if (node.args.length > 0) {
447
- result += node.args.map(arg => this.printOperand(arg)).join(', ');
448
- }
449
- result += ') OVER (';
450
-
451
- const parts: string[] = [];
452
-
453
- if (node.partitionBy && node.partitionBy.length > 0) {
454
- const partitionClause =
455
- 'PARTITION BY ' + node.partitionBy.map(col => `${this.namingStrategy.tableToSymbol(col.table)}.${col.name}`).join(', ');
456
- parts.push(partitionClause);
457
- }
458
-
459
- if (node.orderBy && node.orderBy.length > 0) {
460
- const orderClause =
461
- 'ORDER BY ' +
462
- node.orderBy
463
- .map(o => {
464
- const term = this.printOrderingTerm(o.term);
465
- const collation = o.collation ? ` COLLATE ${o.collation}` : '';
466
- const nulls = o.nulls ? ` NULLS ${o.nulls}` : '';
467
- return `${term} ${o.direction}${collation}${nulls}`;
468
- })
469
- .join(', ');
470
- parts.push(orderClause);
471
- }
472
-
473
- result += parts.join(' ');
474
- result += ')';
475
-
476
- return result;
477
- }
478
-
479
- private printCastOperand(node: CastExpressionNode): string {
480
- const typeLiteral = node.castType.replace(/'/g, "\\'");
481
- return `cast(${this.printOperand(node.expression)}, '${typeLiteral}')`;
482
- }
483
-
484
- private printCollateOperand(node: CollateExpressionNode): string {
485
- return `collate(${this.printOperand(node.expression)}, '${node.collation}')`;
486
- }
487
-
488
- /**
489
- * Converts method chain lines to inline format
490
- * @param lines - Method chain lines
491
- * @returns Inline method chain string
492
- */
493
- private inlineChain(lines: string[]): string {
494
- return lines
495
- .map(line => line.trim())
496
- .filter(line => line.length > 0)
497
- .join(' ');
498
- }
499
-
500
- /**
501
- * Maps SQL operators to TypeScript function names
502
- * @param op - SQL operator
503
- * @returns TypeScript function name
504
- */
505
- private mapOp(op: SqlOperator): string {
506
- const config = SQL_OPERATOR_REGISTRY[op];
507
- if (!config) {
508
- return assertNever(op as never);
509
- }
510
- return config.tsName;
511
- }
512
- }
324
+ const right = this.printOperand(expr.right);
325
+ return `${left} ${expr.operator} ${right}`;
326
+ }
327
+
328
+ /**
329
+ * Prints an IN expression to TypeScript code
330
+ * @param inExpr - IN expression node
331
+ * @returns TypeScript code representation
332
+ */
333
+ private printInExpression(inExpr: InExpressionNode): string {
334
+ const left = this.printOperand(inExpr.left);
335
+ const fn = this.mapOp(inExpr.operator);
336
+ if (Array.isArray(inExpr.right)) {
337
+ const values = inExpr.right.map(v => this.printOperand(v)).join(', ');
338
+ return `${fn}(${left}, [${values}])`;
339
+ }
340
+ const subquery = this.inlineChain(this.buildSelectLines(inExpr.right.query));
341
+ return `${fn}(${left}, (${subquery}))`;
342
+ }
343
+
344
+ /**
345
+ * Prints a null expression to TypeScript code
346
+ * @param nullExpr - Null expression node
347
+ * @returns TypeScript code representation
348
+ */
349
+ private printNullExpression(nullExpr: NullExpressionNode): string {
350
+ const left = this.printOperand(nullExpr.left);
351
+ const fn = this.mapOp(nullExpr.operator);
352
+ return `${fn}(${left})`;
353
+ }
354
+
355
+ /**
356
+ * Prints a BETWEEN expression to TypeScript code
357
+ * @param betweenExpr - BETWEEN expression node
358
+ * @returns TypeScript code representation
359
+ */
360
+ private printBetweenExpression(betweenExpr: BetweenExpressionNode): string {
361
+ const left = this.printOperand(betweenExpr.left);
362
+ const lower = this.printOperand(betweenExpr.lower);
363
+ const upper = this.printOperand(betweenExpr.upper);
364
+ return `${this.mapOp(betweenExpr.operator)}(${left}, ${lower}, ${upper})`;
365
+ }
366
+
367
+ /**
368
+ * Prints an EXISTS expression to TypeScript code
369
+ * @param existsExpr - EXISTS expression node
370
+ * @returns TypeScript code representation
371
+ */
372
+ private printExistsExpression(existsExpr: ExistsExpressionNode): string {
373
+ const subquery = this.inlineChain(this.buildSelectLines(existsExpr.subquery));
374
+ return `${this.mapOp(existsExpr.operator)}(${subquery})`;
375
+ }
376
+
377
+ /**
378
+ * Prints a column operand to TypeScript code
379
+ * @param column - Column node
380
+ * @returns TypeScript code representation
381
+ */
382
+ private printColumnOperand(column: ColumnNode): string {
383
+ return `${this.namingStrategy.tableToSymbol(column.table)}.${column.name}`;
384
+ }
385
+
386
+ /**
387
+ * Prints a literal operand to TypeScript code
388
+ * @param literal - Literal node
389
+ * @returns TypeScript code representation
390
+ */
391
+ private printLiteralOperand(literal: LiteralNode): string {
392
+ if (literal.value === null) return 'null';
393
+ return typeof literal.value === 'string' ? `'${literal.value}'` : String(literal.value);
394
+ }
395
+
396
+ /**
397
+ * Prints a function operand to TypeScript code
398
+ * @param fn - Function node
399
+ * @returns TypeScript code representation
400
+ */
401
+ private printFunctionOperand(fn: FunctionNode): string {
402
+ const args = fn.args.map(a => this.printOperand(a)).join(', ');
403
+ return `${fn.name.toLowerCase()}(${args})`;
404
+ }
405
+
406
+ /**
407
+ * Prints a JSON path operand to TypeScript code
408
+ * @param json - JSON path node
409
+ * @returns TypeScript code representation
410
+ */
411
+ private printJsonPathOperand(json: JsonPathNode): string {
412
+ return `jsonPath(${this.namingStrategy.tableToSymbol(json.column.table)}.${json.column.name}, '${json.path}')`;
413
+ }
414
+
415
+ /**
416
+ * Prints a scalar subquery operand to TypeScript code
417
+ * @param node - Scalar subquery node
418
+ * @returns TypeScript code representation
419
+ */
420
+ private printScalarSubqueryOperand(node: ScalarSubqueryNode): string {
421
+ const subquery = this.inlineChain(this.buildSelectLines(node.query));
422
+ return `(${subquery})`;
423
+ }
424
+
425
+ /**
426
+ * Prints a CASE expression operand to TypeScript code
427
+ * @param node - CASE expression node
428
+ * @returns TypeScript code representation
429
+ */
430
+ private printCaseExpressionOperand(node: CaseExpressionNode): string {
431
+ const clauses = node.conditions.map(
432
+ condition =>
433
+ `{ when: ${this.printExpression(condition.when)}, then: ${this.printOperand(condition.then)} }`
434
+ );
435
+ const elseValue = node.else ? `, ${this.printOperand(node.else)}` : '';
436
+ return `caseWhen([${clauses.join(', ')}]${elseValue})`;
437
+ }
438
+
439
+ /**
440
+ * Prints a window function operand to TypeScript code
441
+ * @param node - Window function node
442
+ * @returns TypeScript code representation
443
+ */
444
+ private printWindowFunctionOperand(node: WindowFunctionNode): string {
445
+ let result = `${node.name}(`;
446
+ if (node.args.length > 0) {
447
+ result += node.args.map(arg => this.printOperand(arg)).join(', ');
448
+ }
449
+ result += ') OVER (';
450
+
451
+ const parts: string[] = [];
452
+
453
+ if (node.partitionBy && node.partitionBy.length > 0) {
454
+ const partitionClause =
455
+ 'PARTITION BY ' + node.partitionBy.map(col => `${this.namingStrategy.tableToSymbol(col.table)}.${col.name}`).join(', ');
456
+ parts.push(partitionClause);
457
+ }
458
+
459
+ if (node.orderBy && node.orderBy.length > 0) {
460
+ const orderClause =
461
+ 'ORDER BY ' +
462
+ node.orderBy
463
+ .map(o => {
464
+ const term = this.printOrderingTerm(o.term);
465
+ const collation = o.collation ? ` COLLATE ${o.collation}` : '';
466
+ const nulls = o.nulls ? ` NULLS ${o.nulls}` : '';
467
+ return `${term} ${o.direction}${collation}${nulls}`;
468
+ })
469
+ .join(', ');
470
+ parts.push(orderClause);
471
+ }
472
+
473
+ result += parts.join(' ');
474
+ result += ')';
475
+
476
+ return result;
477
+ }
478
+
479
+ private printCastOperand(node: CastExpressionNode): string {
480
+ const typeLiteral = node.castType.replace(/'/g, "\\'");
481
+ return `cast(${this.printOperand(node.expression)}, '${typeLiteral}')`;
482
+ }
483
+
484
+ private printCollateOperand(node: CollateExpressionNode): string {
485
+ return `collate(${this.printOperand(node.expression)}, '${node.collation}')`;
486
+ }
487
+
488
+ /**
489
+ * Converts method chain lines to inline format
490
+ * @param lines - Method chain lines
491
+ * @returns Inline method chain string
492
+ */
493
+ private inlineChain(lines: string[]): string {
494
+ return lines
495
+ .map(line => line.trim())
496
+ .filter(line => line.length > 0)
497
+ .join(' ');
498
+ }
499
+
500
+ /**
501
+ * Maps SQL operators to TypeScript function names
502
+ * @param op - SQL operator
503
+ * @returns TypeScript function name
504
+ */
505
+ private mapOp(op: SqlOperator): string {
506
+ const config = SQL_OPERATOR_REGISTRY[op];
507
+ if (!config) {
508
+ return assertNever(op as never);
509
+ }
510
+ return config.tsName;
511
+ }
512
+ }