ts-prorm-orm 1.2.2 → 2.0.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 (129) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/README.md +32 -24
  3. package/dist/compliance/index.d.ts +2 -0
  4. package/dist/compliance/index.js +13 -1
  5. package/dist/connection-manager.js +13 -1
  6. package/dist/core/expressions.d.ts +58 -0
  7. package/dist/core/expressions.js +83 -0
  8. package/dist/core/hooks-manager.d.ts +179 -0
  9. package/dist/core/hooks-manager.js +291 -0
  10. package/dist/core/types.d.ts +235 -0
  11. package/dist/core/types.js +9 -0
  12. package/dist/decorators/index.d.ts +2 -0
  13. package/dist/decorators/index.js +11 -1
  14. package/dist/diagrams/chen-diagram.d.ts +15 -12
  15. package/dist/diagrams/chen-diagram.js +76 -85
  16. package/dist/diagrams/class-diagram.d.ts +9 -8
  17. package/dist/diagrams/class-diagram.js +60 -82
  18. package/dist/diagrams/core/index.d.ts +13 -0
  19. package/dist/diagrams/core/index.js +33 -0
  20. package/dist/diagrams/core/layout.d.ts +104 -0
  21. package/dist/diagrams/core/layout.js +223 -0
  22. package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
  23. package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
  24. package/dist/diagrams/core/theme.d.ts +84 -0
  25. package/dist/diagrams/core/theme.js +62 -0
  26. package/dist/diagrams/dependency-diagram.d.ts +15 -14
  27. package/dist/diagrams/dependency-diagram.js +71 -105
  28. package/dist/diagrams/er-diagram.d.ts +13 -26
  29. package/dist/diagrams/er-diagram.js +180 -259
  30. package/dist/diagrams/flow-diagram.d.ts +16 -11
  31. package/dist/diagrams/flow-diagram.js +96 -91
  32. package/dist/diagrams/gantt-diagram.d.ts +10 -5
  33. package/dist/diagrams/gantt-diagram.js +77 -103
  34. package/dist/diagrams/index-diagram.d.ts +10 -10
  35. package/dist/diagrams/index-diagram.js +106 -116
  36. package/dist/diagrams/index.d.ts +6 -9
  37. package/dist/diagrams/index.js +9 -24
  38. package/dist/diagrams/migration-diagram.d.ts +8 -4
  39. package/dist/diagrams/migration-diagram.js +189 -161
  40. package/dist/diagrams/model-diagram.d.ts +34 -34
  41. package/dist/diagrams/model-diagram.js +106 -485
  42. package/dist/diagrams/package-diagram.d.ts +9 -6
  43. package/dist/diagrams/package-diagram.js +64 -101
  44. package/dist/diagrams/relational-diagram.d.ts +12 -10
  45. package/dist/diagrams/relational-diagram.js +87 -114
  46. package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
  47. package/dist/diagrams/schemadoc-diagram.js +71 -93
  48. package/dist/diagrams/sequence-diagram.d.ts +10 -10
  49. package/dist/diagrams/sequence-diagram.js +64 -89
  50. package/dist/diagrams/state-diagram.d.ts +10 -9
  51. package/dist/diagrams/state-diagram.js +69 -92
  52. package/dist/diagrams/tree-diagram.d.ts +11 -5
  53. package/dist/diagrams/tree-diagram.js +41 -65
  54. package/dist/dialects/clickhouse/index.js +15 -0
  55. package/dist/dialects/cockroachdb/index.d.ts +1 -1
  56. package/dist/dialects/cockroachdb/index.js +32 -63
  57. package/dist/dialects/db2/index.js +23 -8
  58. package/dist/dialects/dialect.d.ts +29 -5
  59. package/dist/dialects/duckdb/index.js +9 -2
  60. package/dist/dialects/hana/index.js +22 -5
  61. package/dist/dialects/lock-clause-helper.d.ts +167 -0
  62. package/dist/dialects/lock-clause-helper.js +316 -0
  63. package/dist/dialects/mariadb/index.d.ts +7 -4
  64. package/dist/dialects/mariadb/index.js +36 -60
  65. package/dist/dialects/mssql/index.js +34 -3
  66. package/dist/dialects/mysql/index.d.ts +1 -1
  67. package/dist/dialects/mysql/index.js +17 -45
  68. package/dist/dialects/oracle/index.d.ts +14 -3
  69. package/dist/dialects/oracle/index.js +66 -36
  70. package/dist/dialects/order-expression-helper.d.ts +72 -0
  71. package/dist/dialects/order-expression-helper.js +154 -0
  72. package/dist/dialects/partial-index.d.ts +52 -0
  73. package/dist/dialects/partial-index.js +251 -0
  74. package/dist/dialects/postgres/index.d.ts +1 -1
  75. package/dist/dialects/postgres/index.js +43 -68
  76. package/dist/dialects/redshift/index.js +9 -2
  77. package/dist/dialects/snowflake/index.js +17 -0
  78. package/dist/dialects/spanner/index.js +7 -2
  79. package/dist/dialects/sqlite/driver.d.ts +55 -0
  80. package/dist/dialects/sqlite/driver.js +102 -0
  81. package/dist/dialects/sqlite/index.d.ts +1 -1
  82. package/dist/dialects/sqlite/index.js +49 -27
  83. package/dist/graph/base-graph-dialect.d.ts +24 -3
  84. package/dist/graph/base-graph-dialect.js +43 -2
  85. package/dist/graph/dgraph/index.js +6 -0
  86. package/dist/graph/gremlin/index.d.ts +6 -0
  87. package/dist/graph/gremlin/index.js +12 -1
  88. package/dist/graph/index.d.ts +1 -1
  89. package/dist/graph/neo4j/index.d.ts +2 -0
  90. package/dist/graph/neo4j/index.js +6 -1
  91. package/dist/graph/types.d.ts +12 -1
  92. package/dist/index.d.ts +13 -4
  93. package/dist/index.js +54 -7
  94. package/dist/logging/index.d.ts +10 -0
  95. package/dist/logging/index.js +23 -0
  96. package/dist/logging/query-logging.d.ts +82 -0
  97. package/dist/logging/query-logging.js +102 -0
  98. package/dist/models/decorators.d.ts +39 -3
  99. package/dist/models/decorators.js +74 -0
  100. package/dist/models/eager-load.d.ts +99 -0
  101. package/dist/models/eager-load.js +348 -5
  102. package/dist/models/indexes.d.ts +3 -2
  103. package/dist/models/indexes.js +7 -1
  104. package/dist/models/model.js +69 -43
  105. package/dist/prorm.d.ts +175 -409
  106. package/dist/prorm.js +1142 -557
  107. package/dist/query-builders/order-limit-builder.js +12 -10
  108. package/dist/query-builders/sql-compiler.d.ts +10 -3
  109. package/dist/query-builders/sql-compiler.js +14 -43
  110. package/dist/query-interface.d.ts +2 -1
  111. package/dist/sql-constants.d.ts +44 -0
  112. package/dist/sql-constants.js +138 -1
  113. package/dist/types/index.d.ts +53 -17
  114. package/dist/types/index.js +10 -15
  115. package/dist/types/query-types.d.ts +26 -0
  116. package/dist/types/query-types.js +30 -0
  117. package/package.json +32 -5
  118. package/dist/decorators/belongs-to-many.js +0 -115
  119. package/dist/decorators/belongs-to.js +0 -115
  120. package/dist/decorators/has-many.js +0 -127
  121. package/dist/decorators/has-one.js +0 -116
  122. package/dist/diagrams/palette.d.ts +0 -138
  123. package/dist/diagrams/palette.js +0 -194
  124. package/dist/hooks/hooks-manager.d.ts +0 -189
  125. package/dist/hooks/hooks-manager.js +0 -350
  126. package/dist/hooks/index.d.ts +0 -8
  127. package/dist/hooks/index.js +0 -37
  128. /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
  129. /package/dist/{logging.js → logging/logger.js} +0 -0
@@ -9,6 +9,8 @@ exports.createOrderBuilder = createOrderBuilder;
9
9
  exports.createOrderLimitBuilder = createOrderLimitBuilder;
10
10
  exports.buildOrder = buildOrder;
11
11
  exports.buildLimitOffset = buildLimitOffset;
12
+ const operators_1 = require("../operators");
13
+ const order_expression_helper_1 = require("../dialects/order-expression-helper");
12
14
  /**
13
15
  * OrderBuilder class for building ORDER BY clauses
14
16
  */
@@ -45,18 +47,18 @@ class OrderBuilder {
45
47
  return item;
46
48
  }
47
49
  // Handle OrderExpression from order helper functions (asc, desc, random)
48
- if (item && typeof item === 'object' && item.__type === 'order') {
49
- const direction = item.direction;
50
- if (direction === 'RANDOM') {
51
- // RANDOM() for SQLite/PostgreSQL, RAND() for MySQL/MariaDB
52
- const dialectName = this.options.dialect?.name;
53
- if (dialectName === 'mysql' || dialectName === 'mariadb') {
54
- return 'RAND()';
55
- }
56
- // Default to RANDOM() (SQLite/PostgreSQL)
50
+ if ((0, operators_1.isOrderExpression)(item)) {
51
+ const dialectName = this.options.dialect?.name;
52
+ if (!dialectName && item.direction === 'RANDOM') {
53
+ // Standalone builder with no dialect configured: there is nothing to
54
+ // look the random function up by, so keep the historical default
55
+ // rather than throwing.
57
56
  return 'RANDOM()';
58
57
  }
59
- return `${this.escapeId(item.field)} ${direction}`;
58
+ // Otherwise render through the same shared helper the dialects' own
59
+ // buildOrderClause() uses, so `order: [desc('name')]` / `random()`
60
+ // produce identical SQL whichever of the two paths a query takes.
61
+ return (0, order_expression_helper_1.renderOrderExpression)({ name: dialectName, escapeId: (id) => this.escapeId(id) }, item);
60
62
  }
61
63
  // Handle array: ['field', 'ASC'] or [['field', 'ASC'], ['field2', 'DESC']]
62
64
  if (Array.isArray(item)) {
@@ -468,11 +468,18 @@ export declare class SqlCompiler {
468
468
  */
469
469
  private compileFrameBound;
470
470
  /**
471
- * Compile lock options for row-level locking
472
- * Supports NOWAIT and SKIP LOCKED for PostgreSQL and MySQL 8.0+
471
+ * Compile lock options for row-level locking.
472
+ *
473
+ * Delegates to the shared dialect lock compiler so this and each dialect's
474
+ * own `buildSelectQuery()` can never disagree about what a given `lock` shape
475
+ * means. Supports `true`, a level string, and the
476
+ * `{ level, nowait, skipLocked, of }` object form; throws when the named
477
+ * dialect cannot express the requested lock.
478
+ *
473
479
  * @param lock - Lock options
474
480
  * @param dialect - The database dialect
475
- * @returns The compiled lock SQL clause
481
+ * @returns The compiled lock SQL clause, or an empty string for no lock and
482
+ * for dialects with no trailing locking clause (SQLite, SQL Server, ...)
476
483
  */
477
484
  compileLockOptions(lock: any, dialect?: string): string;
478
485
  /**
@@ -15,6 +15,7 @@ exports.jsonKeys = jsonKeys;
15
15
  exports.jsonLength = jsonLength;
16
16
  exports.jsonContains = jsonContains;
17
17
  exports.jsonSearch = jsonSearch;
18
+ const lock_clause_helper_1 = require("../dialects/lock-clause-helper");
18
19
  const operators_1 = require("../operators");
19
20
  /**
20
21
  * Default compiler options
@@ -1816,55 +1817,25 @@ class SqlCompiler {
1816
1817
  return bound === 1 ? '1 FOLLOWING' : `${bound} FOLLOWING`;
1817
1818
  }
1818
1819
  /**
1819
- * Compile lock options for row-level locking
1820
- * Supports NOWAIT and SKIP LOCKED for PostgreSQL and MySQL 8.0+
1820
+ * Compile lock options for row-level locking.
1821
+ *
1822
+ * Delegates to the shared dialect lock compiler so this and each dialect's
1823
+ * own `buildSelectQuery()` can never disagree about what a given `lock` shape
1824
+ * means. Supports `true`, a level string, and the
1825
+ * `{ level, nowait, skipLocked, of }` object form; throws when the named
1826
+ * dialect cannot express the requested lock.
1827
+ *
1821
1828
  * @param lock - Lock options
1822
1829
  * @param dialect - The database dialect
1823
- * @returns The compiled lock SQL clause
1830
+ * @returns The compiled lock SQL clause, or an empty string for no lock and
1831
+ * for dialects with no trailing locking clause (SQLite, SQL Server, ...)
1824
1832
  */
1825
1833
  compileLockOptions(lock, dialect = 'postgres') {
1826
- if (!lock) {
1834
+ const spec = (0, lock_clause_helper_1.getLockSpecForDialect)(dialect);
1835
+ if (!spec) {
1827
1836
  return '';
1828
1837
  }
1829
- let lockType;
1830
- let nowait = false;
1831
- let skipLocked = false;
1832
- // Extract lock configuration
1833
- if (lock === true) {
1834
- lockType = 'UPDATE';
1835
- }
1836
- else if (typeof lock === 'string') {
1837
- lockType = lock;
1838
- }
1839
- else if (typeof lock === 'object') {
1840
- lockType = lock.level || lock;
1841
- nowait = lock.nowait === true;
1842
- skipLocked = lock.skipLocked === true;
1843
- }
1844
- // Build base lock clause
1845
- let lockClause = '';
1846
- if (lockType === 'UPDATE' || lockType === 'UPDATE') {
1847
- lockClause = 'FOR UPDATE';
1848
- }
1849
- else if (lockType === 'SHARE') {
1850
- if (dialect === 'mysql') {
1851
- lockClause = 'LOCK IN SHARE MODE';
1852
- }
1853
- else {
1854
- lockClause = 'FOR SHARE';
1855
- }
1856
- }
1857
- else if (lockType === 'KEY SHARE') {
1858
- lockClause = 'FOR KEY SHARE';
1859
- }
1860
- // Add NOWAIT or SKIP LOCKED (PostgreSQL and MySQL 8.0+)
1861
- if (nowait && (dialect === 'postgres' || dialect === 'mysql')) {
1862
- lockClause += ' NOWAIT';
1863
- }
1864
- else if (skipLocked && (dialect === 'postgres' || dialect === 'mysql')) {
1865
- lockClause += ' SKIP LOCKED';
1866
- }
1867
- return lockClause;
1838
+ return (0, lock_clause_helper_1.buildLockClause)(lock, spec);
1868
1839
  }
1869
1840
  /**
1870
1841
  * Compile OVER clause with partition, order, and window frame
@@ -57,7 +57,8 @@ export interface ConstraintDefinition {
57
57
  };
58
58
  onDelete?: string;
59
59
  onUpdate?: string;
60
- where?: WhereOptions;
60
+ /** Partial-index predicate; see `IndexOptions.where` in `src/dialects/dialect.ts`. */
61
+ where?: WhereOptions | string;
61
62
  }
62
63
  /**
63
64
  * Bulk operation options
@@ -113,6 +113,14 @@ export interface PostgresConstants {
113
113
  SEARCH_PATH: SearchPath;
114
114
  AUTOCOMMIT: Autocommit;
115
115
  CACHE: Cache;
116
+ /**
117
+ * Optional: PostgreSQL has no `SET FOREIGN_KEY_CHECKS`. The session-level
118
+ * equivalent is `session_replication_role`, which is present on true
119
+ * PostgreSQL and CockroachDB but absent from some PostgreSQL-derived engines
120
+ * (Redshift does not enforce foreign keys at all), so this is deliberately
121
+ * optional rather than a required member with a fake value.
122
+ */
123
+ FOREIGN_KEY_CHECKS?: ForeignKeyChecks;
116
124
  }
117
125
  /**
118
126
  * SQLite SQL constants
@@ -193,6 +201,10 @@ export declare const COCKROACHDB: CockroachDBConstants;
193
201
  * Amazon Redshift SQL constants
194
202
  * Redshift is derived from PostgreSQL 8.0.2 and only supports the
195
203
  * SERIALIZABLE (default) and READ COMMITTED isolation levels.
204
+ *
205
+ * No FOREIGN_KEY_CHECKS: Redshift treats foreign keys as informational only -
206
+ * it never enforces them and has no `session_replication_role` - so there is
207
+ * nothing to turn off.
196
208
  */
197
209
  export declare const REDSHIFT: RedshiftConstants;
198
210
  /**
@@ -225,6 +237,38 @@ export declare const SQL: SQLConstants;
225
237
  * 'cockroachdb', 'redshift', 'db2', 'snowflake', 'clickhouse')
226
238
  */
227
239
  export declare function getConstantsForDialect(dialect: string): MySQLConstants | PostgresConstants | SQLiteConstants | DB2Constants | SnowflakeConstants | ClickHouseConstants;
240
+ /** Which end of the switch is wanted. */
241
+ export type ForeignKeyChecksMode = 'disable' | 'enable';
242
+ /**
243
+ * Raised when a dialect has no session-level foreign key switch.
244
+ *
245
+ * Mirrors `UnsupportedSchemaObjectError` in ./schema-objects: name the database
246
+ * and say what to do instead, rather than returning SQL that fails at the
247
+ * server. Declared here (not imported) to keep this module dependency-free.
248
+ */
249
+ export declare class UnsupportedForeignKeyChecksError extends Error {
250
+ constructor(dialect: string, hint?: string);
251
+ }
252
+ /**
253
+ * SQL that turns foreign key enforcement off/on for the current session.
254
+ *
255
+ * Every family has its own statement and they are not interchangeable:
256
+ * SQLite/Turso use a PRAGMA, the MySQL family a session variable, and the
257
+ * PostgreSQL family `session_replication_role`. Handing MySQL's
258
+ * `SET FOREIGN_KEY_CHECKS` to anything else - which is what the default branch
259
+ * used to do for every unlisted dialect, PostgreSQL included - produces a
260
+ * syntax error at the server, and the caller only finds out at runtime.
261
+ *
262
+ * The PostgreSQL form needs superuser, or a role granted
263
+ * `SET ON PARAMETER session_replication_role` (PostgreSQL 15+); on an ordinary
264
+ * application role the server answers `permission denied to set parameter`.
265
+ *
266
+ * @throws {UnsupportedForeignKeyChecksError} when the dialect has no
267
+ * session-level equivalent (SQL Server, Oracle and Db2 are per-table or
268
+ * per-constraint; Redshift, Snowflake, ClickHouse and friends do not enforce
269
+ * foreign keys at all).
270
+ */
271
+ export declare function getForeignKeyChecksSQL(dialect: string, mode: ForeignKeyChecksMode): string;
228
272
  /**
229
273
  * Transaction isolation level enum
230
274
  */
@@ -5,8 +5,9 @@
5
5
  * like foreign key checks, transaction isolation levels, etc.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.IsolationLevelEnum = exports.SQL = exports.CLICKHOUSE = exports.SNOWFLAKE = exports.DB2 = exports.REDSHIFT = exports.COCKROACHDB = exports.SQLITE = exports.POSTGRES = exports.MARIADB = exports.MYSQL = void 0;
8
+ exports.IsolationLevelEnum = exports.UnsupportedForeignKeyChecksError = exports.SQL = exports.CLICKHOUSE = exports.SNOWFLAKE = exports.DB2 = exports.REDSHIFT = exports.COCKROACHDB = exports.SQLITE = exports.POSTGRES = exports.MARIADB = exports.MYSQL = void 0;
9
9
  exports.getConstantsForDialect = getConstantsForDialect;
10
+ exports.getForeignKeyChecksSQL = getForeignKeyChecksSQL;
10
11
  /**
11
12
  * MySQL/MariaDB SQL constants
12
13
  */
@@ -87,6 +88,22 @@ exports.POSTGRES = {
87
88
  on: 'SET SESSION statement_cache_mode = ON',
88
89
  off: 'SET SESSION statement_cache_mode = OFF',
89
90
  },
91
+ /**
92
+ * PostgreSQL suppresses foreign key (and trigger) enforcement for the session
93
+ * by pretending to be a replication target. There is no `SET
94
+ * FOREIGN_KEY_CHECKS` - that is MySQL syntax and PostgreSQL rejects it with a
95
+ * syntax error.
96
+ *
97
+ * Requires superuser, or (PostgreSQL 15+) a role that has been granted
98
+ * `SET ON PARAMETER session_replication_role`. On a plain application role
99
+ * the server raises `permission denied to set parameter`; that error is left
100
+ * to surface rather than being swallowed, because silently continuing with
101
+ * foreign keys still enforced is the failure mode this replaced.
102
+ */
103
+ FOREIGN_KEY_CHECKS: {
104
+ disable: "SET session_replication_role = 'replica'",
105
+ enable: "SET session_replication_role = 'origin'",
106
+ },
90
107
  };
91
108
  /**
92
109
  * SQLite SQL constants
@@ -150,11 +167,21 @@ exports.COCKROACHDB = {
150
167
  on: 'SET SESSION statement_cache_mode = ON',
151
168
  off: 'SET SESSION statement_cache_mode = OFF',
152
169
  },
170
+ /** CockroachDB implements `session_replication_role` (v22.2+) with the same
171
+ * `replica`/`origin` values as PostgreSQL. */
172
+ FOREIGN_KEY_CHECKS: {
173
+ disable: "SET session_replication_role = 'replica'",
174
+ enable: "SET session_replication_role = 'origin'",
175
+ },
153
176
  };
154
177
  /**
155
178
  * Amazon Redshift SQL constants
156
179
  * Redshift is derived from PostgreSQL 8.0.2 and only supports the
157
180
  * SERIALIZABLE (default) and READ COMMITTED isolation levels.
181
+ *
182
+ * No FOREIGN_KEY_CHECKS: Redshift treats foreign keys as informational only -
183
+ * it never enforces them and has no `session_replication_role` - so there is
184
+ * nothing to turn off.
158
185
  */
159
186
  exports.REDSHIFT = {
160
187
  ISOLATION_LEVEL: {
@@ -284,10 +311,120 @@ function getConstantsForDialect(dialect) {
284
311
  return exports.SNOWFLAKE;
285
312
  case 'clickhouse':
286
313
  return exports.CLICKHOUSE;
314
+ // Derived dialects report their own name but run the parent server's
315
+ // session SQL. Without these, `getConstantsForDialect('timescaledb')` fell
316
+ // through to the MySQL constants and handed MySQL syntax to a PostgreSQL
317
+ // server.
318
+ case 'timescaledb':
319
+ case 'greenplum':
320
+ case 'yugabytedb':
321
+ return exports.POSTGRES;
322
+ case 'turso':
323
+ return exports.SQLITE;
324
+ case 'tidb':
325
+ return exports.MYSQL;
287
326
  default:
288
327
  return exports.MYSQL;
289
328
  }
290
329
  }
330
+ // ==================== Foreign key checks ====================
331
+ /**
332
+ * Dialects whose session-level foreign key switch is SQLite's PRAGMA.
333
+ * Turso/libSQL is SQLite over the wire and shares the pragma verbatim.
334
+ */
335
+ const SQLITE_FK_DIALECTS = new Set(['sqlite', 'turso']);
336
+ /**
337
+ * Dialects that implement MySQL's `SET FOREIGN_KEY_CHECKS` session variable.
338
+ *
339
+ * TiDB implements the variable for MySQL compatibility. SingleStore and
340
+ * Databricks extend the MySQL dialect class in this codebase but do not support
341
+ * enforced foreign keys at all, so they are deliberately absent - an explicit
342
+ * error naming the database beats a statement the server rejects.
343
+ */
344
+ const MYSQL_FK_DIALECTS = new Set(['mysql', 'mariadb', 'tidb']);
345
+ /**
346
+ * Dialects that implement PostgreSQL's `session_replication_role`.
347
+ *
348
+ * TimescaleDB and Greenplum are PostgreSQL servers; YugabyteDB and CockroachDB
349
+ * reimplement the parameter with the same `replica`/`origin` values. Trino,
350
+ * CrateDB, QuestDB, Exasol, Vertica and Redshift extend the Postgres dialect
351
+ * class here but are separate engines with no such parameter (Redshift never
352
+ * enforces foreign keys in the first place), so they are left out.
353
+ */
354
+ const POSTGRES_FK_DIALECTS = new Set([
355
+ 'postgres',
356
+ 'timescaledb',
357
+ 'greenplum',
358
+ 'yugabytedb',
359
+ 'cockroachdb',
360
+ ]);
361
+ /**
362
+ * Why a given dialect cannot switch foreign key enforcement for a whole
363
+ * session, and what to do instead. Used to build the thrown error message.
364
+ */
365
+ const FK_CHECKS_UNSUPPORTED_HINTS = {
366
+ mssql: 'Use ALTER TABLE <table> NOCHECK CONSTRAINT ALL per table instead.',
367
+ oracle: 'Use ALTER TABLE <table> DISABLE CONSTRAINT <name> per constraint instead.',
368
+ db2: 'Use SET INTEGRITY FOR <table> OFF / IMMEDIATE CHECKED per table instead.',
369
+ redshift: 'Redshift treats foreign keys as informational only and never enforces them.',
370
+ snowflake: 'Snowflake does not enforce foreign keys, so there is nothing to disable.',
371
+ clickhouse: 'ClickHouse has no foreign key constraints.',
372
+ duckdb: 'DuckDB has no session-level switch; drop and recreate the constraint instead.',
373
+ singlestore: 'SingleStore does not support enforced foreign key constraints.',
374
+ databricks: 'Databricks foreign keys are informational only and are never enforced.',
375
+ spanner: 'Spanner has no session-level switch; drop and recreate the constraint instead.',
376
+ };
377
+ /**
378
+ * Raised when a dialect has no session-level foreign key switch.
379
+ *
380
+ * Mirrors `UnsupportedSchemaObjectError` in ./schema-objects: name the database
381
+ * and say what to do instead, rather than returning SQL that fails at the
382
+ * server. Declared here (not imported) to keep this module dependency-free.
383
+ */
384
+ class UnsupportedForeignKeyChecksError extends Error {
385
+ constructor(dialect, hint) {
386
+ super(`Session-level foreign key checks are not supported on ${dialect}` +
387
+ `${hint ? `. ${hint}` : ''}`);
388
+ this.name = 'UnsupportedForeignKeyChecksError';
389
+ }
390
+ }
391
+ exports.UnsupportedForeignKeyChecksError = UnsupportedForeignKeyChecksError;
392
+ /**
393
+ * SQL that turns foreign key enforcement off/on for the current session.
394
+ *
395
+ * Every family has its own statement and they are not interchangeable:
396
+ * SQLite/Turso use a PRAGMA, the MySQL family a session variable, and the
397
+ * PostgreSQL family `session_replication_role`. Handing MySQL's
398
+ * `SET FOREIGN_KEY_CHECKS` to anything else - which is what the default branch
399
+ * used to do for every unlisted dialect, PostgreSQL included - produces a
400
+ * syntax error at the server, and the caller only finds out at runtime.
401
+ *
402
+ * The PostgreSQL form needs superuser, or a role granted
403
+ * `SET ON PARAMETER session_replication_role` (PostgreSQL 15+); on an ordinary
404
+ * application role the server answers `permission denied to set parameter`.
405
+ *
406
+ * @throws {UnsupportedForeignKeyChecksError} when the dialect has no
407
+ * session-level equivalent (SQL Server, Oracle and Db2 are per-table or
408
+ * per-constraint; Redshift, Snowflake, ClickHouse and friends do not enforce
409
+ * foreign keys at all).
410
+ */
411
+ function getForeignKeyChecksSQL(dialect, mode) {
412
+ if (SQLITE_FK_DIALECTS.has(dialect)) {
413
+ return mode === 'disable' ? exports.SQLITE.PRAGMA.foreign_keys.off : exports.SQLITE.PRAGMA.foreign_keys.on;
414
+ }
415
+ if (MYSQL_FK_DIALECTS.has(dialect)) {
416
+ return exports.MYSQL.FOREIGN_KEY_CHECKS[mode];
417
+ }
418
+ if (POSTGRES_FK_DIALECTS.has(dialect)) {
419
+ // COCKROACHDB carries its own copy of the constant; both resolve to the
420
+ // same `session_replication_role` statement.
421
+ const constants = dialect === 'cockroachdb' ? exports.COCKROACHDB : exports.POSTGRES;
422
+ const checks = constants.FOREIGN_KEY_CHECKS;
423
+ if (checks)
424
+ return checks[mode];
425
+ }
426
+ throw new UnsupportedForeignKeyChecksError(dialect, FK_CHECKS_UNSUPPORTED_HINTS[dialect]);
427
+ }
291
428
  /**
292
429
  * Transaction isolation level enum
293
430
  */
@@ -572,7 +572,23 @@ export interface PrormOptions {
572
572
  host?: string;
573
573
  port?: number;
574
574
  storage?: string;
575
+ /**
576
+ * Query logging, following Sequelize's contract:
577
+ * `false` off, `true` console.log, or a function called as `(sql, timing)`.
578
+ * A per-query `logging` overrides this for that call.
579
+ */
575
580
  logging?: boolean | ((sql: string, timing?: number) => void);
581
+ /**
582
+ * Append the elapsed time to each logged query, and log even when `logging`
583
+ * was never set. Matches Sequelize's `benchmark`.
584
+ */
585
+ benchmark?: boolean;
586
+ /**
587
+ * Append the values bound to each statement. Off by default: bound values
588
+ * routinely contain credentials and personal data, so this must be opted
589
+ * into deliberately.
590
+ */
591
+ logQueryParameters?: boolean;
576
592
  loggingLevel?: LoggingLevel | 'debug' | 'info' | 'warn' | 'error';
577
593
  logSQL?: boolean;
578
594
  logSlowQueries?: boolean;
@@ -765,7 +781,8 @@ export interface IndexOptions {
765
781
  unique?: boolean;
766
782
  type?: string;
767
783
  using?: string;
768
- where?: WhereOptions;
784
+ /** Partial-index predicate; see `IndexOptions.where` in `src/dialects/dialect.ts`. */
785
+ where?: WhereOptions | string;
769
786
  /** PostgreSQL: specify tablespace for the index */
770
787
  tablespace?: string;
771
788
  /** PostgreSQL: index storage parameters */
@@ -1519,6 +1536,20 @@ export interface UnpivotOptions {
1519
1536
  export interface FindOptions {
1520
1537
  where?: WhereOptions;
1521
1538
  attributes?: AttributesOptions;
1539
+ /**
1540
+ * Association aliases to count without loading their rows. Each sets
1541
+ * `<alias>Count` on every returned row.
1542
+ *
1543
+ * ```typescript
1544
+ * const users = await User.findAll({ withCount: ['posts'] });
1545
+ * users[0].postsCount; // number
1546
+ * ```
1547
+ *
1548
+ * Resolved with one grouped query per association, so the statement count
1549
+ * does not grow with the number of parent rows. Prefer this over a full
1550
+ * `include` when you only need the size.
1551
+ */
1552
+ withCount?: string[];
1522
1553
  /** Schema to use for the main table */
1523
1554
  schema?: string;
1524
1555
  /**
@@ -1829,21 +1860,26 @@ export interface GroupByItem {
1829
1860
  }
1830
1861
  /**
1831
1862
  * Lock types for row-level locking
1832
- * - 'UPDATE': FOR UPDATE (PostgreSQL/MySQL) - prevents other transactions from modifying the rows
1833
- * - 'SHARE': FOR SHARE (PostgreSQL) / LOCK IN SHARE MODE (MySQL) - allows other transactions to read but not modify
1834
- * - 'KEY SHARE': FOR KEY SHARE (PostgreSQL only) - prevents key updates but allows row updates
1863
+ * - 'UPDATE': FOR UPDATE (PostgreSQL/MySQL/MariaDB/Oracle/Db2/HANA, UPDLOCK on SQL Server) - prevents other transactions from modifying the rows
1864
+ * - 'SHARE': FOR SHARE (PostgreSQL) / LOCK IN SHARE MODE (MySQL/MariaDB, or FOR SHARE when a modifier is used) / HOLDLOCK (SQL Server) - allows other transactions to read but not modify
1865
+ * - 'KEY SHARE': FOR KEY SHARE (PostgreSQL/CockroachDB only) - prevents key updates but allows row updates
1866
+ * - 'NO KEY UPDATE': FOR NO KEY UPDATE (PostgreSQL/CockroachDB only) - like UPDATE but does not block KEY SHARE lockers
1867
+ *
1868
+ * A dialect that cannot express the requested level throws when the query is
1869
+ * built, rather than silently falling back to a weaker lock (or to none).
1835
1870
  */
1836
1871
  export declare enum LockLevel {
1837
1872
  Share = "SHARE",
1838
1873
  Update = "UPDATE",
1839
- KeyShare = "KEY SHARE"
1874
+ KeyShare = "KEY SHARE",
1875
+ NoKeyUpdate = "NO KEY UPDATE"
1840
1876
  }
1841
1877
  /**
1842
1878
  * Lock types for row-level locking
1843
1879
  *
1844
1880
  * Accepts either the raw string literals or the equivalent {@link LockLevel} enum member.
1845
1881
  */
1846
- export type LockType = 'SHARE' | 'UPDATE' | 'KEY SHARE' | LockLevel;
1882
+ export type LockType = 'SHARE' | 'UPDATE' | 'KEY SHARE' | 'NO KEY UPDATE' | LockLevel;
1847
1883
  /**
1848
1884
  * Lock options for row-level locking
1849
1885
  * @example
@@ -1861,6 +1897,15 @@ export type LockType = 'SHARE' | 'UPDATE' | 'KEY SHARE' | LockLevel;
1861
1897
  *
1862
1898
  * // SKIP LOCKED - skip locked rows (PostgreSQL/MySQL 8.0+)
1863
1899
  * User.findAll({ lock: { level: 'UPDATE', skipLocked: true } })
1900
+ *
1901
+ * // Modifiers on their own imply FOR UPDATE
1902
+ * User.findAll({ lock: { skipLocked: true } })
1903
+ *
1904
+ * @remarks
1905
+ * `nowait` and `skipLocked` are mutually exclusive - setting both throws.
1906
+ * Dialects with no row-level locking (SQLite and friends) ignore `lock`
1907
+ * entirely; dialects that have locking but cannot express the exact request
1908
+ * (e.g. `SHARE` on Oracle, `SKIP LOCKED` on Db2) throw when the query is built.
1864
1909
  */
1865
1910
  export type LockOptions = LockType | boolean | {
1866
1911
  of: ModelStatic<any>;
@@ -2880,17 +2925,8 @@ export interface RawQueryResult {
2880
2925
  * prorm.query('SELECT * FROM users', { type: QueryTypes.SELECT })
2881
2926
  * prorm.query('INSERT INTO users VALUES(...)', { type: QueryTypes.INSERT })
2882
2927
  */
2883
- export declare enum QueryTypes {
2884
- SELECT = "SELECT",
2885
- INSERT = "INSERT",
2886
- UPDATE = "UPDATE",
2887
- DELETE = "DELETE",
2888
- BULKINSERT = "BULKINSERT",
2889
- BULKUPDATE = "BULKUPDATE",
2890
- BULKDELETE = "BULKDELETE",
2891
- RAW = "RAW",
2892
- CALL = "CALL"
2893
- }
2928
+ import { QueryTypes } from './query-types';
2929
+ export { QueryTypes };
2894
2930
  export interface QueryOptions {
2895
2931
  plain?: boolean;
2896
2932
  raw?: boolean;
@@ -110,15 +110,20 @@ var ValidateOn;
110
110
  })(ValidateOn || (exports.ValidateOn = ValidateOn = {}));
111
111
  /**
112
112
  * Lock types for row-level locking
113
- * - 'UPDATE': FOR UPDATE (PostgreSQL/MySQL) - prevents other transactions from modifying the rows
114
- * - 'SHARE': FOR SHARE (PostgreSQL) / LOCK IN SHARE MODE (MySQL) - allows other transactions to read but not modify
115
- * - 'KEY SHARE': FOR KEY SHARE (PostgreSQL only) - prevents key updates but allows row updates
113
+ * - 'UPDATE': FOR UPDATE (PostgreSQL/MySQL/MariaDB/Oracle/Db2/HANA, UPDLOCK on SQL Server) - prevents other transactions from modifying the rows
114
+ * - 'SHARE': FOR SHARE (PostgreSQL) / LOCK IN SHARE MODE (MySQL/MariaDB, or FOR SHARE when a modifier is used) / HOLDLOCK (SQL Server) - allows other transactions to read but not modify
115
+ * - 'KEY SHARE': FOR KEY SHARE (PostgreSQL/CockroachDB only) - prevents key updates but allows row updates
116
+ * - 'NO KEY UPDATE': FOR NO KEY UPDATE (PostgreSQL/CockroachDB only) - like UPDATE but does not block KEY SHARE lockers
117
+ *
118
+ * A dialect that cannot express the requested level throws when the query is
119
+ * built, rather than silently falling back to a weaker lock (or to none).
116
120
  */
117
121
  var LockLevel;
118
122
  (function (LockLevel) {
119
123
  LockLevel["Share"] = "SHARE";
120
124
  LockLevel["Update"] = "UPDATE";
121
125
  LockLevel["KeyShare"] = "KEY SHARE";
126
+ LockLevel["NoKeyUpdate"] = "NO KEY UPDATE";
122
127
  })(LockLevel || (exports.LockLevel = LockLevel = {}));
123
128
  // ==================== Transaction Options ====================
124
129
  /**
@@ -166,15 +171,5 @@ var IsolationLevel;
166
171
  * prorm.query('SELECT * FROM users', { type: QueryTypes.SELECT })
167
172
  * prorm.query('INSERT INTO users VALUES(...)', { type: QueryTypes.INSERT })
168
173
  */
169
- var QueryTypes;
170
- (function (QueryTypes) {
171
- QueryTypes["SELECT"] = "SELECT";
172
- QueryTypes["INSERT"] = "INSERT";
173
- QueryTypes["UPDATE"] = "UPDATE";
174
- QueryTypes["DELETE"] = "DELETE";
175
- QueryTypes["BULKINSERT"] = "BULKINSERT";
176
- QueryTypes["BULKUPDATE"] = "BULKUPDATE";
177
- QueryTypes["BULKDELETE"] = "BULKDELETE";
178
- QueryTypes["RAW"] = "RAW";
179
- QueryTypes["CALL"] = "CALL";
180
- })(QueryTypes || (exports.QueryTypes = QueryTypes = {}));
174
+ const query_types_1 = require("./query-types");
175
+ Object.defineProperty(exports, "QueryTypes", { enumerable: true, get: function () { return query_types_1.QueryTypes; } });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Query type discriminator, used by `prorm.query()` to decide how to shape a
3
+ * raw result.
4
+ *
5
+ * This enum existed twice with *different members*: `src/prorm.ts` declared
6
+ * UPSERT/VERSION/SHOWTABLES/DESCRIBE, while `src/types/index.ts` declared
7
+ * BULKUPDATE/CALL. The package root explicitly re-exported the prorm.ts one, so
8
+ * `QueryTypes.CALL` and `QueryTypes.BULKUPDATE` were unreachable for consumers
9
+ * even though internal code in types/index.ts referred to them. This is the
10
+ * union of both, defined once; both modules now re-export it.
11
+ */
12
+ export declare enum QueryTypes {
13
+ SELECT = "SELECT",
14
+ INSERT = "INSERT",
15
+ UPDATE = "UPDATE",
16
+ DELETE = "DELETE",
17
+ UPSERT = "UPSERT",
18
+ BULKINSERT = "BULKINSERT",
19
+ BULKUPDATE = "BULKUPDATE",
20
+ BULKDELETE = "BULKDELETE",
21
+ VERSION = "VERSION",
22
+ SHOWTABLES = "SHOWTABLES",
23
+ DESCRIBE = "DESCRIBE",
24
+ CALL = "CALL",
25
+ RAW = "RAW"
26
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueryTypes = void 0;
4
+ /**
5
+ * Query type discriminator, used by `prorm.query()` to decide how to shape a
6
+ * raw result.
7
+ *
8
+ * This enum existed twice with *different members*: `src/prorm.ts` declared
9
+ * UPSERT/VERSION/SHOWTABLES/DESCRIBE, while `src/types/index.ts` declared
10
+ * BULKUPDATE/CALL. The package root explicitly re-exported the prorm.ts one, so
11
+ * `QueryTypes.CALL` and `QueryTypes.BULKUPDATE` were unreachable for consumers
12
+ * even though internal code in types/index.ts referred to them. This is the
13
+ * union of both, defined once; both modules now re-export it.
14
+ */
15
+ var QueryTypes;
16
+ (function (QueryTypes) {
17
+ QueryTypes["SELECT"] = "SELECT";
18
+ QueryTypes["INSERT"] = "INSERT";
19
+ QueryTypes["UPDATE"] = "UPDATE";
20
+ QueryTypes["DELETE"] = "DELETE";
21
+ QueryTypes["UPSERT"] = "UPSERT";
22
+ QueryTypes["BULKINSERT"] = "BULKINSERT";
23
+ QueryTypes["BULKUPDATE"] = "BULKUPDATE";
24
+ QueryTypes["BULKDELETE"] = "BULKDELETE";
25
+ QueryTypes["VERSION"] = "VERSION";
26
+ QueryTypes["SHOWTABLES"] = "SHOWTABLES";
27
+ QueryTypes["DESCRIBE"] = "DESCRIBE";
28
+ QueryTypes["CALL"] = "CALL";
29
+ QueryTypes["RAW"] = "RAW";
30
+ })(QueryTypes || (exports.QueryTypes = QueryTypes = {}));