@prisma/dev 0.24.16 → 0.25.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 +346 -0
- package/dist/chunk-J6FIMHSD.js +1 -0
- package/dist/chunk-MD3K2IUP.js +1 -0
- package/dist/daemon.cjs +13 -13
- package/dist/daemon.d.cts +9 -1
- package/dist/daemon.d.ts +9 -1
- package/dist/daemon.js +1 -1
- package/dist/index.cjs +20 -20
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +1 -1
- package/dist/vite.cjs +121 -0
- package/dist/vite.d.cts +206 -0
- package/dist/vite.d.ts +204 -0
- package/dist/vite.js +1 -0
- package/package.json +21 -2
- package/dist/chunk-FB4QA6EA.js +0 -1
- /package/dist/{accelerate-45DUGMGZ.js → accelerate-TRR43YJ5.js} +0 -0
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
import { P as PersistenceMode } from './state-CNKFAMiX.js';
|
|
3
|
+
import 'valibot';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Names of the environment variables the plugin writes.
|
|
7
|
+
*
|
|
8
|
+
* Set an entry to `false` to skip that variable, or to a string to rename it.
|
|
9
|
+
*/
|
|
10
|
+
interface PrismaDevEnvOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Direct TCP connection string for the main database.
|
|
13
|
+
*
|
|
14
|
+
* Defaults to `DATABASE_URL`.
|
|
15
|
+
*/
|
|
16
|
+
databaseUrl?: false | string;
|
|
17
|
+
/**
|
|
18
|
+
* The `prisma+postgres://` HTTP connection string, matching how a deployed
|
|
19
|
+
* Prisma Postgres database is addressed.
|
|
20
|
+
*
|
|
21
|
+
* Disabled by default, because it embeds an API key. Set a name to opt in.
|
|
22
|
+
*/
|
|
23
|
+
prismaPostgresUrl?: false | string;
|
|
24
|
+
/**
|
|
25
|
+
* Direct TCP connection string for the shadow database, used by
|
|
26
|
+
* `prisma migrate`.
|
|
27
|
+
*
|
|
28
|
+
* Defaults to `SHADOW_DATABASE_URL`.
|
|
29
|
+
*/
|
|
30
|
+
shadowDatabaseUrl?: false | string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The running database, handed to {@link PrismaDevPluginOptions.onDatabaseReady}.
|
|
35
|
+
*/
|
|
36
|
+
interface PrismaDevDatabase {
|
|
37
|
+
/**
|
|
38
|
+
* Direct TCP connection string for the main database.
|
|
39
|
+
*/
|
|
40
|
+
readonly databaseUrl: string;
|
|
41
|
+
/**
|
|
42
|
+
* The variables this plugin manages, mapped to the local database, ready to
|
|
43
|
+
* spread into a subprocess environment.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* await execa("prisma", ["migrate", "deploy"], { env: { ...process.env, ...database.env } });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* Variables disabled through the `env` option are absent here.
|
|
50
|
+
*/
|
|
51
|
+
readonly env: Readonly<Record<string, string>>;
|
|
52
|
+
/**
|
|
53
|
+
* The server name, matching the `name` option.
|
|
54
|
+
*/
|
|
55
|
+
readonly name: string;
|
|
56
|
+
/**
|
|
57
|
+
* Whether this process started the database, as opposed to attaching to one
|
|
58
|
+
* that `prisma dev` was already running.
|
|
59
|
+
*/
|
|
60
|
+
readonly owned: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* The `prisma+postgres://` HTTP connection string. Carries an API key.
|
|
63
|
+
*/
|
|
64
|
+
readonly prismaPostgresUrl: string;
|
|
65
|
+
/**
|
|
66
|
+
* Direct TCP connection string for the shadow database, which
|
|
67
|
+
* `prisma migrate dev` requires.
|
|
68
|
+
*/
|
|
69
|
+
readonly shadowDatabaseUrl: string;
|
|
70
|
+
}
|
|
71
|
+
interface PrismaDevPluginOptions {
|
|
72
|
+
/**
|
|
73
|
+
* The port the database server listens on.
|
|
74
|
+
*
|
|
75
|
+
* Defaults to `51214`. Only the default falls back to another free port when
|
|
76
|
+
* taken; a port passed here is bound or the start fails, because a caller who
|
|
77
|
+
* names a port has something outside this process depending on it.
|
|
78
|
+
*
|
|
79
|
+
* A named `stateful` server records the ports it settled on and reuses them on
|
|
80
|
+
* the next start, so pinning is not required for a stable address.
|
|
81
|
+
*/
|
|
82
|
+
databasePort?: number;
|
|
83
|
+
/**
|
|
84
|
+
* Whether to log the runtime's own debug output.
|
|
85
|
+
*
|
|
86
|
+
* Defaults to `false`.
|
|
87
|
+
*/
|
|
88
|
+
debug?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Which environment variables to write, and under what names.
|
|
91
|
+
*
|
|
92
|
+
* The plugin owns the variables named here and overwrites whatever the
|
|
93
|
+
* environment already holds, warning when it displaces a different value. Set
|
|
94
|
+
* an entry to `false` to keep your own value for that variable.
|
|
95
|
+
*/
|
|
96
|
+
env?: PrismaDevEnvOptions;
|
|
97
|
+
/**
|
|
98
|
+
* Name of the server, which determines where its data is persisted.
|
|
99
|
+
*
|
|
100
|
+
* Defaults to `default`. Set this per project to keep data isolated.
|
|
101
|
+
*/
|
|
102
|
+
name?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Prepares the database before Vite finishes starting, typically by applying
|
|
105
|
+
* migrations and seeding.
|
|
106
|
+
*
|
|
107
|
+
* Runs after the environment variables have been written, and before any
|
|
108
|
+
* application or framework code has executed, so nothing can observe an
|
|
109
|
+
* unprepared database. `vite dev` waits for it, so a slow migration delays
|
|
110
|
+
* startup.
|
|
111
|
+
*
|
|
112
|
+
* Runs once per database, not once per dev server. A config restart that does
|
|
113
|
+
* not change this plugin's options keeps the running database, and so does not
|
|
114
|
+
* re-run this hook. It does run when the plugin attached to a database
|
|
115
|
+
* `prisma dev` already had running. Make it idempotent -- `prisma migrate
|
|
116
|
+
* deploy` already is.
|
|
117
|
+
*
|
|
118
|
+
* If it rejects, the database is shut down and Vite fails to start rather than
|
|
119
|
+
* serving against a half-prepared database.
|
|
120
|
+
*
|
|
121
|
+
* Prefer `database.env` over the ambient `process.env` when spawning a
|
|
122
|
+
* subprocess. See {@link PrismaDevDatabase.env} for why.
|
|
123
|
+
*/
|
|
124
|
+
onDatabaseReady?: (this: void, database: PrismaDevDatabase) => Promise<void> | void;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the database survives between runs.
|
|
127
|
+
*
|
|
128
|
+
* Defaults to `stateful`: data is persisted under `name` and survives dev
|
|
129
|
+
* server restarts.
|
|
130
|
+
*
|
|
131
|
+
* `stateless` keeps the database in memory and discards it on every shutdown,
|
|
132
|
+
* which gives a clean database on each start. Useful under `test`. Be aware
|
|
133
|
+
* that editing `vite.config.ts` or an `.env` file restarts the dev server, so
|
|
134
|
+
* it also discards the data.
|
|
135
|
+
*
|
|
136
|
+
* A `stateless` database is invisible to `prisma dev ls`, cannot be shared with
|
|
137
|
+
* a running `prisma dev`, and takes any free port rather than the documented
|
|
138
|
+
* defaults unless you set the port options explicitly.
|
|
139
|
+
*/
|
|
140
|
+
persistenceMode?: PersistenceMode;
|
|
141
|
+
/**
|
|
142
|
+
* The port the Prisma Dev HTTP server listens on.
|
|
143
|
+
*
|
|
144
|
+
* Defaults to `51213`. See {@link databasePort} for how an explicitly
|
|
145
|
+
* requested port differs from the default.
|
|
146
|
+
*/
|
|
147
|
+
port?: number;
|
|
148
|
+
/**
|
|
149
|
+
* The port the shadow database server listens on.
|
|
150
|
+
*
|
|
151
|
+
* Defaults to `51215`. See {@link databasePort} for how an explicitly
|
|
152
|
+
* requested port differs from the default.
|
|
153
|
+
*/
|
|
154
|
+
shadowDatabasePort?: number;
|
|
155
|
+
/**
|
|
156
|
+
* The port the colocated Prisma Streams server listens on.
|
|
157
|
+
*
|
|
158
|
+
* Defaults to `51216`. See {@link databasePort} for how an explicitly
|
|
159
|
+
* requested port differs from the default.
|
|
160
|
+
*/
|
|
161
|
+
streamsPort?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Options to use when Vitest loaded the config, layered over the options here.
|
|
164
|
+
*
|
|
165
|
+
* Defaults to `false`, which starts no database under Vitest. Vitest reads the
|
|
166
|
+
* same `vite.config.ts`, so an opt-in keeps a plain test run from starting a
|
|
167
|
+
* database as a config side effect.
|
|
168
|
+
*
|
|
169
|
+
* Set it to an object to opt in. Each entry replaces the corresponding option
|
|
170
|
+
* above, which is how a test run gets its own database rather than sharing the
|
|
171
|
+
* one `vite dev` uses:
|
|
172
|
+
*
|
|
173
|
+
* ```ts
|
|
174
|
+
* prismaDev({
|
|
175
|
+
* name: "my-app",
|
|
176
|
+
* test: { name: "my-app-test", persistenceMode: "stateless" },
|
|
177
|
+
* });
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* `test: {}` opts in with the options above unchanged.
|
|
181
|
+
*/
|
|
182
|
+
test?: false | PrismaDevTestOptions;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The options {@link PrismaDevPluginOptions.test} may override.
|
|
186
|
+
*
|
|
187
|
+
* Every plugin option except `test` itself, so the override cannot nest.
|
|
188
|
+
*/
|
|
189
|
+
type PrismaDevTestOptions = Omit<PrismaDevPluginOptions, "test">;
|
|
190
|
+
/**
|
|
191
|
+
* Runs a local Prisma Postgres database for the lifetime of the Vite dev server
|
|
192
|
+
* and exposes its connection strings through `process.env`.
|
|
193
|
+
*
|
|
194
|
+
* The database runs in the Vite process, so it cannot outlive it. Production
|
|
195
|
+
* builds and `vite preview` are unaffected.
|
|
196
|
+
*
|
|
197
|
+
* Connection strings are never exposed to client code. They are written to
|
|
198
|
+
* `process.env` only, which is what server-side code and Prisma Client read.
|
|
199
|
+
* Routing them through `define` or `import.meta.env` would inline database
|
|
200
|
+
* credentials into browser assets.
|
|
201
|
+
*/
|
|
202
|
+
declare function prismaDev(options?: PrismaDevPluginOptions): Plugin;
|
|
203
|
+
|
|
204
|
+
export { type PrismaDevDatabase, type PrismaDevEnvOptions, type PrismaDevPluginOptions, type PrismaDevTestOptions, prismaDev as default, prismaDev };
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as P,b as u}from"./chunk-J6FIMHSD.js";import"./chunk-662IKR3V.js";import"./chunk-PP43TGA5.js";import"./chunk-KWCQYPJI.js";import{h as y,i as S,l as E}from"./chunk-HFONW2ZS.js";import"./chunk-ANHBRJRZ.js";import"./chunk-EDFHV3AK.js";import"./chunk-DWY47FQV.js";import"./chunk-DOJAPHLY.js";var L="DATABASE_URL",q="SHADOW_DATABASE_URL";function w(e,r={}){let{databaseUrl:t=L,prismaPostgresUrl:n=!1,shadowDatabaseUrl:s=q}=r,a=u(e);return[["databaseUrl",t,a.databaseUrl],["shadowDatabaseUrl",s,a.shadowDatabaseUrl],["prismaPostgresUrl",n,a.prismaPostgresUrl]].filter(i=>typeof i[1]=="string"&&i[1].length>0).map(([i,l,d])=>({key:i,name:l,value:d}))}function A(e,r){let t=[];for(let n of e){let s=r[n.name];s!==n.value&&(s!=null&&s!==""&&t.push({...n,previous:s}),r[n.name]=n.value)}return t}import{setTimeout as k}from"timers/promises";var N="default",V=15e3,B=250;async function O(e){let{lockRetryTimeoutMillis:r=V,persistenceMode:t="stateful",...n}=e??{};if(t==="stateless"){let{server:a}=await P({...n,persistenceMode:t});return b(a)}let s=Date.now()+r;for(;;)try{let{server:a}=await P({...n,persistenceMode:"stateful"});return b(a)}catch(a){if(!(a instanceof E))throw a;let o=await C(n.name,n.debug);if(o)return o;if(Date.now()>=s)throw a;await k(B)}}function b(e){return{close:()=>e.close(),database:e.database,http:e.http,name:e.name,owned:!0,ppg:e.ppg,server:e,shadowDatabase:e.shadowDatabase}}async function C(e,r){let t=await y(e??N,{debug:r});return!S(t)||!t.exports?null:{...t.exports,close:()=>Promise.resolve(),experimental:t.experimental,name:t.name,owned:!1}}var v=new Map;async function R(e){let{name:r}=e,t=G(e),n=v.get(r);if(n&&n.signature===t)return n.holders+=1,await h(r,n,!1);let s={holders:1,pending:$(e,n),signature:t};return v.set(r,s),await h(r,s,!0)}async function D(){await Promise.allSettled([...v.keys()].map(e=>F(e)))}async function h(e,r,t){let n;try{n=await r.pending}catch(a){throw x(e,r),a}let s=!1;return{release:async()=>{s||(s=!0,x(e,r)&&await n.close())},server:n,started:t}}function x(e,r){return r.holders-=1,r.holders>0||v.get(e)!==r?!1:(v.delete(e),!0)}async function $(e,r){return await T(r),await O(e)}async function F(e){let r=v.get(e);r&&(v.delete(e),await T(r))}async function T(e){if(!e)return;await(await e.pending.catch(()=>null))?.close()}function G(e){return JSON.stringify(e,Object.keys(e).sort())}var H=["SIGINT","SIGTERM"],U=!1;function _(){if(!U){U=!0,process.once("beforeExit",()=>{D()});for(let e of H)process.once(e,()=>{D().finally(()=>{process.kill(process.pid,e)})})}}var c="prisma-dev",W="default";function j(e={}){let r=J(e,z());if(r===null)return{apply:()=>!1,name:c};let{debug:t,env:n,name:s,onDatabaseReady:a,persistenceMode:o}=r,i=null;return{apply(d,m){return m.command==="serve"&&m.isPreview!==!0},async closeBundle(){await l()},async configureServer(d){let{logger:m}=d.config;_(),i=await R({databasePort:r.databasePort,debug:t,name:s,persistenceMode:o,port:r.port,shadowDatabasePort:r.shadowDatabasePort,streamsPort:r.streamsPort}),d.httpServer?.once("close",()=>{l()});let g=w(i.server,n),M=A(g,process.env);Q(m,i,g,M),a&&i.started&&await Y(a,K(i.server,g),m,l)},name:c};async function l(){let d=i;i=null,await d?.release()}}var Pe=j;function K(e,r){return{...u(e),env:Object.fromEntries(r.map(({name:t,value:n})=>[t,n])),name:e.name,owned:e.owned}}async function Y(e,r,t,n){try{await e(r)}catch(s){throw t.warn(`[${c}] \`onDatabaseReady\` failed, shutting the database down`,{timestamp:!0}),await n(),s}}function J(e,r){let{test:t=!1,...n}=e;return r?t===!1?null:I({...n,...t}):I(n)}function I(e){return{...e,name:e.name??W,persistenceMode:e.persistenceMode??"stateful"}}function z(){return process.env.VITEST!=null||process.env.VITEST_WORKER_ID!=null}function Q(e,r,t,n){let{server:s}=r,a=X(r),o=t.length>0?t.map(({name:i})=>i).join(", "):"no environment variables";e.info(`[${c}] ${a} database "${s.name}", set ${o}`,{timestamp:!0});for(let{key:i,name:l}of n)e.warn(`[${c}] ${l} pointed somewhere else, replaced it with the local database. Pass \`env: { ${i}: false }\` to keep your own value.`,{timestamp:!0})}function X({server:e,started:r}){return e.owned?r?"started":"reusing":"attached to already-running"}export{Pe as default,j as prismaDev};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "A local Prisma Postgres server for development and testing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Igal Klebanov <igalklebanov@gmail.com> (https://github.com/igalklebanov)",
|
|
@@ -50,6 +50,16 @@
|
|
|
50
50
|
"types": "./dist/state.d.cts",
|
|
51
51
|
"default": "./dist/state.cjs"
|
|
52
52
|
}
|
|
53
|
+
},
|
|
54
|
+
"./vite": {
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./dist/vite.d.ts",
|
|
57
|
+
"default": "./dist/vite.js"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./dist/vite.d.cts",
|
|
61
|
+
"default": "./dist/vite.cjs"
|
|
62
|
+
}
|
|
53
63
|
}
|
|
54
64
|
},
|
|
55
65
|
"keywords": [
|
|
@@ -62,6 +72,14 @@
|
|
|
62
72
|
"testing"
|
|
63
73
|
],
|
|
64
74
|
"license": "ISC",
|
|
75
|
+
"peerDependencies": {
|
|
76
|
+
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
77
|
+
},
|
|
78
|
+
"peerDependenciesMeta": {
|
|
79
|
+
"vite": {
|
|
80
|
+
"optional": true
|
|
81
|
+
}
|
|
82
|
+
},
|
|
65
83
|
"devDependencies": {
|
|
66
84
|
"@arethetypeswrong/cli": "0.18.2",
|
|
67
85
|
"@electric-sql/pglite-prepopulatedfs": "0.0.3",
|
|
@@ -74,6 +92,7 @@
|
|
|
74
92
|
"pkg-types": "2.3.0",
|
|
75
93
|
"tsup": "8.5.1",
|
|
76
94
|
"typescript": "5.9.3",
|
|
95
|
+
"vite": "8.1.5",
|
|
77
96
|
"vitest": "4.0.17",
|
|
78
97
|
"common-stuff": "^0.0.0"
|
|
79
98
|
},
|
|
@@ -91,7 +110,7 @@
|
|
|
91
110
|
"proper-lockfile": "4.1.2",
|
|
92
111
|
"remeda": "2.33.4",
|
|
93
112
|
"std-env": "3.10.0",
|
|
94
|
-
"valibot": "1.2
|
|
113
|
+
"valibot": "1.4.2",
|
|
95
114
|
"zeptomatch": "2.1.0"
|
|
96
115
|
},
|
|
97
116
|
"scripts": {
|
package/dist/chunk-FB4QA6EA.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as D}from"./chunk-662IKR3V.js";import{a as q,b as W,f as x}from"./chunk-PP43TGA5.js";import{a as N,b as R,c as M,d as I,e as v,f as $}from"./chunk-HFONW2ZS.js";import{d as _,j as y}from"./chunk-DWY47FQV.js";import{b as O}from"./chunk-DOJAPHLY.js";import X from"find-my-way";async function C(r,e){let{port:t}=e;if(e.dryRun)return{async close(){},port:t,url:`http://localhost:${t}`};let n=!!e.debug,[{registerAccelerateRoutes:s},{registerUtilityRoutes:i},{createHTTPServer:l}]=await Promise.all([import("./accelerate-45DUGMGZ.js"),import("./utility-YEFNU35E.js"),import("./server-QR7P25DP.js")]),a={databaseDumpPath:e.databaseDumpPath,db:r,debug:n,name:e.name,port:t,shadowDBPort:e.shadowDatabasePort},o=X({defaultRoute(m,d){O(d,"Not Found",404)},ignoreTrailingSlash:!1});s(o,a,n),i(o,a,n);let c=await l({router:o}).listen(t);return e.port=c.port,a.port=c.port,{async close(){let{Engine:m}=await import("./engine-YTEOPVUP.js");await Promise.allSettled([c.close(),m.stopAll()])},port:c.port,url:c.url}}import{isDeepStrictEqual as U}from"util";var Z="application/json",P={connection:"close","content-type":Z},T={apiVersion:"durable.streams/schema-registry/v1",schema:{additionalProperties:!0,properties:{applicationName:{type:["string","null"]},durationMs:{type:"number"},groupKey:{type:["string","null"]},query:{type:"string"},queryId:{type:"string"},reads:{type:"number"},rowsReturned:{type:"number"},tables:{items:{type:"string"},type:"array"},timestamp:{format:"date-time",type:"string"}},required:["durationMs","query","queryId","reads","rowsReturned","tables","timestamp"],type:"object"},search:{aliases:{applicationName:"applicationName",groupKey:"groupKey",queryId:"queryId"},fields:{applicationName:{bindings:[{jsonPointer:"/applicationName",version:1}],exact:!0,exists:!0,kind:"keyword"},eventTime:{bindings:[{jsonPointer:"/timestamp",version:1}],column:!0,exact:!0,exists:!0,kind:"date",sortable:!0},groupKey:{bindings:[{jsonPointer:"/groupKey",version:1}],exact:!0,exists:!0,kind:"keyword"},queryId:{bindings:[{jsonPointer:"/queryId",version:1}],exact:!0,exists:!0,kind:"keyword"}},primaryTimestampField:"eventTime"}};function F(r){return{...r,snapshot:async e=>await ee(r.url,e)}}async function j(r){let e={serverUrl:r.serverUrl,sqlitePath:r.sqlitePath,streamName:R,url:v(r.serverUrl,R)};await te(e);let t=new k({debug:r.debug,streamUrl:e.url}),n=r.bridge.subscribe(s=>{t.enqueue(s)});return{close:async()=>{n(),await t.close()},experimental:e}}async function ee(r,e){if(!r)return q();let t=await re(r);return W(t,e)}async function re(r){let e=await fetch(`${r}?offset=-1&format=json`,{headers:{connection:"close"}});if(!e.ok)throw new Error(`Failed to read ${r}: HTTP ${e.status}`);return await e.json()}var k=class{#t;#r;#e;constructor(e){this.#t=e.debug,this.#r=Promise.resolve(),this.#e=e.streamUrl}enqueue(e){e.length!==0&&(this.#r=this.#r.then(async()=>{await ae(this.#e,e),this.#t&&console.debug(`[streams] appended ${e.length} query insight record(s) to ${this.#e}`)}).catch(t=>{console.error("[streams] failed to ingest query insights into prisma-queries",t)}))}async close(){await this.#r}};async function te(r){let e=await fetch(r.url,{headers:P,method:"PUT"});if(!e.ok)throw await b(e,`Failed to create ${r.streamName}`);let t=await se(r);if(ne(t,r.streamName))return;if(t.currentVersion>0)throw new Error(`Failed to install schema for ${r.streamName}: existing schema registry is incompatible and requires a lens migration`);let n=await fetch(`${r.url}/_schema`,{body:JSON.stringify(T),headers:P,method:"POST"});if(!n.ok)throw await b(n,`Failed to install schema for ${r.streamName}`)}function ne(r,e){if(r.currentVersion<=0||r.schema!==e)return!1;let t=r.schemas[String(r.currentVersion)];return U(t,T.schema)&&U(r.search,T.search)}async function se(r){let e=await fetch(`${r.url}/_schema`,{headers:P,method:"GET"});if(!e.ok)throw await b(e,`Failed to inspect schema for ${r.streamName}`);return await e.json()}async function ae(r,e){let t=await fetch(r,{body:JSON.stringify(e),headers:P,method:"POST"});if(!t.ok)throw await b(t,"Failed to append to prisma-queries")}async function b(r,e){let t=await r.text().catch(()=>"");return new Error(`${e}: HTTP ${r.status}${t?` ${t}`:""}`)}import{randomUUID as ie}from"crypto";import{setTimeout as H}from"timers/promises";import{isDeepStrictEqual as L}from"util";import{process as oe}from"std-env";var le="application/json",S={connection:"close","content-type":le},ce={apiVersion:"durable.streams/profile/v1",profile:{kind:"state-protocol",touch:{enabled:!0,onMissingBefore:"coarse"}}},A={apiVersion:"durable.streams/schema-registry/v1",schema:{additionalProperties:!0,properties:{headers:{properties:{operation:{type:"string"},timestamp:{format:"date-time",type:"string"}},required:["timestamp","operation"],type:"object"},key:{type:"string"},type:{type:"string"}},required:["type","key","headers"],type:"object"},search:{aliases:{rowKey:"key",table:"type"},fields:{eventTime:{bindings:[{jsonPointer:"/headers/timestamp",version:1}],column:!0,exact:!0,exists:!0,kind:"date",sortable:!0},key:{bindings:[{jsonPointer:"/key",version:1}],exact:!0,exists:!0,kind:"keyword"},operation:{bindings:[{jsonPointer:"/headers/operation",version:1}],exact:!0,exists:!0,kind:"keyword"},type:{bindings:[{jsonPointer:"/type",version:1}],exact:!0,exists:!0,kind:"keyword"}},primaryTimestampField:"eventTime"}};async function V(r){let{dbServer:e,debug:t,name:n,persistenceMode:s,port:i,queryInsightsBridge:l,walBridge:a}=r,o=s==="stateless",c=o?we(n):n,m=I(c),d=!o&&await _(m);oe.env.DS_LOCAL_DATA_ROOT=M(),o&&await y(m);let u=await ue({debug:t,hadExistingStreamsData:d,name:c,port:i}),h={serverUrl:u.exports.http.url,sqlitePath:u.exports.sqlite.path,streamName:N,url:v(u.exports.http.url)};try{await he(h);let p=await j({bridge:l,debug:t,serverUrl:u.exports.http.url,sqlitePath:u.exports.sqlite.path}),g=new Q({dbServer:e,debug:t,streamUrl:h.url}),Y=a.subscribe(z=>{g.enqueue(z)});return{close:async()=>{Y(),await g.close(),await p.close(),await u.close(),await H(100),o&&await y(m)},experimental:h,experimentalQueryInsights:p.experimental}}catch(p){throw await u.close().catch(()=>{}),await H(100),o&&await y(m).catch(()=>{}),p}}var me=["database disk image is malformed","duplicate column name:","file is not a database","malformed database schema","no such column:","no such table:","schema_version row missing after migration","unexpected schema version:"];async function ue(r){let{debug:e,hadExistingStreamsData:t,name:n,port:s}=r,{startLocalDurableStreamsServer:i}=await import("@prisma/streams-local"),l=()=>i({hostname:"127.0.0.1",name:n,port:s});try{return await l()}catch(a){if(!t||!pe(a))throw a;return console.warn(`[streams] resetting incompatible durable streams data for "${n}"`),e&&console.debug(`[streams] original durable streams startup error for "${n}"`,a),await y(I(n)),await l()}}function pe(r){return de(r).map(t=>t.toLowerCase()).some(t=>me.some(n=>t.includes(n)))}function de(r){let e=[],t=[r],n=new Set;for(;t.length>0;){let s=t.shift();if(!(s==null||n.has(s))){if(n.add(s),typeof s=="string"){e.push(s);continue}if(s instanceof AggregateError)for(let i of s.errors)t.push(i);if(s instanceof Error){e.push(s.message);let i=s.cause;i!==void 0&&t.push(i)}}}return e}var Q=class{#t;#r;#e;#n;#s;constructor(e){this.#t=e.dbServer,this.#r=e.debug,this.#e=Promise.resolve(),this.#n=e.streamUrl,this.#s=new Set}enqueue(e){e.length!==0&&(this.#e=this.#e.then(async()=>{let t=await this.#i(e);t.length!==0&&(await Se(this.#n,t),this.#r&&console.debug(`[streams] appended ${t.length} state-protocol record(s) to ${this.#n}`))}).catch(t=>{console.error("[streams] failed to ingest WAL events into prisma-wal",t)}))}async close(){await this.#e}async#i(e){let t=[],n=new Date().toISOString();for(let s of e)t.push(...await this.#o(s,n));return t}async#o(e,t){let n=`${e.schema}.${e.table}`,s=await this.#t.getPrimaryKeyColumns(e.schema,e.table),i=K(e.record),l=K(e.oldRecord),a=this.#a(n,s,l),o=this.#a(n,s,i),c=e.txid===""?void 0:e.txid;return e.type==="insert"?i&&o?[{headers:{operation:"insert",timestamp:t,txid:c},key:o,old_value:null,type:n,value:i}]:[]:e.type==="delete"?l&&a?[{headers:{operation:"delete",timestamp:t,txid:c},key:a,old_value:l,type:n,value:null}]:[]:!i||!l||!a||!o?[]:a!==o?[{headers:{operation:"delete",timestamp:t,txid:c},key:a,old_value:l,type:n,value:null},{headers:{operation:"insert",timestamp:t,txid:c},key:o,old_value:null,type:n,value:i}]:[{headers:{operation:"update",timestamp:t,txid:c},key:o,old_value:l,type:n,value:i}]}#a(e,t,n){if(!n)return null;let s=fe(n,t);return s||(this.#s.has(e)||(this.#s.add(e),console.warn(`[streams] falling back to full-row keys for ${e} because no primary key could be resolved`)),ve(n))}};async function he(r){let e=await fetch(r.url,{headers:S,method:"PUT"});if(!e.ok)throw await f(e,`Failed to create ${r.streamName}`);let t=await fetch(`${r.url}/_profile`,{body:JSON.stringify(ce),headers:S,method:"POST"});if(!t.ok)throw await f(t,`Failed to configure ${r.streamName}`);let n=await ge(r);if(ye(n,r.streamName))return;if(n.currentVersion>0)throw new Error(`Failed to install schema for ${r.streamName}: existing schema registry is incompatible and requires a lens migration`);let s=await fetch(`${r.url}/_schema`,{body:JSON.stringify(A),headers:S,method:"POST"});if(!s.ok)throw await f(s,`Failed to install schema for ${r.streamName}`)}async function ge(r){let e=await fetch(`${r.url}/_schema`,{headers:S,method:"GET"});if(!e.ok)throw await f(e,`Failed to inspect schema for ${r.streamName}`);return await e.json()}function ye(r,e){if(r.currentVersion<=0||r.schema!==e)return!1;let t=r.schemas[String(r.currentVersion)];return L(t,A.schema)&&L(r.search,A.search)}async function Se(r,e){let t=await fetch(r,{body:JSON.stringify(e),headers:S,method:"POST"});if(!t.ok)throw await f(t,"Failed to append to prisma-wal")}async function f(r,e){let t=await r.text().catch(()=>"");return new Error(`${e}: HTTP ${r.status}${t?` ${t}`:""}`)}function fe(r,e){if(e.length===0)return null;let t=[];for(let n of e){if(!Object.prototype.hasOwnProperty.call(r,n))return null;let s=Ee(r[n]);if(s==null)return null;t.push(e.length===1?s:`${n}=${s}`)}return t.join("|")}function ve(r){return JSON.stringify(B(r))}function B(r){return Array.isArray(r)?r.map(e=>B(e)):r&&typeof r=="object"?Object.fromEntries(Object.entries(r).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,B(t)])):r}function K(r){return r?structuredClone(r):null}function Ee(r){if(r===null)return"null";if(r===void 0)return"undefined";if(typeof r=="string")return r;if(typeof r=="number")return Number.isFinite(r)?String(r):null;if(typeof r=="bigint")return r.toString();if(typeof r=="boolean")return r?"true":"false";try{return JSON.stringify(r)}catch{return null}}function we(r){return`${r}.${ie().replaceAll("-","")}`}async function J(r){let e=await $.createExclusively(r),t=null,n=null,s=null,i=null;try{[t,s]=await Promise.all([x("database",e),x("shadow_database",e)]);let l,a;e.dryRun?(l=Re(),a=Ie(),i=Te()):(l=await t.attachWalEventBridge(),a=await t.attachQueryInsightsBridge(),i=await V({dbServer:t,debug:e.debug,name:e.name,port:e.streamsPort,persistenceMode:e.persistenceMode,queryInsightsBridge:a,walBridge:l})),n=await C(t,e);let o=Pe(t,s,n,e);await e.writeServerDump(o,e.dryRun?{}:{queryInsights:i.experimentalQueryInsights,streams:i.experimental});let c=xe(l),m=F(i.experimentalQueryInsights),d=t,u=s,h=n,p=i,g=async()=>{c.close(),await G(e,[h,p,d,u])};return{close:g,dbServer:t,httpServer:n,server:{...o,close:g,experimental:{queryInsights:m,streams:i.experimental,wal:c.api},name:e.name},serverState:e,shadowDbServer:s,streamsServer:i,queryInsightsBridge:a,walBridge:l}}catch(l){return await be(e,[n,i,t,s],l)}}function Pe(r,e,t,n){let s=`prisma+postgres://localhost:${t.port}/?${new URLSearchParams({api_key:D({databaseUrl:r.prismaORMConnectionString,name:n.name,shadowDatabaseUrl:e.prismaORMConnectionString})}).toString()}`;return{database:{connectionString:r.connectionString,prismaORMConnectionString:r.prismaORMConnectionString,terminalCommand:r.terminalCommand},http:{url:t.url},ppg:{url:s},shadowDatabase:{connectionString:e.prismaORMConnectionString,prismaORMConnectionString:e.prismaORMConnectionString,terminalCommand:e.terminalCommand}}}async function G(r,e){let t=[];for(let n of e)try{await n.close()}catch(s){t.push(s)}try{await r.close()}catch(n){t.push(n)}if(t.length>0)throw new AggregateError(t,"Failed to close some servers")}async function be(r,e,t){try{await G(r,e.filter(n=>n!==null))}catch(n){throw new AggregateError([t,n],"Failed to start Prisma Dev server cleanly")}throw t}function xe(r){let e=new Set;return{api:{stream:()=>{let t=()=>{},n=ke(r,()=>{e.delete(t)});return t=()=>n.close(),e.add(t),n.stream},subscribe:t=>r.subscribe(t)},close:()=>{for(let t of[...e])t();e.clear()}}}function Re(){return{async close(){},async poll(){},subscribe(){return()=>{}}}}function Ie(){return{async close(){},subscribe(){return()=>{}}}}function Te(){return{async close(){},experimental:{serverUrl:"",sqlitePath:"",streamName:"",url:""},experimentalQueryInsights:{serverUrl:"",sqlitePath:"",streamName:"",url:""}}}function ke(r,e){let t=[],n=!1,s=null,i=r.subscribe(a=>{if(!n){if(s){let o=s;s=null,o.resolve({done:!1,value:a});return}t.push(a)}}),l=()=>{if(!n&&(n=!0,i(),t.length=0,e(),s)){let a=s;s=null,a.resolve({done:!0,value:void 0})}};return{close:l,stream:{[Symbol.asyncIterator](){return this},next(){return t.length>0?Promise.resolve({done:!1,value:t.shift()}):n?Promise.resolve({done:!0,value:void 0}):new Promise((a,o)=>{s={reject:o,resolve:a}})},return(){return l(),Promise.resolve({done:!0,value:void 0})},throw(a){let o=s;return l(),o&&o.reject(a),Promise.reject(a instanceof Error?a:new Error(String(a)))}}}}async function Ae(r){let{server:e}=await J(r);return e}async function pr(r){return await Ae(r)}export{Ae as a,pr as b};
|
|
File without changes
|