@fluojs/drizzle 1.0.0-beta.1
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.ko.md +143 -0
- package/README.md +143 -0
- package/dist/database.d.ts +73 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +170 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/module.d.ts +13 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +86 -0
- package/dist/status.d.ts +17 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +68 -0
- package/dist/tokens.d.ts +7 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +6 -0
- package/dist/transaction.d.ts +25 -0
- package/dist/transaction.d.ts.map +1 -0
- package/dist/transaction.js +39 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fluo 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.ko.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# @fluojs/drizzle
|
|
2
|
+
|
|
3
|
+
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
|
+
|
|
5
|
+
트랜잭션 인지형 데이터베이스 래퍼와 선택적 dispose hook을 제공하는 fluo용 Drizzle ORM 통합 패키지입니다.
|
|
6
|
+
|
|
7
|
+
## 목차
|
|
8
|
+
|
|
9
|
+
- [설치](#설치)
|
|
10
|
+
- [사용 시점](#사용-시점)
|
|
11
|
+
- [빠른 시작](#빠른-시작)
|
|
12
|
+
- [주요 패턴](#주요-패턴)
|
|
13
|
+
- [수동 모듈 구성](#수동-모듈-구성)
|
|
14
|
+
- [공개 API 개요](#공개-api-개요)
|
|
15
|
+
- [관련 패키지](#관련-패키지)
|
|
16
|
+
- [예제 소스](#예제-소스)
|
|
17
|
+
|
|
18
|
+
## 설치
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @fluojs/drizzle
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 사용 시점
|
|
25
|
+
|
|
26
|
+
- Drizzle을 다른 fluo 모듈과 같은 DI·모듈·라이프사이클 모델 안에 넣고 싶을 때
|
|
27
|
+
- repository 코드가 root handle과 현재 트랜잭션 handle 사이를 `current()` 하나로 다루고 싶을 때
|
|
28
|
+
- 애플리케이션 종료 시 underlying driver 정리 로직도 함께 실행해야 할 때
|
|
29
|
+
|
|
30
|
+
## 빠른 시작
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { ConfigService } from '@fluojs/config';
|
|
34
|
+
import { Module } from '@fluojs/core';
|
|
35
|
+
import { DrizzleModule } from '@fluojs/drizzle';
|
|
36
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
37
|
+
import { Pool } from 'pg';
|
|
38
|
+
|
|
39
|
+
@Module({
|
|
40
|
+
imports: [
|
|
41
|
+
DrizzleModule.forRootAsync({
|
|
42
|
+
inject: [ConfigService],
|
|
43
|
+
useFactory: async (config: ConfigService) => {
|
|
44
|
+
const pool = new Pool({
|
|
45
|
+
connectionString: config.getOrThrow<string>('DATABASE_URL'),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
database: drizzle(pool),
|
|
50
|
+
dispose: async () => {
|
|
51
|
+
await pool.end();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
})
|
|
58
|
+
export class AppModule {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 주요 패턴
|
|
62
|
+
|
|
63
|
+
### repository에서 `DrizzleDatabase.current()` 사용하기
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { DrizzleDatabase } from '@fluojs/drizzle';
|
|
67
|
+
import { eq } from 'drizzle-orm';
|
|
68
|
+
import { users } from './schema';
|
|
69
|
+
|
|
70
|
+
export class UserRepository {
|
|
71
|
+
constructor(private readonly db: DrizzleDatabase) {}
|
|
72
|
+
|
|
73
|
+
async findById(id: string) {
|
|
74
|
+
return this.db.current().select().from(users).where(eq(users.id, id));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 수동 트랜잭션 경계
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
await this.db.transaction(async () => {
|
|
83
|
+
const tx = this.db.current();
|
|
84
|
+
await tx.insert(users).values(user);
|
|
85
|
+
await tx.insert(profiles).values(profile);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 인터셉터 기반 요청 단위 트랜잭션
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { UseInterceptors } from '@fluojs/http';
|
|
93
|
+
import { DrizzleTransactionInterceptor } from '@fluojs/drizzle';
|
|
94
|
+
|
|
95
|
+
@UseInterceptors(DrizzleTransactionInterceptor)
|
|
96
|
+
class UsersController {}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 수동 모듈 구성
|
|
100
|
+
|
|
101
|
+
`DrizzleModule.forRoot(...)` / `forRootAsync(...)`를 사용해 Drizzle을 등록합니다. 커스텀 `defineModule(...)` 안에서 Drizzle 지원을 조합해야 할 때도 동일한 모듈 entrypoint를 import해서 사용하세요.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { defineModule } from '@fluojs/runtime';
|
|
105
|
+
import { DrizzleDatabase, DrizzleModule, DrizzleTransactionInterceptor } from '@fluojs/drizzle';
|
|
106
|
+
|
|
107
|
+
const database = {
|
|
108
|
+
transaction: async <T>(callback: (tx: typeof database) => Promise<T>) => callback(database),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
class ManualDrizzleModule {}
|
|
112
|
+
|
|
113
|
+
defineModule(ManualDrizzleModule, {
|
|
114
|
+
exports: [DrizzleDatabase, DrizzleTransactionInterceptor],
|
|
115
|
+
imports: [DrizzleModule.forRoot({ database })],
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 공개 API 개요
|
|
120
|
+
|
|
121
|
+
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
122
|
+
- `DrizzleDatabase`
|
|
123
|
+
- `DrizzleTransactionInterceptor`
|
|
124
|
+
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_OPTIONS`
|
|
125
|
+
- `createDrizzlePlatformStatusSnapshot(...)`
|
|
126
|
+
|
|
127
|
+
### `DrizzleModule`
|
|
128
|
+
|
|
129
|
+
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
130
|
+
- `forRootAsync(...)`는 `AsyncModuleOptions<DrizzleModuleOptions<...>>`를 받습니다.
|
|
131
|
+
- `strictTransactions: true`를 설정하면 transaction 지원이 없는 database handle에서 예외를 던집니다.
|
|
132
|
+
|
|
133
|
+
## 관련 패키지
|
|
134
|
+
|
|
135
|
+
- `@fluojs/runtime`: 모듈 시작과 종료 순서를 관리합니다.
|
|
136
|
+
- `@fluojs/http`: 요청 단위 트랜잭션에 쓰이는 인터셉터 파이프라인을 제공합니다.
|
|
137
|
+
- `@fluojs/prisma`, `@fluojs/mongoose`: 같은 런타임 모델 위에서 동작하는 다른 데이터 통합 패키지입니다.
|
|
138
|
+
|
|
139
|
+
## 예제 소스
|
|
140
|
+
|
|
141
|
+
- `packages/drizzle/src/vertical-slice.test.ts`
|
|
142
|
+
- `packages/drizzle/src/module.test.ts`
|
|
143
|
+
- `packages/drizzle/src/public-api.test.ts`
|
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# @fluojs/drizzle
|
|
2
|
+
|
|
3
|
+
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
|
+
|
|
5
|
+
Drizzle ORM integration for fluo with a transaction-aware database wrapper and an optional dispose hook.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [When to Use](#when-to-use)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Common Patterns](#common-patterns)
|
|
13
|
+
- [Manual Module Composition](#manual-module-composition)
|
|
14
|
+
- [Public API Overview](#public-api-overview)
|
|
15
|
+
- [Related Packages](#related-packages)
|
|
16
|
+
- [Example Sources](#example-sources)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @fluojs/drizzle
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## When to Use
|
|
25
|
+
|
|
26
|
+
- when Drizzle should participate in the same module, DI, and lifecycle model as the rest of the app
|
|
27
|
+
- when repositories need a single `current()` seam that switches between the root handle and the active transaction handle
|
|
28
|
+
- when application shutdown should also run an explicit cleanup hook for the underlying driver resources
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { ConfigService } from '@fluojs/config';
|
|
34
|
+
import { Module } from '@fluojs/core';
|
|
35
|
+
import { DrizzleModule } from '@fluojs/drizzle';
|
|
36
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
37
|
+
import { Pool } from 'pg';
|
|
38
|
+
|
|
39
|
+
@Module({
|
|
40
|
+
imports: [
|
|
41
|
+
DrizzleModule.forRootAsync({
|
|
42
|
+
inject: [ConfigService],
|
|
43
|
+
useFactory: async (config: ConfigService) => {
|
|
44
|
+
const pool = new Pool({
|
|
45
|
+
connectionString: config.getOrThrow<string>('DATABASE_URL'),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
database: drizzle(pool),
|
|
50
|
+
dispose: async () => {
|
|
51
|
+
await pool.end();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
})
|
|
58
|
+
export class AppModule {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Common Patterns
|
|
62
|
+
|
|
63
|
+
### Use `DrizzleDatabase.current()` inside repositories
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { DrizzleDatabase } from '@fluojs/drizzle';
|
|
67
|
+
import { eq } from 'drizzle-orm';
|
|
68
|
+
import { users } from './schema';
|
|
69
|
+
|
|
70
|
+
export class UserRepository {
|
|
71
|
+
constructor(private readonly db: DrizzleDatabase) {}
|
|
72
|
+
|
|
73
|
+
async findById(id: string) {
|
|
74
|
+
return this.db.current().select().from(users).where(eq(users.id, id));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Manual transaction boundaries
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
await this.db.transaction(async () => {
|
|
83
|
+
const tx = this.db.current();
|
|
84
|
+
await tx.insert(users).values(user);
|
|
85
|
+
await tx.insert(profiles).values(profile);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Request-scoped transactions with an interceptor
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { UseInterceptors } from '@fluojs/http';
|
|
93
|
+
import { DrizzleTransactionInterceptor } from '@fluojs/drizzle';
|
|
94
|
+
|
|
95
|
+
@UseInterceptors(DrizzleTransactionInterceptor)
|
|
96
|
+
class UsersController {}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Manual Module Composition
|
|
100
|
+
|
|
101
|
+
Use `DrizzleModule.forRoot(...)` / `forRootAsync(...)` to register Drizzle. When you need to compose Drizzle support inside a custom `defineModule(...)` registration, import the module entrypoint there as well.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { defineModule } from '@fluojs/runtime';
|
|
105
|
+
import { DrizzleDatabase, DrizzleModule, DrizzleTransactionInterceptor } from '@fluojs/drizzle';
|
|
106
|
+
|
|
107
|
+
const database = {
|
|
108
|
+
transaction: async <T>(callback: (tx: typeof database) => Promise<T>) => callback(database),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
class ManualDrizzleModule {}
|
|
112
|
+
|
|
113
|
+
defineModule(ManualDrizzleModule, {
|
|
114
|
+
exports: [DrizzleDatabase, DrizzleTransactionInterceptor],
|
|
115
|
+
imports: [DrizzleModule.forRoot({ database })],
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Public API Overview
|
|
120
|
+
|
|
121
|
+
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
122
|
+
- `DrizzleDatabase`
|
|
123
|
+
- `DrizzleTransactionInterceptor`
|
|
124
|
+
- `DRIZZLE_DATABASE`, `DRIZZLE_DISPOSE`, `DRIZZLE_OPTIONS`
|
|
125
|
+
- `createDrizzlePlatformStatusSnapshot(...)`
|
|
126
|
+
|
|
127
|
+
### `DrizzleModule`
|
|
128
|
+
|
|
129
|
+
- `DrizzleModule.forRoot(options)` / `DrizzleModule.forRootAsync(options)`
|
|
130
|
+
- `forRootAsync(...)` accepts `AsyncModuleOptions<DrizzleModuleOptions<...>>`.
|
|
131
|
+
- Supports `strictTransactions: true` to throw if transaction support is missing.
|
|
132
|
+
|
|
133
|
+
## Related Packages
|
|
134
|
+
|
|
135
|
+
- `@fluojs/runtime`: owns module startup and shutdown sequencing
|
|
136
|
+
- `@fluojs/http`: provides the interceptor pipeline used for request transactions
|
|
137
|
+
- `@fluojs/prisma` and `@fluojs/mongoose`: alternate ORM/ODM integrations with the same fluo runtime model
|
|
138
|
+
|
|
139
|
+
## Example Sources
|
|
140
|
+
|
|
141
|
+
- `packages/drizzle/src/vertical-slice.test.ts`
|
|
142
|
+
- `packages/drizzle/src/module.test.ts`
|
|
143
|
+
- `packages/drizzle/src/public-api.test.ts`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { OnApplicationShutdown } from '@fluojs/runtime';
|
|
2
|
+
import type { DrizzleDatabaseLike, DrizzleHandleProvider } from './types.js';
|
|
3
|
+
type DrizzleRuntimeOptions = {
|
|
4
|
+
strictTransactions: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Transaction-aware Drizzle wrapper that integrates request scoping and shutdown handling with the Fluo runtime.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
10
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside `database.transaction(...)` callbacks.
|
|
11
|
+
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
12
|
+
*/
|
|
13
|
+
export declare class DrizzleDatabase<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown> implements DrizzleHandleProvider<TDatabase, TTransactionDatabase, TTransactionOptions>, OnApplicationShutdown {
|
|
14
|
+
private readonly database;
|
|
15
|
+
private readonly dispose?;
|
|
16
|
+
private readonly databaseOptions;
|
|
17
|
+
private readonly transactions;
|
|
18
|
+
private readonly activeRequestTransactions;
|
|
19
|
+
private lifecycleState;
|
|
20
|
+
constructor(database: TDatabase, dispose?: ((database: TDatabase) => Promise<void> | void) | undefined, databaseOptions?: DrizzleRuntimeOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Returns the active transaction handle when present, otherwise the root Drizzle database handle.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* return db.current().select().from(users);
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @returns The transaction-scoped database inside an active boundary, or the root database outside one.
|
|
30
|
+
*/
|
|
31
|
+
current(): TDatabase | TTransactionDatabase;
|
|
32
|
+
/** Aborts active request transactions, waits for settlement, then runs the optional dispose hook. */
|
|
33
|
+
onApplicationShutdown(): Promise<void>;
|
|
34
|
+
/** Produces the shared persistence status snapshot for platform diagnostics surfaces. */
|
|
35
|
+
createPlatformStatusSnapshot(): import("@fluojs/runtime").PersistencePlatformStatusSnapshot;
|
|
36
|
+
/**
|
|
37
|
+
* Opens a Drizzle transaction boundary or reuses the current one when already inside a transaction.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* await db.transaction(async () => {
|
|
42
|
+
* await db.current().insert(users).values(user);
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @param fn Callback executed inside the transaction scope.
|
|
47
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
48
|
+
* @returns The callback result after the transaction finishes or the direct-execution fallback completes.
|
|
49
|
+
*/
|
|
50
|
+
transaction<T>(fn: () => Promise<T>, options?: TTransactionOptions): Promise<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Opens an abort-aware request transaction boundary for the current HTTP request.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* await db.requestTransaction(async () => next.handle(), request.signal);
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @param fn Callback executed inside the request transaction scope.
|
|
60
|
+
* @param signal Optional abort signal linked to the request lifecycle.
|
|
61
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
62
|
+
* @returns The callback result after the request transaction finishes or the direct-execution fallback completes.
|
|
63
|
+
*/
|
|
64
|
+
requestTransaction<T>(fn: () => Promise<T>, signal?: AbortSignal, options?: TTransactionOptions): Promise<T>;
|
|
65
|
+
private executeTransaction;
|
|
66
|
+
private executeRequestTransaction;
|
|
67
|
+
private executeRequestFallback;
|
|
68
|
+
private trackActiveRequestTransaction;
|
|
69
|
+
private untrackActiveRequestTransaction;
|
|
70
|
+
private resolveTransactionRunner;
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAK7D,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAqBpB,KAAK,qBAAqB,GAAG;IAC3B,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;;;;;GAMG;AACH,qBACa,eAAe,CAC1B,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,CAC7B,YAAW,qBAAqB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,qBAAqB;IAO3G,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAPlC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiD;IAC9E,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAuC;IACjF,OAAO,CAAC,cAAc,CAAkD;gBAGrD,QAAQ,EAAE,SAAS,EACnB,OAAO,CAAC,GAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,aAAA,EACvD,eAAe,GAAE,qBAAqD;IAGzF;;;;;;;;;OASG;IACH,OAAO,IAAI,SAAS,GAAG,oBAAoB;IAI3C,qGAAqG;IAC/F,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5C,yFAAyF;IACzF,4BAA4B;IAS5B;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrF;;;;;;;;;;;;OAYG;IACG,kBAAkB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;YAIpG,kBAAkB;YAoClB,yBAAyB;YAoBzB,sBAAsB;IAYpC,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,+BAA+B;IAIvC,OAAO,CAAC,wBAAwB;CAWjC"}
|
package/dist/database.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
let _initClass;
|
|
2
|
+
function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
|
|
3
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
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
|
+
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
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
|
+
import { createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
9
|
+
import { Inject } from '@fluojs/core';
|
|
10
|
+
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS } from './tokens.js';
|
|
11
|
+
import { createDrizzlePlatformStatusSnapshot } from './status.js';
|
|
12
|
+
const TRANSACTION_NOT_SUPPORTED_ERROR = 'Transaction not supported: Drizzle database does not implement transaction.';
|
|
13
|
+
const NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR = 'Nested Drizzle transaction options are not supported because the active transaction context is reused.';
|
|
14
|
+
let _DrizzleDatabase;
|
|
15
|
+
/**
|
|
16
|
+
* Transaction-aware Drizzle wrapper that integrates request scoping and shutdown handling with the Fluo runtime.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
19
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside `database.transaction(...)` callbacks.
|
|
20
|
+
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
21
|
+
*/
|
|
22
|
+
class DrizzleDatabase {
|
|
23
|
+
static {
|
|
24
|
+
[_DrizzleDatabase, _initClass] = _applyDecs(this, [Inject(DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS)], []).c;
|
|
25
|
+
}
|
|
26
|
+
transactions = new AsyncLocalStorage();
|
|
27
|
+
activeRequestTransactions = new Set();
|
|
28
|
+
lifecycleState = 'ready';
|
|
29
|
+
constructor(database, dispose, databaseOptions = {
|
|
30
|
+
strictTransactions: false
|
|
31
|
+
}) {
|
|
32
|
+
this.database = database;
|
|
33
|
+
this.dispose = dispose;
|
|
34
|
+
this.databaseOptions = databaseOptions;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Returns the active transaction handle when present, otherwise the root Drizzle database handle.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* return db.current().select().from(users);
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @returns The transaction-scoped database inside an active boundary, or the root database outside one.
|
|
46
|
+
*/
|
|
47
|
+
current() {
|
|
48
|
+
return this.transactions.getStore() ?? this.database;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Aborts active request transactions, waits for settlement, then runs the optional dispose hook. */
|
|
52
|
+
async onApplicationShutdown() {
|
|
53
|
+
this.lifecycleState = 'shutting-down';
|
|
54
|
+
for (const transaction of this.activeRequestTransactions) {
|
|
55
|
+
transaction.abort(new Error('Application shutdown interrupted an open request transaction.'));
|
|
56
|
+
}
|
|
57
|
+
await Promise.allSettled(Array.from(this.activeRequestTransactions, transaction => transaction.settled));
|
|
58
|
+
if (this.dispose) {
|
|
59
|
+
await this.dispose(this.database);
|
|
60
|
+
}
|
|
61
|
+
this.lifecycleState = 'stopped';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Produces the shared persistence status snapshot for platform diagnostics surfaces. */
|
|
65
|
+
createPlatformStatusSnapshot() {
|
|
66
|
+
return createDrizzlePlatformStatusSnapshot({
|
|
67
|
+
activeRequestTransactions: this.activeRequestTransactions.size,
|
|
68
|
+
lifecycleState: this.lifecycleState,
|
|
69
|
+
strictTransactions: this.databaseOptions.strictTransactions,
|
|
70
|
+
supportsTransaction: typeof this.database.transaction === 'function'
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Opens a Drizzle transaction boundary or reuses the current one when already inside a transaction.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* await db.transaction(async () => {
|
|
80
|
+
* await db.current().insert(users).values(user);
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @param fn Callback executed inside the transaction scope.
|
|
85
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
86
|
+
* @returns The callback result after the transaction finishes or the direct-execution fallback completes.
|
|
87
|
+
*/
|
|
88
|
+
async transaction(fn, options) {
|
|
89
|
+
return this.executeTransaction(fn, options, false);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Opens an abort-aware request transaction boundary for the current HTTP request.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* await db.requestTransaction(async () => next.handle(), request.signal);
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @param fn Callback executed inside the request transaction scope.
|
|
101
|
+
* @param signal Optional abort signal linked to the request lifecycle.
|
|
102
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
103
|
+
* @returns The callback result after the request transaction finishes or the direct-execution fallback completes.
|
|
104
|
+
*/
|
|
105
|
+
async requestTransaction(fn, signal, options) {
|
|
106
|
+
return this.executeTransaction(fn, options, true, signal);
|
|
107
|
+
}
|
|
108
|
+
async executeTransaction(fn, options, requestScoped, signal) {
|
|
109
|
+
const current = this.transactions.getStore();
|
|
110
|
+
if (current) {
|
|
111
|
+
if (options !== undefined) {
|
|
112
|
+
throw new Error(NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR);
|
|
113
|
+
}
|
|
114
|
+
if (requestScoped && signal) {
|
|
115
|
+
return raceWithAbort(fn, signal);
|
|
116
|
+
}
|
|
117
|
+
return fn();
|
|
118
|
+
}
|
|
119
|
+
const transactionRunner = this.resolveTransactionRunner();
|
|
120
|
+
if (!transactionRunner) {
|
|
121
|
+
if (requestScoped) {
|
|
122
|
+
return this.executeRequestFallback(fn, signal);
|
|
123
|
+
}
|
|
124
|
+
return fn();
|
|
125
|
+
}
|
|
126
|
+
if (!requestScoped) {
|
|
127
|
+
return transactionRunner(transactionDatabase => this.transactions.run(transactionDatabase, fn), options);
|
|
128
|
+
}
|
|
129
|
+
return this.executeRequestTransaction(transactionRunner, fn, options, signal);
|
|
130
|
+
}
|
|
131
|
+
async executeRequestTransaction(transactionRunner, fn, options, signal) {
|
|
132
|
+
const abortContext = createRequestAbortContext(signal);
|
|
133
|
+
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
134
|
+
try {
|
|
135
|
+
return await transactionRunner(transactionDatabase => this.transactions.run(transactionDatabase, () => raceWithAbort(fn, abortContext.signal)), options);
|
|
136
|
+
} finally {
|
|
137
|
+
abortContext.cleanup();
|
|
138
|
+
this.untrackActiveRequestTransaction(active);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async executeRequestFallback(fn, signal) {
|
|
142
|
+
const abortContext = createRequestAbortContext(signal);
|
|
143
|
+
const active = this.trackActiveRequestTransaction(abortContext.controller);
|
|
144
|
+
try {
|
|
145
|
+
return await raceWithAbort(fn, abortContext.signal);
|
|
146
|
+
} finally {
|
|
147
|
+
abortContext.cleanup();
|
|
148
|
+
this.untrackActiveRequestTransaction(active);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
trackActiveRequestTransaction(controller) {
|
|
152
|
+
return trackActiveRequestTransaction(this.activeRequestTransactions, controller);
|
|
153
|
+
}
|
|
154
|
+
untrackActiveRequestTransaction(handle) {
|
|
155
|
+
untrackActiveRequestTransaction(this.activeRequestTransactions, handle);
|
|
156
|
+
}
|
|
157
|
+
resolveTransactionRunner() {
|
|
158
|
+
if (typeof this.database.transaction !== 'function') {
|
|
159
|
+
if (this.databaseOptions.strictTransactions) {
|
|
160
|
+
throw new Error(TRANSACTION_NOT_SUPPORTED_ERROR);
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
return this.database.transaction.bind(this.database);
|
|
165
|
+
}
|
|
166
|
+
static {
|
|
167
|
+
_initClass();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export { _DrizzleDatabase as DrizzleDatabase };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AsyncModuleOptions } from '@fluojs/core';
|
|
2
|
+
import { type ModuleType } from '@fluojs/runtime';
|
|
3
|
+
import type { DrizzleDatabaseLike, DrizzleModuleOptions } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Module entrypoint for wiring a Drizzle database into the Fluo runtime lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DrizzleModule {
|
|
8
|
+
/** Creates a module definition from static Drizzle options. */
|
|
9
|
+
static forRoot<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>): ModuleType;
|
|
10
|
+
/** Creates a module definition from DI-aware async Drizzle options. */
|
|
11
|
+
static forRootAsync<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown>(options: AsyncModuleOptions<DrizzleModuleOptions<TDatabase, TTransactionDatabase, TTransactionOptions>>): ModuleType;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0I5E;;GAEG;AACH,qBAAa,aAAa;IACxB,+DAA+D;IAC/D,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,uEAAuE;IACvE,MAAM,CAAC,YAAY,CACjB,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAChF,oBAAoB,GAAG,SAAS,EAChC,mBAAmB,GAAG,OAAO,EAC7B,OAAO,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,CAAC,GAAG,UAAU;CAGvH"}
|
package/dist/module.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineModule } from '@fluojs/runtime';
|
|
2
|
+
import { DrizzleDatabase } from './database.js';
|
|
3
|
+
import { DRIZZLE_DATABASE, DRIZZLE_DISPOSE, DRIZZLE_OPTIONS } from './tokens.js';
|
|
4
|
+
import { DrizzleTransactionInterceptor } from './transaction.js';
|
|
5
|
+
const DRIZZLE_NORMALIZED_OPTIONS = Symbol('fluo.drizzle.normalized-options');
|
|
6
|
+
const DRIZZLE_MODULE_EXPORTS = [DrizzleDatabase, DrizzleTransactionInterceptor];
|
|
7
|
+
function normalizeDrizzleModuleOptions(options) {
|
|
8
|
+
return {
|
|
9
|
+
...options,
|
|
10
|
+
strictTransactions: options.strictTransactions ?? false
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function createRuntimeOptionsProviderValue(strictTransactions) {
|
|
14
|
+
return {
|
|
15
|
+
strictTransactions
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function createDrizzleRuntimeProviders(normalizedOptionsProvider) {
|
|
19
|
+
return [normalizedOptionsProvider, {
|
|
20
|
+
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
21
|
+
provide: DRIZZLE_DATABASE,
|
|
22
|
+
useFactory: options => options.database
|
|
23
|
+
}, {
|
|
24
|
+
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
25
|
+
provide: DRIZZLE_DISPOSE,
|
|
26
|
+
useFactory: options => options.dispose
|
|
27
|
+
}, {
|
|
28
|
+
inject: [DRIZZLE_NORMALIZED_OPTIONS],
|
|
29
|
+
provide: DRIZZLE_OPTIONS,
|
|
30
|
+
useFactory: options => createRuntimeOptionsProviderValue(options.strictTransactions)
|
|
31
|
+
}, DrizzleDatabase, DrizzleTransactionInterceptor];
|
|
32
|
+
}
|
|
33
|
+
function createMemoizedDrizzleOptionsResolver(options) {
|
|
34
|
+
let cachedResult;
|
|
35
|
+
return (...deps) => {
|
|
36
|
+
if (!cachedResult) {
|
|
37
|
+
cachedResult = Promise.resolve(options.useFactory(...deps)).then(resolved => normalizeDrizzleModuleOptions(resolved));
|
|
38
|
+
}
|
|
39
|
+
if (!cachedResult) {
|
|
40
|
+
throw new Error('Drizzle module options resolver initialization failed.');
|
|
41
|
+
}
|
|
42
|
+
return cachedResult;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function createDrizzleProvidersAsync(options) {
|
|
46
|
+
const resolveOptions = createMemoizedDrizzleOptionsResolver(options);
|
|
47
|
+
const normalizedOptionsProvider = {
|
|
48
|
+
inject: options.inject,
|
|
49
|
+
provide: DRIZZLE_NORMALIZED_OPTIONS,
|
|
50
|
+
scope: 'singleton',
|
|
51
|
+
useFactory: async (...deps) => resolveOptions(...deps)
|
|
52
|
+
};
|
|
53
|
+
return createDrizzleRuntimeProviders(normalizedOptionsProvider);
|
|
54
|
+
}
|
|
55
|
+
function buildDrizzleModule(options) {
|
|
56
|
+
class DrizzleRootModuleDefinition {}
|
|
57
|
+
return defineModule(DrizzleRootModuleDefinition, {
|
|
58
|
+
exports: DRIZZLE_MODULE_EXPORTS,
|
|
59
|
+
providers: createDrizzleRuntimeProviders({
|
|
60
|
+
provide: DRIZZLE_NORMALIZED_OPTIONS,
|
|
61
|
+
useValue: normalizeDrizzleModuleOptions(options)
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function buildDrizzleModuleAsync(options) {
|
|
66
|
+
class DrizzleAsyncModuleDefinition {}
|
|
67
|
+
return defineModule(DrizzleAsyncModuleDefinition, {
|
|
68
|
+
exports: DRIZZLE_MODULE_EXPORTS,
|
|
69
|
+
providers: createDrizzleProvidersAsync(options)
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Module entrypoint for wiring a Drizzle database into the Fluo runtime lifecycle.
|
|
75
|
+
*/
|
|
76
|
+
export class DrizzleModule {
|
|
77
|
+
/** Creates a module definition from static Drizzle options. */
|
|
78
|
+
static forRoot(options) {
|
|
79
|
+
return buildDrizzleModule(options);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Creates a module definition from DI-aware async Drizzle options. */
|
|
83
|
+
static forRootAsync(options) {
|
|
84
|
+
return buildDrizzleModuleAsync(options);
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/status.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PersistencePlatformStatusSnapshot } from '@fluojs/runtime';
|
|
2
|
+
type DrizzlePlatformLifecycleState = 'ready' | 'shutting-down' | 'stopped';
|
|
3
|
+
type DrizzlePlatformStatusSnapshotInput = {
|
|
4
|
+
activeRequestTransactions: number;
|
|
5
|
+
lifecycleState: DrizzlePlatformLifecycleState;
|
|
6
|
+
strictTransactions: boolean;
|
|
7
|
+
supportsTransaction: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Maps Drizzle lifecycle and transaction capability diagnostics into the shared persistence snapshot shape.
|
|
11
|
+
*
|
|
12
|
+
* @param input Current Drizzle ownership, readiness, and health inputs.
|
|
13
|
+
* @returns Platform-facing persistence status data for diagnostics surfaces.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDrizzlePlatformStatusSnapshot(input: DrizzlePlatformStatusSnapshotInput): PersistencePlatformStatusSnapshot;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iCAAiC,EAGlC,MAAM,iBAAiB,CAAC;AAEzB,KAAK,6BAA6B,GAAG,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;AAE3E,KAAK,kCAAkC,GAAG;IACxC,yBAAyB,EAAE,MAAM,CAAC;IAClC,cAAc,EAAE,6BAA6B,CAAC;IAC9C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAqDF;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,kCAAkC,GACxC,iCAAiC,CAgBnC"}
|
package/dist/status.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function createReadiness(input) {
|
|
2
|
+
if (input.lifecycleState === 'shutting-down') {
|
|
3
|
+
return {
|
|
4
|
+
critical: true,
|
|
5
|
+
reason: 'Drizzle integration is shutting down.',
|
|
6
|
+
status: 'not-ready'
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
if (input.lifecycleState === 'stopped') {
|
|
10
|
+
return {
|
|
11
|
+
critical: true,
|
|
12
|
+
reason: 'Drizzle integration is stopped.',
|
|
13
|
+
status: 'not-ready'
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (input.strictTransactions && !input.supportsTransaction) {
|
|
17
|
+
return {
|
|
18
|
+
critical: true,
|
|
19
|
+
reason: 'Drizzle strictTransactions is enabled but database.transaction is unavailable.',
|
|
20
|
+
status: 'not-ready'
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
critical: true,
|
|
25
|
+
status: 'ready'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function createHealth(input) {
|
|
29
|
+
if (input.lifecycleState === 'stopped') {
|
|
30
|
+
return {
|
|
31
|
+
reason: 'Drizzle integration has been disposed.',
|
|
32
|
+
status: 'unhealthy'
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (input.lifecycleState === 'shutting-down') {
|
|
36
|
+
return {
|
|
37
|
+
reason: 'Drizzle integration is draining request transactions during shutdown.',
|
|
38
|
+
status: 'degraded'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
status: 'healthy'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Maps Drizzle lifecycle and transaction capability diagnostics into the shared persistence snapshot shape.
|
|
48
|
+
*
|
|
49
|
+
* @param input Current Drizzle ownership, readiness, and health inputs.
|
|
50
|
+
* @returns Platform-facing persistence status data for diagnostics surfaces.
|
|
51
|
+
*/
|
|
52
|
+
export function createDrizzlePlatformStatusSnapshot(input) {
|
|
53
|
+
return {
|
|
54
|
+
details: {
|
|
55
|
+
activeRequestTransactions: input.activeRequestTransactions,
|
|
56
|
+
lifecycleState: input.lifecycleState,
|
|
57
|
+
strictTransactions: input.strictTransactions,
|
|
58
|
+
supportsTransaction: input.supportsTransaction,
|
|
59
|
+
transactionContext: 'als'
|
|
60
|
+
},
|
|
61
|
+
health: createHealth(input),
|
|
62
|
+
ownership: {
|
|
63
|
+
externallyManaged: true,
|
|
64
|
+
ownsResources: false
|
|
65
|
+
},
|
|
66
|
+
readiness: createReadiness(input)
|
|
67
|
+
};
|
|
68
|
+
}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Dependency-injection token for the raw Drizzle database handle. */
|
|
2
|
+
export declare const DRIZZLE_DATABASE: unique symbol;
|
|
3
|
+
/** Dependency-injection token for the optional Drizzle shutdown dispose hook. */
|
|
4
|
+
export declare const DRIZZLE_DISPOSE: unique symbol;
|
|
5
|
+
/** Dependency-injection token for normalized Drizzle runtime options. */
|
|
6
|
+
export declare const DRIZZLE_OPTIONS: unique symbol;
|
|
7
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,eAAsC,CAAC;AACpE,iFAAiF;AACjF,eAAO,MAAM,eAAe,eAAqC,CAAC;AAClE,yEAAyE;AACzE,eAAO,MAAM,eAAe,eAAqC,CAAC"}
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Dependency-injection token for the raw Drizzle database handle. */
|
|
2
|
+
export const DRIZZLE_DATABASE = Symbol.for('fluo.drizzle.database');
|
|
3
|
+
/** Dependency-injection token for the optional Drizzle shutdown dispose hook. */
|
|
4
|
+
export const DRIZZLE_DISPOSE = Symbol.for('fluo.drizzle.dispose');
|
|
5
|
+
/** Dependency-injection token for normalized Drizzle runtime options. */
|
|
6
|
+
export const DRIZZLE_OPTIONS = Symbol.for('fluo.drizzle.options');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Interceptor, InterceptorContext } from '@fluojs/http';
|
|
2
|
+
import { DrizzleDatabase } from './database.js';
|
|
3
|
+
import type { DrizzleDatabaseLike } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* HTTP interceptor that wraps each request in a Drizzle request transaction boundary.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Pair this with repository/service code that reads `DrizzleDatabase.current()` so downstream calls share the same
|
|
9
|
+
* request-scoped transaction handle.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DrizzleTransactionInterceptor implements Interceptor {
|
|
12
|
+
private readonly database;
|
|
13
|
+
constructor(database: DrizzleDatabase<DrizzleDatabaseLike<unknown, unknown>, unknown, unknown>);
|
|
14
|
+
/**
|
|
15
|
+
* Runs the downstream handler inside a Drizzle request transaction boundary.
|
|
16
|
+
*
|
|
17
|
+
* @param context Interceptor context that supplies the request abort signal.
|
|
18
|
+
* @param next Downstream handler chain.
|
|
19
|
+
* @returns The downstream handler result after the request transaction settles.
|
|
20
|
+
*/
|
|
21
|
+
intercept(context: InterceptorContext, next: {
|
|
22
|
+
handle(): Promise<unknown>;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;GAMG;AACH,qBACa,6BAA8B,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,eAAe,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;IAE/G;;;;;;OAMG;IACG,SAAS,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE;QAAE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAGrG"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
let _initClass;
|
|
2
|
+
function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
|
|
3
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
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
|
+
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
|
+
import { Inject } from '@fluojs/core';
|
|
8
|
+
import { DrizzleDatabase } from './database.js';
|
|
9
|
+
let _DrizzleTransactionIn;
|
|
10
|
+
/**
|
|
11
|
+
* HTTP interceptor that wraps each request in a Drizzle request transaction boundary.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* Pair this with repository/service code that reads `DrizzleDatabase.current()` so downstream calls share the same
|
|
15
|
+
* request-scoped transaction handle.
|
|
16
|
+
*/
|
|
17
|
+
class DrizzleTransactionInterceptor {
|
|
18
|
+
static {
|
|
19
|
+
[_DrizzleTransactionIn, _initClass] = _applyDecs(this, [Inject(DrizzleDatabase)], []).c;
|
|
20
|
+
}
|
|
21
|
+
constructor(database) {
|
|
22
|
+
this.database = database;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Runs the downstream handler inside a Drizzle request transaction boundary.
|
|
27
|
+
*
|
|
28
|
+
* @param context Interceptor context that supplies the request abort signal.
|
|
29
|
+
* @param next Downstream handler chain.
|
|
30
|
+
* @returns The downstream handler result after the request transaction settles.
|
|
31
|
+
*/
|
|
32
|
+
async intercept(context, next) {
|
|
33
|
+
return this.database.requestTransaction(async () => next.handle(), context.requestContext.request.signal);
|
|
34
|
+
}
|
|
35
|
+
static {
|
|
36
|
+
_initClass();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export { _DrizzleTransactionIn as DrizzleTransactionInterceptor };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { MaybePromise } from '@fluojs/core';
|
|
2
|
+
type DrizzleTransactionCallback<TTransactionDatabase, TResult> = (database: TTransactionDatabase) => Promise<TResult>;
|
|
3
|
+
type DrizzleTransactionRunner<TTransactionDatabase, TTransactionOptions> = <T>(callback: DrizzleTransactionCallback<TTransactionDatabase, T>, options?: TTransactionOptions) => Promise<T>;
|
|
4
|
+
/**
|
|
5
|
+
* Minimal Drizzle seam that exposes the optional transaction callback boundary used by the Fluo wrapper.
|
|
6
|
+
*
|
|
7
|
+
* @typeParam TTransactionDatabase Transaction handle shape passed into `database.transaction(...)` callbacks.
|
|
8
|
+
* @typeParam TTransactionOptions Options forwarded to the underlying Drizzle transaction runner.
|
|
9
|
+
*/
|
|
10
|
+
export interface DrizzleDatabaseLike<TTransactionDatabase = unknown, TTransactionOptions = unknown> {
|
|
11
|
+
transaction?: DrizzleTransactionRunner<TTransactionDatabase, TTransactionOptions>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Module options for registering a Drizzle handle and optional shutdown disposal hook.
|
|
15
|
+
*
|
|
16
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
17
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved by `current()`.
|
|
18
|
+
* @typeParam TTransactionOptions Options forwarded to `database.transaction(...)`.
|
|
19
|
+
*/
|
|
20
|
+
export interface DrizzleModuleOptions<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown> {
|
|
21
|
+
/** Root Drizzle database handle shared outside ambient transaction scopes. */
|
|
22
|
+
database: TDatabase;
|
|
23
|
+
/** Optional shutdown hook used to close pools or driver resources during application shutdown. */
|
|
24
|
+
dispose?: (database: TDatabase) => MaybePromise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Throws when transaction helpers are used against a database that does not expose `transaction(...)`.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* Leave this disabled when transaction helpers should fall back to direct execution.
|
|
30
|
+
*/
|
|
31
|
+
strictTransactions?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Public Drizzle wrapper contract exposed through dependency injection.
|
|
35
|
+
*
|
|
36
|
+
* @typeParam TDatabase Root Drizzle database handle registered in the module.
|
|
37
|
+
* @typeParam TTransactionDatabase Transaction-scoped database handle resolved inside transaction boundaries.
|
|
38
|
+
* @typeParam TTransactionOptions Options forwarded to `database.transaction(...)`.
|
|
39
|
+
*/
|
|
40
|
+
export interface DrizzleHandleProvider<TDatabase extends DrizzleDatabaseLike<TTransactionDatabase, TTransactionOptions>, TTransactionDatabase = TDatabase, TTransactionOptions = unknown> {
|
|
41
|
+
/** Returns the ambient transaction database when present, or the root Drizzle handle otherwise. */
|
|
42
|
+
current(): TDatabase | TTransactionDatabase;
|
|
43
|
+
/**
|
|
44
|
+
* Opens an abort-aware request transaction boundary around `fn`.
|
|
45
|
+
*
|
|
46
|
+
* @param fn Callback executed within the request transaction scope.
|
|
47
|
+
* @param signal Optional abort signal linked to the request lifecycle.
|
|
48
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
49
|
+
* @returns The callback result after the request transaction finishes or the direct-execution fallback completes.
|
|
50
|
+
*/
|
|
51
|
+
requestTransaction<T>(fn: () => Promise<T>, signal?: AbortSignal, options?: TTransactionOptions): Promise<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Opens a Drizzle transaction boundary around `fn`.
|
|
54
|
+
*
|
|
55
|
+
* @param fn Callback executed within the transaction scope.
|
|
56
|
+
* @param options Optional transaction options forwarded to `database.transaction(...)`.
|
|
57
|
+
* @returns The callback result after the transaction finishes or the direct-execution fallback completes.
|
|
58
|
+
*/
|
|
59
|
+
transaction<T>(fn: () => Promise<T>, options?: TTransactionOptions): Promise<T>;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,KAAK,0BAA0B,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtH,KAAK,wBAAwB,CAAC,oBAAoB,EAAE,mBAAmB,IAAI,CAAC,CAAC,EAC3E,QAAQ,EAAE,0BAA0B,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAC7D,OAAO,CAAC,EAAE,mBAAmB,KAC1B,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB,CAAC,oBAAoB,GAAG,OAAO,EAAE,mBAAmB,GAAG,OAAO;IAChG,WAAW,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,CAAC;CACnF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB,CAAC,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,oBAAoB,GAAG,SAAS,EAAE,mBAAmB,GAAG,OAAO;IACrL,8EAA8E;IAC9E,QAAQ,EAAE,SAAS,CAAC;IACpB,kGAAkG;IAClG,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACtD;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB,CAAC,SAAS,SAAS,mBAAmB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,oBAAoB,GAAG,SAAS,EAAE,mBAAmB,GAAG,OAAO;IACtL,mGAAmG;IACnG,OAAO,IAAI,SAAS,GAAG,oBAAoB,CAAC;IAC5C;;;;;;;OAOG;IACH,kBAAkB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7G;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjF"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluojs/drizzle",
|
|
3
|
+
"description": "Drizzle ORM integration for Fluo with ALS transaction context, async module factory, and optional dispose hook.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"fluo",
|
|
6
|
+
"drizzle",
|
|
7
|
+
"orm",
|
|
8
|
+
"database",
|
|
9
|
+
"transaction",
|
|
10
|
+
"als"
|
|
11
|
+
],
|
|
12
|
+
"version": "1.0.0-beta.1",
|
|
13
|
+
"private": false,
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/fluojs/fluo.git",
|
|
18
|
+
"directory": "packages/drizzle"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20.0.0"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"main": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@fluojs/runtime": "^1.0.0-beta.1",
|
|
40
|
+
"@fluojs/di": "^1.0.0-beta.1",
|
|
41
|
+
"@fluojs/core": "^1.0.0-beta.1",
|
|
42
|
+
"@fluojs/http": "^1.0.0-beta.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"drizzle-orm": ">=0.30.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"drizzle-orm": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"vitest": "^3.2.4"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|
|
57
|
+
"build": "pnpm exec babel src --extensions .ts --ignore 'src/**/*.test.ts' --out-dir dist --config-file ../../tooling/babel/babel.config.cjs && pnpm exec tsc -p tsconfig.build.json",
|
|
58
|
+
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
59
|
+
"test": "pnpm exec vitest run -c vitest.config.ts",
|
|
60
|
+
"test:watch": "pnpm exec vitest -c vitest.config.ts"
|
|
61
|
+
}
|
|
62
|
+
}
|