@fluojs/prisma 1.0.0 → 1.0.2
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 +9 -2
- package/README.md +9 -2
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +9 -0
- package/dist/service.d.ts +1 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +48 -4
- package/dist/status.d.ts +1 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +16 -1
- package/package.json +7 -7
package/README.ko.md
CHANGED
|
@@ -142,7 +142,7 @@ class UserController {
|
|
|
142
142
|
|
|
143
143
|
`createPrismaPlatformStatusSnapshot(...)`와 `PrismaService.createPlatformStatusSnapshot()`은 같은 라이프사이클 계약을 진단 surface에 노출합니다.
|
|
144
144
|
|
|
145
|
-
- `readiness.status`는 Prisma가 종료 중이거나 stopped 상태일 때, 그리고 `strictTransactions`가 켜져 있는데 `$transaction(...)`을 지원하지 않을 때 `not-ready`입니다.
|
|
145
|
+
- `readiness.status`는 `onModuleInit()`이 클라이언트를 연결하기 전, Prisma가 종료 중이거나 stopped 상태일 때, 그리고 `strictTransactions`가 켜져 있는데 `$transaction(...)`을 지원하지 않을 때 `not-ready`입니다.
|
|
146
146
|
- `health.status`는 종료 중 요청 트랜잭션을 drain하는 동안 `degraded`, disconnect 이후 `unhealthy`입니다.
|
|
147
147
|
- `details.activeRequestTransactions`, `details.lifecycleState`, `details.strictTransactions`, `details.supportsTransaction`, `details.transactionAbortSignalSupport`는 현재 요청 트랜잭션과 트랜잭션 capability 상태를 설명합니다.
|
|
148
148
|
- `details.transactionContext: 'als'`는 요청 및 서비스 트랜잭션 경계가 사용하는 async-local transaction context를 식별합니다.
|
|
@@ -167,6 +167,8 @@ PrismaModule.forRootAsync({
|
|
|
167
167
|
|
|
168
168
|
하나의 컴파일된 애플리케이션 안에서는 하위 provider가 동일하게 resolve된 `PrismaService`, ALS 트랜잭션 컨텍스트, 라이프사이클 관리 대상 클라이언트를 공유합니다. 서로 다른 애플리케이션 컨테이너는 독립된 factory 결과를 받으므로 `$connect` / `$disconnect` 소유권과 요청 트랜잭션 상태가 격리됩니다.
|
|
169
169
|
|
|
170
|
+
트랜잭션 경계에는 호스트가 제공하는 `AsyncLocalStorage` 지원이 필요합니다. `@fluojs/prisma`는 런타임이 노출하는 `globalThis.AsyncLocalStorage` 또는 Node.js의 `process.getBuiltinModule('node:async_hooks')` 호스트 경계를 통해 이를 resolve합니다. 두 경로 모두 사용할 수 없으면 동기 stack fallback으로 async boundary 사이의 `current()`를 잃는 대신, Prisma 트랜잭션을 열기 전에 `transaction()`과 `requestTransaction()`이 예외를 던집니다. 이 상태는 `createPlatformStatusSnapshot().details.transactionContext`에 `unavailable`로 보고됩니다.
|
|
171
|
+
|
|
170
172
|
### 수동 모듈 조합
|
|
171
173
|
|
|
172
174
|
`PrismaModule.forRoot(...)` / `forRootAsync(...)`를 사용해 Prisma를 등록합니다. 커스텀 `defineModule(...)` 등록 안에서 Prisma 지원을 조합해야 할 때도 동일한 모듈 entrypoint를 import해서 사용하세요.
|
|
@@ -196,7 +198,8 @@ defineModule(ManualPrismaModule, {
|
|
|
196
198
|
- `forRootAsync(...)`는 애플리케이션 컨테이너마다 옵션을 한 번 resolve하여, 별도 bootstrap 사이에서 클라이언트 라이프사이클과 요청 트랜잭션 격리를 보존합니다.
|
|
197
199
|
- `strictTransactions: true` 설정 시 트랜잭션 미지원 환경에서 즉시 예외를 발생시킵니다.
|
|
198
200
|
- `strictTransactions`가 `false`이면 클라이언트가 interactive `$transaction`을 제공하지 않을 때 직접 실행으로 fallback합니다.
|
|
199
|
-
-
|
|
201
|
+
- sync 및 async 등록 모두에서 `client`는 실제 object/function handle이어야 하며, 누락된 handle은 모듈 등록 또는 async bootstrap 중 거부됩니다.
|
|
202
|
+
- 이름 있는 등록의 `name`은 public token 생성 전에 trim되며, 빈 이름은 거부됩니다.
|
|
200
203
|
|
|
201
204
|
### `PrismaService<TClient>`
|
|
202
205
|
|
|
@@ -207,6 +210,10 @@ defineModule(ManualPrismaModule, {
|
|
|
207
210
|
- `requestTransaction(fn, signal?, options?): Promise<T>`
|
|
208
211
|
- HTTP 요청 라이프사이클에 특화된 트랜잭션 경계를 실행합니다. Abort를 인식하고, shutdown 중에는 disconnect 전에 열린 요청 트랜잭션을 drain하며, Prisma client가 `signal` 옵션을 거부하면 해당 옵션 없이 재시도합니다. `transaction()`과 마찬가지로 중첩 호출은 활성 트랜잭션 컨텍스트를 재사용하고, 트랜잭션 설정을 조용히 무시하지 않도록 중첩 옵션을 거부합니다.
|
|
209
212
|
|
|
213
|
+
### `PrismaTransactionInterceptor`
|
|
214
|
+
|
|
215
|
+
- 기본 이름 없는 `PrismaService` 등록을 위한 HTTP interceptor입니다. 요청 handler를 `PrismaService.requestTransaction(...)`으로 감싸 downstream `current()` 호출이 같은 transaction client를 공유하게 합니다.
|
|
216
|
+
|
|
210
217
|
### `PRISMA_CLIENT` (Token)
|
|
211
218
|
|
|
212
219
|
원시 `PrismaClient` 인스턴스를 위한 주입 토큰입니다.
|
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ class UserController {
|
|
|
142
142
|
|
|
143
143
|
`createPrismaPlatformStatusSnapshot(...)` and `PrismaService.createPlatformStatusSnapshot()` expose the same lifecycle contract to diagnostics surfaces:
|
|
144
144
|
|
|
145
|
-
- `readiness.status` is `not-ready` while Prisma is shutting down or stopped, and when `strictTransactions` is enabled without `$transaction(...)` support.
|
|
145
|
+
- `readiness.status` is `not-ready` before `onModuleInit()` connects the client, while Prisma is shutting down or stopped, and when `strictTransactions` is enabled without `$transaction(...)` support.
|
|
146
146
|
- `health.status` is `degraded` while request transactions are draining during shutdown and `unhealthy` after disconnect.
|
|
147
147
|
- `details.activeRequestTransactions`, `details.lifecycleState`, `details.strictTransactions`, `details.supportsTransaction`, and `details.transactionAbortSignalSupport` describe the current request transaction and transaction-capability state.
|
|
148
148
|
- `details.transactionContext: 'als'` identifies the async-local transaction context used by request and service transaction boundaries.
|
|
@@ -167,6 +167,8 @@ PrismaModule.forRootAsync({
|
|
|
167
167
|
|
|
168
168
|
Within one compiled application, downstream providers share the same resolved `PrismaService`, ALS transaction context, and lifecycle-managed client. Separate application containers receive independent factory results, so `$connect` / `$disconnect` ownership and request transaction state remain isolated.
|
|
169
169
|
|
|
170
|
+
Transaction boundaries require host-provided `AsyncLocalStorage` support. `@fluojs/prisma` resolves it through `globalThis.AsyncLocalStorage` when a runtime exposes one, or through the host's `process.getBuiltinModule('node:async_hooks')` boundary on Node.js. If neither path is available, `transaction()` and `requestTransaction()` reject before opening a Prisma transaction instead of using a synchronous stack fallback that would lose `current()` across async boundaries; `createPlatformStatusSnapshot().details.transactionContext` reports `unavailable` in that state.
|
|
171
|
+
|
|
170
172
|
### Manual Module Composition
|
|
171
173
|
|
|
172
174
|
Use `PrismaModule.forRoot(...)` / `forRootAsync(...)` to register Prisma. When you need to compose Prisma support inside a custom `defineModule(...)` registration, import the module entrypoint there as well.
|
|
@@ -196,7 +198,8 @@ defineModule(ManualPrismaModule, {
|
|
|
196
198
|
- `forRootAsync(...)` resolves options once per application container, preserving client lifecycle and request transaction isolation across separate bootstraps.
|
|
197
199
|
- Supports `strictTransactions: true` to throw if transaction support is missing.
|
|
198
200
|
- When `strictTransactions` is `false`, PrismaService falls back to direct execution if the client does not expose interactive `$transaction`.
|
|
199
|
-
-
|
|
201
|
+
- `client` must be a concrete object/function handle for both sync and async registration; missing handles are rejected during module registration or async bootstrap.
|
|
202
|
+
- Names are trimmed for named registrations, and blank names are rejected before public tokens are created.
|
|
200
203
|
|
|
201
204
|
### `PrismaService<TClient>`
|
|
202
205
|
|
|
@@ -207,6 +210,10 @@ defineModule(ManualPrismaModule, {
|
|
|
207
210
|
- `requestTransaction(fn, signal?, options?): Promise<T>`
|
|
208
211
|
- Specialized transaction boundary for HTTP request lifecycles. It is abort-aware, drains during shutdown before disconnect, and retries without `signal` when a Prisma client rejects that option. Like `transaction()`, nested calls reuse the active transaction context and reject nested options to avoid silently ignoring transaction settings.
|
|
209
212
|
|
|
213
|
+
### `PrismaTransactionInterceptor`
|
|
214
|
+
|
|
215
|
+
- HTTP interceptor for the default unnamed `PrismaService` registration. It wraps a request handler in `PrismaService.requestTransaction(...)` so downstream `current()` calls share the same transaction client.
|
|
216
|
+
|
|
210
217
|
### `PRISMA_CLIENT` (Token)
|
|
211
218
|
|
|
212
219
|
Injectable token for the raw `PrismaClient` instance.
|
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,EAAU,KAAK,kBAAkB,EAAc,MAAM,cAAc,CAAC;AAE3E,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAShE,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAapB,KAAK,wBAAwB,CAC3B,OAAO,SAAS,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,EACzE,kBAAkB,EAClB,mBAAmB,IACjB,kBAAkB,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG;IACvH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,kBAAkB,EAAc,MAAM,cAAc,CAAC;AAE3E,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAShE,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAapB,KAAK,wBAAwB,CAC3B,OAAO,SAAS,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,EACzE,kBAAkB,EAClB,mBAAmB,IACjB,kBAAkB,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG;IACvH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA0LF;;GAEG;AACH,qBAAa,YAAY;IACvB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CACZ,OAAO,SAAS,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,EACzE,kBAAkB,GAAG,4BAA4B,CAAC,OAAO,CAAC,EAC1D,mBAAmB,GAAG,6BAA6B,CAAC,OAAO,CAAC,EAE5D,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,GAC7E,UAAU;IAIb;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,OAAO,SAAS,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,EACzE,kBAAkB,GAAG,4BAA4B,CAAC,OAAO,CAAC,EAC1D,mBAAmB,GAAG,6BAA6B,CAAC,OAAO,CAAC,EAE5D,OAAO,EAAE,wBAAwB,CAAC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,GAClF,UAAU;CAGd"}
|
package/dist/module.js
CHANGED
|
@@ -4,10 +4,16 @@ import { PrismaService } from './service.js';
|
|
|
4
4
|
import { getPrismaClientToken, getPrismaOptionsToken, getPrismaServiceToken } from './tokens.js';
|
|
5
5
|
import { PrismaTransactionInterceptor } from './transaction.js';
|
|
6
6
|
const PRISMA_NORMALIZED_OPTIONS = Symbol('fluo.prisma.normalized-options');
|
|
7
|
+
function isObjectLike(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null || typeof value === 'function';
|
|
9
|
+
}
|
|
7
10
|
function normalizePrismaRegistrationName(name) {
|
|
8
11
|
if (name === undefined) {
|
|
9
12
|
return undefined;
|
|
10
13
|
}
|
|
14
|
+
if (typeof name !== 'string') {
|
|
15
|
+
throw new Error('PrismaModule name must be a string when provided.');
|
|
16
|
+
}
|
|
11
17
|
const normalizedName = name.trim();
|
|
12
18
|
if (normalizedName.length === 0) {
|
|
13
19
|
throw new Error('PrismaModule name must be a non-empty string when provided.');
|
|
@@ -19,6 +25,9 @@ function getPrismaNormalizedOptionsToken(name) {
|
|
|
19
25
|
return normalizedName === undefined ? PRISMA_NORMALIZED_OPTIONS : Symbol.for(`fluo.prisma.normalized-options:${normalizedName}`);
|
|
20
26
|
}
|
|
21
27
|
function normalizePrismaModuleOptions(options) {
|
|
28
|
+
if (!isObjectLike(options.client)) {
|
|
29
|
+
throw new Error('PrismaModule requires a client option.');
|
|
30
|
+
}
|
|
22
31
|
return {
|
|
23
32
|
name: normalizePrismaRegistrationName(options.name),
|
|
24
33
|
client: options.client,
|
package/dist/service.d.ts
CHANGED
|
@@ -80,6 +80,7 @@ export declare class PrismaService<TClient extends PrismaClientLike<TTransaction
|
|
|
80
80
|
private runWithRequestTransactionClient;
|
|
81
81
|
private runNestedRequestTransaction;
|
|
82
82
|
private assertRequestTransactionsAvailable;
|
|
83
|
+
private assertTransactionContextAvailable;
|
|
83
84
|
private throwIfRequestAborted;
|
|
84
85
|
private runRequestTransactionWithAbortSignal;
|
|
85
86
|
private canAttemptTransactionAbortSignalOption;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK3E,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAQpB,UAAU,oBAAoB;IAC5B,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AA8FD;;;;;;GAMG;AACH,qBACa,aAAa,CACxB,OAAO,SAAS,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,EACzE,kBAAkB,GAAG,4BAA4B,CAAC,OAAO,CAAC,EAC1D,mBAAmB,GAAG,6BAA6B,CAAC,OAAO,CAAC,CAE5D,YAAW,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,EAAE,YAAY,EAAE,qBAAqB;IAQpH,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAPjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuD;IACpF,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAuC;IACjF,OAAO,CAAC,6BAA6B,CAA4C;IACjF,OAAO,CAAC,cAAc,CAAgE;gBAGnE,MAAM,EAAE,OAAO,EACf,cAAc,GAAE,oBAAoD;IAGvF;;;;;;;;;OASG;IACH,OAAO,IAAI,OAAO,GAAG,kBAAkB;YAIzB,wBAAwB;IAyChC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5C;;;;OAIG;IACH,4BAA4B;IAa5B;;;;;;;;;;;;;;;;;OAiBG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAQrF;;;;;;;;;;;;;;;;;;OAkBG;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;YAkCpG,+BAA+B;YAyB/B,2BAA2B;IAqCzC,OAAO,CAAC,kCAAkC;IAM1C,OAAO,CAAC,iCAAiC;IAMzC,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,oCAAoC;IAY5C,OAAO,CAAC,sCAAsC;YAYhC,qCAAqC;IAyBnD,OAAO,CAAC,6BAA6B;IAUrC,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,0BAA0B;IAWlC,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,+BAA+B;CAGxC"}
|
package/dist/service.js
CHANGED
|
@@ -4,14 +4,49 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
4
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
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
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
7
|
import { createAbortError, createRequestAbortContext, raceWithAbort, trackActiveRequestTransaction, untrackActiveRequestTransaction } from '@fluojs/runtime';
|
|
9
8
|
import { Inject } from '@fluojs/core';
|
|
10
9
|
import { createPrismaPlatformStatusSnapshot } from './status.js';
|
|
11
10
|
import { PRISMA_CLIENT, PRISMA_OPTIONS } from './tokens.js';
|
|
12
11
|
const NESTED_TRANSACTION_OPTIONS_NOT_SUPPORTED_ERROR = 'Nested Prisma transaction options are not supported because the active transaction context is reused.';
|
|
13
12
|
const REQUEST_TRANSACTION_UNAVAILABLE_ERROR = 'Prisma request transactions are not available during shutdown.';
|
|
14
|
-
|
|
13
|
+
const TRANSACTION_CONTEXT_UNAVAILABLE_ERROR = 'Prisma transaction context requires AsyncLocalStorage support from the host runtime.';
|
|
14
|
+
class AsyncLocalStorageTransactionContextStore {
|
|
15
|
+
kind = 'als';
|
|
16
|
+
storage;
|
|
17
|
+
constructor(AsyncLocalStorage) {
|
|
18
|
+
this.storage = new AsyncLocalStorage();
|
|
19
|
+
}
|
|
20
|
+
getStore() {
|
|
21
|
+
return this.storage.getStore();
|
|
22
|
+
}
|
|
23
|
+
run(context, callback) {
|
|
24
|
+
return this.storage.run(context, callback);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
class UnavailableTransactionContextStore {
|
|
28
|
+
kind = 'unavailable';
|
|
29
|
+
getStore() {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
run(_context, _callback) {
|
|
33
|
+
throw new Error(TRANSACTION_CONTEXT_UNAVAILABLE_ERROR);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function resolveAsyncLocalStorageConstructor(host = globalThis) {
|
|
37
|
+
if (typeof host.AsyncLocalStorage === 'function') {
|
|
38
|
+
return host.AsyncLocalStorage;
|
|
39
|
+
}
|
|
40
|
+
return host.process?.getBuiltinModule?.('node:async_hooks').AsyncLocalStorage;
|
|
41
|
+
}
|
|
42
|
+
function createTransactionContextStore() {
|
|
43
|
+
const AsyncLocalStorage = resolveAsyncLocalStorageConstructor();
|
|
44
|
+
if (typeof AsyncLocalStorage === 'function') {
|
|
45
|
+
return new AsyncLocalStorageTransactionContextStore(AsyncLocalStorage);
|
|
46
|
+
}
|
|
47
|
+
return new UnavailableTransactionContextStore();
|
|
48
|
+
}
|
|
49
|
+
|
|
15
50
|
/**
|
|
16
51
|
* Prisma runtime facade that owns lifecycle hooks and transaction context access.
|
|
17
52
|
*
|
|
@@ -19,11 +54,12 @@ let _PrismaService;
|
|
|
19
54
|
* @typeParam TTransactionClient Transaction-scoped client resolved inside `$transaction(...)` callbacks.
|
|
20
55
|
* @typeParam TTransactionOptions Options forwarded to Prisma interactive transactions.
|
|
21
56
|
*/
|
|
57
|
+
let _PrismaService;
|
|
22
58
|
class PrismaService {
|
|
23
59
|
static {
|
|
24
60
|
[_PrismaService, _initClass] = _applyDecs(this, [Inject(PRISMA_CLIENT, PRISMA_OPTIONS)], []).c;
|
|
25
61
|
}
|
|
26
|
-
transactions =
|
|
62
|
+
transactions = createTransactionContextStore();
|
|
27
63
|
activeRequestTransactions = new Set();
|
|
28
64
|
transactionAbortSignalSupport = 'unknown';
|
|
29
65
|
lifecycleState = 'created';
|
|
@@ -60,6 +96,7 @@ class PrismaService {
|
|
|
60
96
|
}
|
|
61
97
|
return fn();
|
|
62
98
|
}
|
|
99
|
+
this.assertTransactionContextAvailable();
|
|
63
100
|
const deferredRequestTransactionHandles = new Set();
|
|
64
101
|
try {
|
|
65
102
|
return await run(transactionClient => this.transactions.run({
|
|
@@ -103,7 +140,8 @@ class PrismaService {
|
|
|
103
140
|
supportsConnect: typeof this.client.$connect === 'function',
|
|
104
141
|
supportsDisconnect: typeof this.client.$disconnect === 'function',
|
|
105
142
|
supportsTransaction: typeof this.client.$transaction === 'function',
|
|
106
|
-
transactionAbortSignalSupport: this.transactionAbortSignalSupport
|
|
143
|
+
transactionAbortSignalSupport: this.transactionAbortSignalSupport,
|
|
144
|
+
transactionContext: this.transactions.kind
|
|
107
145
|
});
|
|
108
146
|
}
|
|
109
147
|
|
|
@@ -175,6 +213,7 @@ class PrismaService {
|
|
|
175
213
|
}
|
|
176
214
|
return fn();
|
|
177
215
|
}
|
|
216
|
+
this.assertTransactionContextAvailable();
|
|
178
217
|
return run(transactionClient => this.transactions.run({
|
|
179
218
|
client: transactionClient,
|
|
180
219
|
requestAbortSignal: signal
|
|
@@ -210,6 +249,11 @@ class PrismaService {
|
|
|
210
249
|
throw new Error(REQUEST_TRANSACTION_UNAVAILABLE_ERROR);
|
|
211
250
|
}
|
|
212
251
|
}
|
|
252
|
+
assertTransactionContextAvailable() {
|
|
253
|
+
if (this.transactions.kind === 'unavailable') {
|
|
254
|
+
throw new Error(TRANSACTION_CONTEXT_UNAVAILABLE_ERROR);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
213
257
|
throwIfRequestAborted(signal) {
|
|
214
258
|
if (signal.aborted) {
|
|
215
259
|
throw createAbortError(signal.reason);
|
package/dist/status.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ type PrismaPlatformStatusSnapshotInput = {
|
|
|
8
8
|
supportsDisconnect: boolean;
|
|
9
9
|
supportsTransaction: boolean;
|
|
10
10
|
transactionAbortSignalSupport: 'unknown' | 'supported' | 'unsupported';
|
|
11
|
+
transactionContext?: 'als' | 'unavailable';
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* Create prisma platform status snapshot.
|
package/dist/status.d.ts.map
CHANGED
|
@@ -1 +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,4BAA4B,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;AAEtF,KAAK,iCAAiC,GAAG;IACvC,yBAAyB,EAAE,MAAM,CAAC;IAClC,cAAc,EAAE,4BAA4B,CAAC;IAC7C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,6BAA6B,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;
|
|
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,4BAA4B,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;AAEtF,KAAK,iCAAiC,GAAG;IACvC,yBAAyB,EAAE,MAAM,CAAC;IAClC,cAAc,EAAE,4BAA4B,CAAC;IAC7C,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,6BAA6B,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IACvE,kBAAkB,CAAC,EAAE,KAAK,GAAG,aAAa,CAAC;CAC5C,CAAC;AAqEF;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,iCAAiC,GACvC,iCAAiC,CAqBnC"}
|
package/dist/status.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
function createReadiness(input) {
|
|
2
|
+
if (input.lifecycleState === 'created') {
|
|
3
|
+
return {
|
|
4
|
+
critical: true,
|
|
5
|
+
reason: 'Prisma integration has not connected yet.',
|
|
6
|
+
status: 'not-ready'
|
|
7
|
+
};
|
|
8
|
+
}
|
|
2
9
|
if (input.lifecycleState === 'shutting-down') {
|
|
3
10
|
return {
|
|
4
11
|
critical: true,
|
|
@@ -20,6 +27,13 @@ function createReadiness(input) {
|
|
|
20
27
|
status: 'not-ready'
|
|
21
28
|
};
|
|
22
29
|
}
|
|
30
|
+
if (input.supportsTransaction && input.transactionContext === 'unavailable') {
|
|
31
|
+
return {
|
|
32
|
+
critical: true,
|
|
33
|
+
reason: 'Prisma transaction context requires AsyncLocalStorage support from the host runtime.',
|
|
34
|
+
status: 'not-ready'
|
|
35
|
+
};
|
|
36
|
+
}
|
|
23
37
|
return {
|
|
24
38
|
critical: true,
|
|
25
39
|
status: 'ready'
|
|
@@ -50,6 +64,7 @@ function createHealth(input) {
|
|
|
50
64
|
* @returns The create prisma platform status snapshot result.
|
|
51
65
|
*/
|
|
52
66
|
export function createPrismaPlatformStatusSnapshot(input) {
|
|
67
|
+
const transactionContext = input.transactionContext ?? 'als';
|
|
53
68
|
return {
|
|
54
69
|
details: {
|
|
55
70
|
activeRequestTransactions: input.activeRequestTransactions,
|
|
@@ -59,7 +74,7 @@ export function createPrismaPlatformStatusSnapshot(input) {
|
|
|
59
74
|
supportsDisconnect: input.supportsDisconnect,
|
|
60
75
|
supportsTransaction: input.supportsTransaction,
|
|
61
76
|
transactionAbortSignalSupport: input.transactionAbortSignalSupport,
|
|
62
|
-
transactionContext
|
|
77
|
+
transactionContext
|
|
63
78
|
},
|
|
64
79
|
health: createHealth(input),
|
|
65
80
|
ownership: {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"transaction",
|
|
10
10
|
"als"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.
|
|
12
|
+
"version": "1.0.2",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,11 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.
|
|
40
|
-
"@fluojs/
|
|
41
|
-
"@fluojs/
|
|
42
|
-
"@fluojs/
|
|
43
|
-
"@fluojs/runtime": "^1.0.0"
|
|
39
|
+
"@fluojs/core": "^1.0.3",
|
|
40
|
+
"@fluojs/http": "^1.1.0",
|
|
41
|
+
"@fluojs/di": "^1.0.3",
|
|
42
|
+
"@fluojs/runtime": "^1.1.2"
|
|
44
43
|
},
|
|
45
44
|
"peerDependencies": {
|
|
46
45
|
"@prisma/client": ">=5.0.0"
|
|
@@ -51,7 +50,8 @@
|
|
|
51
50
|
}
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
|
-
"vitest": "^3.2.4"
|
|
53
|
+
"vitest": "^3.2.4",
|
|
54
|
+
"@fluojs/validation": "^1.0.5"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|