ts-prorm-orm 1.2.3 → 2.1.0

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 (204) hide show
  1. package/CHANGELOG.md +331 -1
  2. package/README.md +32 -24
  3. package/dist/compliance/data-classifier.d.ts +6 -0
  4. package/dist/compliance/data-classifier.js +6 -0
  5. package/dist/compliance/data-lineage.d.ts +4 -0
  6. package/dist/compliance/data-lineage.js +4 -0
  7. package/dist/compliance/data-masker.d.ts +4 -0
  8. package/dist/compliance/data-masker.js +4 -0
  9. package/dist/compliance/index.d.ts +4 -0
  10. package/dist/compliance/index.js +15 -1
  11. package/dist/compliance/pseudonymization.d.ts +4 -0
  12. package/dist/compliance/pseudonymization.js +4 -0
  13. package/dist/compliance/query-firewall.d.ts +9 -9
  14. package/dist/compliance/query-firewall.js +9 -9
  15. package/dist/compliance/rate-limiter.d.ts +4 -0
  16. package/dist/compliance/rate-limiter.js +4 -0
  17. package/dist/compliance/row-level-security.d.ts +2 -0
  18. package/dist/compliance/row-level-security.js +2 -0
  19. package/dist/compliance/security-decorator.d.ts +8 -0
  20. package/dist/compliance/security-decorator.js +8 -0
  21. package/dist/compliance/session-isolation.d.ts +4 -0
  22. package/dist/compliance/session-isolation.js +4 -0
  23. package/dist/compliance/worm-storage.d.ts +4 -0
  24. package/dist/compliance/worm-storage.js +4 -0
  25. package/dist/connection-manager.js +13 -1
  26. package/dist/core/expressions.d.ts +58 -0
  27. package/dist/core/expressions.js +83 -0
  28. package/dist/core/hooks-manager.d.ts +179 -0
  29. package/dist/core/hooks-manager.js +291 -0
  30. package/dist/core/types.d.ts +235 -0
  31. package/dist/core/types.js +9 -0
  32. package/dist/decorators/audit.d.ts +3 -1
  33. package/dist/decorators/audit.js +3 -1
  34. package/dist/decorators/check.d.ts +15 -15
  35. package/dist/decorators/check.js +15 -15
  36. package/dist/decorators/collate.d.ts +16 -0
  37. package/dist/decorators/collate.js +16 -0
  38. package/dist/decorators/comment.d.ts +3 -1
  39. package/dist/decorators/comment.js +3 -1
  40. package/dist/decorators/database-settings.d.ts +6 -0
  41. package/dist/decorators/database-settings.js +6 -0
  42. package/dist/decorators/default.d.ts +2 -0
  43. package/dist/decorators/default.js +2 -0
  44. package/dist/decorators/encryption.d.ts +7 -1
  45. package/dist/decorators/encryption.js +7 -1
  46. package/dist/decorators/engine.d.ts +4 -0
  47. package/dist/decorators/engine.js +4 -0
  48. package/dist/decorators/fk-constraints.d.ts +32 -32
  49. package/dist/decorators/fk-constraints.js +32 -32
  50. package/dist/decorators/foreign-table.d.ts +1 -1
  51. package/dist/decorators/generated.d.ts +8 -0
  52. package/dist/decorators/generated.js +8 -0
  53. package/dist/decorators/hstore.d.ts +6 -0
  54. package/dist/decorators/hstore.js +6 -0
  55. package/dist/decorators/index.d.ts +2 -0
  56. package/dist/decorators/index.js +11 -1
  57. package/dist/decorators/json-column.d.ts +2 -0
  58. package/dist/decorators/json-column.js +2 -0
  59. package/dist/decorators/jsonb.d.ts +6 -0
  60. package/dist/decorators/jsonb.js +6 -0
  61. package/dist/decorators/permissions.d.ts +12 -0
  62. package/dist/decorators/permissions.js +12 -0
  63. package/dist/decorators/procedure.d.ts +4 -2
  64. package/dist/decorators/procedure.js +4 -2
  65. package/dist/decorators/query-options.d.ts +24 -0
  66. package/dist/decorators/query-options.js +24 -0
  67. package/dist/decorators/range.d.ts +8 -0
  68. package/dist/decorators/range.js +8 -0
  69. package/dist/decorators/set-column.d.ts +2 -0
  70. package/dist/decorators/set-column.js +2 -0
  71. package/dist/decorators/spatial.d.ts +2 -0
  72. package/dist/decorators/spatial.js +2 -0
  73. package/dist/decorators/storage.d.ts +24 -0
  74. package/dist/decorators/storage.js +24 -0
  75. package/dist/decorators/timezone.d.ts +7 -7
  76. package/dist/decorators/timezone.js +7 -7
  77. package/dist/decorators/trigger.d.ts +3 -1
  78. package/dist/decorators/trigger.js +3 -1
  79. package/dist/decorators/uuid.d.ts +6 -0
  80. package/dist/decorators/uuid.js +6 -0
  81. package/dist/decorators/view.d.ts +7 -1
  82. package/dist/decorators/view.js +7 -1
  83. package/dist/diagrams/chen-diagram.d.ts +15 -12
  84. package/dist/diagrams/chen-diagram.js +76 -85
  85. package/dist/diagrams/class-diagram.d.ts +9 -8
  86. package/dist/diagrams/class-diagram.js +60 -82
  87. package/dist/diagrams/core/index.d.ts +13 -0
  88. package/dist/diagrams/core/index.js +33 -0
  89. package/dist/diagrams/core/layout.d.ts +104 -0
  90. package/dist/diagrams/core/layout.js +223 -0
  91. package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
  92. package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
  93. package/dist/diagrams/core/theme.d.ts +84 -0
  94. package/dist/diagrams/core/theme.js +62 -0
  95. package/dist/diagrams/dependency-diagram.d.ts +15 -14
  96. package/dist/diagrams/dependency-diagram.js +71 -105
  97. package/dist/diagrams/er-diagram.d.ts +13 -26
  98. package/dist/diagrams/er-diagram.js +180 -259
  99. package/dist/diagrams/flow-diagram.d.ts +16 -11
  100. package/dist/diagrams/flow-diagram.js +96 -91
  101. package/dist/diagrams/gantt-diagram.d.ts +10 -5
  102. package/dist/diagrams/gantt-diagram.js +77 -103
  103. package/dist/diagrams/index-diagram.d.ts +10 -10
  104. package/dist/diagrams/index-diagram.js +106 -116
  105. package/dist/diagrams/index.d.ts +6 -9
  106. package/dist/diagrams/index.js +9 -24
  107. package/dist/diagrams/migration-diagram.d.ts +8 -4
  108. package/dist/diagrams/migration-diagram.js +189 -161
  109. package/dist/diagrams/model-diagram.d.ts +34 -34
  110. package/dist/diagrams/model-diagram.js +106 -485
  111. package/dist/diagrams/package-diagram.d.ts +9 -6
  112. package/dist/diagrams/package-diagram.js +64 -101
  113. package/dist/diagrams/relational-diagram.d.ts +12 -10
  114. package/dist/diagrams/relational-diagram.js +87 -114
  115. package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
  116. package/dist/diagrams/schemadoc-diagram.js +71 -93
  117. package/dist/diagrams/sequence-diagram.d.ts +10 -10
  118. package/dist/diagrams/sequence-diagram.js +64 -89
  119. package/dist/diagrams/state-diagram.d.ts +10 -9
  120. package/dist/diagrams/state-diagram.js +69 -92
  121. package/dist/diagrams/tree-diagram.d.ts +11 -5
  122. package/dist/diagrams/tree-diagram.js +41 -65
  123. package/dist/dialects/clickhouse/index.js +15 -0
  124. package/dist/dialects/cockroachdb/index.d.ts +1 -1
  125. package/dist/dialects/cockroachdb/index.js +32 -63
  126. package/dist/dialects/db2/index.js +23 -8
  127. package/dist/dialects/dialect.d.ts +141 -5
  128. package/dist/dialects/duckdb/index.js +9 -2
  129. package/dist/dialects/hana/index.js +22 -5
  130. package/dist/dialects/lock-clause-helper.d.ts +167 -0
  131. package/dist/dialects/lock-clause-helper.js +316 -0
  132. package/dist/dialects/mariadb/index.d.ts +7 -4
  133. package/dist/dialects/mariadb/index.js +36 -60
  134. package/dist/dialects/mssql/index.js +34 -3
  135. package/dist/dialects/mysql/index.d.ts +1 -1
  136. package/dist/dialects/mysql/index.js +17 -45
  137. package/dist/dialects/oracle/index.d.ts +14 -3
  138. package/dist/dialects/oracle/index.js +66 -36
  139. package/dist/dialects/order-expression-helper.d.ts +72 -0
  140. package/dist/dialects/order-expression-helper.js +154 -0
  141. package/dist/dialects/partial-index.d.ts +52 -0
  142. package/dist/dialects/partial-index.js +251 -0
  143. package/dist/dialects/postgres/index.d.ts +1 -1
  144. package/dist/dialects/postgres/index.js +43 -68
  145. package/dist/dialects/redshift/index.js +9 -2
  146. package/dist/dialects/snowflake/index.js +17 -0
  147. package/dist/dialects/spanner/index.js +7 -2
  148. package/dist/dialects/sqlite/driver.d.ts +55 -0
  149. package/dist/dialects/sqlite/driver.js +102 -0
  150. package/dist/dialects/sqlite/index.d.ts +1 -1
  151. package/dist/dialects/sqlite/index.js +49 -27
  152. package/dist/external-fields/decorator.d.ts +2 -0
  153. package/dist/external-fields/decorator.js +2 -0
  154. package/dist/graph/base-graph-dialect.d.ts +24 -3
  155. package/dist/graph/base-graph-dialect.js +43 -2
  156. package/dist/graph/dgraph/index.js +6 -0
  157. package/dist/graph/gremlin/index.d.ts +6 -0
  158. package/dist/graph/gremlin/index.js +12 -1
  159. package/dist/graph/index.d.ts +1 -1
  160. package/dist/graph/neo4j/index.d.ts +2 -0
  161. package/dist/graph/neo4j/index.js +6 -1
  162. package/dist/graph/types.d.ts +12 -1
  163. package/dist/index.d.ts +12 -3
  164. package/dist/index.js +53 -7
  165. package/dist/logging/index.d.ts +10 -0
  166. package/dist/logging/index.js +23 -0
  167. package/dist/logging/query-logging.d.ts +82 -0
  168. package/dist/logging/query-logging.js +102 -0
  169. package/dist/models/associations.d.ts +38 -0
  170. package/dist/models/associations.js +16 -0
  171. package/dist/models/decorators.d.ts +55 -19
  172. package/dist/models/decorators.js +95 -19
  173. package/dist/models/eager-load.d.ts +99 -0
  174. package/dist/models/eager-load.js +348 -5
  175. package/dist/models/indexes.d.ts +3 -2
  176. package/dist/models/indexes.js +7 -1
  177. package/dist/models/model.js +69 -43
  178. package/dist/prorm.d.ts +175 -409
  179. package/dist/prorm.js +1132 -553
  180. package/dist/query-builders/order-limit-builder.js +12 -10
  181. package/dist/query-builders/sql-compiler.d.ts +10 -3
  182. package/dist/query-builders/sql-compiler.js +14 -43
  183. package/dist/query-interface.d.ts +2 -1
  184. package/dist/schema-objects.d.ts +42 -0
  185. package/dist/schema-objects.js +28 -0
  186. package/dist/sql-constants.d.ts +44 -0
  187. package/dist/sql-constants.js +138 -1
  188. package/dist/types/index.d.ts +387 -17
  189. package/dist/types/index.js +10 -15
  190. package/dist/types/query-types.d.ts +26 -0
  191. package/dist/types/query-types.js +30 -0
  192. package/package.json +39 -8
  193. package/dist/decorators/belongs-to-many.js +0 -115
  194. package/dist/decorators/belongs-to.js +0 -115
  195. package/dist/decorators/has-many.js +0 -127
  196. package/dist/decorators/has-one.js +0 -116
  197. package/dist/diagrams/palette.d.ts +0 -138
  198. package/dist/diagrams/palette.js +0 -194
  199. package/dist/hooks/hooks-manager.d.ts +0 -189
  200. package/dist/hooks/hooks-manager.js +0 -350
  201. package/dist/hooks/index.d.ts +0 -8
  202. package/dist/hooks/index.js +0 -37
  203. /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
  204. /package/dist/{logging.js → logging/logger.js} +0 -0
@@ -40,6 +40,7 @@
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.ClickHouseDialect = void 0;
42
42
  exports.createClickHouseDialect = createClickHouseDialect;
43
+ const partial_index_1 = require("../partial-index");
43
44
  // Lazily-loaded `@clickhouse/client` module. The native/runtime driver is only
44
45
  // required the first time a connection is opened, so merely importing this ORM
45
46
  // never pulls in the ClickHouse driver.
@@ -59,6 +60,7 @@ function loadClickHouse() {
59
60
  }
60
61
  const query_stream_helper_1 = require("../query-stream-helper");
61
62
  const prorm_1 = require("../../prorm");
63
+ const order_expression_helper_1 = require("../order-expression-helper");
62
64
  /**
63
65
  * ClickHouse dialect class that implements the Dialect interface.
64
66
  *
@@ -950,6 +952,12 @@ class ClickHouseDialect {
950
952
  if (options?.ifNotExists)
951
953
  sql += ' IF NOT EXISTS';
952
954
  sql += ` ${this.escapeId(indexName)} ${expr} TYPE ${type} GRANULARITY ${granularity}`;
955
+ // ClickHouse indexes are data-skipping indexes on the whole part set; there
956
+ // is no predicate to restrict them. `where` was accepted and dropped on the
957
+ // floor here, so the caller silently got an unfiltered index.
958
+ if (options?.where) {
959
+ throw (0, partial_index_1.unsupportedPartialIndex)(this.name);
960
+ }
953
961
  await this.query(sql);
954
962
  }
955
963
  async removeIndex(tableName, indexName) {
@@ -959,6 +967,7 @@ class ClickHouseDialect {
959
967
  await this.addIndex(tableName, indexDef.name, indexDef.fields, {
960
968
  type: indexDef.type,
961
969
  using: indexDef.using,
970
+ where: indexDef.where,
962
971
  });
963
972
  }
964
973
  async dropIndex(tableName, indexName, options) {
@@ -1359,6 +1368,12 @@ class ClickHouseDialect {
1359
1368
  return '';
1360
1369
  const parts = [];
1361
1370
  const processItem = (item) => {
1371
+ // Order helpers: asc('name') / desc('name') / random()
1372
+ const orderExpr = (0, order_expression_helper_1.renderOrderExpressionItem)(this, item);
1373
+ if (orderExpr !== null) {
1374
+ parts.push(orderExpr);
1375
+ return;
1376
+ }
1362
1377
  if (typeof item === 'string') {
1363
1378
  const [field, dir] = item.split(' ');
1364
1379
  parts.push(dir ? `${this.escapeId(field)} ${dir.toUpperCase()}` : this.escapeId(field));
@@ -1013,7 +1013,7 @@ export declare class CockroachDBDialect implements Dialect {
1013
1013
  type?: string;
1014
1014
  using?: string;
1015
1015
  fields: string[];
1016
- where?: WhereOptions;
1016
+ where?: WhereOptions | string;
1017
1017
  expression?: string;
1018
1018
  include?: string[];
1019
1019
  concurrently?: boolean;
@@ -36,7 +36,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.CockroachDBTransaction = exports.CockroachDBDialect = void 0;
37
37
  exports.createCockroachDBDialect = createCockroachDBDialect;
38
38
  const operators_1 = require("../../operators");
39
+ const lock_clause_helper_1 = require("../lock-clause-helper");
40
+ const partial_index_1 = require("../partial-index");
39
41
  const prorm_1 = require("../../prorm");
42
+ const order_expression_helper_1 = require("../order-expression-helper");
40
43
  // Lazily-loaded `pg` driver. Required only when a connection is opened, so
41
44
  // importing this ORM never loads the pg driver.
42
45
  let pgModule = null;
@@ -2327,9 +2330,14 @@ class CockroachDBDialect {
2327
2330
  if (options?.include && options.include.length > 0) {
2328
2331
  sql += ` INCLUDE (${options.include.map((f) => this.escapeId(f)).join(', ')})`;
2329
2332
  }
2333
+ // Partial index predicate. The ordinary WHERE builder emits `$1`-style
2334
+ // placeholders and this DDL is executed without a value list, so the
2335
+ // predicate is compiled with its values inlined as escaped literals.
2330
2336
  if (options?.where) {
2331
- const whereClause = this.buildWhereClause(options.where);
2332
- sql += ` WHERE ${whereClause.sql}`;
2337
+ const predicate = (0, partial_index_1.buildPartialIndexPredicate)(options.where, this.name, this);
2338
+ if (predicate) {
2339
+ sql += ` WHERE ${predicate}`;
2340
+ }
2333
2341
  }
2334
2342
  await this.query(sql);
2335
2343
  }
@@ -2385,9 +2393,12 @@ class CockroachDBDialect {
2385
2393
  if (indexDef.include && indexDef.include.length > 0) {
2386
2394
  sql += ` INCLUDE (${indexDef.include.map((f) => this.escapeId(f)).join(', ')})`;
2387
2395
  }
2388
- if (indexDef.where && Object.keys(indexDef.where).length > 0) {
2389
- const whereClause = this.buildWhereClause(indexDef.where);
2390
- sql += ` WHERE ${whereClause.sql}`;
2396
+ // Partial index predicate - inlined literals, not placeholders. See addIndex.
2397
+ if (indexDef.where) {
2398
+ const predicate = (0, partial_index_1.buildPartialIndexPredicate)(indexDef.where, this.name, this);
2399
+ if (predicate) {
2400
+ sql += ` WHERE ${predicate}`;
2401
+ }
2391
2402
  }
2392
2403
  await this.query(sql);
2393
2404
  }
@@ -3252,12 +3263,18 @@ class CockroachDBDialect {
3252
3263
  * Build an ORDER BY clause
3253
3264
  */
3254
3265
  buildOrderClause(order, options) {
3255
- const orderArray = order;
3256
- if (!orderArray || !Array.isArray(orderArray) || orderArray.length === 0) {
3266
+ const orderArray = (0, order_expression_helper_1.normalizeOrderItems)(order);
3267
+ if (orderArray.length === 0) {
3257
3268
  return '';
3258
3269
  }
3259
3270
  const orderParts = [];
3260
3271
  for (const item of orderArray) {
3272
+ // Order helpers: asc('name') / desc('name') / random()
3273
+ const orderExpr = (0, order_expression_helper_1.renderOrderExpressionItem)(this, item);
3274
+ if (orderExpr !== null) {
3275
+ orderParts.push(orderExpr);
3276
+ continue;
3277
+ }
3261
3278
  if (Array.isArray(item)) {
3262
3279
  const field = typeof item[0] === 'string' ? this.escapeId(item[0]) : item[0];
3263
3280
  const direction = item[1] ? ` ${item[1]}` : '';
@@ -3977,35 +3994,10 @@ class CockroachDBDialect {
3977
3994
  }
3978
3995
  // Build LIMIT/OFFSET clause
3979
3996
  sql += this.buildLimitOffset(options.limit, options.offset);
3980
- // Handle row-level locking (CockroachDB specific)
3981
- if (options.lock) {
3982
- let lockType;
3983
- // lock: true is equivalent to 'UPDATE'
3984
- if (options.lock === true) {
3985
- lockType = 'UPDATE';
3986
- }
3987
- else if (typeof options.lock === 'string') {
3988
- lockType = options.lock;
3989
- }
3990
- else if (typeof options.lock === 'object' && options.lock.of) {
3991
- // lock: { of: Model } - defaults to FOR UPDATE for table-specific locking
3992
- lockType = 'UPDATE';
3993
- }
3994
- if (lockType === 'UPDATE') {
3995
- sql += ' FOR UPDATE';
3996
- }
3997
- else if (lockType === 'SHARE') {
3998
- sql += ' FOR SHARE';
3999
- }
4000
- else if (lockType === 'KEY SHARE') {
4001
- sql += ' FOR KEY SHARE';
4002
- }
4003
- // Handle lock on specific table (CockroachDB supports OF clause)
4004
- if (typeof options.lock === 'object' && options.lock.of) {
4005
- const model = options.lock.of;
4006
- sql += ` OF ${this.escapeId(model.tableName || '')}`;
4007
- }
4008
- }
3997
+ // Handle row-level locking. CockroachDB implements the PostgreSQL locking
3998
+ // grammar; the shared helper compiles every documented `lock` shape so the
3999
+ // object forms can't silently produce an unlocked SELECT.
4000
+ sql += (0, lock_clause_helper_1.appendLockClause)(options.lock, lock_clause_helper_1.COCKROACHDB_LOCK_SPEC, (id) => this.escapeId(id));
4009
4001
  // Build UNION clause if provided
4010
4002
  if (options.union && options.union.length > 0) {
4011
4003
  const unionType = options.unionType || 'UNION';
@@ -4156,33 +4148,10 @@ class CockroachDBDialect {
4156
4148
  * Get CockroachDB specific lock options
4157
4149
  */
4158
4150
  getLockOptions(lock) {
4159
- const params = [];
4160
- let sql = '';
4161
- const lockType = typeof lock === 'string' ? lock : lock?.level;
4162
- switch (lockType) {
4163
- case 'UPDATE':
4164
- sql = 'FOR UPDATE';
4165
- break;
4166
- case 'SHARE':
4167
- sql = 'FOR SHARE';
4168
- break;
4169
- case 'KEY SHARE':
4170
- sql = 'FOR KEY SHARE';
4171
- break;
4172
- default:
4173
- return { sql: '', params };
4174
- }
4175
- if (typeof lock === 'object' && lock?.of) {
4176
- const model = lock.of;
4177
- sql += ` OF ${this.escapeId(model.tableName || '')}`;
4178
- }
4179
- if (typeof lock === 'object' && lock?.nowait) {
4180
- sql += ' NOWAIT';
4181
- }
4182
- else if (typeof lock === 'object' && lock?.skipLocked) {
4183
- sql += ' SKIP LOCKED';
4184
- }
4185
- return { sql, params };
4151
+ return {
4152
+ sql: (0, lock_clause_helper_1.buildLockClause)(lock, lock_clause_helper_1.COCKROACHDB_LOCK_SPEC, (id) => this.escapeId(id)),
4153
+ params: [],
4154
+ };
4186
4155
  }
4187
4156
  // ---------------------------------------------------------------------------
4188
4157
  // User / Privilege management — CockroachDB dialect
@@ -14,6 +14,7 @@
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.DB2Dialect = void 0;
17
+ const partial_index_1 = require("../partial-index");
17
18
  // Lazily-loaded `ibm_db` driver. This native (ODBC-based) addon is only loaded
18
19
  // the first time a connection is opened, so importing this ORM never dlopens
19
20
  // the ibm_db native binding.
@@ -32,7 +33,9 @@ function loadIbmDb() {
32
33
  return ibmDbModule;
33
34
  }
34
35
  const query_stream_helper_1 = require("../query-stream-helper");
36
+ const lock_clause_helper_1 = require("../lock-clause-helper");
35
37
  const prorm_1 = require("../../prorm");
38
+ const order_expression_helper_1 = require("../order-expression-helper");
36
39
  /**
37
40
  * Db2-specific transaction class.
38
41
  * Db2 transactions (via ibm_db) are tied to a specific connection - the
@@ -1031,6 +1034,13 @@ class DB2Dialect {
1031
1034
  if (options?.include && options.include.length > 0) {
1032
1035
  sql += ` INCLUDE (${options.include.map((f) => this.escapeId(f)).join(', ')})`;
1033
1036
  }
1037
+ // Db2 has no partial/filtered index predicate (only `EXCLUDE NULL KEYS` on
1038
+ // a unique index, which is not a general WHERE). `where` used to be
1039
+ // accepted by createIndex and then silently dropped here, so the caller got
1040
+ // a full index without being told; say so instead.
1041
+ if (options?.where) {
1042
+ throw (0, partial_index_1.unsupportedPartialIndex)(this.name);
1043
+ }
1034
1044
  return sql;
1035
1045
  }
1036
1046
  async addIndex(tableName, indexName, fields, options) {
@@ -1671,12 +1681,18 @@ class DB2Dialect {
1671
1681
  return { sql, values };
1672
1682
  }
1673
1683
  buildOrderClause(order, _options) {
1674
- const orderArray = order;
1675
- if (!orderArray || !Array.isArray(orderArray) || orderArray.length === 0) {
1684
+ const orderArray = (0, order_expression_helper_1.normalizeOrderItems)(order);
1685
+ if (orderArray.length === 0) {
1676
1686
  return '';
1677
1687
  }
1678
1688
  const orderParts = [];
1679
1689
  for (const item of orderArray) {
1690
+ // Order helpers: asc('name') / desc('name') / random()
1691
+ const orderExpr = (0, order_expression_helper_1.renderOrderExpressionItem)(this, item);
1692
+ if (orderExpr !== null) {
1693
+ orderParts.push(orderExpr);
1694
+ continue;
1695
+ }
1680
1696
  if (Array.isArray(item)) {
1681
1697
  const field = typeof item[0] === 'string' ? this.escapeId(item[0]) : item[0];
1682
1698
  const direction = item[1] ? ` ${item[1]}` : '';
@@ -1902,12 +1918,11 @@ class DB2Dialect {
1902
1918
  if (options.limit !== undefined || options.offset !== undefined) {
1903
1919
  sql += this.buildLimitOffset(options.limit, options.offset);
1904
1920
  }
1905
- if (options.lock) {
1906
- sql += ' FOR UPDATE';
1907
- if (options.lock === 'SHARE') {
1908
- sql += ' WITH RS';
1909
- }
1910
- }
1921
+ // Row-level locking: `FOR UPDATE`, with the read-stability isolation clause
1922
+ // for a shared lock. Db2 has no `NOWAIT` and spells lock-avoidance as
1923
+ // `SKIP LOCKED DATA` inside an isolation clause, so both modifiers throw
1924
+ // rather than being silently dropped.
1925
+ sql += (0, lock_clause_helper_1.appendLockClause)(options.lock, lock_clause_helper_1.DB2_LOCK_SPEC);
1911
1926
  return { sql, values };
1912
1927
  }
1913
1928
  /**
@@ -4,6 +4,16 @@
4
4
  */
5
5
  import { Transaction, TransactionOptions, QueryResult, QueryOptions, DataType, WhereOptions, Order, IncludeOptions, PartitionBound, CreatePartitionOptions, AttachPartitionOptions, DetachPartitionOptions, RefreshOptions, MaterializedViewOptions, DropMaterializedViewOptions, StoredProcedureOptions, DropStoredProcedureOptions, ExecuteStoredProcedureOptions, TriggerOptions, DropTriggerOptions, SequenceOptions, DropSequenceOptions, PolicyOptions, DropPolicyOptions, StreamOptions } from '../types';
6
6
  import type { Readable } from 'stream';
7
+ /**
8
+ * The contract every SQL engine implements.
9
+ *
10
+ * A dialect owns everything engine-specific: identifier quoting, value escaping,
11
+ * how DDL is written, which clauses are legal, and how pagination and locking
12
+ * are spelled. Model code builds the same `FindOptions` regardless, and
13
+ * the dialect is the single place that turns it into SQL for one engine —
14
+ * which is why `LIMIT ... OFFSET` on PostgreSQL becomes `OFFSET ... FETCH
15
+ * NEXT` on MSSQL without the caller changing.
16
+ */
7
17
  export interface Dialect {
8
18
  /**
9
19
  * The name of the dialect
@@ -582,6 +592,10 @@ export interface Dialect {
582
592
  executeStoredProcedure(options: ExecuteStoredProcedureOptions): Promise<QueryResult>;
583
593
  hasStoredProcedure(procedureName: string, schema?: string): Promise<boolean>;
584
594
  }
595
+ /**
596
+ * One column in a `CREATE TABLE` or `ALTER TABLE`: its type, nullability,
597
+ * default, and key or reference membership.
598
+ */
585
599
  export interface ColumnDefinition {
586
600
  type: DataType;
587
601
  allowNull?: boolean;
@@ -616,6 +630,10 @@ export interface ColumnDefinition {
616
630
  */
617
631
  invisible?: boolean;
618
632
  }
633
+ /**
634
+ * Table-level options for `CREATE TABLE` — the engine, charset, comment,
635
+ * partitioning and any indexes or constraints declared inline.
636
+ */
619
637
  export interface TableOptions {
620
638
  ifNotExists?: boolean;
621
639
  engine?: string;
@@ -627,8 +645,18 @@ export interface TableOptions {
627
645
  rowFormat?: string;
628
646
  indexes?: TableIndex[];
629
647
  constraints?: TableConstraint[];
630
- /** Unique keys to create with the table */
631
- uniqueKeys?: Record<string, string[]>;
648
+ /**
649
+ * Unique keys to create with the table.
650
+ *
651
+ * Both shapes are accepted because both have always been passed: the legacy
652
+ * `{ name: fields[] }` map, and the `UniqueKeyOptions`-style array that
653
+ * `ModelOptions.uniqueKeys` is declared as. The dialects already branch on
654
+ * `Array.isArray`; the type now says so.
655
+ */
656
+ uniqueKeys?: Record<string, string[]> | Array<{
657
+ name?: string;
658
+ fields: string[];
659
+ }>;
632
660
  /** PostgreSQL tablespace */
633
661
  tablespace?: string;
634
662
  /** PostgreSQL: inherit from parent table */
@@ -657,18 +685,26 @@ export interface TableOptions {
657
685
  validToColumn?: string;
658
686
  };
659
687
  }
688
+ /**
689
+ * An index declared alongside the table rather than in a separate statement.
690
+ */
660
691
  export interface TableIndex {
661
692
  name?: string;
662
693
  unique?: boolean;
663
694
  type?: string;
664
695
  using?: string;
665
696
  fields: string[];
666
- where?: WhereOptions;
697
+ /** See {@link IndexOptions.where}. */
698
+ where?: WhereOptions | string;
667
699
  /** Expression for expression-based indexes (e.g., LOWER(column)) */
668
700
  expression?: string;
669
701
  /** Include columns for covering index (PostgreSQL 11+, MySQL 8.0.17+) */
670
702
  include?: string[];
671
703
  }
704
+ /**
705
+ * A constraint declared alongside the table: primary key, unique, check,
706
+ * foreign key or exclusion.
707
+ */
672
708
  export interface TableConstraint {
673
709
  name?: string;
674
710
  type: 'PRIMARY KEY' | 'UNIQUE' | 'FOREIGN KEY' | 'CHECK';
@@ -681,10 +717,18 @@ export interface TableConstraint {
681
717
  };
682
718
  check?: string;
683
719
  }
720
+ /**
721
+ * Options for `DROP TABLE`, including `ifExists` and whether to cascade to
722
+ * dependent objects.
723
+ */
684
724
  export interface DropTableOptions {
685
725
  ifExists?: boolean;
686
726
  cascade?: boolean;
687
727
  }
728
+ /**
729
+ * What the engine reports back about an existing table — the shape returned
730
+ * by `describeTable`, used by schema diffing.
731
+ */
688
732
  export interface TableDescription {
689
733
  [columnName: string]: {
690
734
  type: string;
@@ -694,13 +738,30 @@ export interface TableDescription {
694
738
  autoIncrement: boolean;
695
739
  };
696
740
  }
741
+ /**
742
+ * Options for `CREATE INDEX`: uniqueness, method, included columns, and the
743
+ * `where` predicate that makes it partial. Not every engine supports partial
744
+ * indexes; the dialect rejects the option rather than silently dropping it.
745
+ */
697
746
  export interface IndexOptions {
698
747
  /** Explicit index name (used by the `(tableName, fields, options)` addIndex shorthand) */
699
748
  name?: string;
700
749
  unique?: boolean;
701
750
  type?: string;
702
751
  using?: string;
703
- where?: WhereOptions;
752
+ /**
753
+ * Partial (filtered) index predicate.
754
+ *
755
+ * Compiled into the `CREATE INDEX ... WHERE ...` clause with every value
756
+ * inlined as an escaped literal, because DDL is executed without a parameter
757
+ * list - see `src/dialects/partial-index.ts`. A string is taken as a
758
+ * predicate the caller already wrote and passed through unchanged.
759
+ *
760
+ * Only databases with real partial indexes accept this (PostgreSQL family,
761
+ * SQLite/Turso, SQL Server filtered indexes); the rest throw an
762
+ * `UnsupportedSchemaObjectError` rather than emit SQL the server rejects.
763
+ */
764
+ where?: WhereOptions | string;
704
765
  /** Expression for expression-based indexes (e.g., LOWER(column)) */
705
766
  expression?: string;
706
767
  /** Include columns for covering index (PostgreSQL 11+, MySQL 8.0.17+) */
@@ -721,20 +782,31 @@ export interface IndexOptions {
721
782
  */
722
783
  invisible?: boolean;
723
784
  }
785
+ /**
786
+ * An existing index as reported by the engine.
787
+ */
724
788
  export interface IndexDefinition {
725
789
  name: string;
726
790
  unique?: boolean;
727
791
  type?: string;
728
792
  using?: string;
729
793
  fields: string[];
730
- where?: WhereOptions;
794
+ /** See {@link IndexOptions.where}. */
795
+ where?: WhereOptions | string;
731
796
  /** See {@link IndexOptions.invisible}. */
732
797
  invisible?: boolean;
733
798
  }
799
+ /**
800
+ * Options for `DROP INDEX`, including `ifExists` and concurrency where the
801
+ * engine offers it.
802
+ */
734
803
  export interface DropIndexOptions {
735
804
  ifExists?: boolean;
736
805
  cascade?: boolean;
737
806
  }
807
+ /**
808
+ * An existing constraint as reported by the engine.
809
+ */
738
810
  export interface ConstraintDefinition {
739
811
  name: string;
740
812
  type: 'PRIMARY KEY' | 'UNIQUE' | 'FOREIGN KEY' | 'CHECK';
@@ -748,6 +820,9 @@ export interface ConstraintDefinition {
748
820
  check?: string;
749
821
  deferrable?: 'INITIALLY DEFERRED' | 'INITIALLY IMMEDIATE';
750
822
  }
823
+ /**
824
+ * Options for dropping a named constraint.
825
+ */
751
826
  export interface DropConstraintOptions {
752
827
  ifExists?: boolean;
753
828
  cascade?: boolean;
@@ -772,6 +847,10 @@ export interface DropViewOptions {
772
847
  /** If true, also drops dependent views (PostgreSQL) */
773
848
  cascade?: boolean;
774
849
  }
850
+ /**
851
+ * Options for dropping a schema, including whether to cascade to the objects
852
+ * inside it.
853
+ */
775
854
  export interface DropSchemaOptions {
776
855
  ifExists?: boolean;
777
856
  cascade?: boolean;
@@ -865,6 +944,10 @@ export interface DropDomainOptions {
865
944
  /** Schema the domain lives in */
866
945
  schema?: string;
867
946
  }
947
+ /**
948
+ * Options for `CREATE VIEW` — the defining query, whether it is materialised,
949
+ * and whether to replace an existing view.
950
+ */
868
951
  export interface ViewOptions {
869
952
  /** Replace the view if it already exists (CREATE OR REPLACE) */
870
953
  replace?: boolean;
@@ -873,12 +956,19 @@ export interface ViewOptions {
873
956
  /** View comment */
874
957
  comment?: string;
875
958
  }
959
+ /**
960
+ * A foreign server: the wrapper that reaches it and the connection options it
961
+ * needs. See the foreign-data-wrappers guide.
962
+ */
876
963
  export interface FdwForeignServerOptions {
877
964
  fdw: string;
878
965
  options?: Record<string, string>;
879
966
  version?: string;
880
967
  ifNotExists?: boolean;
881
968
  }
969
+ /**
970
+ * Changes to an existing foreign server's version or options.
971
+ */
882
972
  export interface FdwAlterForeignServerOptions {
883
973
  options?: Record<string, string>;
884
974
  addOptions?: Record<string, string>;
@@ -886,16 +976,26 @@ export interface FdwAlterForeignServerOptions {
886
976
  dropOptions?: string[];
887
977
  version?: string;
888
978
  }
979
+ /**
980
+ * Maps a local role to credentials on a foreign server.
981
+ */
889
982
  export interface FdwUserMappingOptions {
890
983
  serverName: string;
891
984
  user: string;
892
985
  options?: Record<string, string>;
893
986
  ifNotExists?: boolean;
894
987
  }
988
+ /**
989
+ * One column of a foreign table, including the remote name when it differs.
990
+ */
895
991
  export interface FdwForeignTableColumnDef {
896
992
  type: string;
897
993
  options?: string;
898
994
  }
995
+ /**
996
+ * A foreign table: which server it lives on, its columns, and the remote
997
+ * object it maps to.
998
+ */
899
999
  export interface FdwForeignTableOptions {
900
1000
  serverName: string;
901
1001
  schema?: string;
@@ -903,21 +1003,36 @@ export interface FdwForeignTableOptions {
903
1003
  options?: Record<string, string>;
904
1004
  ifNotExists?: boolean;
905
1005
  }
1006
+ /**
1007
+ * Options for importing a remote schema wholesale, with optional limits on
1008
+ * which tables come across.
1009
+ */
906
1010
  export interface FdwImportForeignSchemaOptions {
907
1011
  localSchema?: string;
908
1012
  limitTo?: string[];
909
1013
  except?: string[];
910
1014
  options?: Record<string, string>;
911
1015
  }
1016
+ /**
1017
+ * Options for dropping a view, including the materialised variant.
1018
+ */
912
1019
  export interface DropViewOptions {
913
1020
  ifExists?: boolean;
914
1021
  cascade?: boolean;
915
1022
  }
1023
+ /**
1024
+ * Shared options for the statement builders: the transaction to run inside
1025
+ * and any per-statement logging override.
1026
+ */
916
1027
  export interface BuildOptions {
917
1028
  replacements?: Record<string, any>;
918
1029
  model?: any;
919
1030
  include?: IncludeOptions[];
920
1031
  }
1032
+ /**
1033
+ * Options for building an `INSERT`, including returning clauses and conflict
1034
+ * handling where the engine supports them.
1035
+ */
921
1036
  export interface InsertOptions {
922
1037
  /** Schema to use for the table */
923
1038
  schema?: string;
@@ -927,6 +1042,10 @@ export interface InsertOptions {
927
1042
  /** Fields to update on conflict (MySQL: ON DUPLICATE KEY UPDATE, PostgreSQL/SQLite: ON CONFLICT DO UPDATE, MariaDB: ON DUPLICATE KEY UPDATE) */
928
1043
  updateOnDuplicate?: string[];
929
1044
  }
1045
+ /**
1046
+ * Options for an insert-or-update, including which columns decide whether a
1047
+ * row already exists and which are written on conflict.
1048
+ */
930
1049
  export interface UpsertQueryOptions {
931
1050
  /** Fields to use for conflict resolution (ON CONFLICT for PostgreSQL/SQLite, ON DUPLICATE KEY for MySQL/MariaDB) */
932
1051
  conflictFields?: string[];
@@ -939,15 +1058,28 @@ export interface UpsertQueryOptions {
939
1058
  /** Model raw attributes for type casting */
940
1059
  model?: any;
941
1060
  }
1061
+ /**
1062
+ * Options for building an `UPDATE`: the `where` that selects rows, and any
1063
+ * limit or ordering the engine permits on it.
1064
+ */
942
1065
  export interface UpdateOptions {
943
1066
  limit?: number;
944
1067
  returning?: boolean | string[];
945
1068
  }
1069
+ /**
1070
+ * Options for building a `DELETE`, including the `where` and any limit the
1071
+ * engine permits.
1072
+ */
946
1073
  export interface DeleteOptions {
947
1074
  limit?: number;
948
1075
  returning?: boolean | string[];
949
1076
  truncate?: boolean;
950
1077
  }
1078
+ /**
1079
+ * Everything a `SELECT` can carry once associations have been resolved:
1080
+ * columns, joins, filtering, grouping, ordering, pagination and locking. This
1081
+ * is the dialect-facing form of `FindOptions`.
1082
+ */
951
1083
  export interface SelectOptions {
952
1084
  tableName: string;
953
1085
  /** Schema to use for the table */
@@ -1027,6 +1159,10 @@ export interface CTEOption {
1027
1159
  /** Optional explicit column list: `name (col1, col2, ...) AS (...)`. */
1028
1160
  columns?: string[];
1029
1161
  }
1162
+ /**
1163
+ * Construction options for a dialect instance — the connection settings and
1164
+ * behaviour flags it needs to build and run statements.
1165
+ */
1030
1166
  export interface DialectOptions {
1031
1167
  host?: string;
1032
1168
  port?: number;
@@ -36,6 +36,7 @@ function loadDuckDb() {
36
36
  const query_stream_helper_1 = require("../query-stream-helper");
37
37
  const prorm_1 = require("../../prorm");
38
38
  const operators_1 = require("../../operators");
39
+ const order_expression_helper_1 = require("../order-expression-helper");
39
40
  function promisifyAll(target, sql, params) {
40
41
  return new Promise((resolve, reject) => {
41
42
  const cb = (err, rows) => {
@@ -1437,12 +1438,18 @@ class DuckDBDialect {
1437
1438
  return { sql: result.sql, values };
1438
1439
  }
1439
1440
  buildOrderClause(order) {
1440
- const orderArray = order;
1441
- if (!orderArray || !Array.isArray(orderArray) || orderArray.length === 0) {
1441
+ const orderArray = (0, order_expression_helper_1.normalizeOrderItems)(order);
1442
+ if (orderArray.length === 0) {
1442
1443
  return '';
1443
1444
  }
1444
1445
  const orderParts = [];
1445
1446
  for (const item of orderArray) {
1447
+ // Order helpers: asc('name') / desc('name') / random()
1448
+ const orderExpr = (0, order_expression_helper_1.renderOrderExpressionItem)(this, item);
1449
+ if (orderExpr !== null) {
1450
+ orderParts.push(orderExpr);
1451
+ continue;
1452
+ }
1446
1453
  if (Array.isArray(item)) {
1447
1454
  const field = typeof item[0] === 'string' ? this.escapeId(item[0]) : item[0];
1448
1455
  const direction = item[1] ? ` ${item[1]}` : '';