@btravstack/prisma 0.5.0 → 0.6.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.md +1 -0
- package/dist/index.cjs +32 -11
- package/dist/index.d.cts +12 -7
- package/dist/index.d.mts +12 -7
- package/dist/index.mjs +34 -13
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ import { PrismaPg } from "@prisma/adapter-pg";
|
|
|
32
32
|
declare class PrismaClient {
|
|
33
33
|
constructor(options: { readonly adapter: PrismaPg });
|
|
34
34
|
$disconnect(): Promise<void>;
|
|
35
|
+
$queryRaw(query: TemplateStringsArray, ...values: unknown[]): Promise<unknown>;
|
|
35
36
|
$extends(extension: unknown): this;
|
|
36
37
|
}
|
|
37
38
|
declare const unthrownPrisma: unknown;
|
package/dist/index.cjs
CHANGED
|
@@ -60,7 +60,12 @@ const instrument = (client, logger, meter) => {
|
|
|
60
60
|
/** Injected so a spec can drive the arm where the optional peer is absent. */
|
|
61
61
|
const defaultLoader = async () => (await import("@prisma/instrumentation")).PrismaInstrumentation;
|
|
62
62
|
/**
|
|
63
|
-
* Prisma's own OpenTelemetry instrumentation,
|
|
63
|
+
* Prisma's own OpenTelemetry instrumentation, loaded if it is installed.
|
|
64
|
+
*
|
|
65
|
+
* Handed to `@btravstack/observability/otel` through the `Instrumentations`
|
|
66
|
+
* set port rather than registered here: a graph with no SDK collects nothing
|
|
67
|
+
* and this is never called, so engine tracing follows from composing `otel()`
|
|
68
|
+
* instead of from importing this package.
|
|
64
69
|
*
|
|
65
70
|
* **A dynamic import, and it has to be**: `@prisma/instrumentation` is an
|
|
66
71
|
* OPTIONAL peer, so a static import would make every consumer install it. The
|
|
@@ -79,7 +84,7 @@ const defaultLoader = async () => (await import("@prisma/instrumentation")).Pris
|
|
|
79
84
|
* is worse than none, so the one path that quietly produces no spans says so at
|
|
80
85
|
* `debug` — the level for something that is a choice rather than a fault.
|
|
81
86
|
*/
|
|
82
|
-
const
|
|
87
|
+
const loadPrismaInstrumentation = async (logger, load = defaultLoader) => {
|
|
83
88
|
try {
|
|
84
89
|
const instrumentation = new (await (load()))();
|
|
85
90
|
instrumentation.enable();
|
|
@@ -117,11 +122,10 @@ const prismaDatabase = (name) => ({ client, instrumented }) => {
|
|
|
117
122
|
const instrumentedProvider = (0, _btravstack_di.Provider)(port)({
|
|
118
123
|
settings: config.port,
|
|
119
124
|
logger: _btravstack_core.Logger,
|
|
120
|
-
tracer: _btravstack_core.Tracer,
|
|
121
125
|
meter: _btravstack_core.Meter
|
|
122
126
|
}, {
|
|
123
|
-
acquire: ({ settings, logger,
|
|
124
|
-
return (0, unthrown.fromSafePromise)(
|
|
127
|
+
acquire: ({ settings, logger, meter }) => {
|
|
128
|
+
return (0, unthrown.fromSafePromise)(Promise.resolve(instrument(open(settings.url), logger, meter)));
|
|
125
129
|
},
|
|
126
130
|
release: (db) => db.$disconnect()
|
|
127
131
|
});
|
|
@@ -129,20 +133,37 @@ const prismaDatabase = (name) => ({ client, instrumented }) => {
|
|
|
129
133
|
acquire: ({ settings }) => (0, unthrown.OkAsync)(open(settings.url)),
|
|
130
134
|
release: (db) => db.$disconnect()
|
|
131
135
|
});
|
|
136
|
+
const healthCheck = _btravstack_di.Provider.member(_btravstack_core.HealthChecks)({ db: port }, { sync: ({ db }) => ({
|
|
137
|
+
name,
|
|
138
|
+
check: () => (0, unthrown.fromPromise)(db.$queryRaw`SELECT 1`, (cause) => new _btravstack_core.HealthCheckFailed({ reason: cause instanceof Error ? cause.message : "database unreachable" })).map(() => void 0)
|
|
139
|
+
}) });
|
|
140
|
+
const instrumentation = _btravstack_di.Provider.member(_btravstack_core.Instrumentations)({ logger: _btravstack_core.Logger }, { sync: ({ logger }) => () => loadPrismaInstrumentation(logger) });
|
|
132
141
|
const instrumentedModule = (0, _btravstack_di.Module)(name)({
|
|
133
142
|
needs: [
|
|
134
143
|
_btravstack_config.Env,
|
|
135
144
|
_btravstack_core.Logger,
|
|
136
|
-
_btravstack_core.Meter
|
|
137
|
-
|
|
145
|
+
_btravstack_core.Meter
|
|
146
|
+
],
|
|
147
|
+
provides: [
|
|
148
|
+
config,
|
|
149
|
+
instrumentedProvider,
|
|
150
|
+
healthCheck,
|
|
151
|
+
instrumentation
|
|
138
152
|
],
|
|
139
|
-
|
|
140
|
-
|
|
153
|
+
exports: [
|
|
154
|
+
DatabasePort,
|
|
155
|
+
_btravstack_core.HealthChecks,
|
|
156
|
+
_btravstack_core.Instrumentations
|
|
157
|
+
]
|
|
141
158
|
});
|
|
142
159
|
const plainModule = (0, _btravstack_di.Module)(name)({
|
|
143
160
|
needs: [_btravstack_config.Env],
|
|
144
|
-
provides: [
|
|
145
|
-
|
|
161
|
+
provides: [
|
|
162
|
+
config,
|
|
163
|
+
plainProvider,
|
|
164
|
+
healthCheck
|
|
165
|
+
],
|
|
166
|
+
exports: [DatabasePort, _btravstack_core.HealthChecks]
|
|
146
167
|
});
|
|
147
168
|
return Object.assign(instrumented !== false ? instrumentedModule : plainModule, { port: DatabasePort });
|
|
148
169
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Env } from "@btravstack/config";
|
|
2
|
-
import { Logger, Meter
|
|
2
|
+
import { HealthChecks, Instrumentations, Logger, Meter } from "@btravstack/core";
|
|
3
3
|
import { Module, PortClassOf } from "@btravstack/di";
|
|
4
4
|
import { PrismaPg } from "@prisma/adapter-pg";
|
|
5
5
|
//#region src/prisma.d.ts
|
|
@@ -11,6 +11,13 @@ import { PrismaPg } from "@prisma/adapter-pg";
|
|
|
11
11
|
*/
|
|
12
12
|
type PrismaLike = {
|
|
13
13
|
readonly $disconnect: () => Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* What the health check asks. Part of the contract rather than optional
|
|
16
|
+
* because every generated Prisma client has it, and a probe that has to
|
|
17
|
+
* feature-detect its own client cannot report the difference between "the
|
|
18
|
+
* database is down" and "this client cannot be asked".
|
|
19
|
+
*/
|
|
20
|
+
readonly $queryRaw: (query: TemplateStringsArray, ...values: unknown[]) => Promise<unknown>;
|
|
14
21
|
};
|
|
15
22
|
/** What {@link prismaDatabase} is handed. */
|
|
16
23
|
type PrismaOptions<C extends PrismaLike, Instrumented extends boolean> = {
|
|
@@ -56,15 +63,13 @@ type PrismaOptions<C extends PrismaLike, Instrumented extends boolean> = {
|
|
|
56
63
|
* against this same URL *before the process starts*; an application that
|
|
57
64
|
* migrates itself at boot races every other replica.
|
|
58
65
|
*/
|
|
59
|
-
declare const prismaDatabase: <const N extends string>(name: N) => <C extends PrismaLike, Instrumented extends boolean = true>({ client, instrumented }: PrismaOptions<C, Instrumented>) => (Instrumented extends true ? Module<PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never, import("@btravstack/config").ConfigInvalid, Exclude<Env, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
60
|
-
readonly url: string;
|
|
61
|
-
}>> | Exclude<Logger, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
66
|
+
declare const prismaDatabase: <const N extends string>(name: N) => <C extends PrismaLike, Instrumented extends boolean = true>({ client, instrumented }: PrismaOptions<C, Instrumented>) => (Instrumented extends true ? Module<HealthChecks | Instrumentations | (PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never), import("@btravstack/config").ConfigInvalid, Exclude<Env, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
62
67
|
readonly url: string;
|
|
63
|
-
}>> | Exclude<
|
|
68
|
+
}>> | Exclude<Logger, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
64
69
|
readonly url: string;
|
|
65
|
-
}>> | Exclude<
|
|
70
|
+
}>> | Exclude<Meter, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
66
71
|
readonly url: string;
|
|
67
|
-
}>>> : Module<PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never, import("@btravstack/config").ConfigInvalid, Exclude<Env, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
72
|
+
}>>> : Module<HealthChecks | (PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never), import("@btravstack/config").ConfigInvalid, Exclude<Env, HealthChecks | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
68
73
|
readonly url: string;
|
|
69
74
|
}>>>) & {
|
|
70
75
|
readonly port: PortClassOf<N, C>;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Env } from "@btravstack/config";
|
|
2
|
-
import { Logger, Meter
|
|
2
|
+
import { HealthChecks, Instrumentations, Logger, Meter } from "@btravstack/core";
|
|
3
3
|
import { Module, PortClassOf } from "@btravstack/di";
|
|
4
4
|
import { PrismaPg } from "@prisma/adapter-pg";
|
|
5
5
|
//#region src/prisma.d.ts
|
|
@@ -11,6 +11,13 @@ import { PrismaPg } from "@prisma/adapter-pg";
|
|
|
11
11
|
*/
|
|
12
12
|
type PrismaLike = {
|
|
13
13
|
readonly $disconnect: () => Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* What the health check asks. Part of the contract rather than optional
|
|
16
|
+
* because every generated Prisma client has it, and a probe that has to
|
|
17
|
+
* feature-detect its own client cannot report the difference between "the
|
|
18
|
+
* database is down" and "this client cannot be asked".
|
|
19
|
+
*/
|
|
20
|
+
readonly $queryRaw: (query: TemplateStringsArray, ...values: unknown[]) => Promise<unknown>;
|
|
14
21
|
};
|
|
15
22
|
/** What {@link prismaDatabase} is handed. */
|
|
16
23
|
type PrismaOptions<C extends PrismaLike, Instrumented extends boolean> = {
|
|
@@ -56,15 +63,13 @@ type PrismaOptions<C extends PrismaLike, Instrumented extends boolean> = {
|
|
|
56
63
|
* against this same URL *before the process starts*; an application that
|
|
57
64
|
* migrates itself at boot races every other replica.
|
|
58
65
|
*/
|
|
59
|
-
declare const prismaDatabase: <const N extends string>(name: N) => <C extends PrismaLike, Instrumented extends boolean = true>({ client, instrumented }: PrismaOptions<C, Instrumented>) => (Instrumented extends true ? Module<PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never, import("@btravstack/config").ConfigInvalid, Exclude<Env, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
60
|
-
readonly url: string;
|
|
61
|
-
}>> | Exclude<Logger, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
66
|
+
declare const prismaDatabase: <const N extends string>(name: N) => <C extends PrismaLike, Instrumented extends boolean = true>({ client, instrumented }: PrismaOptions<C, Instrumented>) => (Instrumented extends true ? Module<HealthChecks | Instrumentations | (PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never), import("@btravstack/config").ConfigInvalid, Exclude<Env, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
62
67
|
readonly url: string;
|
|
63
|
-
}>> | Exclude<
|
|
68
|
+
}>> | Exclude<Logger, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
64
69
|
readonly url: string;
|
|
65
|
-
}>> | Exclude<
|
|
70
|
+
}>> | Exclude<Meter, HealthChecks | Instrumentations | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
66
71
|
readonly url: string;
|
|
67
|
-
}>>> : Module<PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never, import("@btravstack/config").ConfigInvalid, Exclude<Env, import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
72
|
+
}>>> : Module<HealthChecks | (PortClassOf<N, C> extends (infer T) ? T extends PortClassOf<N, C> ? T extends import("@btravstack/di").AnyPort ? InstanceType<T> : T extends import("@btravstack/di").AnyProvider ? InstanceType<T["port"]> : never : never : never), import("@btravstack/config").ConfigInvalid, Exclude<Env, HealthChecks | import("@btravstack/di").PortInstance<string, C> | import("@btravstack/di").PortInstance<`${N}Config`, {
|
|
68
73
|
readonly url: string;
|
|
69
74
|
}>>>) & {
|
|
70
75
|
readonly port: PortClassOf<N, C>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Config, Env } from "@btravstack/config";
|
|
2
|
-
import { Logger, Meter
|
|
2
|
+
import { HealthCheckFailed, HealthChecks, Instrumentations, Logger, Meter } from "@btravstack/core";
|
|
3
3
|
import { Module, Port, Provider } from "@btravstack/di";
|
|
4
4
|
import { PrismaPg } from "@prisma/adapter-pg";
|
|
5
|
-
import { OkAsync, fromSafePromise } from "unthrown";
|
|
5
|
+
import { OkAsync, fromPromise, fromSafePromise } from "unthrown";
|
|
6
6
|
//#region src/instrument.ts
|
|
7
7
|
/**
|
|
8
8
|
* Every query, wrapped: a span around it, a count of how it came out, and a log
|
|
@@ -59,7 +59,12 @@ const instrument = (client, logger, meter) => {
|
|
|
59
59
|
/** Injected so a spec can drive the arm where the optional peer is absent. */
|
|
60
60
|
const defaultLoader = async () => (await import("@prisma/instrumentation")).PrismaInstrumentation;
|
|
61
61
|
/**
|
|
62
|
-
* Prisma's own OpenTelemetry instrumentation,
|
|
62
|
+
* Prisma's own OpenTelemetry instrumentation, loaded if it is installed.
|
|
63
|
+
*
|
|
64
|
+
* Handed to `@btravstack/observability/otel` through the `Instrumentations`
|
|
65
|
+
* set port rather than registered here: a graph with no SDK collects nothing
|
|
66
|
+
* and this is never called, so engine tracing follows from composing `otel()`
|
|
67
|
+
* instead of from importing this package.
|
|
63
68
|
*
|
|
64
69
|
* **A dynamic import, and it has to be**: `@prisma/instrumentation` is an
|
|
65
70
|
* OPTIONAL peer, so a static import would make every consumer install it. The
|
|
@@ -78,7 +83,7 @@ const defaultLoader = async () => (await import("@prisma/instrumentation")).Pris
|
|
|
78
83
|
* is worse than none, so the one path that quietly produces no spans says so at
|
|
79
84
|
* `debug` — the level for something that is a choice rather than a fault.
|
|
80
85
|
*/
|
|
81
|
-
const
|
|
86
|
+
const loadPrismaInstrumentation = async (logger, load = defaultLoader) => {
|
|
82
87
|
try {
|
|
83
88
|
const instrumentation = new (await (load()))();
|
|
84
89
|
instrumentation.enable();
|
|
@@ -116,11 +121,10 @@ const prismaDatabase = (name) => ({ client, instrumented }) => {
|
|
|
116
121
|
const instrumentedProvider = Provider(port)({
|
|
117
122
|
settings: config.port,
|
|
118
123
|
logger: Logger,
|
|
119
|
-
tracer: Tracer,
|
|
120
124
|
meter: Meter
|
|
121
125
|
}, {
|
|
122
|
-
acquire: ({ settings, logger,
|
|
123
|
-
return fromSafePromise(
|
|
126
|
+
acquire: ({ settings, logger, meter }) => {
|
|
127
|
+
return fromSafePromise(Promise.resolve(instrument(open(settings.url), logger, meter)));
|
|
124
128
|
},
|
|
125
129
|
release: (db) => db.$disconnect()
|
|
126
130
|
});
|
|
@@ -128,20 +132,37 @@ const prismaDatabase = (name) => ({ client, instrumented }) => {
|
|
|
128
132
|
acquire: ({ settings }) => OkAsync(open(settings.url)),
|
|
129
133
|
release: (db) => db.$disconnect()
|
|
130
134
|
});
|
|
135
|
+
const healthCheck = Provider.member(HealthChecks)({ db: port }, { sync: ({ db }) => ({
|
|
136
|
+
name,
|
|
137
|
+
check: () => fromPromise(db.$queryRaw`SELECT 1`, (cause) => new HealthCheckFailed({ reason: cause instanceof Error ? cause.message : "database unreachable" })).map(() => void 0)
|
|
138
|
+
}) });
|
|
139
|
+
const instrumentation = Provider.member(Instrumentations)({ logger: Logger }, { sync: ({ logger }) => () => loadPrismaInstrumentation(logger) });
|
|
131
140
|
const instrumentedModule = Module(name)({
|
|
132
141
|
needs: [
|
|
133
142
|
Env,
|
|
134
143
|
Logger,
|
|
135
|
-
Meter
|
|
136
|
-
|
|
144
|
+
Meter
|
|
145
|
+
],
|
|
146
|
+
provides: [
|
|
147
|
+
config,
|
|
148
|
+
instrumentedProvider,
|
|
149
|
+
healthCheck,
|
|
150
|
+
instrumentation
|
|
137
151
|
],
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
exports: [
|
|
153
|
+
DatabasePort,
|
|
154
|
+
HealthChecks,
|
|
155
|
+
Instrumentations
|
|
156
|
+
]
|
|
140
157
|
});
|
|
141
158
|
const plainModule = Module(name)({
|
|
142
159
|
needs: [Env],
|
|
143
|
-
provides: [
|
|
144
|
-
|
|
160
|
+
provides: [
|
|
161
|
+
config,
|
|
162
|
+
plainProvider,
|
|
163
|
+
healthCheck
|
|
164
|
+
],
|
|
165
|
+
exports: [DatabasePort, HealthChecks]
|
|
145
166
|
});
|
|
146
167
|
return Object.assign(instrumented !== false ? instrumentedModule : plainModule, { port: DatabasePort });
|
|
147
168
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btravstack/prisma",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "The Prisma starter for @btravstack/core: DATABASE_URL through Config, the Postgres driver adapter, and a client whose pool is the application scope's",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"typescript": "7.0.2",
|
|
54
54
|
"unthrown": "5.7.0",
|
|
55
55
|
"vitest": "4.1.11",
|
|
56
|
-
"@btravstack/config": "0.
|
|
57
|
-
"@btravstack/core": "0.
|
|
58
|
-
"@btravstack/di": "0.
|
|
56
|
+
"@btravstack/config": "0.6.0",
|
|
57
|
+
"@btravstack/core": "0.6.0",
|
|
58
|
+
"@btravstack/di": "0.6.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@prisma/adapter-pg": "^7.0.0",
|
|
62
62
|
"@prisma/instrumentation": "^7.0.0",
|
|
63
63
|
"unthrown": "^5.0.0",
|
|
64
|
-
"@btravstack/config": "^0.
|
|
65
|
-
"@btravstack/core": "^0.
|
|
66
|
-
"@btravstack/di": "^0.
|
|
64
|
+
"@btravstack/config": "^0.6.0",
|
|
65
|
+
"@btravstack/core": "^0.6.0",
|
|
66
|
+
"@btravstack/di": "^0.6.0"
|
|
67
67
|
},
|
|
68
68
|
"peerDependenciesMeta": {
|
|
69
69
|
"@prisma/instrumentation": {
|