@xfcfam/xf-sql 0.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +167 -0
  3. package/dist/index.d.ts +26 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +27 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/api/A.d.ts +17 -0
  8. package/dist/src/api/A.d.ts.map +1 -0
  9. package/dist/src/api/A.js +17 -0
  10. package/dist/src/api/A.js.map +1 -0
  11. package/dist/src/business/B.d.ts +17 -0
  12. package/dist/src/business/B.d.ts.map +1 -0
  13. package/dist/src/business/B.js +17 -0
  14. package/dist/src/business/B.js.map +1 -0
  15. package/dist/src/repository/R.d.ts +17 -0
  16. package/dist/src/repository/R.d.ts.map +1 -0
  17. package/dist/src/repository/R.js +17 -0
  18. package/dist/src/repository/R.js.map +1 -0
  19. package/dist/src/repository/base/DatabaseRepository.d.ts +184 -0
  20. package/dist/src/repository/base/DatabaseRepository.d.ts.map +1 -0
  21. package/dist/src/repository/base/DatabaseRepository.js +216 -0
  22. package/dist/src/repository/base/DatabaseRepository.js.map +1 -0
  23. package/dist/src/repository/base/TransactionalDatabaseRepository.d.ts +86 -0
  24. package/dist/src/repository/base/TransactionalDatabaseRepository.d.ts.map +1 -0
  25. package/dist/src/repository/base/TransactionalDatabaseRepository.js +104 -0
  26. package/dist/src/repository/base/TransactionalDatabaseRepository.js.map +1 -0
  27. package/dist/src/repository/general/DatabaseRepository.d.ts +192 -0
  28. package/dist/src/repository/general/DatabaseRepository.d.ts.map +1 -0
  29. package/dist/src/repository/general/DatabaseRepository.js +224 -0
  30. package/dist/src/repository/general/DatabaseRepository.js.map +1 -0
  31. package/dist/src/repository/general/TransactionalDatabaseRepository.d.ts +91 -0
  32. package/dist/src/repository/general/TransactionalDatabaseRepository.d.ts.map +1 -0
  33. package/dist/src/repository/general/TransactionalDatabaseRepository.js +114 -0
  34. package/dist/src/repository/general/TransactionalDatabaseRepository.js.map +1 -0
  35. package/dist/src/repository/structs/CheckViolationException.d.ts +19 -0
  36. package/dist/src/repository/structs/CheckViolationException.d.ts.map +1 -0
  37. package/dist/src/repository/structs/CheckViolationException.js +22 -0
  38. package/dist/src/repository/structs/CheckViolationException.js.map +1 -0
  39. package/dist/src/repository/structs/ConnectionException.d.ts +15 -0
  40. package/dist/src/repository/structs/ConnectionException.d.ts.map +1 -0
  41. package/dist/src/repository/structs/ConnectionException.js +16 -0
  42. package/dist/src/repository/structs/ConnectionException.js.map +1 -0
  43. package/dist/src/repository/structs/DatabaseException.d.ts +14 -0
  44. package/dist/src/repository/structs/DatabaseException.d.ts.map +1 -0
  45. package/dist/src/repository/structs/DatabaseException.js +15 -0
  46. package/dist/src/repository/structs/DatabaseException.js.map +1 -0
  47. package/dist/src/repository/structs/DeadlockException.d.ts +16 -0
  48. package/dist/src/repository/structs/DeadlockException.d.ts.map +1 -0
  49. package/dist/src/repository/structs/DeadlockException.js +17 -0
  50. package/dist/src/repository/structs/DeadlockException.js.map +1 -0
  51. package/dist/src/repository/structs/ForeignKeyViolationException.d.ts +20 -0
  52. package/dist/src/repository/structs/ForeignKeyViolationException.d.ts.map +1 -0
  53. package/dist/src/repository/structs/ForeignKeyViolationException.js +23 -0
  54. package/dist/src/repository/structs/ForeignKeyViolationException.js.map +1 -0
  55. package/dist/src/repository/structs/NotNullViolationException.d.ts +20 -0
  56. package/dist/src/repository/structs/NotNullViolationException.d.ts.map +1 -0
  57. package/dist/src/repository/structs/NotNullViolationException.js +23 -0
  58. package/dist/src/repository/structs/NotNullViolationException.js.map +1 -0
  59. package/dist/src/repository/structs/UniqueViolationException.d.ts +36 -0
  60. package/dist/src/repository/structs/UniqueViolationException.d.ts.map +1 -0
  61. package/dist/src/repository/structs/UniqueViolationException.js +40 -0
  62. package/dist/src/repository/structs/UniqueViolationException.js.map +1 -0
  63. package/dist/src/repository/transfers/CheckViolationException.d.ts +19 -0
  64. package/dist/src/repository/transfers/CheckViolationException.d.ts.map +1 -0
  65. package/dist/src/repository/transfers/CheckViolationException.js +22 -0
  66. package/dist/src/repository/transfers/CheckViolationException.js.map +1 -0
  67. package/dist/src/repository/transfers/ConnectionException.d.ts +15 -0
  68. package/dist/src/repository/transfers/ConnectionException.d.ts.map +1 -0
  69. package/dist/src/repository/transfers/ConnectionException.js +16 -0
  70. package/dist/src/repository/transfers/ConnectionException.js.map +1 -0
  71. package/dist/src/repository/transfers/DatabaseException.d.ts +14 -0
  72. package/dist/src/repository/transfers/DatabaseException.d.ts.map +1 -0
  73. package/dist/src/repository/transfers/DatabaseException.js +15 -0
  74. package/dist/src/repository/transfers/DatabaseException.js.map +1 -0
  75. package/dist/src/repository/transfers/DeadlockException.d.ts +16 -0
  76. package/dist/src/repository/transfers/DeadlockException.d.ts.map +1 -0
  77. package/dist/src/repository/transfers/DeadlockException.js +17 -0
  78. package/dist/src/repository/transfers/DeadlockException.js.map +1 -0
  79. package/dist/src/repository/transfers/ForeignKeyViolationException.d.ts +20 -0
  80. package/dist/src/repository/transfers/ForeignKeyViolationException.d.ts.map +1 -0
  81. package/dist/src/repository/transfers/ForeignKeyViolationException.js +23 -0
  82. package/dist/src/repository/transfers/ForeignKeyViolationException.js.map +1 -0
  83. package/dist/src/repository/transfers/NotNullViolationException.d.ts +20 -0
  84. package/dist/src/repository/transfers/NotNullViolationException.d.ts.map +1 -0
  85. package/dist/src/repository/transfers/NotNullViolationException.js +23 -0
  86. package/dist/src/repository/transfers/NotNullViolationException.js.map +1 -0
  87. package/dist/src/repository/transfers/UniqueViolationException.d.ts +36 -0
  88. package/dist/src/repository/transfers/UniqueViolationException.d.ts.map +1 -0
  89. package/dist/src/repository/transfers/UniqueViolationException.js +40 -0
  90. package/dist/src/repository/transfers/UniqueViolationException.js.map +1 -0
  91. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Israel Sanjurjo and the XF contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # `@xfcfam/xf-sql`
2
+
3
+ SQL Access Layer Generalization for the **XF Architecture Model**.
4
+ Encapsulates the [Kysely](https://kysely.dev) query builder behind a
5
+ single XF-canonical class plus a typed Exception hierarchy.
6
+
7
+ **Dialect-agnostic.** xf-sql talks to any database for which Kysely
8
+ has a dialect implementation. Pair it with one of the adapter
9
+ packages:
10
+
11
+ - [`@xfcfam/xf-sql-postgres`](https://www.npmjs.com/package/@xfcfam/xf-sql-postgres) — Postgres via `pg`
12
+ - (future) `@xfcfam/xf-sql-mysql`, `@xfcfam/xf-sql-sqlite`, …
13
+
14
+ Or supply any Kysely `Dialect` directly to `DatabaseRepository`.
15
+
16
+ Peer dependency: `@xfcfam/xf`. `kysely` is a direct (bundled) dependency.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pnpm add @xfcfam/xf @xfcfam/xf-sql kysely
22
+ # plus one dialect adapter, e.g.
23
+ pnpm add @xfcfam/xf-sql-postgres pg
24
+ ```
25
+
26
+ ## What ships here
27
+
28
+ | Export | Role |
29
+ |---|---|
30
+ | `DatabaseRepository<Schema>` | Access Layer Generalization. Constructor `({ dialect })`. Protected `db: Kysely<Schema>`. `exec(op)` wrapper that funnels errors through `translateError`. Overridable hooks: `onConnected`, `onDisconnected`, `onQuery`, `onError`. |
31
+ | `TransactionalDatabaseRepository<Schema>` | Adds `transaction(callback)` that commits / rolls back the Kysely transaction and translates errors. Overridable hooks: `onTransactionStart`, `onTransactionCommit`, `onTransactionRollback`. |
32
+ | `DatabaseException` | Base class for every typed DB error. |
33
+ | `ConnectionException` | Database unreachable (DNS, refused, TLS, timeout). |
34
+ | `UniqueViolationException` | `UNIQUE` / `PRIMARY KEY` constraint violated. Carries `constraint`, `table`, `column`. |
35
+ | `ForeignKeyViolationException` | `FOREIGN KEY` constraint violated. Carries `constraint`, `table`. |
36
+ | `CheckViolationException` | `CHECK` constraint violated. Carries `constraint`, `table`. |
37
+ | `NotNullViolationException` | `NOT NULL` column set to `NULL`. Carries `table`, `column`. |
38
+ | `DeadlockException` | DB-detected deadlock; typically retryable. |
39
+
40
+ ## Quick usage
41
+
42
+ ```typescript
43
+ import { TransactionalDatabaseRepository, UniqueViolationException } from '@xfcfam/xf-sql'
44
+ import { PostgresDialect } from 'kysely'
45
+ import { Pool } from 'pg'
46
+
47
+ interface Schema {
48
+ users: { id: number; name: string; email: string; created_at: Date }
49
+ }
50
+
51
+ export class UsersDb extends TransactionalDatabaseRepository<Schema> {
52
+ constructor() {
53
+ super({
54
+ dialect: new PostgresDialect({
55
+ pool: new Pool({ connectionString: process.env.DATABASE_URL }),
56
+ }),
57
+ })
58
+ }
59
+ async init() { await super.init() }
60
+ async terminate() { await super.terminate() }
61
+
62
+ getUser(id: number) {
63
+ return this.exec(() =>
64
+ this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
65
+ )
66
+ }
67
+
68
+ createUser(input: { name: string; email: string }) {
69
+ return this.exec(() =>
70
+ this.db
71
+ .insertInto('users')
72
+ .values({ ...input, created_at: new Date() })
73
+ .returningAll()
74
+ .executeTakeFirstOrThrow()
75
+ )
76
+ }
77
+ }
78
+ ```
79
+
80
+ > The example above uses the generic `DatabaseRepository` with a
81
+ > raw Kysely dialect. In a real project you would typically extend
82
+ > `PostgresDatabaseRepository` from `@xfcfam/xf-sql-postgres`, which
83
+ > wires the dialect and translates Postgres errors automatically.
84
+
85
+ ## Batching pattern (deferred writes)
86
+
87
+ When a workload generates many small writes, batching them into a
88
+ single transaction can cut latency and load on the database
89
+ dramatically. xf-sql doesn't ship a dedicated "batch repository" —
90
+ batching is a Business-Layer concern (a policy on **when** to write),
91
+ not a SQL protocol concern. Compose the building blocks:
92
+
93
+ - **`BatchedBusiness<T>`** from `@xfcfam/xf` accumulates items in
94
+ memory and flushes them by size, by time, manually or on terminate.
95
+ Dialect-agnostic — works with Postgres, MySQL, SQLite, anything.
96
+ - **`TransactionalDatabaseRepository`** in the consumer's Access
97
+ Layer executes the flush as a single transaction.
98
+
99
+ ```typescript
100
+ import { BatchedBusiness } from '@xfcfam/xf'
101
+ import { R } from '../R.js' // your Access injection
102
+
103
+ interface AuditEvent { actor: string; action: string; at: Date }
104
+
105
+ export class AuditBatchBusiness extends BatchedBusiness<AuditEvent> {
106
+ constructor() {
107
+ super({
108
+ maxSize: 500, // flush when 500 events queued, OR
109
+ maxAgeMs: 5_000, // every 5 seconds, whichever comes first
110
+ onErrorPolicy: 'retain',
111
+ flush: batch => R.auditDb.recordMany(batch), // single TX on the receiving Repository
112
+ })
113
+ }
114
+
115
+ record(event: AuditEvent) { this.add(event) }
116
+
117
+ protected override onFlushStart(batch: readonly AuditEvent[], reason) {
118
+ console.log(`[audit] flushing ${batch.length} events (${reason})`)
119
+ }
120
+ protected override onFlushError(batch, err) {
121
+ console.error(`[audit] flush failed, ${batch.length} events retained`, err)
122
+ }
123
+ }
124
+ ```
125
+
126
+ And on the receiving Repository:
127
+
128
+ ```typescript
129
+ import { TransactionalDatabaseRepository } from '@xfcfam/xf-sql'
130
+
131
+ export class AuditDb extends TransactionalDatabaseRepository<Schema> {
132
+ recordMany(batch: readonly AuditEvent[]) {
133
+ return this.transaction(async (trx) => {
134
+ await trx.insertInto('audit').values([...batch]).execute()
135
+ })
136
+ }
137
+ }
138
+ ```
139
+
140
+ This pattern is **fully compatible across dialects** — `AuditBatchBusiness`
141
+ doesn't know whether the target is Postgres, MySQL or SQLite. Swap the
142
+ dialect adapter, the business component stays unchanged.
143
+
144
+ ## Error translation
145
+
146
+ xf-sql defines the Exception types but **does not translate driver
147
+ errors itself** — it doesn't know about Postgres SQLSTATEs or MySQL
148
+ error numbers. Either:
149
+
150
+ - Use a dialect adapter (e.g. `PostgresDatabaseRepository`) that
151
+ overrides `translateError` for you, **or**
152
+ - Override `translateError(err)` in your own subclass and map the
153
+ driver's error shape to the `*Exception` types above.
154
+
155
+ Wrap queries in `this.exec(() => …)` so the translation runs.
156
+ Transactions are wrapped automatically by
157
+ `TransactionalDatabaseRepository.transaction`.
158
+
159
+ ## Documentation
160
+
161
+ - Specification — [xfcfam.org](https://xfcfam.org)
162
+ - Kysely docs — [kysely.dev](https://kysely.dev)
163
+ - Source — [github.com/xfcfam/lib-npm](https://github.com/xfcfam/lib-npm)
164
+
165
+ ## License
166
+
167
+ MIT.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `@xfcfam/xf-sql` — SQL Access Layer Generalization for the XF
3
+ * Architecture Model.
4
+ *
5
+ * Encapsulates the [Kysely](https://kysely.dev) query builder behind
6
+ * an XF-canonical Generalization (`DatabaseRepository`) plus a
7
+ * transaction-aware specialisation (`TransactionalDatabaseRepository`)
8
+ * and a typed Exception hierarchy.
9
+ *
10
+ * xf-sql is **dialect-agnostic**: pair it with one of the dialect
11
+ * adapter packages (`@xfcfam/xf-sql-postgres`,
12
+ * `@xfcfam/xf-sql-mysql`, …) or supply any Kysely `Dialect` directly.
13
+ *
14
+ * Peer dependency: `@xfcfam/xf`. `kysely` is a direct (bundled) dependency.
15
+ */
16
+ export { DatabaseRepository } from './src/repository/general/DatabaseRepository.js';
17
+ export type { DatabaseOptions } from './src/repository/general/DatabaseRepository.js';
18
+ export { TransactionalDatabaseRepository } from './src/repository/general/TransactionalDatabaseRepository.js';
19
+ export { DatabaseException } from './src/repository/transfers/DatabaseException.js';
20
+ export { ConnectionException } from './src/repository/transfers/ConnectionException.js';
21
+ export { UniqueViolationException } from './src/repository/transfers/UniqueViolationException.js';
22
+ export { ForeignKeyViolationException } from './src/repository/transfers/ForeignKeyViolationException.js';
23
+ export { CheckViolationException } from './src/repository/transfers/CheckViolationException.js';
24
+ export { NotNullViolationException } from './src/repository/transfers/NotNullViolationException.js';
25
+ export { DeadlockException } from './src/repository/transfers/DeadlockException.js';
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AACnF,YAAY,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,EAAE,+BAA+B,EAAE,MAAM,6DAA6D,CAAA;AAG7G,OAAO,EAAE,iBAAiB,EAAE,MAAiB,iDAAiD,CAAA;AAC9F,OAAO,EAAE,mBAAmB,EAAE,MAAe,mDAAmD,CAAA;AAChG,OAAO,EAAE,wBAAwB,EAAE,MAAU,wDAAwD,CAAA;AACrG,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAW,uDAAuD,CAAA;AACpG,OAAO,EAAE,yBAAyB,EAAE,MAAS,yDAAyD,CAAA;AACtG,OAAO,EAAE,iBAAiB,EAAE,MAAiB,iDAAiD,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `@xfcfam/xf-sql` — SQL Access Layer Generalization for the XF
3
+ * Architecture Model.
4
+ *
5
+ * Encapsulates the [Kysely](https://kysely.dev) query builder behind
6
+ * an XF-canonical Generalization (`DatabaseRepository`) plus a
7
+ * transaction-aware specialisation (`TransactionalDatabaseRepository`)
8
+ * and a typed Exception hierarchy.
9
+ *
10
+ * xf-sql is **dialect-agnostic**: pair it with one of the dialect
11
+ * adapter packages (`@xfcfam/xf-sql-postgres`,
12
+ * `@xfcfam/xf-sql-mysql`, …) or supply any Kysely `Dialect` directly.
13
+ *
14
+ * Peer dependency: `@xfcfam/xf`. `kysely` is a direct (bundled) dependency.
15
+ */
16
+ // ── Access — base ─────────────────────────────────────────
17
+ export { DatabaseRepository } from './src/repository/general/DatabaseRepository.js';
18
+ export { TransactionalDatabaseRepository } from './src/repository/general/TransactionalDatabaseRepository.js';
19
+ // ── Access — structs (Exceptions) ─────────────────────────
20
+ export { DatabaseException } from './src/repository/transfers/DatabaseException.js';
21
+ export { ConnectionException } from './src/repository/transfers/ConnectionException.js';
22
+ export { UniqueViolationException } from './src/repository/transfers/UniqueViolationException.js';
23
+ export { ForeignKeyViolationException } from './src/repository/transfers/ForeignKeyViolationException.js';
24
+ export { CheckViolationException } from './src/repository/transfers/CheckViolationException.js';
25
+ export { NotNullViolationException } from './src/repository/transfers/NotNullViolationException.js';
26
+ export { DeadlockException } from './src/repository/transfers/DeadlockException.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAA;AAEnF,OAAO,EAAE,+BAA+B,EAAE,MAAM,6DAA6D,CAAA;AAE7G,6DAA6D;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAiB,iDAAiD,CAAA;AAC9F,OAAO,EAAE,mBAAmB,EAAE,MAAe,mDAAmD,CAAA;AAChG,OAAO,EAAE,wBAAwB,EAAE,MAAU,wDAAwD,CAAA;AACrG,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAW,uDAAuD,CAAA;AACpG,OAAO,EAAE,yBAAyB,EAAE,MAAS,yDAAyD,CAAA;AACtG,OAAO,EAAE,iBAAiB,EAAE,MAAiB,iDAAiD,CAAA"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interaction Layer Injection — placeholder.
3
+ *
4
+ * `A` is the canonical injection of the Interaction Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `A` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `A` from their own artefact.
11
+ */
12
+ export declare class A {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=A.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A.d.ts","sourceRoot":"","sources":["../../../src/api/A.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interaction Layer Injection — placeholder.
3
+ *
4
+ * `A` is the canonical injection of the Interaction Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `A` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `A` from their own artefact.
11
+ */
12
+ export class A {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A.js","sourceRoot":"","sources":["../../../src/api/A.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `B` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `B` from their own artefact.
11
+ */
12
+ export declare class B {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=B.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.d.ts","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `B` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `B` from their own artefact.
11
+ */
12
+ export class B {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.js","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Access Layer Injection — placeholder.
3
+ *
4
+ * `R` is the canonical injection of the Access Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `R` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `R` from their own artefact.
11
+ */
12
+ export declare class R {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=R.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"R.d.ts","sourceRoot":"","sources":["../../../src/repository/R.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Access Layer Injection — placeholder.
3
+ *
4
+ * `R` is the canonical injection of the Access Layer. `@xfcfam/xf-sql`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `R` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `R` from their own artefact.
11
+ */
12
+ export class R {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"R.js","sourceRoot":"","sources":["../../../src/repository/R.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,184 @@
1
+ import { Repository } from '@xfarch/xf';
2
+ import { Kysely, type Dialect } from 'kysely';
3
+ /**
4
+ * Configuration accepted by {@link DatabaseRepository}'s constructor.
5
+ *
6
+ * The `dialect` is the only required field. Dialect adapter packages
7
+ * such as `@xfarch/xf-sql-postgres` build it for you behind a
8
+ * higher-level options shape.
9
+ */
10
+ export interface DatabaseOptions {
11
+ /** Kysely Dialect implementation (Postgres, MySQL, SQLite, …). */
12
+ dialect: Dialect;
13
+ }
14
+ /**
15
+ * Base Generalization for the Access Layer when the underlying
16
+ * external system is a SQL database.
17
+ *
18
+ * Encapsulates the [Kysely](https://kysely.dev) query builder behind
19
+ * a single XF-canonical class. The implementer's concrete Logical
20
+ * extends this (or a dialect-specific subclass such as
21
+ * `PostgresDatabaseRepository`) and exposes domain-meaningful methods
22
+ * that compose queries against `this.db`, a `Kysely<Schema>` bound
23
+ * to the implementer's typed schema.
24
+ *
25
+ * Concrete dialect support lives in adapter packages — install one of
26
+ * `@xfarch/xf-sql-postgres`, `@xfarch/xf-sql-mysql`, etc., or supply
27
+ * any Kysely-compatible `Dialect` directly.
28
+ *
29
+ * ──────────────────────────────────────────────────────────────────
30
+ * IMPORTANT — Required configuration for subclasses
31
+ * ──────────────────────────────────────────────────────────────────
32
+ * The underlying Kysely instance is held in a static private WeakMap
33
+ * and created inside {@link init}. If a subclass overrides `init()` /
34
+ * `terminate()`, it MUST chain through `super`:
35
+ *
36
+ * async init() { await super.init(); // own setup }
37
+ * async terminate() { // own teardown; await super.terminate() }
38
+ *
39
+ * Forgetting `super.init()` leaves `this.db` uninitialised and every
40
+ * query will throw {@link NotInitializedException}.
41
+ *
42
+ * ──────────────────────────────────────────────────────────────────
43
+ * Overridable observation hooks
44
+ * ──────────────────────────────────────────────────────────────────
45
+ * - {@link onConnected} ← after `init()` creates the Kysely instance
46
+ * - {@link onDisconnected} ← after `terminate()` destroys it
47
+ * - {@link onQuery} ← for every query Kysely executes
48
+ * - {@link onError} ← for every {@link exec}-wrapped operation that rejects
49
+ *
50
+ * Transaction hooks ({@link onTransactionStart} / Commit / Rollback)
51
+ * live on {@link TransactionalDatabaseRepository}, the subclass that
52
+ * exposes explicit transaction control.
53
+ *
54
+ * ──────────────────────────────────────────────────────────────────
55
+ * Error translation
56
+ * ──────────────────────────────────────────────────────────────────
57
+ * Dialect-specific errors (driver Error objects) are not translated
58
+ * by this class — it does not know about Postgres SQLSTATEs, MySQL
59
+ * error numbers, etc. Use a dialect adapter subclass (such as
60
+ * `PostgresDatabaseRepository`) or override {@link translateError}
61
+ * yourself to map errors to the typed Exceptions exported from this
62
+ * package (`UniqueViolationException`, etc.).
63
+ *
64
+ * @typeParam Schema Implementer-defined TypeScript interface mapping
65
+ * table names to their column shapes. See the
66
+ * Kysely docs for the conventions on
67
+ * `Generated`, `ColumnType`, etc.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * import { DatabaseRepository } from '@xfarch/xf-sql'
72
+ * import { PostgresDialect } from 'kysely'
73
+ * import { Pool } from 'pg'
74
+ *
75
+ * interface Schema {
76
+ * users: { id: number; name: string; email: string }
77
+ * }
78
+ *
79
+ * export class UsersDb extends DatabaseRepository<Schema> {
80
+ * constructor() {
81
+ * super({
82
+ * dialect: new PostgresDialect({
83
+ * pool: new Pool({ connectionString: process.env.DATABASE_URL }),
84
+ * }),
85
+ * })
86
+ * }
87
+ * async init() { await super.init() }
88
+ * async terminate() { await super.terminate() }
89
+ *
90
+ * getUser(id: number) {
91
+ * return this.db
92
+ * .selectFrom('users')
93
+ * .where('id', '=', id)
94
+ * .selectAll()
95
+ * .executeTakeFirstOrThrow()
96
+ * }
97
+ * }
98
+ * ```
99
+ */
100
+ export declare abstract class DatabaseRepository<Schema = unknown> extends Repository<null> {
101
+ private static readonly state;
102
+ /** Options provided at construction time. */
103
+ protected readonly options: DatabaseOptions;
104
+ constructor(options: DatabaseOptions);
105
+ /**
106
+ * Typed Kysely instance bound to `Schema`. Use it to compose queries:
107
+ * `this.db.selectFrom('users')…`, `this.db.insertInto('users')…`.
108
+ * Throws if {@link init} has not been called.
109
+ */
110
+ protected get db(): Kysely<Schema>;
111
+ /**
112
+ * Subclasses that override this method MUST call `await super.init()`
113
+ * **first**; otherwise {@link db} will throw on use.
114
+ */
115
+ init(): Promise<void>;
116
+ /**
117
+ * Subclasses that override this method MUST call `await super.terminate()`
118
+ * **last** to release the connection pool held by the Kysely instance.
119
+ */
120
+ terminate(): Promise<void>;
121
+ /**
122
+ * Hook for dialect-specific error translation. Default
123
+ * implementation is identity (returns the input unchanged).
124
+ *
125
+ * Dialect adapter subclasses (such as `PostgresDatabaseRepository`)
126
+ * override this to map driver errors to the typed Exceptions
127
+ * exported from this package.
128
+ *
129
+ * Called automatically by {@link exec}; not called for direct
130
+ * `this.db.…` usage, where the implementer is responsible for
131
+ * wrapping queries in `this.exec(...)`.
132
+ */
133
+ protected translateError(err: unknown): unknown;
134
+ /**
135
+ * Execute an operation against the database, translating any
136
+ * dialect-specific errors to xf-sql Exception types via
137
+ * {@link translateError}.
138
+ *
139
+ * Use this whenever you need automatic error translation. For raw
140
+ * Kysely access without translation, use {@link db} directly.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * async createUser(input: UserInput) {
145
+ * return this.exec(() =>
146
+ * this.db.insertInto('users').values(input).returningAll().executeTakeFirstOrThrow()
147
+ * )
148
+ * }
149
+ * ```
150
+ */
151
+ protected exec<R>(op: () => Promise<R>): Promise<R>;
152
+ /**
153
+ * Invoked after `init()` has created the Kysely instance. Default
154
+ * no-op. Override for connection-open telemetry, schema migrations,
155
+ * connection warmup, etc.
156
+ */
157
+ protected onConnected(): Promise<void>;
158
+ /**
159
+ * Invoked after `terminate()` has destroyed the Kysely instance.
160
+ * Default no-op. Override for connection-close telemetry.
161
+ */
162
+ protected onDisconnected(): Promise<void>;
163
+ /**
164
+ * Invoked for every query Kysely executes (both standalone and
165
+ * inside transactions). Receives the compiled SQL and the bound
166
+ * parameters. Default no-op.
167
+ *
168
+ * Use for audit logging or query profiling. The hook runs
169
+ * synchronously inside Kysely's pipeline — keep it cheap and avoid
170
+ * blocking work.
171
+ */
172
+ protected onQuery(_sql: string, _params: readonly unknown[]): void;
173
+ /**
174
+ * Invoked when an `exec()`-wrapped operation rejects, or when
175
+ * Kysely emits a query-level error. The `operation` label
176
+ * distinguishes the source (`'exec'`, `'query'`, or the value
177
+ * supplied by a subclass). Default no-op.
178
+ *
179
+ * The hook fires before {@link translateError}; the (possibly
180
+ * untranslated) error is still re-thrown to the caller.
181
+ */
182
+ protected onError(_operation: string, _error: unknown): void;
183
+ }
184
+ //# sourceMappingURL=DatabaseRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseRepository.d.ts","sourceRoot":"","sources":["../../../../src/repository/base/DatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAA;CACjB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqFG;AACH,8BAAsB,kBAAkB,CAAC,MAAM,GAAG,OAAO,CAAE,SAAQ,UAAU,CAAC,IAAI,CAAC;IACjF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAEpE,6CAA6C;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;gBAE/B,OAAO,EAAE,eAAe;IAKpC;;;;OAIG;IACH,SAAS,KAAK,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,CAMjC;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAShC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAI/C;;;;;;;;;;;;;;;;OAgBG;cACa,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWzD;;;;OAIG;cACa,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAE5C;;;OAGG;cACa,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/C;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI;IAElE;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;CAC7D"}