@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.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/src/api/A.d.ts +17 -0
- package/dist/src/api/A.d.ts.map +1 -0
- package/dist/src/api/A.js +17 -0
- package/dist/src/api/A.js.map +1 -0
- package/dist/src/business/B.d.ts +17 -0
- package/dist/src/business/B.d.ts.map +1 -0
- package/dist/src/business/B.js +17 -0
- package/dist/src/business/B.js.map +1 -0
- package/dist/src/repository/R.d.ts +17 -0
- package/dist/src/repository/R.d.ts.map +1 -0
- package/dist/src/repository/R.js +17 -0
- package/dist/src/repository/R.js.map +1 -0
- package/dist/src/repository/base/DatabaseRepository.d.ts +184 -0
- package/dist/src/repository/base/DatabaseRepository.d.ts.map +1 -0
- package/dist/src/repository/base/DatabaseRepository.js +216 -0
- package/dist/src/repository/base/DatabaseRepository.js.map +1 -0
- package/dist/src/repository/base/TransactionalDatabaseRepository.d.ts +86 -0
- package/dist/src/repository/base/TransactionalDatabaseRepository.d.ts.map +1 -0
- package/dist/src/repository/base/TransactionalDatabaseRepository.js +104 -0
- package/dist/src/repository/base/TransactionalDatabaseRepository.js.map +1 -0
- package/dist/src/repository/general/DatabaseRepository.d.ts +192 -0
- package/dist/src/repository/general/DatabaseRepository.d.ts.map +1 -0
- package/dist/src/repository/general/DatabaseRepository.js +224 -0
- package/dist/src/repository/general/DatabaseRepository.js.map +1 -0
- package/dist/src/repository/general/TransactionalDatabaseRepository.d.ts +91 -0
- package/dist/src/repository/general/TransactionalDatabaseRepository.d.ts.map +1 -0
- package/dist/src/repository/general/TransactionalDatabaseRepository.js +114 -0
- package/dist/src/repository/general/TransactionalDatabaseRepository.js.map +1 -0
- package/dist/src/repository/structs/CheckViolationException.d.ts +19 -0
- package/dist/src/repository/structs/CheckViolationException.d.ts.map +1 -0
- package/dist/src/repository/structs/CheckViolationException.js +22 -0
- package/dist/src/repository/structs/CheckViolationException.js.map +1 -0
- package/dist/src/repository/structs/ConnectionException.d.ts +15 -0
- package/dist/src/repository/structs/ConnectionException.d.ts.map +1 -0
- package/dist/src/repository/structs/ConnectionException.js +16 -0
- package/dist/src/repository/structs/ConnectionException.js.map +1 -0
- package/dist/src/repository/structs/DatabaseException.d.ts +14 -0
- package/dist/src/repository/structs/DatabaseException.d.ts.map +1 -0
- package/dist/src/repository/structs/DatabaseException.js +15 -0
- package/dist/src/repository/structs/DatabaseException.js.map +1 -0
- package/dist/src/repository/structs/DeadlockException.d.ts +16 -0
- package/dist/src/repository/structs/DeadlockException.d.ts.map +1 -0
- package/dist/src/repository/structs/DeadlockException.js +17 -0
- package/dist/src/repository/structs/DeadlockException.js.map +1 -0
- package/dist/src/repository/structs/ForeignKeyViolationException.d.ts +20 -0
- package/dist/src/repository/structs/ForeignKeyViolationException.d.ts.map +1 -0
- package/dist/src/repository/structs/ForeignKeyViolationException.js +23 -0
- package/dist/src/repository/structs/ForeignKeyViolationException.js.map +1 -0
- package/dist/src/repository/structs/NotNullViolationException.d.ts +20 -0
- package/dist/src/repository/structs/NotNullViolationException.d.ts.map +1 -0
- package/dist/src/repository/structs/NotNullViolationException.js +23 -0
- package/dist/src/repository/structs/NotNullViolationException.js.map +1 -0
- package/dist/src/repository/structs/UniqueViolationException.d.ts +36 -0
- package/dist/src/repository/structs/UniqueViolationException.d.ts.map +1 -0
- package/dist/src/repository/structs/UniqueViolationException.js +40 -0
- package/dist/src/repository/structs/UniqueViolationException.js.map +1 -0
- package/dist/src/repository/transfers/CheckViolationException.d.ts +19 -0
- package/dist/src/repository/transfers/CheckViolationException.d.ts.map +1 -0
- package/dist/src/repository/transfers/CheckViolationException.js +22 -0
- package/dist/src/repository/transfers/CheckViolationException.js.map +1 -0
- package/dist/src/repository/transfers/ConnectionException.d.ts +15 -0
- package/dist/src/repository/transfers/ConnectionException.d.ts.map +1 -0
- package/dist/src/repository/transfers/ConnectionException.js +16 -0
- package/dist/src/repository/transfers/ConnectionException.js.map +1 -0
- package/dist/src/repository/transfers/DatabaseException.d.ts +14 -0
- package/dist/src/repository/transfers/DatabaseException.d.ts.map +1 -0
- package/dist/src/repository/transfers/DatabaseException.js +15 -0
- package/dist/src/repository/transfers/DatabaseException.js.map +1 -0
- package/dist/src/repository/transfers/DeadlockException.d.ts +16 -0
- package/dist/src/repository/transfers/DeadlockException.d.ts.map +1 -0
- package/dist/src/repository/transfers/DeadlockException.js +17 -0
- package/dist/src/repository/transfers/DeadlockException.js.map +1 -0
- package/dist/src/repository/transfers/ForeignKeyViolationException.d.ts +20 -0
- package/dist/src/repository/transfers/ForeignKeyViolationException.d.ts.map +1 -0
- package/dist/src/repository/transfers/ForeignKeyViolationException.js +23 -0
- package/dist/src/repository/transfers/ForeignKeyViolationException.js.map +1 -0
- package/dist/src/repository/transfers/NotNullViolationException.d.ts +20 -0
- package/dist/src/repository/transfers/NotNullViolationException.d.ts.map +1 -0
- package/dist/src/repository/transfers/NotNullViolationException.js +23 -0
- package/dist/src/repository/transfers/NotNullViolationException.js.map +1 -0
- package/dist/src/repository/transfers/UniqueViolationException.d.ts +36 -0
- package/dist/src/repository/transfers/UniqueViolationException.d.ts.map +1 -0
- package/dist/src/repository/transfers/UniqueViolationException.js +40 -0
- package/dist/src/repository/transfers/UniqueViolationException.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Repository, NotInitializedException } from '@xfarch/xf';
|
|
2
|
+
import { Kysely } from 'kysely';
|
|
3
|
+
/**
|
|
4
|
+
* Base Generalization for the Access Layer when the underlying
|
|
5
|
+
* external system is a SQL database.
|
|
6
|
+
*
|
|
7
|
+
* Encapsulates the [Kysely](https://kysely.dev) query builder behind
|
|
8
|
+
* a single XF-canonical class. The implementer's concrete Logical
|
|
9
|
+
* extends this (or a dialect-specific subclass such as
|
|
10
|
+
* `PostgresDatabaseRepository`) and exposes domain-meaningful methods
|
|
11
|
+
* that compose queries against `this.db`, a `Kysely<Schema>` bound
|
|
12
|
+
* to the implementer's typed schema.
|
|
13
|
+
*
|
|
14
|
+
* Concrete dialect support lives in adapter packages — install one of
|
|
15
|
+
* `@xfarch/xf-sql-postgres`, `@xfarch/xf-sql-mysql`, etc., or supply
|
|
16
|
+
* any Kysely-compatible `Dialect` directly.
|
|
17
|
+
*
|
|
18
|
+
* ──────────────────────────────────────────────────────────────────
|
|
19
|
+
* IMPORTANT — Required configuration for subclasses
|
|
20
|
+
* ──────────────────────────────────────────────────────────────────
|
|
21
|
+
* The underlying Kysely instance is held in a static private WeakMap
|
|
22
|
+
* and created inside {@link init}. If a subclass overrides `init()` /
|
|
23
|
+
* `terminate()`, it MUST chain through `super`:
|
|
24
|
+
*
|
|
25
|
+
* async init() { await super.init(); // own setup }
|
|
26
|
+
* async terminate() { // own teardown; await super.terminate() }
|
|
27
|
+
*
|
|
28
|
+
* Forgetting `super.init()` leaves `this.db` uninitialised and every
|
|
29
|
+
* query will throw {@link NotInitializedException}.
|
|
30
|
+
*
|
|
31
|
+
* ──────────────────────────────────────────────────────────────────
|
|
32
|
+
* Overridable observation hooks
|
|
33
|
+
* ──────────────────────────────────────────────────────────────────
|
|
34
|
+
* - {@link onConnected} ← after `init()` creates the Kysely instance
|
|
35
|
+
* - {@link onDisconnected} ← after `terminate()` destroys it
|
|
36
|
+
* - {@link onQuery} ← for every query Kysely executes
|
|
37
|
+
* - {@link onError} ← for every {@link exec}-wrapped operation that rejects
|
|
38
|
+
*
|
|
39
|
+
* Transaction hooks ({@link onTransactionStart} / Commit / Rollback)
|
|
40
|
+
* live on {@link TransactionalDatabaseRepository}, the subclass that
|
|
41
|
+
* exposes explicit transaction control.
|
|
42
|
+
*
|
|
43
|
+
* ──────────────────────────────────────────────────────────────────
|
|
44
|
+
* Error translation
|
|
45
|
+
* ──────────────────────────────────────────────────────────────────
|
|
46
|
+
* Dialect-specific errors (driver Error objects) are not translated
|
|
47
|
+
* by this class — it does not know about Postgres SQLSTATEs, MySQL
|
|
48
|
+
* error numbers, etc. Use a dialect adapter subclass (such as
|
|
49
|
+
* `PostgresDatabaseRepository`) or override {@link translateError}
|
|
50
|
+
* yourself to map errors to the typed Exceptions exported from this
|
|
51
|
+
* package (`UniqueViolationException`, etc.).
|
|
52
|
+
*
|
|
53
|
+
* @typeParam Schema Implementer-defined TypeScript interface mapping
|
|
54
|
+
* table names to their column shapes. See the
|
|
55
|
+
* Kysely docs for the conventions on
|
|
56
|
+
* `Generated`, `ColumnType`, etc.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { DatabaseRepository } from '@xfarch/xf-sql'
|
|
61
|
+
* import { PostgresDialect } from 'kysely'
|
|
62
|
+
* import { Pool } from 'pg'
|
|
63
|
+
*
|
|
64
|
+
* interface Schema {
|
|
65
|
+
* users: { id: number; name: string; email: string }
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* export class UsersDb extends DatabaseRepository<Schema> {
|
|
69
|
+
* constructor() {
|
|
70
|
+
* super({
|
|
71
|
+
* dialect: new PostgresDialect({
|
|
72
|
+
* pool: new Pool({ connectionString: process.env.DATABASE_URL }),
|
|
73
|
+
* }),
|
|
74
|
+
* })
|
|
75
|
+
* }
|
|
76
|
+
* async init() { await super.init() }
|
|
77
|
+
* async terminate() { await super.terminate() }
|
|
78
|
+
*
|
|
79
|
+
* getUser(id: number) {
|
|
80
|
+
* return this.db
|
|
81
|
+
* .selectFrom('users')
|
|
82
|
+
* .where('id', '=', id)
|
|
83
|
+
* .selectAll()
|
|
84
|
+
* .executeTakeFirstOrThrow()
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export class DatabaseRepository extends Repository {
|
|
90
|
+
static state = new WeakMap();
|
|
91
|
+
/** Options provided at construction time. */
|
|
92
|
+
options;
|
|
93
|
+
constructor(options) {
|
|
94
|
+
super(null);
|
|
95
|
+
this.options = options;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Typed Kysely instance bound to `Schema`. Use it to compose queries:
|
|
99
|
+
* `this.db.selectFrom('users')…`, `this.db.insertInto('users')…`.
|
|
100
|
+
* Throws if {@link init} has not been called.
|
|
101
|
+
*/
|
|
102
|
+
get db() {
|
|
103
|
+
const s = DatabaseRepository.state.get(this);
|
|
104
|
+
if (s === undefined) {
|
|
105
|
+
throw new NotInitializedException('DatabaseRepository: init() was not called (or super.init() was skipped)');
|
|
106
|
+
}
|
|
107
|
+
return s.db;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Subclasses that override this method MUST call `await super.init()`
|
|
111
|
+
* **first**; otherwise {@link db} will throw on use.
|
|
112
|
+
*/
|
|
113
|
+
async init() {
|
|
114
|
+
const db = new Kysely({
|
|
115
|
+
dialect: this.options.dialect,
|
|
116
|
+
log: (event) => {
|
|
117
|
+
if (event.level === 'query') {
|
|
118
|
+
this.onQuery(event.query.sql, event.query.parameters);
|
|
119
|
+
}
|
|
120
|
+
else if (event.level === 'error') {
|
|
121
|
+
// Kysely-emitted query errors are also routed through onError
|
|
122
|
+
// for symmetry with exec() failures.
|
|
123
|
+
this.onError('query', event.error);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
DatabaseRepository.state.set(this, { db });
|
|
128
|
+
await this.onConnected();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Subclasses that override this method MUST call `await super.terminate()`
|
|
132
|
+
* **last** to release the connection pool held by the Kysely instance.
|
|
133
|
+
*/
|
|
134
|
+
async terminate() {
|
|
135
|
+
const s = DatabaseRepository.state.get(this);
|
|
136
|
+
if (s !== undefined) {
|
|
137
|
+
await s.db.destroy();
|
|
138
|
+
DatabaseRepository.state.delete(this);
|
|
139
|
+
await this.onDisconnected();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Hook for dialect-specific error translation. Default
|
|
144
|
+
* implementation is identity (returns the input unchanged).
|
|
145
|
+
*
|
|
146
|
+
* Dialect adapter subclasses (such as `PostgresDatabaseRepository`)
|
|
147
|
+
* override this to map driver errors to the typed Exceptions
|
|
148
|
+
* exported from this package.
|
|
149
|
+
*
|
|
150
|
+
* Called automatically by {@link exec}; not called for direct
|
|
151
|
+
* `this.db.…` usage, where the implementer is responsible for
|
|
152
|
+
* wrapping queries in `this.exec(...)`.
|
|
153
|
+
*/
|
|
154
|
+
translateError(err) {
|
|
155
|
+
return err;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Execute an operation against the database, translating any
|
|
159
|
+
* dialect-specific errors to xf-sql Exception types via
|
|
160
|
+
* {@link translateError}.
|
|
161
|
+
*
|
|
162
|
+
* Use this whenever you need automatic error translation. For raw
|
|
163
|
+
* Kysely access without translation, use {@link db} directly.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* async createUser(input: UserInput) {
|
|
168
|
+
* return this.exec(() =>
|
|
169
|
+
* this.db.insertInto('users').values(input).returningAll().executeTakeFirstOrThrow()
|
|
170
|
+
* )
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
async exec(op) {
|
|
175
|
+
try {
|
|
176
|
+
return await op();
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
this.onError('exec', err);
|
|
180
|
+
throw this.translateError(err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ─── Overridable observation hooks ────────────────────────
|
|
184
|
+
/**
|
|
185
|
+
* Invoked after `init()` has created the Kysely instance. Default
|
|
186
|
+
* no-op. Override for connection-open telemetry, schema migrations,
|
|
187
|
+
* connection warmup, etc.
|
|
188
|
+
*/
|
|
189
|
+
async onConnected() { }
|
|
190
|
+
/**
|
|
191
|
+
* Invoked after `terminate()` has destroyed the Kysely instance.
|
|
192
|
+
* Default no-op. Override for connection-close telemetry.
|
|
193
|
+
*/
|
|
194
|
+
async onDisconnected() { }
|
|
195
|
+
/**
|
|
196
|
+
* Invoked for every query Kysely executes (both standalone and
|
|
197
|
+
* inside transactions). Receives the compiled SQL and the bound
|
|
198
|
+
* parameters. Default no-op.
|
|
199
|
+
*
|
|
200
|
+
* Use for audit logging or query profiling. The hook runs
|
|
201
|
+
* synchronously inside Kysely's pipeline — keep it cheap and avoid
|
|
202
|
+
* blocking work.
|
|
203
|
+
*/
|
|
204
|
+
onQuery(_sql, _params) { }
|
|
205
|
+
/**
|
|
206
|
+
* Invoked when an `exec()`-wrapped operation rejects, or when
|
|
207
|
+
* Kysely emits a query-level error. The `operation` label
|
|
208
|
+
* distinguishes the source (`'exec'`, `'query'`, or the value
|
|
209
|
+
* supplied by a subclass). Default no-op.
|
|
210
|
+
*
|
|
211
|
+
* The hook fires before {@link translateError}; the (possibly
|
|
212
|
+
* untranslated) error is still re-thrown to the caller.
|
|
213
|
+
*/
|
|
214
|
+
onError(_operation, _error) { }
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=DatabaseRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatabaseRepository.js","sourceRoot":"","sources":["../../../../src/repository/base/DatabaseRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type Transaction } from 'kysely';
|
|
2
|
+
import { DatabaseRepository } from './DatabaseRepository.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generalization for SQL Access Layer components that need explicit
|
|
5
|
+
* transaction control on top of {@link DatabaseRepository}.
|
|
6
|
+
*
|
|
7
|
+
* Extends `DatabaseRepository<Schema>` and adds {@link transaction},
|
|
8
|
+
* a helper that runs a callback inside a Kysely transaction:
|
|
9
|
+
* commits on success, rolls back on throw.
|
|
10
|
+
*
|
|
11
|
+
* Error translation flows through {@link DatabaseRepository.translateError}
|
|
12
|
+
* — overriding it once on a dialect subclass covers both `exec` and
|
|
13
|
+
* `transaction`.
|
|
14
|
+
*
|
|
15
|
+
* ──────────────────────────────────────────────────────────────────
|
|
16
|
+
* Overridable transaction hooks
|
|
17
|
+
* ──────────────────────────────────────────────────────────────────
|
|
18
|
+
* - {@link onTransactionStart} ← before the callback runs
|
|
19
|
+
* - {@link onTransactionCommit} ← after the callback resolves
|
|
20
|
+
* - {@link onTransactionRollback} ← when the callback throws
|
|
21
|
+
*
|
|
22
|
+
* Each hook receives a `txId` — a short opaque identifier that
|
|
23
|
+
* correlates the three events of the same transaction. The id is
|
|
24
|
+
* generated per-call and has no meaning to the database (it's a
|
|
25
|
+
* sibling of telemetry trace ids, not of SQL `SAVEPOINT` names).
|
|
26
|
+
*
|
|
27
|
+
* @typeParam Schema See {@link DatabaseRepository}.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { TransactionalDatabaseRepository } from '@xfarch/xf-sql'
|
|
32
|
+
*
|
|
33
|
+
* export class OrdersDb extends TransactionalDatabaseRepository<Schema> {
|
|
34
|
+
* constructor() { super({ dialect: ... }) }
|
|
35
|
+
* async init() { await super.init() }
|
|
36
|
+
* async terminate() { await super.terminate() }
|
|
37
|
+
*
|
|
38
|
+
* async checkout(order: Order) {
|
|
39
|
+
* return this.transaction(async (trx) => {
|
|
40
|
+
* await trx.insertInto('orders').values(order).execute()
|
|
41
|
+
* await trx.updateTable('inventory')
|
|
42
|
+
* .set((eb) => ({ stock: eb('stock', '-', order.qty) }))
|
|
43
|
+
* .where('sku', '=', order.sku)
|
|
44
|
+
* .execute()
|
|
45
|
+
* return order.id
|
|
46
|
+
* })
|
|
47
|
+
* }
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare abstract class TransactionalDatabaseRepository<Schema = unknown> extends DatabaseRepository<Schema> {
|
|
52
|
+
/**
|
|
53
|
+
* Run `callback` inside a database transaction. Commits if the
|
|
54
|
+
* callback resolves; rolls back if it throws.
|
|
55
|
+
*
|
|
56
|
+
* The argument passed to `callback` is a `Transaction<Schema>` —
|
|
57
|
+
* a Kysely-typed transaction handle. Use it (not `this.db`) for
|
|
58
|
+
* queries inside the transaction so they participate in the same
|
|
59
|
+
* unit of work.
|
|
60
|
+
*
|
|
61
|
+
* Errors thrown inside the callback are translated through
|
|
62
|
+
* {@link DatabaseRepository.translateError} before being rethrown.
|
|
63
|
+
*/
|
|
64
|
+
protected transaction<R>(callback: (trx: Transaction<Schema>) => Promise<R>): Promise<R>;
|
|
65
|
+
/**
|
|
66
|
+
* Invoked just before the transaction callback runs. Default no-op.
|
|
67
|
+
* `txId` is a short opaque identifier that correlates the three
|
|
68
|
+
* events of the same transaction.
|
|
69
|
+
*/
|
|
70
|
+
protected onTransactionStart(_txId: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Invoked after the transaction callback resolves successfully and
|
|
73
|
+
* the commit completes. `durationMs` measures the full lifetime of
|
|
74
|
+
* the transaction (including commit latency). Default no-op.
|
|
75
|
+
*/
|
|
76
|
+
protected onTransactionCommit(_txId: string, _durationMs: number): void;
|
|
77
|
+
/**
|
|
78
|
+
* Invoked when the transaction callback throws and the rollback
|
|
79
|
+
* completes. `reason` is the original error (before
|
|
80
|
+
* {@link DatabaseRepository.translateError} is applied to the
|
|
81
|
+
* rethrow). Default no-op.
|
|
82
|
+
*/
|
|
83
|
+
protected onTransactionRollback(_txId: string, _reason: unknown): void;
|
|
84
|
+
private static makeTxId;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=TransactionalDatabaseRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransactionalDatabaseRepository.d.ts","sourceRoot":"","sources":["../../../../src/repository/base/TransactionalDatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,8BAAsB,+BAA+B,CAAC,MAAM,GAAG,OAAO,CACpE,SAAQ,kBAAkB,CAAC,MAAM,CAAC;IAElC;;;;;;;;;;;OAWG;cACa,WAAW,CAAC,CAAC,EAC3B,QAAQ,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACjD,OAAO,CAAC,CAAC,CAAC;IAgBb;;;;OAIG;IACH,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAEjD;;;;OAIG;IACH,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAEvE;;;;;OAKG;IACH,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAItE,OAAO,CAAC,MAAM,CAAC,QAAQ;CAKxB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DatabaseRepository } from './DatabaseRepository.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generalization for SQL Access Layer components that need explicit
|
|
4
|
+
* transaction control on top of {@link DatabaseRepository}.
|
|
5
|
+
*
|
|
6
|
+
* Extends `DatabaseRepository<Schema>` and adds {@link transaction},
|
|
7
|
+
* a helper that runs a callback inside a Kysely transaction:
|
|
8
|
+
* commits on success, rolls back on throw.
|
|
9
|
+
*
|
|
10
|
+
* Error translation flows through {@link DatabaseRepository.translateError}
|
|
11
|
+
* — overriding it once on a dialect subclass covers both `exec` and
|
|
12
|
+
* `transaction`.
|
|
13
|
+
*
|
|
14
|
+
* ──────────────────────────────────────────────────────────────────
|
|
15
|
+
* Overridable transaction hooks
|
|
16
|
+
* ──────────────────────────────────────────────────────────────────
|
|
17
|
+
* - {@link onTransactionStart} ← before the callback runs
|
|
18
|
+
* - {@link onTransactionCommit} ← after the callback resolves
|
|
19
|
+
* - {@link onTransactionRollback} ← when the callback throws
|
|
20
|
+
*
|
|
21
|
+
* Each hook receives a `txId` — a short opaque identifier that
|
|
22
|
+
* correlates the three events of the same transaction. The id is
|
|
23
|
+
* generated per-call and has no meaning to the database (it's a
|
|
24
|
+
* sibling of telemetry trace ids, not of SQL `SAVEPOINT` names).
|
|
25
|
+
*
|
|
26
|
+
* @typeParam Schema See {@link DatabaseRepository}.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { TransactionalDatabaseRepository } from '@xfarch/xf-sql'
|
|
31
|
+
*
|
|
32
|
+
* export class OrdersDb extends TransactionalDatabaseRepository<Schema> {
|
|
33
|
+
* constructor() { super({ dialect: ... }) }
|
|
34
|
+
* async init() { await super.init() }
|
|
35
|
+
* async terminate() { await super.terminate() }
|
|
36
|
+
*
|
|
37
|
+
* async checkout(order: Order) {
|
|
38
|
+
* return this.transaction(async (trx) => {
|
|
39
|
+
* await trx.insertInto('orders').values(order).execute()
|
|
40
|
+
* await trx.updateTable('inventory')
|
|
41
|
+
* .set((eb) => ({ stock: eb('stock', '-', order.qty) }))
|
|
42
|
+
* .where('sku', '=', order.sku)
|
|
43
|
+
* .execute()
|
|
44
|
+
* return order.id
|
|
45
|
+
* })
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export class TransactionalDatabaseRepository extends DatabaseRepository {
|
|
51
|
+
/**
|
|
52
|
+
* Run `callback` inside a database transaction. Commits if the
|
|
53
|
+
* callback resolves; rolls back if it throws.
|
|
54
|
+
*
|
|
55
|
+
* The argument passed to `callback` is a `Transaction<Schema>` —
|
|
56
|
+
* a Kysely-typed transaction handle. Use it (not `this.db`) for
|
|
57
|
+
* queries inside the transaction so they participate in the same
|
|
58
|
+
* unit of work.
|
|
59
|
+
*
|
|
60
|
+
* Errors thrown inside the callback are translated through
|
|
61
|
+
* {@link DatabaseRepository.translateError} before being rethrown.
|
|
62
|
+
*/
|
|
63
|
+
async transaction(callback) {
|
|
64
|
+
const txId = TransactionalDatabaseRepository.makeTxId();
|
|
65
|
+
const startedAt = Date.now();
|
|
66
|
+
this.onTransactionStart(txId);
|
|
67
|
+
try {
|
|
68
|
+
const result = await this.db.transaction().execute(callback);
|
|
69
|
+
this.onTransactionCommit(txId, Date.now() - startedAt);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
this.onTransactionRollback(txId, err);
|
|
74
|
+
throw this.translateError(err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// ─── Overridable transaction hooks ────────────────────────
|
|
78
|
+
/**
|
|
79
|
+
* Invoked just before the transaction callback runs. Default no-op.
|
|
80
|
+
* `txId` is a short opaque identifier that correlates the three
|
|
81
|
+
* events of the same transaction.
|
|
82
|
+
*/
|
|
83
|
+
onTransactionStart(_txId) { }
|
|
84
|
+
/**
|
|
85
|
+
* Invoked after the transaction callback resolves successfully and
|
|
86
|
+
* the commit completes. `durationMs` measures the full lifetime of
|
|
87
|
+
* the transaction (including commit latency). Default no-op.
|
|
88
|
+
*/
|
|
89
|
+
onTransactionCommit(_txId, _durationMs) { }
|
|
90
|
+
/**
|
|
91
|
+
* Invoked when the transaction callback throws and the rollback
|
|
92
|
+
* completes. `reason` is the original error (before
|
|
93
|
+
* {@link DatabaseRepository.translateError} is applied to the
|
|
94
|
+
* rethrow). Default no-op.
|
|
95
|
+
*/
|
|
96
|
+
onTransactionRollback(_txId, _reason) { }
|
|
97
|
+
// ─── Internals ────────────────────────────────────────────
|
|
98
|
+
static makeTxId() {
|
|
99
|
+
const t = Date.now().toString(36);
|
|
100
|
+
const r = Math.floor(Math.random() * 0x100000).toString(36).padStart(4, '0');
|
|
101
|
+
return `tx-${t}-${r}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=TransactionalDatabaseRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransactionalDatabaseRepository.js","sourceRoot":"","sources":["../../../../src/repository/base/TransactionalDatabaseRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,OAAgB,+BACpB,SAAQ,kBAA0B;IAElC;;;;;;;;;;;OAWG;IACO,KAAK,CAAC,WAAW,CACzB,QAAkD;QAElD,MAAM,IAAI,GAAG,+BAA+B,CAAC,QAAQ,EAAE,CAAA;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YAC5D,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAA;YACtD,OAAO,MAAM,CAAA;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YACrC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IAED,6DAA6D;IAE7D;;;;OAIG;IACO,kBAAkB,CAAC,KAAa,IAAS,CAAC;IAEpD;;;;OAIG;IACO,mBAAmB,CAAC,KAAa,EAAE,WAAmB,IAAS,CAAC;IAE1E;;;;;OAKG;IACO,qBAAqB,CAAC,KAAa,EAAE,OAAgB,IAAS,CAAC;IAEzE,6DAA6D;IAErD,MAAM,CAAC,QAAQ;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC5E,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAA;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Repository } from '@xfcfam/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 `@xfcfam/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
|
+
* `@xfcfam/xf-sql-postgres`, `@xfcfam/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 '@xfcfam/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
|
+
* The hook may be `async` — the `exec()` call site `await`s it, so
|
|
183
|
+
* an async override is fully observed before the error is rethrown.
|
|
184
|
+
* Note: the Kysely log callback (`'query'` source) is synchronous by
|
|
185
|
+
* Kysely's API contract and cannot `await` the hook; async overrides
|
|
186
|
+
* that target only that source will execute fire-and-forget from that
|
|
187
|
+
* path. If reliable async observability of query-level Kysely errors
|
|
188
|
+
* is required, wrap the hook body with its own error handling.
|
|
189
|
+
*/
|
|
190
|
+
protected onError(_operation: string, _error: unknown): void | Promise<void>;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=DatabaseRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatabaseRepository.d.ts","sourceRoot":"","sources":["../../../../src/repository/general/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;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAC7E"}
|