@prisma/dev
Version:
A local Prisma Postgres server for development and testing
6 lines (5 loc) • 37.2 kB
JavaScript
;var Vt=Object.create;var K=Object.defineProperty;var Ft=Object.getOwnPropertyDescriptor;var Gt=Object.getOwnPropertyNames;var Kt=Object.getPrototypeOf,Qt=Object.prototype.hasOwnProperty;var D=(t,e)=>()=>(t&&(e=t(t=0)),e);var $e=(t,e)=>{for(var r in e)K(t,r,{get:e[r],enumerable:!0})},ke=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Gt(e))!Qt.call(t,n)&&n!==r&&K(t,n,{get:()=>e[n],enumerable:!(o=Ft(e,n))||o.enumerable});return t};var u=(t,e,r)=>(r=t!=null?Vt(Kt(t)):{},ke(e||!t||!t.__esModule?K(r,"default",{value:t,enumerable:!0}):r,t)),Jt=t=>ke(K({},"__esModule",{value:!0}),t);var p=D(()=>{"use strict"});function Me(t){return Buffer.from(JSON.stringify(Object.fromEntries(Object.entries(t).sort(([[e],[r]])=>e.localeCompare(r)))),"utf8").toString("base64url")}function zt(t){let e=Buffer.from(t,"base64url").toString("utf8"),{issues:r,output:o,success:n}=(0,g.safeParse)(Wt,e,{abortEarly:!0});return n?[null,o]:[r]}var g,Ce,Wt,$,ae=D(()=>{"use strict";p();g=require("valibot"),Ce=/^(postgres|postgresql):\/\//,Wt=(0,g.pipe)((0,g.string)(),(0,g.parseJson)(),(0,g.object)({databaseUrl:(0,g.pipe)((0,g.string)(),(0,g.url)(),(0,g.regex)(Ce)),name:(0,g.optional)((0,g.pipe)((0,g.string)(),(0,g.minLength)(1))),shadowDatabaseUrl:(0,g.pipe)((0,g.string)(),(0,g.url)(),(0,g.regex)(Ce))}));$=async(t,e)=>{let{authorization:r}=t,{HTTPException:o}=await import("hono/http-exception");if(!r)throw new o(401,{message:"Missing API Key"});let[n,s="",a]=r.split(" ");if(n!=="Bearer"||a)throw new o(401,{message:"Invalid API Key"});let[i,c]=zt(s);if(i)throw new o(401,{message:"Invalid API Key",cause:i.join(", ")});let{databaseUrl:d,name:m,shadowDatabaseUrl:h}=c,b=e.get("name"),T=new URL(e.req.url).port;if(!m)throw new o(401,{message:`Wrong API Key; The Prisma Dev server running at port ${T} requires an API Key from a newer version of \`prisma dev\`. Check the "${b}" server's output for the updated \`DATABASE_URL\` value.`});if(m!==b)throw new o(401,{message:`Wrong API Key; The Prisma Dev server running at port ${T} is named "${b}", but the API Key is for "${m}"`});let{hostname:R,port:N}=new URL(d),{port:jt}=e.get("db"),{hostname:Nt,port:Ut}=new URL(h),qt=e.get("shadowDBPort");if(R!=="localhost"||Number(N)!==jt||Nt!=="localhost"||Number(Ut)!==qt)throw new o(401,{message:"Wrong API Key; Check your Prisma schema's `provider.url` value (probably defined in `.env`'s `DATABASE_URL` environment variable) is aligned with `prisma dev`'s output"});return{decodedAPIKey:c}}});function ue(t,{suffix:e="nodejs"}={}){if(typeof t!="string")throw new TypeError(`Expected a string, got ${typeof t}`);return e&&(t+=`-${e}`),Q.default.platform==="darwin"?Yt(t):Q.default.platform==="win32"?Xt(t):Zt(t)}var y,ie,Q,O,ce,M,Yt,Xt,Zt,Le=D(()=>{"use strict";p();y=u(require("path"),1),ie=u(require("os"),1),Q=u(require("process"),1),O=ie.default.homedir(),ce=ie.default.tmpdir(),{env:M}=Q.default,Yt=t=>{let e=y.default.join(O,"Library");return{data:y.default.join(e,"Application Support",t),config:y.default.join(e,"Preferences",t),cache:y.default.join(e,"Caches",t),log:y.default.join(e,"Logs",t),temp:y.default.join(ce,t)}},Xt=t=>{let e=M.APPDATA||y.default.join(O,"AppData","Roaming"),r=M.LOCALAPPDATA||y.default.join(O,"AppData","Local");return{data:y.default.join(r,t,"Data"),config:y.default.join(e,t,"Config"),cache:y.default.join(r,t,"Cache"),log:y.default.join(r,t,"Log"),temp:y.default.join(ce,t)}},Zt=t=>{let e=y.default.basename(O);return{data:y.default.join(M.XDG_DATA_HOME||y.default.join(O,".local","share"),t),config:y.default.join(M.XDG_CONFIG_HOME||y.default.join(O,".config"),t),cache:y.default.join(M.XDG_CACHE_HOME||y.default.join(O,".cache"),t),log:y.default.join(M.XDG_STATE_HOME||y.default.join(O,".local","state"),t),temp:y.default.join(ce,e,t)}}});function Ue(t,e){return`${Ne.cache}/engine/${t}/${e}`}function U(t){return`${Ne.data}/${t}`}async function qe(t){try{return await(0,v.access)(t,v.constants.F_OK),!0}catch(e){if(de(e))return!1;throw e}}async function Ve(t,e){let r=await er(t);await(0,v.writeFile)(e,r),await(0,v.chmod)(e,"755")}async function Fe(t,e){await t.stream().pipeTo(J.WriteStream.toWeb((0,J.createWriteStream)(e,{encoding:"utf8"})))}function de(t){return t!=null&&typeof t=="object"&&"code"in t&&t.code==="ENOENT"}async function Ge(t){try{return await(0,v.readFile)(t,{encoding:"utf-8"})}catch(e){if(de(e))return null;throw e}}async function Ke(t){await(0,v.mkdir)(t,{recursive:!0})}async function Qe(t,e){try{return(await(0,v.readdir)(t,{withFileTypes:!0})).reduce((o,n)=>(n.isDirectory()&&!n.name.startsWith(".")&&(!e||(0,je.default)(e,n.name))&&o.push(n.name),o),[])}catch(r){if(de(r))return[];throw r}}var J,v,He,Be,je,Ne,er,W=D(()=>{"use strict";p();J=require("fs"),v=require("fs/promises"),He=require("util"),Be=require("zlib");Le();je=u(require("zeptomatch"),1),Ne=ue("prisma-dev"),er=(0,He.promisify)(Be.unzip)});function X(t){let e,r,o=new Promise((a,i)=>{e=a,r=i}),n=a=>{n=s=null,r(a),t?.onRejected?.(a),t?.onFulfilled?.()},s=a=>{s=n=null,e(a),t?.onResolved?.(a),t?.onFulfilled?.()};return{isFulfilled:()=>s===n,promise:o,reject:a=>n?.(a),resolve:a=>s?.(a)}}var ye=D(()=>{"use strict";p()});function Z(t,e){return console.error(t),t instanceof q?e.json({EngineNotStarted:{reason:{EngineStartupError:{logs:[],msg:t.message}}}},500):t instanceof H?e.text(t.responseBody,t.statusCode):e.body(null,500)}var rt,ot,nt,st,at,it,dr,lr,tt,B,q,H,Pe=D(()=>{"use strict";p();rt=require("child_process"),ot=require("events"),nt=require("fs/promises"),st=require("path"),at=require("timers/promises");ye();it=require("std-env");W();({PRISMA_DEV_FORCE_ENGINE_BINARY_DOWNLOAD:dr,PRISMA_DEV_FORCE_ENGINE_BINARY_PATH:lr,PRISMA_DEV_FORCE_NETWORK_DELAY_MS:tt}=it.process.env),B=class t{static#t=new Map;#e;#r;constructor(e){this.#e=e,this.#r=null}static async get(e){let{debug:r}=e,o=`${e.schemaHash}:${e.clientVersion}`;try{let n=t.#t.get(o);if(n)return n;let s=new t(e);return t.#t.set(o,s),r&&console.debug("[Query Engine] starting...",e),await s.start(),r&&console.debug("[Query Engine] started!"),s}finally{t.stopAll(o)}}static async stopAll(e){let o=(await Promise.allSettled(Array.from(t.#t.entries()).filter(([n])=>n!==e).map(async([n,s])=>{try{await s.stop()}finally{t.#t.delete(n)}}))).filter(n=>n.status==="rejected").map(n=>n.reason);if(o.length>0)throw new AggregateError(o,"Failed to stop engines")}async commitTransaction(e,r){return await this.#i(e,r,"commit")}async request(e,r){let{url:o}=await this.start(),n=this.#o(r),s=await fetch(o,{body:typeof e=="string"?e:JSON.stringify(e),headers:{...n,"Content-Type":"application/json"},method:"POST"});if(!s.ok)throw await H.fromResponse(s);return await s.text()}async rollbackTransaction(e,r){return await this.#i(e,r,"rollback")}async startTransaction(e,r){let{url:o}=await this.start(),n=this.#o(r),s=await fetch(`${o}/transaction/start`,{body:JSON.stringify(e),headers:{...n,"Content-Type":"application/json"},method:"POST"});if(!s.ok)throw await H.fromResponse(s);return await s.json()}async start(){if(this.#r!=null)return await this.#r;let{promise:e,reject:r,resolve:o}=X();this.#r=e;let n=lr||await this.#s();this.#e.debug&&console.debug("[Query Engine] spinning up at path...",n);let{proxySignals:s}=await import("foreground-child/proxy-signals"),a=(0,rt.spawn)(n,["--enable-raw-queries","--enable-telemetry-in-response","--port","0"],{env:{LOG_QUERIES:"y",PRISMA_DML:this.#e.base64Schema,QE_LOG_LEVEL:"TRACE",RUST_BACKTRACE:"1",RUST_LOG:"info"},stdio:["ignore","pipe","pipe"],windowsHide:!0});s(a),a.stderr.setEncoding("utf8"),a.stdout.setEncoding("utf8");let i=m=>{let h=m.split(`
`).find(N=>N.includes("Started query engine http server"));if(!h)return;a.stdout.removeListener("data",i);let{fields:b}=JSON.parse(h);if(b==null)return r(new Error(`Unexpected data during initialization, "fields" are missing: ${m}`));let{ip:T,port:R}=b;if(T==null||R==null)return r(new Error(`This version of query-engine is not compatible with minippg, "ip" and "port" are missing in the startup log entry.
Received data: ${m}`));o({childProcess:a,url:`http://${T}:${R}`})},c=m=>{this.#r=null,r(new q(String(m))),a.removeListener("exit",d),a.kill()};a.once("error",c);let d=(m,h)=>{this.#r=null,r(new q(`Query Engine exited with code ${m} and signal ${h}`))};return a.once("exit",d),a.stdout.on("data",i),this.#e.debug&&(a.stderr.on("data",console.error.bind(console,"[Query Engine]")),a.stdout.on("data",console.debug.bind(console,"[Query Engine]"))),await this.#r}async stop(){if(this.#r==null)return;let{childProcess:e}=await this.#r;e.exitCode==null&&e.signalCode==null&&(this.#r=null,e.kill(),await(0,ot.once)(e,"exit"))}async#s(){this.#e.debug&&console.debug("[Query Engine] getting engine commit hash...");let e=await this.#a();this.#e.debug&&console.debug("[Query Engine] got engine commit hash",e);let r=Ue(this.#e.clientVersion,e);this.#e.debug&&console.debug("[Query Engine] cache directory path",r),await(0,nt.mkdir)(r,{recursive:!0});let{binaryTarget:o}=this.#e.platform,n=o==="windows"?".exe":"",s=(0,st.join)(r,`query-engine-${o}${n}`);return this.#e.debug&&console.debug("[Query Engine] binary path",s),(dr==="1"||await qe(s)===!1)&&await this.#n({commitHash:e,extension:n,engineBinaryPath:s}),s}async#a(){let e=await fetch(`https://registry.npmjs.org/@prisma/client/${this.#e.clientVersion}`);if(!e.ok)throw new Error(`Couldn't fetch package.json from npm registry, status code: ${e.status}`);let o=(await e.json()).devDependencies?.["@prisma/engines-version"];if(!o)throw new Error("Couldn't find engines version in package.json");let n=o.split(".").at(-1);if(!n)throw new Error("Couldn't find commit hash in engines version");return n}async#n(e){let{commitHash:r,extension:o,engineBinaryPath:n}=e,{binaryTarget:s}=this.#e.platform,a=`https://binaries.prisma.sh/all_commits/${r}/${s}/query-engine${o}.gz`;this.#e.debug&&console.debug("[Query Engine] downloading engine from url",a);let i=await fetch(a);if(!i.ok)throw new Error(`Couldn't download engine. URL: ${a}, status code: ${i.status}`);tt&&await(0,at.setTimeout)(Number(tt)),await Ve(await i.arrayBuffer(),n),this.#e.debug&&console.debug("[Query Engine] downloaded and saved at",n)}#o(e){let r={};for(let[o,n]of Object.entries(e))n!=null&&(r[o]=n);return r}async#i(e,r,o){let{url:n}=await this.#r,s=this.#o(r),a=await fetch(`${n}/transaction/${e}/${o}`,{headers:{...s,"Content-Type":"application/json"},method:"POST"});if(!a.ok)throw await H.fromResponse(a);try{return await a.json()}catch{return{}}}};q=class extends Error{name="EngineStartError"},H=class t extends Error{constructor(r,o,n){super(`${r}: Query Engine response status ${o}, body: ${n}`);this.action=r;this.statusCode=o;this.responseBody=n}name="EngineHttpError";static async fromResponse(r){let o=new URL(r.url),n=await r.text();return new t(o.pathname,r.status,n)}}});async function ct(t){let{output:e,success:r}=(0,S.safeParse)(pr,await t.req.json(),{abortEarly:!0});return r?e:t.text("Invalid input",400)}var S,pr,ut=D(()=>{"use strict";p();S=require("valibot"),pr=(0,S.object)({tags:(0,S.union)([(0,S.pipe)((0,S.array)((0,S.string)()),(0,S.minLength)(1)),(0,S.literal)("all")])})});async function dt(t){return we===void 0&&(we=await I.Server.create({databaseUrl:t.get("db").connectionString,maxResponseSize:(0,I.parseSize)("128 MiB"),queryTimeout:(0,I.parseDuration)("PT5M"),maxTransactionTimeout:(0,I.parseDuration)("PT5M"),maxTransactionWaitTime:(0,I.parseDuration)("PT5M"),perRequestLogContext:{logFormat:"text",logLevel:t.get("debug")?"debug":"off"}})),we}var I,ee,we,lt=D(()=>{"use strict";p();I=require("@prisma/query-plan-executor"),ee=require("@prisma/query-plan-executor")});async function ve(t){let r=new TextEncoder().encode(t),o=await crypto.subtle.digest("SHA-256",r);return Array.from(new Uint8Array(o)).map(a=>a.toString(16).padStart(2,"0")).join("")}function pt(t){let e=t.req.param("schemaHash"),r=re.get(e);return r==null?t.json({EngineNotStarted:{reason:"SchemaMissing"}},404):{schemaHash:e,schemas:r}}async function mt(t,e,r){let o=Se.Buffer.from(t,"base64").toString("utf8"),n=(0,te.getSchema)(o),s=n.list.find(d=>d.type==="datasource");if(!s)throw new Error("No datasource block found in schema.");let a=s.assignments.find(d=>d.type==="assignment"&&d.key==="url");a?a.value=`"${e.toString()}"`:s.assignments.push({key:"url",type:"assignment",value:`"${e.toString()}"`});let i=(0,te.printSchema)(n);r&&console.log("[Accelerate] schema with override:",i);let c=await ve(i);return{base64Override:Se.Buffer.from(i,"utf8").toString("base64"),overrideHash:c}}var Se,te,re,ht=D(()=>{"use strict";p();Se=require("buffer"),te=require("@mrleebo/prisma-ast"),re=new Map});function oe(t){let{req:e}=t;return{traceparent:e.header("traceparent"),"X-capture-telemetry":e.header("X-capture-telemetry")}}var ft=D(()=>{"use strict";p()});async function gt(t){let{issues:e,output:r,success:o}=(0,f.safeParse)(mr,await t.req.json(),{abortEarly:!0});return o?r:t.json({EngineNotStarted:{reason:"InvalidRequest",issues:e}},400)}function bt(t,e){let{output:r,success:o}=(0,f.safeParse)(hr,t);return o?r:e.json({EngineMalfunction:{}},500)}var f,mr,hr,yt=D(()=>{"use strict";p();f=require("valibot"),mr=(0,f.object)({isolation_level:(0,f.optional)((0,f.string)()),max_wait:(0,f.pipe)((0,f.number)(),(0,f.integer)(),(0,f.minValue)(0)),timeout:(0,f.pipe)((0,f.number)(),(0,f.integer)(),(0,f.minValue)(0))});hr=(0,f.looseObject)({id:(0,f.union)([(0,f.string)(),(0,f.number)()])})});var St={};$e(St,{accelerateRoute:()=>V});async function De(t){let{req:e}=t,r=pt(t);if(r instanceof Response)return r;let{base64Override:o,overrideHash:n}=r.schemas;return await B.get({base64Schema:o,clientVersion:process.env.PRISMA_DEV_FORCE_CLIENT_VERSION||e.param("clientVersion"),debug:t.get("debug"),platform:t.get("platform"),schemaHash:n})}var Pt,wt,k,V,fr,F,gr,br,vt=D(()=>{"use strict";p();Pt=require("hono/http-exception"),wt=require("hono/tiny"),k=require("hono/validator");ae();ut();Pe();lt();ht();ft();yt();V=new wt.Hono;V.post("/invalidate",(0,k.validator)("header",$),async t=>{let e=await ct(t);return e instanceof Response?e:t.body(null)});fr="/:clientVersion/:schemaHash",F=V.basePath(fr);V.route("/",F);gr=["/graphql","/itx/:transactionId/graphql"];F.on("POST",[...gr],(0,k.validator)("header",$),async t=>{let{req:e}=t;try{let r=await De(t);if(r instanceof Response)return r;let o=await e.text(),n=e.param("transactionId"),s=await r.request(o,{...oe(t),"X-transaction-id":n});return t.text(s)}catch(r){return Z(r,t)}});F.basePath("/itx/:transactionId").on("POST",["/commit","/rollback"],(0,k.validator)("header",$),async t=>{let{req:e}=t;try{let r=await De(t);if(r instanceof Response)return r;let n=`${e.routePath.split("/").filter(Boolean).at(-1)}Transaction`,s=e.param("transactionId"),a=await r[n](s,oe(t));return t.json(a)}catch(r){return Z(r,t)}});F.put("/schema",(0,k.validator)("header",$),async t=>{let{req:e}=t,r=await e.text();if(!r)return t.text("Missing schema",400);let o=e.param("schemaHash"),n=re.get(o);if(n==null){if(o!==await ve(r))return t.text("Schema hash mismatch",400);let s=await mt(r,t.get("db").prismaORMConnectionString,t.get("debug"));return re.set(o,{base64Original:r,...s}),t.text(o)}return r!==n.base64Original?t.text("Schema mismatch",400):t.text(o)});F.post("/transaction/start",(0,k.validator)("header",$),async t=>{let{req:e}=t,r=await gt(t);if(r instanceof Response)return r;try{let o=await De(t);if(o instanceof Response)return o;let n=await o.startTransaction(r,oe(t)),s=bt(n,t);if(s instanceof Response)return s;let{id:a}=s,i=e.param("clientVersion"),c=e.param("schemaHash");return t.json({...n,"data-proxy":{endpoint:`${new URL(e.url).origin}/${i}/${c}/itx/${a}`}})}catch(o){return Z(o,t)}});br=[["/connection-info","GET"],["/query","POST"],["/transaction/start","POST"],["/transaction/:transactionId/commit","POST"],["/transaction/:transactionId/query","POST"],["/transaction/:transactionId/rollback","POST"]];for(let[t,e]of br)V.on(e,t,(0,k.validator)("header",$),async r=>{let o=r.req.header("prisma-engine-hash");if(o!=="0.0.0"&&o!==ee.version)throw new Pt.HTTPException(400,{message:`Using an HTTP connection string is not supported with Prisma Client version ${o} by this version of \`prisma dev\`. Please either use a direct TCP connection string or upgrade your client to version ${ee.version}.`});return await(await dt(r)).fetch(r.req.raw)})});var Et={};$e(Et,{utilityRoute:()=>Te});var Dt,Tt,Te,po,xt=D(()=>{"use strict";p();Dt=require("hono/tiny"),Tt=require("http-status-codes"),Te=new Dt.Hono;Te.post("/database/dump",async t=>{let e=t.get("db"),r=t.get("databaseDumpPath");return await e.dump(r),t.json({dumpPath:r},Tt.StatusCodes.CREATED)});po=Te.get("/health",t=>t.json({name:t.get("name")}))});var Tr={};module.exports=Jt(Tr);p();var Bt=require("timers/promises");p();ae();p();var Ye=require("pathe/utils");W();p();var A=require("get-port-please"),Y=require("remeda"),le=51214,pe=51213,me=51215,z=65535,L=0,_=-1/0;async function ge(t){let{debug:e,name:r,requestedPorts:o,servers:n}=t,{portsUsedByOtherServers:s,portsUsedByThisServerLastTime:a}=or(r,n);e&&(console.debug(`ports used by other servers: ${Object.keys(s).join(", ")}`),console.debug(`ports used by "${r}" server last time: ${JSON.stringify(a)}`));let i={databasePort:_,port:_,shadowDatabasePort:_},c=["port","databasePort","shadowDatabasePort"];for(let d of c){let m=await tr({debug:e,portKey:d,portsUsedByOtherServers:s,portsUsedByThisServerLastTime:a,requestedPorts:o})??await rr({debug:e,pickedPorts:i,portKey:d,portsUsedByOtherServers:s,portsUsedByThisServerLastTime:a});e&&console.debug(`Got port for "${d}": ${m}`),i[d]=m}return e&&console.debug(`Picked ports: ${JSON.stringify(i)}`),i}async function tr(t){let{debug:e,portKey:r,portsUsedByOtherServers:o,portsUsedByThisServerLastTime:n,requestedPorts:s}=t,{[r]:a,...i}=s;if(Je(a))return await nr({debug:e,otherRequestedPorts:i,portKey:r,portsUsedByOtherServers:o,requestedPort:a}),a;let c=n?.[r]??_;if(!Je(c))return e&&console.debug(`No port specified for "${r}". Trying to pick a new port.`),null;let d=c in o;return d||Object.values(i).includes(c)?(e&&console.debug(`Port ${c} that was used last time for this server, ${d?"is also used by another server":"has been requested for another service"}. Trying to pick a new port.`),null):await(0,A.checkPort)(c)===!1?(e&&console.debug(`Port ${c}, that was used last time for this server, is not available. Trying to pick a new port.`),null):(e&&console.debug(`Using port ${c} for "${r}" as it was used last time and is available.`),c)}async function rr(t){let{debug:e,pickedPorts:r,portKey:o,portsUsedByOtherServers:n,portsUsedByThisServerLastTime:s}=t,a=Math.max(le,pe,me)+1,i=[...Object.values(r),...Object.keys(n).map(Number),...Object.values(s||{})],c=Math.min(Math.max(a,...i)+100,z),d=(0,Y.difference)((0,Y.range)(a,c),i),m={port:pe,databasePort:le,shadowDatabasePort:me}[o];try{return await(0,A.getPort)({port:m in n||Object.values(r).includes(m)||Object.values(s||{}).includes(m)?void 0:m,ports:d})}catch(h){if(h instanceof Error&&h.name==="GetPortError"&&c+1<=z)return e&&console.debug(`Expanding port lookup to range [${c+1}, ${z}].`),await(0,A.getPort)({portRange:[c+1,z]});throw h}}function Je(t){return Number.isFinite(t)&&t>=0}function or(t,e){let r={},o;for(let n of e){let{databasePort:s,port:a,shadowDatabasePort:i}=n;if(n.name===t){o={databasePort:s,port:a,shadowDatabasePort:i};continue}r[s]=!0,r[a]=!0,r[i]=!0}return{portsUsedByOtherServers:r,portsUsedByThisServerLastTime:o}}async function nr(t){let{debug:e,otherRequestedPorts:r,portKey:o,portsUsedByOtherServers:n,requestedPort:s}=t;if(s!==L){if(s in n)throw e&&console.error(`Port ${s} was requested for "${o}", but is already used by another server.`),new fe(s);if(Object.values(r).includes(s))throw e&&console.error(`Port ${s} was requested for "${o}", but also for another key.`),new he(s);if((0,A.isUnsafePort)(s))throw e&&console.error(`Port ${s} was requested for "${o}", but is unsafe.`),new x(s);if(await(0,A.checkPort)(s)===!1)throw e&&console.error(`Port ${s} was requested for "${o}", but is not available.`),new x(s)}}var x=class extends Error{constructor(r){super(`Port \`${r}\` is not available.`);this.port=r}name="PortNotAvailableError"},he=class extends Error{constructor(r){super(`Port number \`${r}\` was requested twice. Please choose a different port for each service.`);this.port=r}name="PortRequestedTwiceError"},fe=class extends Error{constructor(r){super(`Port number \`${r}\` belongs to another Prisma Dev server. Please choose a different port.`);this.port=r}name="PortBelongsToAnotherServerError"};var w={connectionLimit:1,connectTimeout:0,database:"template1",maxIdleConnectionLifetime:0,password:"postgres",poolTimeout:0,socketTimeout:0,sslMode:"disable",username:"postgres"},sr=`postgres://${w.username}:${w.password}@localhost`,Xe=new URLSearchParams({sslmode:w.sslMode}),ar=new URLSearchParams({...Object.fromEntries(Xe.entries()),connection_limit:String(w.connectionLimit),connect_timeout:String(w.connectTimeout),max_idle_connection_lifetime:String(w.maxIdleConnectionLifetime),pool_timeout:String(w.poolTimeout),single_use_connections:"true",socket_timeout:String(w.socketTimeout)});async function be(t,e){let r=t==="database"?e.databasePort:e.shadowDatabasePort;if(e.dryRun)return We(t,e,{db:null,port:r,server:null});let{debug:o}=e,s=await(t==="shadow_database"?ir:Ze)(e.pgliteDataDirPath,o);o&&s.onNotification((h,b)=>{console.debug(`[${t}][${h}] ${b}`)});let{PGLiteSocketHandler:a,PGLiteSocketServer:i}=await import("@electric-sql/pglite-socket"),c=t==="shadow_database"?e.shadowDatabaseIdleTimeoutMillis:e.databaseIdleTimeoutMillis;cr(c,s,a);let d=new i({connectionQueueTimeout:t==="shadow_database"?e.shadowDatabaseConnectTimeoutMillis:e.databaseConnectTimeoutMillis,db:s,debug:o,inspect:o,port:r});o&&(d.addEventListener("listening",h=>{let{detail:b}=h;console.debug(`[${t}] server listening on ${JSON.stringify(b)}`)}),d.addEventListener("connection",h=>{let{clientAddress:b,clientPort:T}=h.detail;console.debug(`[${t}] client connected from ${b}:${T}`)}),d.addEventListener("error",h=>{let{detail:b}=h;console.error(`[${t}] server error:`,b)}));try{await d.start()}catch(h){throw h instanceof Error&&"code"in h&&h.code==="EADDRINUSE"?new x(r):h}let m=Number(d.getServerConn().split(":").at(1));return e[t==="database"?"databasePort":"shadowDatabasePort"]=m,We(t,e,{db:s,port:m,server:d})}function We(t,e,r){let{debug:o}=e,{db:n,port:s,server:a}=r||{};return o&&console.debug(`[${t}] server started on port ${s}`),{...w,close:async()=>{let i=[];try{await a?.stop(),o&&console.debug(`[${t}] server stopped on port ${s}`)}catch(c){console.error(`[${t}] server stop error`,c),i.push(c)}if(t==="database")try{await n?.syncToFs(),o&&console.debug(`[${t}] synced to filesystem`)}catch(c){console.error(`[${t}] sync error`,c),i.push(c)}try{await n?.close(),o&&console.debug(`[${t}] closed`)}catch(c){console.error(`[${t}] close error`,c),i.push(c)}if(i.length>0)throw new AggregateError(i,`Failed to close ${t} properly`)},connectionString:ze(s,Xe),dump:async i=>{t==="shadow_database"||!n||await ur({db:n,debug:o,destinationPath:i})},port:s,prismaORMConnectionString:ze(s,ar),terminalCommand:`PGPASSWORD=${w.password} PGSSLMODE=${w.sslMode} psql -h localhost -p ${s} -U ${w.username} -d ${w.database}`}}function ze(t,e){return`${sr}:${t}/${w.database}?${e.toString()}`}async function Ze(t,e){let{PGlite:r}=await import("@electric-sql/pglite");return await r.create({database:w.database,dataDir:t,debug:e?5:void 0,extensions:await et(),relaxedDurability:!1,username:w.username})}async function ir(t,e){let{PGlite:r}=await import("@electric-sql/pglite");return await r.create({database:w.database,dataDir:"memory://",debug:e?5:void 0,extensions:await et(),relaxedDurability:!1,username:w.username})}async function et(){let t=await Promise.all([import("@electric-sql/pglite/contrib/amcheck"),import("@electric-sql/pglite/contrib/bloom"),import("@electric-sql/pglite/contrib/btree_gin"),import("@electric-sql/pglite/contrib/btree_gist"),import("@electric-sql/pglite/contrib/citext"),import("@electric-sql/pglite/contrib/cube"),import("@electric-sql/pglite/contrib/dict_int"),import("@electric-sql/pglite/contrib/dict_xsyn"),import("@electric-sql/pglite/contrib/earthdistance"),import("@electric-sql/pglite/contrib/file_fdw"),import("@electric-sql/pglite/contrib/fuzzystrmatch"),import("@electric-sql/pglite/contrib/hstore"),import("@electric-sql/pglite/contrib/intarray"),import("@electric-sql/pglite/contrib/isn"),import("@electric-sql/pglite/contrib/lo"),import("@electric-sql/pglite/contrib/ltree"),import("@electric-sql/pglite/contrib/pageinspect"),import("@electric-sql/pglite/contrib/pg_buffercache"),import("@electric-sql/pglite/contrib/pg_freespacemap"),import("@electric-sql/pglite/contrib/pg_surgery"),import("@electric-sql/pglite/contrib/pg_trgm"),import("@electric-sql/pglite/contrib/pg_visibility"),import("@electric-sql/pglite/contrib/pg_walinspect"),import("@electric-sql/pglite/contrib/seg"),import("@electric-sql/pglite/contrib/tablefunc"),import("@electric-sql/pglite/contrib/tcn"),import("@electric-sql/pglite/contrib/tsm_system_rows"),import("@electric-sql/pglite/contrib/tsm_system_time"),import("@electric-sql/pglite/contrib/unaccent"),import("@electric-sql/pglite/contrib/uuid_ossp"),import("@electric-sql/pglite/vector")]);return Object.assign({},...t)}function cr(t,e,r){if(e.__IDLE_TIMEOUT__=t,r.prototype.__ATTACH_OVERRIDDEN__)return;r.prototype.__ATTACH_OVERRIDDEN__=!0;let o=r.prototype.attach;r.prototype.attach=async function(n){let s=await o.call(this,n);if(!Number.isFinite(this.db.__IDLE_TIMEOUT__))return s;let a=null,i=()=>{a!=null&&(clearTimeout(a),a=null)},c=()=>{i(),a=setTimeout(()=>{this.dispatchEvent(new CustomEvent("close")),this.detach(!1)},this.db.__IDLE_TIMEOUT__)};return n.on("error",()=>{i()}),n.on("data",()=>{c()}),n.on("close",()=>{i()}),c(),s}}async function ur(t){let{dataDir:e,db:r,debug:o,destinationPath:n}=t,s=r||await Ze(e,o),{pgDump:a}=await import("@electric-sql/pglite-tools/pg_dump"),i=await a({args:["--schema-only","--no-owner"],fileName:n?(0,Ye.filename)(n):void 0,pg:await s.clone()});return n?(o&&console.debug(`[DB] Dumping database to ${n}`),await Fe(i,n)):(o&&console.debug("[DB] Dumping database to memory"),await i.text())}p();var Ot=require("http"),_t=require("util"),At=u(require("@prisma/get-platform"),1);ye();Pe();async function It(t,e){let{port:r}=e;if(e.dryRun)return Rt(r,null);let o=await yr(t,e),{promise:n,reject:s,resolve:a}=X(),{serve:i}=await import("@hono/node-server"),c=i({createServer:Ot.createServer,fetch:o.fetch,overrideGlobalObjects:!1,port:r},a);c.on("error",m=>{if(typeof m=="object"&&"code"in m&&m.code==="EADDRINUSE")return s(new x(r));console.error("[Accelerate]",m)});let{port:d}=await n;return e.port=d,Rt(d,c)}function Rt(t,e){return{async close(){e&&await Promise.allSettled([(0,_t.promisify)(e.close.bind(e))(),B.stopAll()])},port:t,url:`http://localhost:${t}`}}async function yr(t,e){let{debug:r}=e,[{Hono:o},{accelerateRoute:n},{utilityRoute:s}]=await Promise.all([import("hono/tiny"),Promise.resolve().then(()=>(vt(),St)),Promise.resolve().then(()=>(xt(),Et))]),a=new o,i=await At.default.getPlatformInfo();if(r&&console.debug("[Accelerate] platform info: %s",JSON.stringify(i)),r){let{logger:d}=await import("hono/logger");a.use("*",d((...m)=>console.log("[Accelerate]",...m)))}a.use("*",async(d,m)=>(d.set("databaseDumpPath",e.databaseDumpPath),d.set("db",t),d.set("debug",!!r),d.set("name",e.name),d.set("platform",i),d.set("shadowDBPort",e.shadowDatabasePort),await m()));let c=new o;return c.route("/",n),c.route("/",s),a.route("/",c),a}p();var Lt=require("fs/promises"),C=require("pathe"),j=require("proper-lockfile"),Ae=require("std-env"),l=require("valibot");W();p();var Pr=require("timers/promises"),$t=require("std-env");function kt(t,e){if(t==null)return!1;try{return $t.process.kill?.(t,0)??!0}catch(r){return e&&console.error(`Error checking if process with PID ${t} exists:`,r),!1}}var Re=(0,l.pipe)((0,l.string)(),(0,l.url)()),Ct=(0,l.object)({connectionString:Re,prismaORMConnectionString:(0,l.optional)(Re),terminalCommand:(0,l.optional)((0,l.string)())}),Mt=(0,l.object)({url:Re}),Ee=(0,l.pipe)((0,l.number)(),(0,l.integer)(),(0,l.minValue)(1)),wr=(0,l.object)({database:Ct,http:Mt,ppg:Mt,shadowDatabase:Ct}),Sr=(0,l.object)({databasePort:Ee,exports:(0,l.optional)(wr),name:(0,l.pipe)((0,l.string)(),(0,l.minLength)(1)),pid:(0,l.optional)((0,l.pipe)((0,l.number)(),(0,l.integer)(),(0,l.minValue)(0))),port:Ee,shadowDatabasePort:Ee,version:(0,l.literal)("1")}),Ie=Symbol("initialize"),xe="default",E=class{_databasePort;databaseConnectTimeoutMillis;databaseIdleTimeoutMillis;debug;dryRun;name;persistenceMode;pid;shadowDatabaseConnectTimeoutMillis;shadowDatabaseIdleTimeoutMillis;_port;_shadowDatabasePort;constructor(e){this._databasePort=e.databasePort??_,this.databaseConnectTimeoutMillis=e.databaseConnectTimeoutMillis??6e4,this.databaseIdleTimeoutMillis=e.databaseIdleTimeoutMillis??1/0,this.debug=e.debug??!1,this.dryRun=e.dryRun??!1,this.name=e.name??xe,this.persistenceMode=e.persistenceMode,this.pid=e.pid??Ae.process.pid,this.shadowDatabaseConnectTimeoutMillis=e.shadowDatabaseConnectTimeoutMillis??this.databaseConnectTimeoutMillis,this.shadowDatabaseIdleTimeoutMillis=e.shadowDatabaseIdleTimeoutMillis??this.databaseIdleTimeoutMillis,this._port=e.port??_,this._shadowDatabasePort=e.shadowDatabasePort??_}static async createExclusively(e){let r=e?.dryRun!==!0&&e?.persistenceMode==="stateful"?new G(e):new Oe(e);return await r[Ie](),r}static async fromServerDump(e){let{debug:r,name:o=xe}=e??{},n=U(o),s=G.getServerDumpPath(n),a=await Ge(s);if(a==null)return r&&console.debug(`[State] No server dump file found at: ${s}`),null;r&&(console.debug(`[State] server dump file found at "${s}":`),console.debug(a));let{issues:i,output:c,success:d}=(0,l.safeParse)((0,l.pipe)((0,l.string)(),(0,l.parseJson)(),Sr),a);if(!d)throw r&&console.debug(`[State] Invalid server dump file at "${s}":
${JSON.stringify(i,null,2)}`),new Error(`Invalid Prisma Dev state for "${o}".`);return new G({databasePort:c.databasePort,debug:r,dryRun:!1,name:o,pid:c.pid,port:c.port,serverDump:c,shadowDatabasePort:c.shadowDatabasePort})}static async scan(e){let{debug:r,globs:o}=e??{},n=(0,C.join)(U(xe),"..");r&&console.debug(`[State] scanning for server states in: ${n}`);let s=await Qe(n,o);return r&&console.debug(`[State] found server names: ${JSON.stringify(s)}`),await Promise.all(s.map(a=>vr(a,e)))}get databasePort(){return this._databasePort}set databasePort(e){this.#t("databasePort",e)}get port(){return this._port}set port(e){this.#t("port",e)}get shadowDatabasePort(){return this._shadowDatabasePort}set shadowDatabasePort(e){this.#t("shadowDatabasePort",e)}#t(e,r){if(r<0||!Number.isInteger(r))throw new Error(`Invalid port number: ${r}`);let o=`_${e}`;if(this[o]!==L&&this[o]!==r)throw new Error(`\`${e}\` is already set to ${this[o]}, cannot change it to ${r}`);this[o]=r}},Oe=class extends E{constructor(e){super({...e,databasePort:e?.databasePort||L,persistenceMode:"stateless",port:e?.port||L,shadowDatabasePort:e?.shadowDatabasePort||L})}get databaseDumpPath(){return"<DUMP_PATH>"}get pgliteDataDirPath(){return"memory://"}async[Ie](){let e;try{e=await E.scan({debug:this.debug,onlyMetadata:!0})}catch(o){this.debug&&console.warn("[State] failed to scan for existing servers, assuming filesystem does not exist or other reasons.",o),e=[]}let r=await ge({debug:this.debug,name:this.dryRun?this.name:"",requestedPorts:{databasePort:this.databasePort,port:this.port,shadowDatabasePort:this.shadowDatabasePort},servers:e});this._databasePort=r.databasePort,this._port=r.port,this._shadowDatabasePort=r.shadowDatabasePort}async close(){}async writeServerDump(){}},G=class t extends E{#t;#e;#r;#s;#a;#n;#o;constructor(e){super({...e,persistenceMode:"stateful"}),this.#n=!1,this.#e=U(this.name),this.#t=(0,C.join)(this.#e,"db_dump.bak"),this.#r=(0,C.join)(this.#e,".lock"),this.#s=(0,C.join)(this.#e,".pglite"),this.#o=e?.serverDump??null,this.#a=t.getServerDumpPath(this.#e)}static getServerDumpPath(e){return(0,C.join)(e,"server.json")}get databaseDumpPath(){return this.#t}get exports(){return this.#o?.exports}get pgliteDataDirPath(){return this.#s}async[Ie](){await Ke(this.#e),this.debug&&console.debug(`[State] using data directory: ${this.#e}`);try{await(0,j.lock)(this.#e,{lockfilePath:this.#r}),this.debug&&console.debug(`[State] obtained lock on: ${this.#e}`);let e=await E.scan({debug:this.debug,onlyMetadata:!0}),r=await ge({debug:this.debug,name:this.name,requestedPorts:{databasePort:this.databasePort,port:this.port,shadowDatabasePort:this.shadowDatabasePort},servers:e});this._databasePort=r.databasePort,this._port=r.port,this._shadowDatabasePort=r.shadowDatabasePort,await this.writeServerDump()}catch(e){throw e instanceof Error&&"code"in e&&e.code==="ELOCKED"?new ne(this):e}}async close(){if(!this.#n)try{await(0,j.unlock)(this.#e,{lockfilePath:this.#r}),this.#n=!0,this.debug&&console.debug(`[State] released lock on: ${this.#e}`)}catch(e){throw this.debug&&console.error(`[State] failed to release lock on: ${this.#e}`,e),e}}async writeServerDump(e){this.#o={name:this.name,version:"1",pid:Ae.process.pid,port:this.port,databasePort:this.databasePort,shadowDatabasePort:this.shadowDatabasePort,exports:e},await(0,Lt.writeFile)(this.#a,`${JSON.stringify(this.#o,null,2)}
`,{encoding:"utf-8"})}};async function vr(t,e){let{debug:r,onlyMetadata:o}=e||{},n=typeof t=="string"?t:t.name,s=typeof t!="string"?t:void 0,a={databasePort:s?.databasePort??-1,exports:s?.exports,name:n,pid:s?.pid,port:s?.port??-1,shadowDatabasePort:s?.shadowDatabasePort??-1,version:"1"};try{let i=s||await E.fromServerDump({debug:r,name:n});if(!i)return r&&console.debug(`[State] no server state found for name: ${n}`),{...a,status:"no_such_server"};a.databasePort=i.databasePort,a.exports=i.exports,a.pid=i.pid,a.port=i.port,a.shadowDatabasePort=i.shadowDatabasePort;let{exports:c,pid:d}=i;if(o)return{...a,status:"unknown"};if(!kt(d,r))return r&&console.debug(`[State] server state for "${n}" has no running process with PID: ${d}`),{...a,status:"not_running"};let m=U(n);try{if(!await(0,j.check)(m,{lockfilePath:(0,C.join)(m,".lock")}))return r&&console.debug(`[State] server state for "${n}" is not locked, indicating it is not running.`),{...a,status:"starting_up"}}catch(N){r&&console.error(`[State] server state for "${n}" failed to check lock:`,N)}if(!c)return{...a,status:"starting_up"};let{http:h}=c,{hc:b}=await import("hono/client"),T=await b(h.url).health.$get();if(!T.ok)return r&&console.debug(`[State] server state for "${n}" is not live: ${JSON.stringify(T)}`),{...a,status:"not_running"};let R=await T.json();return R.name!==t?(r&&console.debug(`[State] server state for "${n}" has mismatched health response: ${JSON.stringify(R)}`),{...a,status:"unknown"}):(r&&console.debug(`[State] server state for "${t}" is live: ${JSON.stringify(R)}`),{...a,status:"running"})}catch(i){return r&&console.error(`[State] failed to get server status for "${n}":`,i),{...a,status:"error"}}}var _e=class extends Error{name="ServerStateAlreadyExistsError";constructor(e){super(`A Prisma Dev server with the name "${e}" is already running.`)}},ne=class extends _e{#t;name="ServerAlreadyRunningError";constructor(e){super(e.name),this.#t=e}get server(){return E.fromServerDump({debug:this.#t.debug,name:this.#t.name})}};async function Ht(t){let e=await E.createExclusively(t),[r,o]=await Promise.all([be("database",e),be("shadow_database",e)]),n=await It(r,e),s=`prisma+postgres://localhost:${n.port}/?${new URLSearchParams({api_key:Me({databaseUrl:r.prismaORMConnectionString,name:e.name,shadowDatabaseUrl:o.prismaORMConnectionString})}).toString()}`,a={database:{connectionString:r.connectionString,prismaORMConnectionString:r.prismaORMConnectionString,terminalCommand:r.terminalCommand},http:{url:n.url},ppg:{url:s},shadowDatabase:{connectionString:o.prismaORMConnectionString,prismaORMConnectionString:o.prismaORMConnectionString,terminalCommand:o.terminalCommand}};return await e.writeServerDump(a),{...a,close:()=>i(e,[n,r,o]),name:e.name};async function i(c,d){let h=(await Promise.allSettled(d.map(b=>b.close()))).filter(b=>b.status==="rejected").map(b=>new Error(b.reason));try{await c.close()}catch(b){h.push(b)}if(h.length>0)throw new AggregateError(h,"Failed to close some servers")}}var se;process.once("SIGTERM",()=>{console.log("SIGTERM received, shutting down..."),process.removeAllListeners("SIGINT"),process.exitCode=143,se?.close().finally(()=>process.exit())});process.once("SIGINT",()=>{console.log("SIGINT received, shutting down..."),process.removeAllListeners("SIGTERM"),process.exitCode=130,se?.close().finally(()=>process.exit())});async function Dr(){let[,,t]=process.argv;if(!t)return process.send?.({type:"error",error:'Missing "name" argument, server cannot be started'},void 0),process.exit(1);try{se=await Ht({debug:!0,persistenceMode:"stateful",name:t}),process.send?.({type:"started",server:se},void 0)}catch(e){console.error(e);let r=e instanceof Error?e.message:String(e);process.send?.({type:"error",error:r},void 0),await(0,Bt.setTimeout)(1e3),process.exit(1)}}Dr();