@fluojs/drizzle 1.1.0 → 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.
- package/README.ko.md +80 -24
- package/README.md +80 -24
- package/dist/database.d.ts +8 -1
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +189 -41
- package/dist/module.d.ts +21 -5
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +21 -77
- package/dist/named-registration.d.ts +20 -0
- package/dist/named-registration.d.ts.map +1 -0
- package/dist/named-registration.js +84 -0
- package/dist/registration-name.d.ts +9 -0
- package/dist/registration-name.d.ts.map +1 -0
- package/dist/registration-name.js +17 -0
- package/dist/registration-providers.d.ts +44 -0
- package/dist/registration-providers.d.ts.map +1 -0
- package/dist/registration-providers.js +120 -0
- package/dist/tokens.d.ts +29 -0
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +47 -1
- package/dist/transaction.d.ts +28 -3
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +50 -5
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/database.js
CHANGED
|
@@ -5,19 +5,23 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
5
5
|
function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
7
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
|
-
import { createAbortError, createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
9
8
|
import { Inject } from '@fluojs/core';
|
|
10
|
-
import {
|
|
9
|
+
import { createAbortError, createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
11
10
|
import { createDrizzlePlatformStatusSnapshot } from './status.js';
|
|
11
|
+
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS } from './tokens.js';
|
|
12
12
|
const TRANSACTION_NOT_SUPPORTED_ERROR = 'Transaction not supported: Drizzle database does not implement transaction.';
|
|
13
13
|
const NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR = 'Nested Drizzle transaction options are not supported because the active transaction context is reused.';
|
|
14
14
|
const TRANSACTION_UNAVAILABLE_ERROR = 'Drizzle transactions are not available during application shutdown.';
|
|
15
15
|
const REQUEST_TRANSACTION_UNAVAILABLE_ERROR = 'Drizzle request transactions are not available during shutdown.';
|
|
16
16
|
function createCurrentlessDrizzleFacade(target) {
|
|
17
17
|
return new Proxy(target, {
|
|
18
|
-
get(database, prop
|
|
18
|
+
get(database, prop) {
|
|
19
19
|
if (prop in database) {
|
|
20
|
-
|
|
20
|
+
const value = Reflect.get(database, prop, database);
|
|
21
|
+
if (typeof value === 'function') {
|
|
22
|
+
return value.bind(database);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
21
25
|
}
|
|
22
26
|
const currentDatabase = database.current();
|
|
23
27
|
const value = Reflect.get(currentDatabase, prop, currentDatabase);
|
|
@@ -92,7 +96,8 @@ class DrizzleDatabase {
|
|
|
92
96
|
* @remarks
|
|
93
97
|
* This compatibility helper is used by `DrizzleModule` provider wiring. Application code should prefer
|
|
94
98
|
* `DrizzleModule.forRoot(...)` or `DrizzleModule.forRootAsync(...)`, then type injected repository handles as
|
|
95
|
-
* `DrizzleDatabaseFacade<TDatabase>` when direct Drizzle methods are needed.
|
|
99
|
+
* `DrizzleDatabaseFacade<TDatabase>` when direct Drizzle methods are needed. Wrapper and lifecycle methods remain
|
|
100
|
+
* bound to the lifecycle owner while unknown Drizzle query properties forward to the ambient `current()` handle.
|
|
96
101
|
*
|
|
97
102
|
* @param database Root Drizzle database handle registered in the module.
|
|
98
103
|
* @param dispose Optional shutdown hook used to close pools or driver resources.
|
|
@@ -116,7 +121,11 @@ class DrizzleDatabase {
|
|
|
116
121
|
* @returns The transaction-scoped database inside an active boundary, or the root database outside one.
|
|
117
122
|
*/
|
|
118
123
|
current() {
|
|
119
|
-
|
|
124
|
+
const current = this.transactions.getStore();
|
|
125
|
+
if (!current || current.transactionBoundaryOwner.closed) {
|
|
126
|
+
return this.database;
|
|
127
|
+
}
|
|
128
|
+
return current.database;
|
|
120
129
|
}
|
|
121
130
|
|
|
122
131
|
/** Aborts active request transactions, waits for settlement, then runs the optional dispose hook. */
|
|
@@ -180,67 +189,162 @@ class DrizzleDatabase {
|
|
|
180
189
|
async executeTransaction(fn, options, requestScoped, signal) {
|
|
181
190
|
const current = this.transactions.getStore();
|
|
182
191
|
if (current) {
|
|
192
|
+
if (current.transactionBoundaryOwner.closed) {
|
|
193
|
+
if (requestScoped) {
|
|
194
|
+
return this.executeInheritedRequestTransaction(current, fn, options, signal);
|
|
195
|
+
}
|
|
196
|
+
return this.executeManualRootTransaction(fn, options);
|
|
197
|
+
}
|
|
198
|
+
if (!requestScoped) {
|
|
199
|
+
return this.executeNestedManualTransaction(current.transactionBoundaryOwner, fn, options);
|
|
200
|
+
}
|
|
183
201
|
if (requestScoped) {
|
|
184
202
|
this.assertRequestTransactionsAvailable();
|
|
185
203
|
} else {
|
|
186
204
|
this.assertTransactionsAvailable();
|
|
187
205
|
}
|
|
188
|
-
if (options !== undefined) {
|
|
189
|
-
throw new Error(NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR);
|
|
190
|
-
}
|
|
191
206
|
if (requestScoped) {
|
|
192
207
|
return this.executeNestedRequestTransaction(current, fn, signal);
|
|
193
208
|
}
|
|
194
|
-
return fn();
|
|
195
209
|
}
|
|
196
210
|
if (!requestScoped) {
|
|
197
|
-
this.
|
|
211
|
+
return this.executeManualRootTransaction(fn, options);
|
|
198
212
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
213
|
+
return this.executeRequestRootTransaction(fn, options, signal);
|
|
214
|
+
}
|
|
215
|
+
async executeManualRootTransaction(fn, options) {
|
|
216
|
+
const deferredRequestTransactionSettlements = new Set();
|
|
217
|
+
const fallbackTransactionOwner = {
|
|
218
|
+
closed: false,
|
|
219
|
+
callbackSettlements: new Set(),
|
|
220
|
+
requestTransactionSettlements: new Set()
|
|
221
|
+
};
|
|
222
|
+
const activeTransactionScope = this.trackAvailableTransactionScope();
|
|
223
|
+
try {
|
|
224
|
+
const transactionRunner = this.resolveTransactionRunner();
|
|
225
|
+
if (!transactionRunner) {
|
|
226
|
+
try {
|
|
227
|
+
return await this.transactions.run({
|
|
228
|
+
database: this.database,
|
|
229
|
+
fallbackTransactionOwner,
|
|
230
|
+
transactionBoundaryOwner: fallbackTransactionOwner
|
|
231
|
+
}, fn);
|
|
232
|
+
} finally {
|
|
233
|
+
await this.closeTransactionBoundaryOwner(fallbackTransactionOwner);
|
|
234
|
+
}
|
|
203
235
|
}
|
|
204
|
-
return
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}, fn), options);
|
|
214
|
-
} finally {
|
|
215
|
-
for (const handle of deferredRequestTransactionSettlements) {
|
|
216
|
-
this.untrackActiveRequestTransaction(handle);
|
|
236
|
+
return await transactionRunner(async transactionDatabase => {
|
|
237
|
+
try {
|
|
238
|
+
return await this.transactions.run({
|
|
239
|
+
database: transactionDatabase,
|
|
240
|
+
deferredRequestTransactionSettlements,
|
|
241
|
+
transactionBoundaryOwner: fallbackTransactionOwner
|
|
242
|
+
}, fn);
|
|
243
|
+
} finally {
|
|
244
|
+
await this.closeTransactionBoundaryOwner(fallbackTransactionOwner);
|
|
217
245
|
}
|
|
218
|
-
|
|
246
|
+
}, options);
|
|
247
|
+
} finally {
|
|
248
|
+
await this.closeTransactionBoundaryOwner(fallbackTransactionOwner);
|
|
249
|
+
for (const handle of fallbackTransactionOwner.requestTransactionSettlements) {
|
|
250
|
+
this.untrackActiveRequestTransaction(handle);
|
|
219
251
|
}
|
|
252
|
+
for (const handle of deferredRequestTransactionSettlements) {
|
|
253
|
+
this.untrackActiveRequestTransaction(handle);
|
|
254
|
+
}
|
|
255
|
+
activeTransactionScope.settle();
|
|
220
256
|
}
|
|
221
|
-
return this.executeRequestTransaction(transactionRunner, fn, options, signal);
|
|
222
257
|
}
|
|
223
258
|
async executeRequestTransaction(transactionRunner, fn, options, signal) {
|
|
224
259
|
this.assertRequestTransactionsAvailable();
|
|
225
260
|
const abortContext = createRequestAbortContext(signal);
|
|
226
261
|
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
262
|
+
const transactionBoundaryOwner = {
|
|
263
|
+
closed: false,
|
|
264
|
+
callbackSettlements: new Set(),
|
|
265
|
+
requestTransactionSettlements: new Set()
|
|
266
|
+
};
|
|
227
267
|
try {
|
|
228
|
-
const result = await transactionRunner(transactionDatabase =>
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
268
|
+
const result = await transactionRunner(async transactionDatabase => {
|
|
269
|
+
try {
|
|
270
|
+
return await this.transactions.run({
|
|
271
|
+
database: transactionDatabase,
|
|
272
|
+
inheritedRequestAbortSignal: signal ?? abortContext.signal,
|
|
273
|
+
requestAbortSignal: abortContext.signal,
|
|
274
|
+
transactionBoundaryOwner
|
|
275
|
+
}, () => raceWithAbort(fn, abortContext.signal));
|
|
276
|
+
} finally {
|
|
277
|
+
await this.closeTransactionBoundaryOwner(transactionBoundaryOwner);
|
|
278
|
+
}
|
|
279
|
+
}, options);
|
|
232
280
|
this.throwIfRequestAborted(abortContext.signal);
|
|
233
281
|
return result;
|
|
234
282
|
} finally {
|
|
283
|
+
transactionBoundaryOwner.closed = true;
|
|
235
284
|
abortContext.cleanup();
|
|
236
285
|
this.untrackActiveRequestTransaction(active);
|
|
237
286
|
}
|
|
238
287
|
}
|
|
288
|
+
async executeRequestRootTransaction(fn, options, signal) {
|
|
289
|
+
const transactionRunner = this.resolveTransactionRunner();
|
|
290
|
+
if (!transactionRunner) {
|
|
291
|
+
return this.executeRequestFallback(fn, signal);
|
|
292
|
+
}
|
|
293
|
+
return this.executeRequestTransaction(transactionRunner, fn, options, signal);
|
|
294
|
+
}
|
|
295
|
+
async executeInheritedRequestTransaction(current, fn, options, signal) {
|
|
296
|
+
const inheritedRequestAbortSignal = current.inheritedRequestAbortSignal ?? current.requestAbortSignal;
|
|
297
|
+
if (!inheritedRequestAbortSignal) {
|
|
298
|
+
return this.executeRequestRootTransaction(fn, options, signal);
|
|
299
|
+
}
|
|
300
|
+
const abortSignalView = createRequestAbortSignalView(inheritedRequestAbortSignal, signal);
|
|
301
|
+
try {
|
|
302
|
+
this.throwIfRequestAborted(abortSignalView.signal);
|
|
303
|
+
return await this.executeRequestRootTransaction(fn, options, abortSignalView.signal);
|
|
304
|
+
} finally {
|
|
305
|
+
abortSignalView.cleanup();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
async executeNestedManualTransaction(owner, fn, options) {
|
|
309
|
+
this.assertTransactionsAvailable();
|
|
310
|
+
if (options !== undefined) {
|
|
311
|
+
throw new Error(NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR);
|
|
312
|
+
}
|
|
313
|
+
const callback = Promise.resolve().then(fn);
|
|
314
|
+
const removeSettlement = () => {
|
|
315
|
+
owner.callbackSettlements.delete(settlement);
|
|
316
|
+
};
|
|
317
|
+
const settlement = callback.then(removeSettlement, removeSettlement);
|
|
318
|
+
owner.callbackSettlements.add(settlement);
|
|
319
|
+
return callback;
|
|
320
|
+
}
|
|
239
321
|
async executeNestedRequestTransaction(current, fn, signal) {
|
|
322
|
+
const fallbackTransactionOwner = current.fallbackTransactionOwner;
|
|
323
|
+
if (fallbackTransactionOwner?.closed) {
|
|
324
|
+
if (current.requestAbortSignal) {
|
|
325
|
+
const abortSignalView = createRequestAbortSignalView(current.requestAbortSignal, signal);
|
|
326
|
+
try {
|
|
327
|
+
return await this.executeRequestFallback(fn, abortSignalView.signal);
|
|
328
|
+
} finally {
|
|
329
|
+
abortSignalView.cleanup();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return this.executeRequestFallback(fn, signal);
|
|
333
|
+
}
|
|
334
|
+
const runCallback = () => {
|
|
335
|
+
const callback = fn();
|
|
336
|
+
const transactionBoundaryOwner = current.transactionBoundaryOwner;
|
|
337
|
+
const removeSettlement = () => {
|
|
338
|
+
transactionBoundaryOwner.callbackSettlements.delete(settlement);
|
|
339
|
+
};
|
|
340
|
+
const settlement = callback.then(removeSettlement, removeSettlement);
|
|
341
|
+
transactionBoundaryOwner.callbackSettlements.add(settlement);
|
|
342
|
+
return callback;
|
|
343
|
+
};
|
|
240
344
|
if (current.requestAbortSignal) {
|
|
241
345
|
const abortSignalView = createRequestAbortSignalView(current.requestAbortSignal, signal);
|
|
242
346
|
try {
|
|
243
|
-
const result = await raceWithAbort(
|
|
347
|
+
const result = await raceWithAbort(runCallback, abortSignalView.signal);
|
|
244
348
|
this.throwIfRequestAborted(abortSignalView.signal);
|
|
245
349
|
return result;
|
|
246
350
|
} finally {
|
|
@@ -250,17 +354,27 @@ class DrizzleDatabase {
|
|
|
250
354
|
this.assertRequestTransactionsAvailable();
|
|
251
355
|
const abortContext = createRequestAbortContext(signal);
|
|
252
356
|
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
253
|
-
|
|
357
|
+
let ownerDefersSettlement = false;
|
|
358
|
+
if (fallbackTransactionOwner) {
|
|
359
|
+
fallbackTransactionOwner.requestTransactionSettlements.add(active);
|
|
360
|
+
ownerDefersSettlement = true;
|
|
361
|
+
} else if (current.deferredRequestTransactionSettlements) {
|
|
362
|
+
current.deferredRequestTransactionSettlements.add(active);
|
|
363
|
+
ownerDefersSettlement = true;
|
|
364
|
+
}
|
|
254
365
|
try {
|
|
255
366
|
const result = await this.transactions.run({
|
|
256
367
|
database: current.database,
|
|
257
|
-
|
|
258
|
-
|
|
368
|
+
fallbackTransactionOwner,
|
|
369
|
+
inheritedRequestAbortSignal: current.inheritedRequestAbortSignal,
|
|
370
|
+
requestAbortSignal: abortContext.signal,
|
|
371
|
+
transactionBoundaryOwner: current.transactionBoundaryOwner
|
|
372
|
+
}, () => raceWithAbort(runCallback, abortContext.signal));
|
|
259
373
|
this.throwIfRequestAborted(abortContext.signal);
|
|
260
374
|
return result;
|
|
261
375
|
} finally {
|
|
262
376
|
abortContext.cleanup();
|
|
263
|
-
if (
|
|
377
|
+
if (ownerDefersSettlement) {
|
|
264
378
|
this.markRequestTransactionInactiveForStatus(active);
|
|
265
379
|
} else {
|
|
266
380
|
this.untrackActiveRequestTransaction(active);
|
|
@@ -270,16 +384,46 @@ class DrizzleDatabase {
|
|
|
270
384
|
async executeRequestFallback(fn, signal) {
|
|
271
385
|
this.assertRequestTransactionsAvailable();
|
|
272
386
|
const abortContext = createRequestAbortContext(signal);
|
|
387
|
+
if (abortContext.signal.aborted) {
|
|
388
|
+
const abortError = createAbortError(abortContext.signal.reason);
|
|
389
|
+
abortContext.cleanup();
|
|
390
|
+
throw abortError;
|
|
391
|
+
}
|
|
273
392
|
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
393
|
+
const fallbackTransactionOwner = {
|
|
394
|
+
closed: false,
|
|
395
|
+
callbackSettlements: new Set(),
|
|
396
|
+
requestTransactionSettlements: new Set()
|
|
397
|
+
};
|
|
274
398
|
try {
|
|
275
|
-
const result = await raceWithAbort(
|
|
399
|
+
const result = await raceWithAbort(() => {
|
|
400
|
+
const callback = new Promise(resolve => resolve(this.transactions.run({
|
|
401
|
+
database: this.database,
|
|
402
|
+
fallbackTransactionOwner,
|
|
403
|
+
inheritedRequestAbortSignal: signal ?? abortContext.signal,
|
|
404
|
+
requestAbortSignal: abortContext.signal,
|
|
405
|
+
transactionBoundaryOwner: fallbackTransactionOwner
|
|
406
|
+
}, fn)));
|
|
407
|
+
return callback.finally(async () => {
|
|
408
|
+
await this.closeTransactionBoundaryOwner(fallbackTransactionOwner);
|
|
409
|
+
for (const handle of fallbackTransactionOwner.requestTransactionSettlements) {
|
|
410
|
+
this.untrackActiveRequestTransaction(handle);
|
|
411
|
+
}
|
|
412
|
+
this.untrackActiveRequestTransaction(active);
|
|
413
|
+
});
|
|
414
|
+
}, abortContext.signal);
|
|
276
415
|
this.throwIfRequestAborted(abortContext.signal);
|
|
277
416
|
return result;
|
|
278
417
|
} finally {
|
|
279
418
|
abortContext.cleanup();
|
|
280
|
-
this.untrackActiveRequestTransaction(active);
|
|
281
419
|
}
|
|
282
420
|
}
|
|
421
|
+
async closeTransactionBoundaryOwner(owner) {
|
|
422
|
+
while (owner.callbackSettlements.size > 0) {
|
|
423
|
+
await Promise.all(owner.callbackSettlements);
|
|
424
|
+
}
|
|
425
|
+
owner.closed = true;
|
|
426
|
+
}
|
|
283
427
|
assertRequestTransactionsAvailable() {
|
|
284
428
|
if (this.lifecycleState !== 'ready') {
|
|
285
429
|
throw new Error(REQUEST_TRANSACTION_UNAVAILABLE_ERROR);
|
|
@@ -328,6 +472,10 @@ class DrizzleDatabase {
|
|
|
328
472
|
}
|
|
329
473
|
};
|
|
330
474
|
}
|
|
475
|
+
trackAvailableTransactionScope() {
|
|
476
|
+
this.assertTransactionsAvailable();
|
|
477
|
+
return this.trackActiveTransactionScope();
|
|
478
|
+
}
|
|
331
479
|
resolveTransactionRunner() {
|
|
332
480
|
if (typeof this.database.transaction !== 'function') {
|
|
333
481
|
if (this.databaseOptions.strictTransactions) {
|
package/dist/module.d.ts
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import type { AsyncModuleOptions } from '@fluojs/core';
|
|
2
|
-
import {
|
|
2
|
+
import type { ModuleType } from '@fluojs/runtime';
|
|
3
3
|
import type { DrizzleDatabaseLike, DrizzleModuleOptions } from './types.js';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Configures an async Drizzle module registration through an injected factory.
|
|
6
|
+
*
|
|
7
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
8
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside transaction callbacks.
|
|
9
|
+
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
10
|
+
*/
|
|
11
|
+
export type DrizzleAsyncModuleOptions<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase, TTransactionOptions> = AsyncModuleOptions<Omit<DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>, 'global' | 'name'>> & Pick<DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>, 'global' | 'name'>;
|
|
5
12
|
/**
|
|
6
13
|
* Module entrypoint for wiring a Drizzle database into the Fluo runtime lifecycle.
|
|
7
14
|
*/
|
|
8
15
|
export declare class DrizzleModule {
|
|
9
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Creates a module definition from static Drizzle options.
|
|
18
|
+
*
|
|
19
|
+
* @param options Static Drizzle registration options.
|
|
20
|
+
* @returns A runtime module definition for the requested Drizzle registration.
|
|
21
|
+
*/
|
|
10
22
|
static forRoot<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>): ModuleType;
|
|
11
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Creates a module definition from DI-aware async Drizzle options.
|
|
25
|
+
*
|
|
26
|
+
* @param options Async Drizzle registration options.
|
|
27
|
+
* @returns A runtime module definition for the requested Drizzle registration.
|
|
28
|
+
*/
|
|
12
29
|
static forRootAsync<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: DrizzleAsyncModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>): ModuleType;
|
|
13
30
|
}
|
|
14
|
-
export {};
|
|
15
31
|
//# sourceMappingURL=module.d.ts.map
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,CACnC,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,EACpB,mBAAmB,IACjB,kBAAkB,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,GACzH,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC;AAEtG;;GAEG;AACH,qBAAa,aAAa;IACxB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CACZ,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU;IAIlG;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,yBAAyB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU;CAGxG"}
|
package/dist/module.js
CHANGED
|
@@ -1,89 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (!isObjectLike(options.database)) {
|
|
11
|
-
throw new Error('DrizzleModule requires a database option.');
|
|
12
|
-
}
|
|
13
|
-
return {
|
|
14
|
-
...options,
|
|
15
|
-
strictTransactions: options.strictTransactions ?? false
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function createRuntimeOptionsProviderValue(strictTransactions) {
|
|
19
|
-
return {
|
|
20
|
-
strictTransactions
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function createDrizzleRuntimeProviders(normalizedOptionsProvider) {
|
|
24
|
-
return [normalizedOptionsProvider, {
|
|
25
|
-
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
26
|
-
provide: DRIZZLE_DATABASE,
|
|
27
|
-
useFactory: options => options.database
|
|
28
|
-
}, {
|
|
29
|
-
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
30
|
-
provide: DRIZZLE_DISPOSE,
|
|
31
|
-
useFactory: options => options.dispose
|
|
32
|
-
}, {
|
|
33
|
-
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
34
|
-
provide: DRIZZLE_OPTIONS,
|
|
35
|
-
useFactory: options => createRuntimeOptionsProviderValue(options.strictTransactions)
|
|
36
|
-
}, {
|
|
37
|
-
inject: [DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS],
|
|
38
|
-
provide: DrizzleDatabase,
|
|
39
|
-
useFactory: (database, dispose, databaseOptions) => DrizzleDatabase.createFacade(database, dispose, databaseOptions)
|
|
40
|
-
}, {
|
|
41
|
-
provide: DRIZZLE_HANDLE_PROVIDER,
|
|
42
|
-
useExisting: DrizzleDatabase
|
|
43
|
-
}];
|
|
44
|
-
}
|
|
45
|
-
function createDrizzleProvidersAsync(options) {
|
|
46
|
-
const normalizedOptionsProvider = {
|
|
47
|
-
inject: options.inject,
|
|
48
|
-
provide: DRIZZLE_NORMALIZED_OPTIONS,
|
|
49
|
-
scope: 'singleton',
|
|
50
|
-
useFactory: async (...deps) => normalizeDrizzleModuleOptions({
|
|
51
|
-
...(await options.useFactory(...deps)),
|
|
52
|
-
global: options.global
|
|
53
|
-
})
|
|
54
|
-
};
|
|
55
|
-
return createDrizzleRuntimeProviders(normalizedOptionsProvider);
|
|
56
|
-
}
|
|
57
|
-
function buildDrizzleModule(options) {
|
|
58
|
-
class DrizzleRootModuleDefinition {}
|
|
59
|
-
return defineModule(DrizzleRootModuleDefinition, {
|
|
60
|
-
exports: DRIZZLE_MODULE_EXPORTS,
|
|
61
|
-
global: options.global ?? false,
|
|
62
|
-
providers: createDrizzleRuntimeProviders({
|
|
63
|
-
provide: DRIZZLE_NORMALIZED_OPTIONS,
|
|
64
|
-
useValue: normalizeDrizzleModuleOptions(options)
|
|
65
|
-
})
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
function buildDrizzleModuleAsync(options) {
|
|
69
|
-
class DrizzleAsyncModuleDefinition {}
|
|
70
|
-
return defineModule(DrizzleAsyncModuleDefinition, {
|
|
71
|
-
exports: DRIZZLE_MODULE_EXPORTS,
|
|
72
|
-
global: options.global ?? false,
|
|
73
|
-
providers: createDrizzleProvidersAsync(options)
|
|
74
|
-
});
|
|
75
|
-
}
|
|
1
|
+
import { buildDrizzleModule, buildDrizzleModuleAsync } from './named-registration.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configures an async Drizzle module registration through an injected factory.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
7
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside transaction callbacks.
|
|
8
|
+
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
9
|
+
*/
|
|
76
10
|
|
|
77
11
|
/**
|
|
78
12
|
* Module entrypoint for wiring a Drizzle database into the Fluo runtime lifecycle.
|
|
79
13
|
*/
|
|
80
14
|
export class DrizzleModule {
|
|
81
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Creates a module definition from static Drizzle options.
|
|
17
|
+
*
|
|
18
|
+
* @param options Static Drizzle registration options.
|
|
19
|
+
* @returns A runtime module definition for the requested Drizzle registration.
|
|
20
|
+
*/
|
|
82
21
|
static forRoot(options) {
|
|
83
22
|
return buildDrizzleModule(options);
|
|
84
23
|
}
|
|
85
24
|
|
|
86
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Creates a module definition from DI-aware async Drizzle options.
|
|
27
|
+
*
|
|
28
|
+
* @param options Async Drizzle registration options.
|
|
29
|
+
* @returns A runtime module definition for the requested Drizzle registration.
|
|
30
|
+
*/
|
|
87
31
|
static forRootAsync(options) {
|
|
88
32
|
return buildDrizzleModuleAsync(options);
|
|
89
33
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ModuleType } from '@fluojs/runtime';
|
|
2
|
+
import type { DrizzleAsyncModuleOptions } from './module.js';
|
|
3
|
+
import type { DrizzleDatabaseLike, DrizzleModuleOptions } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Builds a synchronous Drizzle runtime module definition.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
* @param options Static Drizzle registration options.
|
|
9
|
+
* @returns A module definition for the default or named registration.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildDrizzleModule<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>): ModuleType;
|
|
12
|
+
/**
|
|
13
|
+
* Builds an asynchronous Drizzle runtime module definition.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
* @param options Async Drizzle registration options.
|
|
17
|
+
* @returns A module definition for the default or named registration.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildDrizzleModuleAsync<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: DrizzleAsyncModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>): ModuleType;
|
|
20
|
+
//# sourceMappingURL=named-registration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-registration.d.ts","sourceRoot":"","sources":["../src/named-registration.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAmB7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAmF5E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU,CAajG;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,yBAAyB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,GAAG,UAAU,CAUtG"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { defineModule } from '@fluojs/runtime';
|
|
2
|
+
import { DrizzleDatabase } from './database.js';
|
|
3
|
+
import { createDrizzleRuntimeProviders, getNormalizedOptionsToken, getRegistrationGuardToken } from './registration-providers.js';
|
|
4
|
+
import { normalizeDrizzleRegistrationName } from './registration-name.js';
|
|
5
|
+
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_HANDLE_PROVIDER, DRIZZLE_OPTIONS, getDrizzleDatabaseToken, getDrizzleDisposeToken, getDrizzleHandleProviderToken, getDrizzleOptionsToken } from './tokens.js';
|
|
6
|
+
import { DrizzleTransactionInterceptor } from './transaction.js';
|
|
7
|
+
const DRIZZLE_MODULE_EXPORTS = [DrizzleDatabase, DrizzleTransactionInterceptor, DRIZZLE_HANDLE_PROVIDER, DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS];
|
|
8
|
+
function isObjectLike(value) {
|
|
9
|
+
return typeof value === 'object' && value !== null || typeof value === 'function';
|
|
10
|
+
}
|
|
11
|
+
function assertNamedRegistrationIsScoped(name, global) {
|
|
12
|
+
if (name !== undefined && global) {
|
|
13
|
+
throw new Error('Named Drizzle registrations are scoped and cannot be registered globally.');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function normalizeDrizzleModuleOptions(options) {
|
|
17
|
+
if (!isObjectLike(options.database)) {
|
|
18
|
+
throw new Error('DrizzleModule requires a database option.');
|
|
19
|
+
}
|
|
20
|
+
const name = normalizeDrizzleRegistrationName(options.name);
|
|
21
|
+
assertNamedRegistrationIsScoped(name, options.global);
|
|
22
|
+
return {
|
|
23
|
+
...options,
|
|
24
|
+
global: name === undefined ? options.global : false,
|
|
25
|
+
name,
|
|
26
|
+
strictTransactions: options.strictTransactions ?? false
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function createDrizzleProvidersAsync(options, name) {
|
|
30
|
+
const registrationGuardToken = name === undefined ? undefined : getRegistrationGuardToken(name);
|
|
31
|
+
const normalizedOptionsProvider = {
|
|
32
|
+
inject: registrationGuardToken === undefined ? options.inject : [registrationGuardToken, ...(options.inject ?? [])],
|
|
33
|
+
provide: getNormalizedOptionsToken(name),
|
|
34
|
+
scope: 'singleton',
|
|
35
|
+
useFactory: async (...dependencies) => normalizeDrizzleModuleOptions({
|
|
36
|
+
...(await options.useFactory(...(registrationGuardToken === undefined ? dependencies : dependencies.slice(1)))),
|
|
37
|
+
global: options.global,
|
|
38
|
+
name
|
|
39
|
+
})
|
|
40
|
+
};
|
|
41
|
+
return createDrizzleRuntimeProviders(normalizedOptionsProvider, name);
|
|
42
|
+
}
|
|
43
|
+
function getDrizzleModuleExports(name) {
|
|
44
|
+
return name === undefined ? DRIZZLE_MODULE_EXPORTS : [getDrizzleDatabaseToken(name), getDrizzleDisposeToken(name), getDrizzleHandleProviderToken(name), getDrizzleOptionsToken(name)];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Builds a synchronous Drizzle runtime module definition.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
* @param options Static Drizzle registration options.
|
|
52
|
+
* @returns A module definition for the default or named registration.
|
|
53
|
+
*/
|
|
54
|
+
export function buildDrizzleModule(options) {
|
|
55
|
+
const normalizedOptions = normalizeDrizzleModuleOptions(options);
|
|
56
|
+
const name = normalizedOptions.name;
|
|
57
|
+
class DrizzleRootModuleDefinition {}
|
|
58
|
+
return defineModule(DrizzleRootModuleDefinition, {
|
|
59
|
+
exports: getDrizzleModuleExports(name),
|
|
60
|
+
global: normalizedOptions.global ?? false,
|
|
61
|
+
providers: createDrizzleRuntimeProviders({
|
|
62
|
+
provide: getNormalizedOptionsToken(name),
|
|
63
|
+
useValue: normalizedOptions
|
|
64
|
+
}, name)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Builds an asynchronous Drizzle runtime module definition.
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
* @param options Async Drizzle registration options.
|
|
73
|
+
* @returns A module definition for the default or named registration.
|
|
74
|
+
*/
|
|
75
|
+
export function buildDrizzleModuleAsync(options) {
|
|
76
|
+
const name = normalizeDrizzleRegistrationName(options.name);
|
|
77
|
+
assertNamedRegistrationIsScoped(name, options.global);
|
|
78
|
+
class DrizzleAsyncModuleDefinition {}
|
|
79
|
+
return defineModule(DrizzleAsyncModuleDefinition, {
|
|
80
|
+
exports: getDrizzleModuleExports(name),
|
|
81
|
+
global: name === undefined ? options.global ?? false : false,
|
|
82
|
+
providers: createDrizzleProvidersAsync(options, name)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a public Drizzle registration name before it becomes part of a DI token.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
* @param name Optional registration name supplied by a module or token helper.
|
|
6
|
+
* @returns The trimmed registration name, or `undefined` for the default registration.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeDrizzleRegistrationName(name?: string): string | undefined;
|
|
9
|
+
//# sourceMappingURL=registration-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration-name.d.ts","sourceRoot":"","sources":["../src/registration-name.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYlF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a public Drizzle registration name before it becomes part of a DI token.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
* @param name Optional registration name supplied by a module or token helper.
|
|
6
|
+
* @returns The trimmed registration name, or `undefined` for the default registration.
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeDrizzleRegistrationName(name) {
|
|
9
|
+
if (name === undefined) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const normalizedName = name.trim();
|
|
13
|
+
if (normalizedName.length === 0) {
|
|
14
|
+
throw new Error('DrizzleModule name must be a non-empty string when provided.');
|
|
15
|
+
}
|
|
16
|
+
return normalizedName;
|
|
17
|
+
}
|