UNPKG

@prisma/dev

Version:

A local Prisma Postgres server for development and testing

4 lines (3 loc) 6.17 kB
import{a as M,b as A,c as I,d as m,e as T}from"./chunk-LMPFMHCB.js";import{b as c,f as $,g as k,h as R}from"./chunk-I55EQWKN.js";import{writeFile as Z}from"fs/promises";import{join as d}from"pathe";import{check as z,lock as K}from"proper-lockfile";import{process as F}from"std-env";import{integer as J,literal as W,minLength as G,minValue as U,number as j,object as f,optional as b,parseJson as Q,pipe as l,safeParse as X,string as g,url as ee}from"valibot";import{process as Y}from"std-env";function V(r,e){if(r==null)return!1;try{return Y.kill?.(r,0)??!0}catch(t){return e&&console.error(`Error checking if process with PID ${r} exists:`,t),!1}}var w=l(g(),ee()),N=f({connectionString:w,prismaORMConnectionString:b(w),terminalCommand:b(g())}),L=f({url:w}),D=l(j(),J(),U(1)),te=f({database:N,http:L,ppg:L,shadowDatabase:N}),re=f({databasePort:D,exports:b(te),name:l(g(),G(1)),pid:b(l(j(),J(),U(0))),port:D,shadowDatabasePort:D,version:W("1")}),E=Symbol("initialize"),y="default",i=class{_databasePort;debug;dryRun;name;persistenceMode;pid;_port;_shadowDatabasePort;constructor(e){this._databasePort=e.databasePort??m,this.debug=e.debug??!1,this.dryRun=e.dryRun??!1,this.name=e.name??y,this.persistenceMode=e.persistenceMode,this.pid=e.pid??F.pid,this._port=e.port??m,this._shadowDatabasePort=e.shadowDatabasePort??m}static async createExclusively(e){let t=e?.dryRun!==!0&&e?.persistenceMode!=="stateless"?new p(e):new x(e);return await t[E](),t}static async fromServerDump(e){let{debug:t,name:o=y}=e??{},s=c(o),a=p.getServerDumpPath(s),u=await $(a);if(u==null)return t&&console.debug(`[State] No server dump file found at: ${a}`),null;t&&(console.debug(`[State] server dump file found at "${a}":`),console.debug(u));let{issues:h,output:n,success:P}=X(l(g(),Q(),re),u);if(!P)throw t&&console.debug(`[State] Invalid server dump file at "${a}": ${JSON.stringify(h,null,2)}`),new Error(`Invalid Prisma Dev state for "${o}".`);return new p({databasePort:n.databasePort,debug:t,dryRun:!1,name:o,pid:n.pid,port:n.port,serverDump:n,shadowDatabasePort:n.shadowDatabasePort})}static async scan(e){let{debug:t}=e??{},o=d(c(y),"..");t&&console.debug(`[State] scanning for server states in: ${o}`);let s=await R(o);return t&&console.debug(`[State] found server names: ${JSON.stringify(s)}`),await Promise.all(s.map(a=>se(a,e)))}get databasePort(){return this._databasePort}get port(){return this._port}get shadowDatabasePort(){return this._shadowDatabasePort}},x=class extends i{constructor(e){super({...e,databasePort:e?.databasePort??M,persistenceMode:"stateless",port:e?.port??A,shadowDatabasePort:e?.shadowDatabasePort??I})}get databaseDumpPath(){return"<DUMP_PATH>"}get pgliteDataDirPath(){return"memory://"}async[E](){}async close(){}async writeServerDump(){}},p=class r extends i{#t;#e;#a;#o;#r;#s=null;constructor(e){super({...e,persistenceMode:"stateful"}),this.#e=c(this.name),this.#t=d(this.#e,"db_dump.bak"),this.#a=d(this.#e,".pglite"),this.#r=e?.serverDump??null,this.#o=r.getServerDumpPath(this.#e)}static getServerDumpPath(e){return d(e,"server.json")}get databaseDumpPath(){return this.#t}get exports(){return this.#r?.exports}get pgliteDataDirPath(){return this.#a}async[E](){await k(this.#e),this.debug&&console.debug(`[State] using data directory: ${this.#e}`);try{this.#s=await K(this.#e,{lockfilePath:d(this.#e,".lock")}),this.debug&&console.debug(`[State] obtained lock on: ${this.#e}`);let e=await i.scan({debug:this.debug,onlyMetadata:!0}),t=await T({debug:this.debug,name:this.name,requestedPorts:{databasePort:this.databasePort,port:this.port,shadowDatabasePort:this.shadowDatabasePort},servers:e});this._databasePort=t.databasePort,this._port=t.port,this._shadowDatabasePort=t.shadowDatabasePort,await this.writeServerDump()}catch(e){throw e instanceof Error&&"code"in e&&e.code==="ELOCKED"?new O(this):e}}async close(){if(this.#s!=null)try{await this.#s(),this.#s=null,this.debug&&console.debug(`[State] released lock on: ${this.#e}`)}catch(e){throw console.error(`[State] failed to release lock on: ${this.#e}`),e}}async writeServerDump(e){this.#r={name:this.name,version:"1",pid:F.pid,port:this.port,databasePort:this.databasePort,shadowDatabasePort:this.shadowDatabasePort,exports:e},await Z(this.#o,`${JSON.stringify(this.#r,null,2)} `,{encoding:"utf-8"})}};async function se(r,e){let{debug:t,onlyMetadata:o}=e||{},s={databasePort:-1,exports:void 0,name:r,pid:void 0,port:-1,shadowDatabasePort:-1,version:"1"};try{let a=await i.fromServerDump({debug:t,name:r});if(!a)return t&&console.debug(`[State] no server state found for name: ${r}`),{...s,status:"no_such_server"};s.databasePort=a.databasePort,s.exports=a.exports,s.pid=a.pid,s.port=a.port,s.shadowDatabasePort=a.shadowDatabasePort;let{exports:u,pid:h}=a;if(o)return{...s,status:"unknown"};if(!V(h,t))return t&&console.debug(`[State] server state for "${r}" has no running process with PID: ${h}`),{...s,status:"not_running"};let n=c(r);try{if(!await z(n,{lockfilePath:d(n,".lock")}))return t&&console.debug(`[State] server state for "${r}" is not locked, indicating it is not running.`),{...s,status:"starting_up"}}catch(C){t&&console.error(`[State] server state for "${r}" failed to check lock:`,C)}if(!u)return{...s,status:"starting_up"};let{http:P}=u,{hc:B}=await import("hono/client"),v=await B(P.url).health.$get();if(!v.ok)return t&&console.debug(`[State] server state for "${r}" is not live: ${JSON.stringify(v)}`),{...s,status:"not_running"};let S=await v.json();return S.name!==r?(t&&console.debug(`[State] server state for "${r}" has mismatched health response: ${JSON.stringify(S)}`),{...s,status:"unknown"}):(t&&console.debug(`[State] server state for "${r}" is live: ${JSON.stringify(S)}`),{...s,status:"running"})}catch(a){return t&&console.error(`[State] failed to get server status for "${r}":`,a),{...s,status:"error"}}}var _=class extends Error{name="ServerStateAlreadyExistsError";constructor(e){super(`A Prisma Dev server with the name "${e}" is already running.`)}},O=class extends _{#t;name="ServerAlreadyRunningError";constructor(e){super(e.name),this.#t=e}get server(){return i.fromServerDump({debug:this.#t.debug,name:this.#t.name})}};export{i as a,_ as b,O as c};