ts-prorm-orm 1.2.3 → 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 +199 -1
  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 +12 -3
  93. package/dist/index.js +53 -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 +1132 -553
  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
package/CHANGELOG.md CHANGED
@@ -5,16 +5,147 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.2.3]
8
+ ## [2.0.0]
9
+
10
+ ### Breaking
11
+
12
+ - **JSON/JSONB columns now return parsed values on every dialect.** Previously
13
+ the PostgreSQL and MySQL drivers returned an object while SQLite (and any
14
+ dialect storing JSON as TEXT) returned the raw string. Reads are now
15
+ consistent, which means **code that called `JSON.parse` on the result under
16
+ SQLite must drop that call** — it will now be parsing an object.
17
+
18
+ This is the only change requiring action on upgrade. Text that isn't valid
19
+ JSON is still returned as-is rather than throwing, so rows written by earlier
20
+ versions read back correctly.
21
+
22
+ ### Changed
23
+
24
+ - **JSON/JSONB columns now round-trip losslessly, and read back as parsed
25
+ values on every dialect.** Two separate problems, fixed together.
26
+
27
+ *Reads were dialect-specific.* The PostgreSQL and MySQL drivers already
28
+ returned an object; SQLite (and anything else storing JSON as TEXT) returned
29
+ the raw string, so the same model code behaved differently per engine.
30
+ `findAll`/`findOne`/`findByPk` now parse the string form everywhere.
31
+ **If you were calling `JSON.parse` yourself on SQLite, remove it** — the value
32
+ arrives parsed. Values that are already objects are untouched, and text that
33
+ isn't valid JSON is returned as-is rather than throwing, so rows written
34
+ before this release still read back correctly.
35
+
36
+ *Writes were asymmetric with reads.* A string value was written to the column
37
+ **unencoded** while the read side parsed unconditionally, so any string that
38
+ happened to be valid JSON changed type on the way back: `'123'` returned the
39
+ number `123`, `'true'` a boolean, `'{"a":1}'` an object, and
40
+ `'12345678901234567890'` came back as `12345678901234567000` — silent
41
+ precision loss. It also wrote invalid JSON on PostgreSQL, which rejects a bare
42
+ `hello` for a `json` column. Every value is now encoded on write, strings
43
+ included, in both the `define()` and class-based paths.
44
+
45
+ - **JSON/JSONB values were not serialized on write at all in some paths.** A
46
+ plain object survived by accident (the dialect's value escaper stringifies
47
+ objects), but an array was expanded into the `(a, b)` IN-list form and
48
+ produced invalid SQL. `create`, `bulkCreate`, `update` and `upsert` now
49
+ serialize explicitly.
9
50
 
10
51
  ### Fixed
11
52
 
53
+ - **`FindOptions.lock` never reached the dialect.** `findAll({ lock: 'UPDATE',
54
+ transaction: t })` compiled to a plain SELECT, so code written to serialize
55
+ concurrent updates took no lock at all. It is now forwarded, and PostgreSQL /
56
+ MySQL emit `FOR UPDATE` / `FOR SHARE` / `LOCK IN SHARE MODE` as documented.
57
+ Dialects without row-level locking (SQLite) still ignore it.
58
+ - **`FindOptions.union` / `unionType` were silently no-ops** on models built by
59
+ `prorm.define()` — the branches were declared, documented and compiled by the
60
+ dialects, but never passed to them, so only the main query ran.
61
+ - **`FindOptions.using` never worked.** It resolved the target through
62
+ `prorm.connectionManager`, which nothing ever set, so every call threw
63
+ `Connection 'x' not found. Available: none`; the class-based path then called
64
+ `.get()` on a plain object. `ConnectionManager.addConnection()` now registers
65
+ itself on the instance it creates, and `using` is implemented on both query
66
+ paths.
12
67
  - **`raw: true` was accepted and ignored.** Rows came back as full model
13
68
  instances carrying `save`/`update`/`destroy` and internal bookkeeping fields
14
69
  — slower than asked for, and wrong for grouped aggregates that correspond to
15
70
  no model instance. It now returns plain row objects.
16
71
  - `normalizeOperatorKeys` is exported from the package root, alongside the
17
72
  `operatorToWhereKey` and `getOperatorString` helpers it belongs with.
73
+ - **Row locking never compiled from the object form.** `lock: { level: 'UPDATE' }`
74
+ — and any object carrying `nowait` / `skipLocked` — emitted no lock clause at
75
+ all. Every documented shape now compiles across 9 dialects, including SQL
76
+ Server's table-hint syntax (`WITH (UPDLOCK, ROWLOCK, READPAST)`). A level a
77
+ dialect lacks throws naming the supported levels.
78
+ - **Composite unique constraints were never emitted.** Neither the `uniqueKeys`
79
+ model option nor the attribute-level `uniqueKey` grouping produced any SQL, so
80
+ uniqueness the model declared was never enforced by the database. Worse,
81
+ `sync({ alter: true })` *destroyed* constraints that had been emitted, because
82
+ SQLite implements `changeColumn` by rebuilding the table and the rebuild
83
+ dropped the `UNIQUE` clause. Both declaration forms now emit a real
84
+ constraint, and declared keys are re-applied after an alter.
85
+ - **Partial indexes.** `IndexOptions.where` compiled to bound placeholders,
86
+ which no database accepts in a `CREATE INDEX` predicate. Db2, SAP HANA and
87
+ ClickHouse silently dropped the predicate and returned an **unfiltered**
88
+ index; MariaDB and Oracle emitted a `WHERE` clause they have never accepted.
89
+ Predicates are now inlined as escaped literals where supported, and dialects
90
+ without partial indexes throw with the reason.
91
+ - **`ORDER BY` was broken on three dialects.** `[['name','DESC']]` produced
92
+ `ORDER BY [0] NAME, [1] DESC` on SQL Server and Snowflake; on Oracle a plain
93
+ `'name'` emitted one term per *character*. The `asc()` / `desc()` / `random()`
94
+ helpers were silently ignored on every dialect and on all four graph
95
+ dialects. `random()` now resolves per engine — `NEWID()` on SQL Server, where
96
+ `RAND()` is a per-query constant and would not shuffle at all.
97
+ - **Two filtering `include`s on the same parent column** merged into a shape the
98
+ where-builders don't recognise, collapsed to `"id" = ?`, and returned one
99
+ arbitrary parent.
100
+ - **`{ all: true }` includes** were never expanded, and did not compose with
101
+ `required: true`.
102
+ - **A bare-model include** (`include: [Post]`) threw a `TypeError` at the top
103
+ level and silently loaded nothing when nested; 11 documented `IncludeOptions`
104
+ fields were being dropped when include entries were rebuilt.
105
+ - **`findAndCountAll` ignored `union`**, so `count` described only the main
106
+ branch while `rows` covered all of them.
107
+ - **Foreign-key check toggling emitted MySQL syntax on PostgreSQL.** It now
108
+ routes per dialect family, and dialects with no session-level switch throw
109
+ naming their own alternative.
110
+ - **The published package could ship a stale build.** `npm run build` was a
111
+ plain `tsc`, which emits but never deletes, so a leftover `dist/logging.js`
112
+ from a removed source file shadowed `dist/logging/index.js` — Node resolves a
113
+ file before a directory — and the built package threw
114
+ `logQuery is not a function` on `bulkCreate`. The test suite could not catch
115
+ it, because it runs against `src/`. `build` now cleans first, and
116
+ `check:package` fails the publish on any stale output.
117
+
118
+ ### Added
119
+
120
+ - **30 previously unreachable exports.** `src/cache`, `src/audit`,
121
+ `src/prisma-migrate`, the `@Audit` decorator, `GraphCapabilityError` and
122
+ `DataLineage` were implemented but not exported, and the `exports` map allowed
123
+ no deep imports either. Five colliding cache type names are aliased so no
124
+ existing export changed meaning. `ts-prorm-orm/cache`, `/audit`, `/graph` and
125
+ `/prisma-migrate` subpaths expose them under their real names.
126
+ - **Bun support.** The SQLite dialect now resolves its driver per runtime:
127
+ `better-sqlite3` on Node, the built-in `bun:sqlite` on Bun. Bun needs no
128
+ native build step, and under Bun the better-sqlite3 addon may not be
129
+ installable at all. The two APIs differ in one place — bun:sqlite has no
130
+ `db.pragma()` — so the driver module adds it, keeping a single shape for the
131
+ dialect to code against with no runtime branching in the SQL layer. Under Bun
132
+ it still falls back to better-sqlite3 if that is what a project already
133
+ depends on. `scripts/bun-smoke.ts` exercises CRUD, operators, eager loading,
134
+ ordering, JSON, aggregates, paranoid deletes and transactions on Bun.
135
+ - **Documentation.** 29 developer guides plus an index, with every SQL example
136
+ captured from the running code rather than written from memory.
137
+ - **Tests.** ~4,000 connection-free tests across dialects, models, query
138
+ builders, compliance, optimizers, schema, graph and the CLI. `collectCoverageFrom`
139
+ now scopes coverage to shipped source (`src/test.ts` was inflating the
140
+ denominator despite being excluded from the build); no coverage threshold is
141
+ enforced.
142
+
143
+ ### Removed
144
+
145
+ - **`docs-next`** and its entire Vercel deployment pipeline. Documentation is
146
+ now a static React viewer published to GitLab Pages, and database image
147
+ mirroring moved to the project's own GitLab Container Registry.
148
+
18
149
 
19
150
  ## [1.2.2]
20
151
 
@@ -42,6 +173,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42
173
  ### Added
43
174
 
44
175
  - **`avg()`** — the one standard aggregate that was missing.
176
+ - Removed `src/hooks/` — a 488-line model-level hook system imported by nothing
177
+ and exported from nowhere, the third such parallel implementation found (after
178
+ the association decorators and the duplicate eager-loaders). Its `HookName`
179
+ union was salvaged into `core/types`.
45
180
  - `exports` now permits `ts-prorm-orm/package.json`, which build tooling and
46
181
  version checks commonly read.
47
182
 
@@ -142,6 +277,69 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
142
277
 
143
278
  ## [Unreleased]
144
279
 
280
+ ### Fixed
281
+
282
+ - **Query logging fired twice and ignored per-query overrides.** The user's
283
+ `logging` callback was handed to the internal Logger as well as being invoked
284
+ by the query path, so it ran on both - and the Logger's copy honoured no
285
+ per-query setting, making `findAll({ logging: false })` log anyway. The
286
+ internal Logger now handles only slow-query detection and its own levels.
287
+ - **Four operations logged nothing at all.** `count`, `bulkCreate`, `increment`
288
+ and the aggregates never emitted a line, so turning logging on showed an
289
+ incomplete picture of what the ORM was doing. Every operation now routes
290
+ through one path.
291
+ - **`instance.validate({ hooks: true })` ran no hooks.** It read a
292
+ `_hooksManager` property that nothing ever assigned, so the flag was accepted
293
+ and both `beforeValidate` and `afterValidate` were skipped. Both call sites
294
+ (prorm.ts and models/model.ts) now use the model's declared hooks, the same
295
+ source every other lifecycle hook comes from.
296
+
297
+ ### Added
298
+
299
+ - **Sequelize-compatible query logging.** `logging` accepts `false`, `true` or a
300
+ `(sql, timing)` function at instance level, overridable per query - so one
301
+ noisy call can be traced without enabling logging globally, and one call can
302
+ be silenced without disabling it. Adds `benchmark` (append elapsed time) and
303
+ `logQueryParameters` (append bound values, off by default since bound values
304
+ routinely contain credentials). The resolution logic lives in
305
+ `src/logging/query-logging.ts` and is exported: `logQuery`,
306
+ `resolveQueryLogger`, `formatQueryLog`.
307
+ - **`unset<Association>()` on belongsTo** — clears the foreign key and persists
308
+ it. `set<Association>(null)` does the same thing and now explicitly accepts
309
+ null, but reads as an assignment rather than a removal.
310
+ - **`HookName` / `ModelHookMap` types** — hook names as a union rather than
311
+ `string`, so a misspelled hook is a compile error instead of a callback that
312
+ silently never runs.
313
+ - **`@AbstractModel`** — a base class that defines fields shared by several
314
+ models without getting a table of its own. Columns declared on it, and any
315
+ `@PrimaryKey` / `@AutoIncrement` / defaults on them, are inherited by the
316
+ concrete models that extend it; a subclass may redeclare a column to override
317
+ it. Passing the abstract class to `addModel()` is an error naming the class.
318
+ - **Finders**: `findOneOrFail` / `findByPkOrFail` (throw `EmptyResultError`
319
+ rather than returning null), `findLast` (inverts the ordering), `exists(where)`
320
+ (a COUNT rather than fetching a row), and `findInBatches` / `findEach` for
321
+ walking a large set without holding it in memory. Batching pages by primary
322
+ key rather than OFFSET, so per-batch cost stays flat and concurrent writes
323
+ cannot cause a page to be skipped.
324
+ - **Eleven lifecycle hooks that never fired for model-level operations**:
325
+ `beforeUpdate`/`afterUpdate`, `beforeDestroy`/`afterDestroy`,
326
+ `beforeSave`/`afterSave`, `beforeFind`/`afterFind`, `beforeCount`, and
327
+ `beforeUpsert`/`afterUpsert`. They existed for instance methods only, so
328
+ `Model.update(...)` bypassed them entirely. `beforeFind` may return replacement
329
+ options and `afterFind` a replacement result set.
330
+ - **`Model.increment()` / `Model.decrement()`** — add to or subtract from
331
+ numeric columns with `SET n = n + 1` in a single statement, so two concurrent
332
+ callers each apply their delta. Previously only per-instance helpers existed,
333
+ leaving a read-modify-write that silently drops one of two simultaneous
334
+ updates. Accepts a column, a list, or a per-column map; honours `where` and
335
+ paranoid filtering.
336
+ - **`Model.bulkUpdate(rows)`** — write different values to many rows in one
337
+ statement, compiled as a `CASE` per column (portable across every supported
338
+ dialect) rather than one UPDATE per row. Columns a row omits keep their
339
+ current value; rows not listed are untouched. Identify rows by a non-primary
340
+ column with `{ key }`.
341
+
342
+
145
343
  ### Comprehensive Feature Reference
146
344
 
147
345
  This section provides a complete reference of all ORM features organized by category.
package/README.md CHANGED
@@ -29,6 +29,13 @@ A TypeScript ORM supporting multiple database dialects with full TypeScript supp
29
29
  - **Validation**: Built-in and custom validators
30
30
  - **Stored Procedures**: Create and call stored procedures (across supported dialects)
31
31
  - **Triggers**: Database triggers with FOR EACH ROW and WHEN clauses (across supported dialects)
32
+ - **Query logging**: Sequelize-compatible `logging` (`false` / `true` / a
33
+ `(sql, timing)` function), overridable per query, plus `benchmark` for elapsed
34
+ time and `logQueryParameters` for bound values. Every operation logs, not just
35
+ some
36
+ - **Bulk writes**: `increment`/`decrement` do the arithmetic in the database, so
37
+ concurrent updates don't lose each other; `bulkUpdate` writes different values
38
+ to many rows in one statement instead of one round trip per row
32
39
  - **Aggregates**: `count`, `sum`, `avg`, `min`, `max` — all issuing real SQL
33
40
  aggregates and honouring `where`, scopes, soft-deletes and relation filters;
34
41
  `group` + `having` for grouped results
@@ -646,29 +653,30 @@ npm run diagram:model
646
653
 
647
654
  ## Documentation
648
655
 
649
- Full documentation is available in the `docs/` directory:
650
-
651
- - [Getting Started](./docs/) - Main documentation entry point
652
- - [Dialects](./docs/dialects/) - Database-specific documentation
653
- - [SQLite](./docs/dialects/sqlite.md)
654
- - [MySQL](./docs/dialects/mysql.md)
655
- - [PostgreSQL](./docs/dialects/postgres.md)
656
- - [MariaDB](./docs/dialects/mariadb.md)
657
- - [Oracle](./docs/dialects/oracle.md)
658
- - [MSSQL](./docs/dialects/mssql.md)
659
- - [API Reference](./docs/api/) - API documentation
660
- - [Models](./docs/api/models.md)
661
- - [Query Builder](./docs/api/queries.md)
662
- - [Hooks](./docs/api/hooks.md)
663
- - [Associations](./docs/api/associations.md)
664
-
665
- Additional documentation:
666
- - [Models](./docs/MODELS.md) - Model definition
667
- - [Migrations](./docs/MIGRATIONS.md) - Database migrations
668
- - [Associations](./docs/ASSOCIATIONS.md) - Relationship types
669
- - [Hooks](./docs/HOOKS.md) - Lifecycle hooks
670
- - [Stored Procedures](./docs/STORED_PROCEDURES.md) - Advanced database features
671
- - [Triggers](./docs/TRIGGERS.md) - Database triggers
656
+ Full documentation is in the [`docs/`](./docs/README.md) directory — start
657
+ there for the complete index.
658
+
659
+ **Core**
660
+ - [Defining models](./docs/guides/models.md) · [Data types](./docs/guides/data-types.md) · [Querying](./docs/guides/querying.md) · [Query operators](./docs/guides/query-operators.md)
661
+ - [SQL function builders](./docs/guides/sql-functions.md) · [Associations](./docs/guides/associations.md) · [Eager loading](./docs/guides/eager-loading.md) · [Scopes](./docs/guides/scopes.md) · [Hooks](./docs/guides/hooks.md) · [Validation](./docs/guides/validation.md) · [Virtual fields](./docs/guides/virtual-fields.md)
662
+ - [Transactions](./docs/guides/transactions.md) · [Bulk operations](./docs/guides/bulk-operations.md) · [Raw queries](./docs/guides/raw-queries.md) · [Streaming](./docs/guides/streams.md) · [Error handling](./docs/guides/error-handling.md)
663
+
664
+ **Schema**
665
+ - [Indexes & constraints](./docs/guides/indexes-and-constraints.md) · [Schema objects](./docs/guides/schema-objects.md) (views, triggers, procedures, sequences, RLS, partitions)
666
+ - [Migrations](./docs/guides/migrations.md) · [QueryInterface](./docs/guides/query-interface.md) · [Schema diffing](./docs/guides/schema-diffing.md) · [Prisma import](./docs/guides/prisma-import.md)
667
+
668
+ **Connections & performance**
669
+ - [Connection pooling](./docs/guides/connection-pooling.md) · [Multiple databases](./docs/guides/multiple-databases.md) · [Read replicas](./docs/guides/replication.md)
670
+ - [Caching](./docs/guides/caching.md) · [Query optimization](./docs/guides/query-optimization.md) · [Logging](./docs/guides/logging.md)
671
+
672
+ **Extending & operating**
673
+ - [Decorators](./docs/guides/decorators.md) · [TypeScript types](./docs/guides/typescript-types.md) · [External fields](./docs/guides/external-fields.md) · [SQL constants](./docs/guides/sql-constants.md) · [Extension catalogue](./docs/guides/extensions.md)
674
+ - [Audit logging](./docs/guides/audit-logging.md) · [User management](./docs/guides/user-management.md) · [Compliance](./docs/guides/compliance.md) · [Foreign data wrappers](./docs/guides/foreign-data-wrappers.md) · [Runbooks](./docs/runbooks/README.md)
675
+
676
+ **Databases & tooling**
677
+ - [Database types](./docs/database-types.md) · [SQL dialects](./docs/dialects/README.md) ([SQLite](./docs/dialects/sqlite.md), [PostgreSQL](./docs/dialects/postgres.md), [MySQL](./docs/dialects/mysql.md), [MariaDB](./docs/dialects/mariadb.md), [Oracle](./docs/dialects/oracle.md), [MSSQL](./docs/dialects/mssql.md), …)
678
+ - [Store adapters](./docs/stores/README.md) · [Graph databases](./docs/guides/graph-databases.md) · [SQLite advanced](./docs/guides/sqlite-advanced.md)
679
+ - [CLI](./docs/guides/cli.md) · [Diagrams](./docs/diagrams/README.md) · [Docker & sandboxes](./docs/guides/docker/)
672
680
 
673
681
  ### Architecture / Component Guides
674
682
 
@@ -676,7 +684,7 @@ In-depth, code-level reference docs for each major subsystem, living alongside t
676
684
 
677
685
  - [Dialects](src/dialects/README.md) - The `Dialect` interface and per-database (SQLite/MySQL/PostgreSQL/MariaDB/Oracle/MSSQL/CockroachDB/Redshift/Db2/Snowflake/ClickHouse/DuckDB/HANA/Spanner) implementations of connections, DDL, views, partitioning, RLS, and query building.
678
686
  - [Models](src/models/README.md) - The model layer: attribute/data types, `prorm.define()`, associations, scopes, indexes/constraints, and the model registry.
679
- - [Query Builders](src/query-builders/README.md) - Translates `where`/`order`/`limit`/`include` options into dialect-specific SQL strings and bound parameter values. Includes a typed SQL function-builder library (`src/query-builders/functions/**` - window functions, date/time, JSON paths, string/math functions, CASE expressions, cross-dialect aggregates, full-text search) usable via `import { ... } from 'ts-prorm-orm'`; see [SQL Functions](docs/query-features/queries.md#sql-functions) for worked examples.
687
+ - [Query Builders](src/query-builders/README.md) - Translates `where`/`order`/`limit`/`include` options into dialect-specific SQL strings and bound parameter values. Includes a typed SQL function-builder library (`src/query-builders/functions/**` - window functions, date/time, JSON paths, string/math functions, CASE expressions, cross-dialect aggregates, full-text search) usable via `import { ... } from 'ts-prorm-orm'`; see [`src/query-builders/README.md`](src/query-builders/README.md) for the function list.
680
688
  - [Extension Catalog](src/extensions/README.md) - A discoverability reference (not executable code) of ~124 verified real extensions/plugins/licensed features across dialects, queryable via `findExtension()`/`listExtensionsForDialect()`/`listExtensionsByCategory()`/`searchExtensions()`.
681
689
  - [Query Optimizers](src/query-optimizers/README.md) - Opt-in performance tooling (query hints, explain plans, slow-query logging, batch optimization, prepared-statement/result caching).
682
690
  - [Migrations](src/migrations/README.md) - Migration files, the `Migrator`, `PrormMeta` history tracking, seeders, `QueryInterface`, and schema diffing (`src/schema/`).
@@ -91,3 +91,5 @@ export { DSARWorkflow, DSARRequest, RequestStatus, RequestType, FulfillmentOptio
91
91
  export { PrivacyImpactAssessment, AssessmentStatus, RiskSeverity, PIARecord, RiskRecord, PIACreateOptions, RiskRecordOptions, } from './privacy-impact-assessment';
92
92
  export { BackupVerification, BackupSource, BackupConfig, BackupMetadata, VerificationResult, VerificationSchedule, VerificationHistoryEntry, } from './backup-verification';
93
93
  export { QueryFirewall, FirewallRule, FirewallRuleType, FirewallMode, FirewallModeEnum, FirewallOptions, QueryAnalysis, QueryOperation, BlockedQuery, getRecommendedRules, FIREWALL_RULES, OWASP_SQL_INJECTION_PATTERNS, CIS_BENCHMARK_RULES, PCI_DSS_RULES, HIPAA_RULES, SOX_RULES, NIST_CSF_RULES, POSTGRESQL_RULES, MYSQL_RULES, MARIADB_RULES, MSSQL_RULES, ORACLE_RULES, SQLITE_RULES, DATABASE_RULES, DatabaseType, FirewallRules, FirewallRuleDecoratorOptions, PostgreSQLFirewall, MySQLFirewall, MariaDBFirewall, MSSQLFirewall, OracleFirewall, SQLiteFirewall, applyFirewallRulesToModel, } from './query-firewall';
94
+ export { DataLineage, LineageTrack, getLineageFields, getLineageOptions, createDerivedRecord, createComputedRecord, applyHooks as applyLineageHooks, } from './data-lineage';
95
+ export type { DataSource, TransformationRecord, LineageRecord, LineageChain, LineageOptions, LineageTrackOptions, } from './data-lineage';
@@ -70,7 +70,7 @@
70
70
  Object.defineProperty(exports, "__esModule", { value: true });
71
71
  exports.getPIIFields = exports.getClassification = exports.FieldClassification = exports.Classify = exports.DataClassifier = exports.createDSARResponse = exports.exportStream = exports.exportData = exports.DataPortabilityExporter = exports.applyPseudonymizationHooks = exports.Pseudonymize = exports.detokenize = exports.tokenize = exports.configure = exports.PseudonymizationService = exports.isImmutable = exports.enableVersioning = exports.makeImmutable = exports.ImmutableRecord = exports.applyMaskingHooks = exports.maskMany = exports.mask = exports.maskValue = exports.maskField = exports.Mask = exports.MaskPatternEnum = exports.DataMasker = exports.registerHooks = exports.rlsMiddleware = exports.runInContext = exports.getContext = exports.setContext = exports.apply = exports.initRLS = exports.RLS = exports.RowLevelSecurity = exports.ConsentVersioning = exports.LegalBasisEnum = exports.ConsentRecord = exports.RightToErasure = exports.DataRetentionPolicy = exports.TLSEnforcer = exports.getEncryptedFields = exports.applyEncryptionHooks = exports.Encrypt = exports.decryptValue = exports.encryptValue = exports.configureFieldEncryption = exports.FieldEncryption = exports.ComplianceAuditTrail = void 0;
72
72
  exports.SensitiveDataDiscovery = exports.getRecommendedLimits = exports.satisfiesCompliance = exports.checkRateLimit = exports.initRateLimiter = exports.getGlobalLimiter = exports.getRateLimitOptions = exports.RateLimit = exports.RateLimiter = exports.isArchived = exports.isFrozen = exports.applyWORMHooks = exports.getWORMOptions = exports.WORM = exports.WORMStorage = exports.getTenantIsolationOptions = exports.getTenantAuditMetadata = exports.sessionIsolationMiddleware = exports.TenantIsolation = exports.SessionIsolation = exports.initBreachDetector = exports.getGlobalBreachDetector = exports.BreachDetector = exports.analyzeQuerySecurity = exports.initSecurityMonitor = exports.getGlobalMonitor = exports.ComplianceSecurityMonitor = exports.SecurityMonitor = exports.isImmutableModel = exports.hasAudit = exports.getSecurityFrameworks = exports.getDatabaseSecurity = exports.getTableSecurity = exports.DatabaseSecurity = exports.Table = exports.setupAllSecurity = exports.setupSecurity = exports.getAllFrameworks = exports.getFrameworkCategory = exports.isValidFramework = exports.FrameworkCount = exports.FrameworkRequirements = exports.FrameworkCategories = exports.AllFrameworks = exports.SecurityFramework = exports.Security = exports.autoDiscover = exports.isSensitive = exports.getPCIFields = exports.getPHIFields = void 0;
73
- exports.applyFirewallRulesToModel = exports.SQLiteFirewall = exports.OracleFirewall = exports.MSSQLFirewall = exports.MariaDBFirewall = exports.MySQLFirewall = exports.PostgreSQLFirewall = exports.FirewallRules = exports.DATABASE_RULES = exports.SQLITE_RULES = exports.ORACLE_RULES = exports.MSSQL_RULES = exports.MARIADB_RULES = exports.MYSQL_RULES = exports.POSTGRESQL_RULES = exports.NIST_CSF_RULES = exports.SOX_RULES = exports.HIPAA_RULES = exports.PCI_DSS_RULES = exports.CIS_BENCHMARK_RULES = exports.OWASP_SQL_INJECTION_PATTERNS = exports.FIREWALL_RULES = exports.getRecommendedRules = exports.FirewallModeEnum = exports.QueryFirewall = exports.BackupVerification = exports.PrivacyImpactAssessment = exports.DSARWorkflow = exports.generateTransferReport = exports.getComplianceTransfers = exports.CrossBorderLog = exports.generateComplianceReport = exports.getPatterns = exports.unregisterPattern = exports.registerPattern = void 0;
73
+ exports.applyLineageHooks = exports.createComputedRecord = exports.createDerivedRecord = exports.getLineageOptions = exports.getLineageFields = exports.LineageTrack = exports.DataLineage = exports.applyFirewallRulesToModel = exports.SQLiteFirewall = exports.OracleFirewall = exports.MSSQLFirewall = exports.MariaDBFirewall = exports.MySQLFirewall = exports.PostgreSQLFirewall = exports.FirewallRules = exports.DATABASE_RULES = exports.SQLITE_RULES = exports.ORACLE_RULES = exports.MSSQL_RULES = exports.MARIADB_RULES = exports.MYSQL_RULES = exports.POSTGRESQL_RULES = exports.NIST_CSF_RULES = exports.SOX_RULES = exports.HIPAA_RULES = exports.PCI_DSS_RULES = exports.CIS_BENCHMARK_RULES = exports.OWASP_SQL_INJECTION_PATTERNS = exports.FIREWALL_RULES = exports.getRecommendedRules = exports.FirewallModeEnum = exports.QueryFirewall = exports.BackupVerification = exports.PrivacyImpactAssessment = exports.DSARWorkflow = exports.generateTransferReport = exports.getComplianceTransfers = exports.CrossBorderLog = exports.generateComplianceReport = exports.getPatterns = exports.unregisterPattern = exports.registerPattern = void 0;
74
74
  // Audit Trail
75
75
  var audit_trail_1 = require("./audit-trail");
76
76
  Object.defineProperty(exports, "ComplianceAuditTrail", { enumerable: true, get: function () { return audit_trail_1.ComplianceAuditTrail; } });
@@ -258,3 +258,15 @@ Object.defineProperty(exports, "MSSQLFirewall", { enumerable: true, get: functio
258
258
  Object.defineProperty(exports, "OracleFirewall", { enumerable: true, get: function () { return query_firewall_1.OracleFirewall; } });
259
259
  Object.defineProperty(exports, "SQLiteFirewall", { enumerable: true, get: function () { return query_firewall_1.SQLiteFirewall; } });
260
260
  Object.defineProperty(exports, "applyFirewallRulesToModel", { enumerable: true, get: function () { return query_firewall_1.applyFirewallRulesToModel; } });
261
+ // Data Lineage
262
+ // `applyHooks` is aliased to `applyLineageHooks` for the same reason
263
+ // data-masker's and pseudonymization's are: three modules in this barrel each
264
+ // export a function by that name.
265
+ var data_lineage_1 = require("./data-lineage");
266
+ Object.defineProperty(exports, "DataLineage", { enumerable: true, get: function () { return data_lineage_1.DataLineage; } });
267
+ Object.defineProperty(exports, "LineageTrack", { enumerable: true, get: function () { return data_lineage_1.LineageTrack; } });
268
+ Object.defineProperty(exports, "getLineageFields", { enumerable: true, get: function () { return data_lineage_1.getLineageFields; } });
269
+ Object.defineProperty(exports, "getLineageOptions", { enumerable: true, get: function () { return data_lineage_1.getLineageOptions; } });
270
+ Object.defineProperty(exports, "createDerivedRecord", { enumerable: true, get: function () { return data_lineage_1.createDerivedRecord; } });
271
+ Object.defineProperty(exports, "createComputedRecord", { enumerable: true, get: function () { return data_lineage_1.createComputedRecord; } });
272
+ Object.defineProperty(exports, "applyLineageHooks", { enumerable: true, get: function () { return data_lineage_1.applyHooks; } });
@@ -37,6 +37,12 @@ class ConnectionManager {
37
37
  throw new Error(`Connection with name '${name}' already exists`);
38
38
  }
39
39
  const prorm = new prorm_1.Prorm(options);
40
+ // Let the instance find its siblings. This is what makes
41
+ // `Model.findAll({ using: 'other' })` resolvable: the query path looks the
42
+ // target connection up through `prorm.connectionManager`, which nothing
43
+ // used to set, so `using` failed with "Available: none" no matter how many
44
+ // connections had been added.
45
+ prorm.connectionManager = this;
40
46
  this.connections.set(name, prorm);
41
47
  // Set as default if it's the first connection
42
48
  if (this._defaultConnection === null) {
@@ -78,8 +84,11 @@ class ConnectionManager {
78
84
  if (!prorm) {
79
85
  return false;
80
86
  }
81
- // Close the connection
87
+ // Close the connection and detach it from this manager, so a model still
88
+ // holding a reference to it can't route a `using` query through a
89
+ // registry it is no longer a member of.
82
90
  await prorm.close();
91
+ prorm.connectionManager = null;
83
92
  this.connections.delete(name);
84
93
  // Update default if needed
85
94
  if (this._defaultConnection === name) {
@@ -167,6 +176,9 @@ class ConnectionManager {
167
176
  async closeAll() {
168
177
  const closePromises = Array.from(this.connections.values()).map((seq) => seq.close());
169
178
  await Promise.all(closePromises);
179
+ for (const prorm of this.connections.values()) {
180
+ prorm.connectionManager = null;
181
+ }
170
182
  this.connections.clear();
171
183
  this._defaultConnection = null;
172
184
  }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Raw SQL expression wrappers used by the Prorm instance API.
3
+ *
4
+ * `Literal` embeds SQL verbatim; `Col` references a column without quoting it
5
+ * as a value. Note that `src/operators.ts` also exposes `literal()`/`col()`
6
+ * factories producing a different shape - the dialects consume the operators
7
+ * form, so prefer those in new code.
8
+ */
9
+ /**
10
+ * Represents a raw SQL literal value
11
+ * Used for inserting raw SQL expressions into queries
12
+ *
13
+ * @example
14
+ * // Use in default values
15
+ * createdAt: { type: DATE, defaultValue: prorm.literal('NOW()') }
16
+ *
17
+ * @example
18
+ * // Use in updates
19
+ * User.update({ count: prorm.literal('count + 1') }, {...})
20
+ *
21
+ * @example
22
+ * // Use in select with calculations
23
+ * User.findAll({ attributes: [[prorm.literal('1 + 1'), 'two']] })
24
+ */
25
+ export declare class Literal {
26
+ readonly val: string;
27
+ constructor(sql: string);
28
+ /**
29
+ * Get the raw SQL string
30
+ */
31
+ toString(): string;
32
+ }
33
+ /**
34
+ * Class representing a column reference for use with Prorm functions
35
+ * Used to create properly quoted column identifiers
36
+ *
37
+ * @example
38
+ * // Single column: col('name') -> "name"
39
+ * // Table and column: col('User', 'name') -> "User"."name"
40
+ * // Dot notation: col('table.column') -> "table"."column"
41
+ */
42
+ export declare class Col {
43
+ private readonly col;
44
+ /**
45
+ * Create a column reference
46
+ * @param tableOrColumn - Table name (if second param provided) or column name
47
+ * @param column - Column name (if first param is table name)
48
+ */
49
+ constructor(tableOrColumn: string, column?: string);
50
+ /**
51
+ * Get the SQL representation of the column
52
+ */
53
+ toSql(): string;
54
+ /**
55
+ * Get the column as a string
56
+ */
57
+ toString(): string;
58
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /**
3
+ * Raw SQL expression wrappers used by the Prorm instance API.
4
+ *
5
+ * `Literal` embeds SQL verbatim; `Col` references a column without quoting it
6
+ * as a value. Note that `src/operators.ts` also exposes `literal()`/`col()`
7
+ * factories producing a different shape - the dialects consume the operators
8
+ * form, so prefer those in new code.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.Col = exports.Literal = void 0;
12
+ /**
13
+ * Represents a raw SQL literal value
14
+ * Used for inserting raw SQL expressions into queries
15
+ *
16
+ * @example
17
+ * // Use in default values
18
+ * createdAt: { type: DATE, defaultValue: prorm.literal('NOW()') }
19
+ *
20
+ * @example
21
+ * // Use in updates
22
+ * User.update({ count: prorm.literal('count + 1') }, {...})
23
+ *
24
+ * @example
25
+ * // Use in select with calculations
26
+ * User.findAll({ attributes: [[prorm.literal('1 + 1'), 'two']] })
27
+ */
28
+ class Literal {
29
+ constructor(sql) {
30
+ this.val = sql;
31
+ }
32
+ /**
33
+ * Get the raw SQL string
34
+ */
35
+ toString() {
36
+ return this.val;
37
+ }
38
+ }
39
+ exports.Literal = Literal;
40
+ /**
41
+ * Class representing a column reference for use with Prorm functions
42
+ * Used to create properly quoted column identifiers
43
+ *
44
+ * @example
45
+ * // Single column: col('name') -> "name"
46
+ * // Table and column: col('User', 'name') -> "User"."name"
47
+ * // Dot notation: col('table.column') -> "table"."column"
48
+ */
49
+ class Col {
50
+ /**
51
+ * Create a column reference
52
+ * @param tableOrColumn - Table name (if second param provided) or column name
53
+ * @param column - Column name (if first param is table name)
54
+ */
55
+ constructor(tableOrColumn, column) {
56
+ if (column !== undefined) {
57
+ // col('User', 'name') -> "User"."name"
58
+ this.col = `"${tableOrColumn}"."${column}"`;
59
+ }
60
+ else if (tableOrColumn.includes('.')) {
61
+ // col('table.column') -> "table"."column"
62
+ const [table, col] = tableOrColumn.split('.');
63
+ this.col = `"${table}"."${col}"`;
64
+ }
65
+ else {
66
+ // col('name') -> "name"
67
+ this.col = `"${tableOrColumn}"`;
68
+ }
69
+ }
70
+ /**
71
+ * Get the SQL representation of the column
72
+ */
73
+ toSql() {
74
+ return this.col;
75
+ }
76
+ /**
77
+ * Get the column as a string
78
+ */
79
+ toString() {
80
+ return this.col;
81
+ }
82
+ }
83
+ exports.Col = Col;