UNPKG

@prisma/dev

Version:

A local Prisma Postgres server for development and testing

108 lines (104 loc) • 28 kB
"use strict";var He=Object.create;var x=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Je=Object.getOwnPropertyNames;var Ye=Object.getPrototypeOf,Xe=Object.prototype.hasOwnProperty;var Ve=(e,t)=>{for(var r in t)x(e,r,{get:t[r],enumerable:!0})},se=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Je(t))!Xe.call(e,s)&&s!==r&&x(e,s,{get:()=>t[s],enumerable:!(n=Ke(t,s))||n.enumerable});return e};var S=(e,t,r)=>(r=e!=null?He(Ye(e)):{},se(t||!e||!e.__esModule?x(r,"default",{value:e,enumerable:!0}):r,e)),Ze=e=>se(x({},"__esModule",{value:!0}),e);var Zt={};Ve(Zt,{attachWalEventBridge:()=>k,dumpDB:()=>ze,shouldPollWalAfterMessages:()=>G,shouldPollWalAfterResponse:()=>te,startDBServer:()=>Kt,startLazyShadowDBServer:()=>Qe});module.exports=Ze(Zt);var et=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,b=et();var F=require("net"),Oe=require("path"),Me=require("pathe/utils");var B=require("fs"),P=require("fs/promises"),oe=require("util"),ae=require("zlib");var g=S(require("path"),1),q=S(require("os"),1),L=S(require("process"),1),R=q.default.homedir(),W=q.default.tmpdir(),{env:v}=L.default,tt=e=>{let t=g.default.join(R,"Library");return{data:g.default.join(t,"Application Support",e),config:g.default.join(t,"Preferences",e),cache:g.default.join(t,"Caches",e),log:g.default.join(t,"Logs",e),temp:g.default.join(W,e)}},rt=e=>{let t=v.APPDATA||g.default.join(R,"AppData","Roaming"),r=v.LOCALAPPDATA||g.default.join(R,"AppData","Local");return{data:g.default.join(r,e,"Data"),config:g.default.join(t,e,"Config"),cache:g.default.join(r,e,"Cache"),log:g.default.join(r,e,"Log"),temp:g.default.join(W,e)}},nt=e=>{let t=g.default.basename(R);return{data:g.default.join(v.XDG_DATA_HOME||g.default.join(R,".local","share"),e),config:g.default.join(v.XDG_CONFIG_HOME||g.default.join(R,".config"),e),cache:g.default.join(v.XDG_CACHE_HOME||g.default.join(R,".cache"),e),log:g.default.join(v.XDG_STATE_HOME||g.default.join(R,".local","state"),e),temp:g.default.join(W,t,e)}};function z(e,{suffix:t="nodejs"}={}){if(typeof e!="string")throw new TypeError(`Expected a string, got ${typeof e}`);return t&&(e+=`-${t}`),L.default.platform==="darwin"?tt(e):L.default.platform==="win32"?rt(e):nt(e)}var st=S(require("zeptomatch"),1),or=z("prisma-dev"),ar=(0,oe.promisify)(ae.unzip);async function ie(e){try{return await(0,P.access)(e,P.constants.F_OK),!0}catch(t){if(ot(t))return!1;throw t}}async function ue(e,t){await e.stream().pipeTo(B.WriteStream.toWeb((0,B.createWriteStream)(t,{encoding:"utf8"})))}function ot(e){return e!=null&&typeof e=="object"&&"code"in e&&e.code==="ENOENT"}var j=require("get-port-please"),ce=require("remeda");var N=class extends Error{constructor(r){super(`Port \`${r}\` is not available.`);this.port=r}name="PortNotAvailableError"};var K=require("perf_hooks"),Pe=require("@electric-sql/pglite");var me=require("buffer");var le=/(?:"[^"]+"|`[^`]+`|\[[^\]]+\]|\w+)/,at=new RegExp(`(?:${le.source}\\.)*${le.source}`),it=new RegExp(`(?:FROM|JOIN|UPDATE|INTO|TABLE)\\s+(${at.source})`,"gi"),ut=/"([^"]+)"|`([^`]+)`|\[([^\]]+)\]|(\w+)/g,de=/prismaQuery='([^']+)'/,ct=new Set([T(` select b.oid, b.typarray from pg_catalog.pg_type a left join pg_catalog.pg_type b on b.oid = a.typelem where a.typcategory = $1 group by b.oid, b.typarray order by b.oid `),T('GRANT "pg_write_all_data" TO "prisma_application"'),T("SELECT SUM(reads)::BIGINT AS reads, SUM(writes)::BIGINT AS writes, SUM(COALESCE(extends, $1))::BIGINT AS extends FROM pg_stat_io"),T("SELECT pg_database_size(current_database())::BIGINT, SUM(pg_total_relation_size(relid))::BIGINT AS pg_total_relation_size FROM pg_stat_user_tables"),T("SELECT COUNT(*) AS cnt FROM pg_stat_activity WHERE pid <> pg_backend_pid() and xact_start notnull")]),lt=[/^BEGIN\b/i,/^COMMIT\b/i,/^ROLLBACK\b/i,/^SAVEPOINT\b/i,/^RELEASE\b/i,/^SET\b/i,/^SHOW\b/i,/^DISCARD\b/i,/^DEALLOCATE\b/i,/^CLOSE\b/i,/^CREATE EXTENSION\b/i,/^WITH state_assign\b/i];function T(e){return e.replace(/\s+/g," ").trim()}function pe(e){return be(T(e))}function ge(e){if(!e?.action||!e.model&&/raw/i.test(e.action))return null;let t=e.payload?be(JSON.stringify(e.payload)):"0";return`${e.model??""}.${e.action}:${t}`}function dt(e){let t=new Set;for(let r of e.matchAll(it)){let n=r[1];if(!n)continue;let s;for(let o of n.matchAll(ut))s=o[1]??o[2]??o[3]??o[4];s&&!s.startsWith("pg_")&&t.add(s)}return Array.from(t)}function mt(e){return ct.has(e)?!0:lt.some(t=>t.test(e))}function fe(e){if(mt(T(e)))return null;let t=dt(e);return t.length===0&&/\bpg_\w+/i.test(e)?null:t}function H(e){if(Array.isArray(e))return e.map(H);if(e!==null&&typeof e=="object"){let t=e;return t.$type==="Param"?"<<redacted>>":Object.fromEntries(Object.entries(t).map(([r,n])=>[r,H(n)]))}return e}function ye(e){let t=e.match(de);if(!t?.[1])return{cleanedSql:T(e),prismaQueryInfo:null};let r=e.replace(de,"");r=r.replace(/,\s*,/g,",").replace(/\/\*\s*,/g,"/*").replace(/,\s*\*\//g,"*/").replace(/\/\*\s*\*\//g,"").replace(/\s+/g," ").trim();let n=decodeURIComponent(t[1]),s=n.indexOf(":");if(s===-1)return{cleanedSql:r,prismaQueryInfo:{action:n,isRaw:!0}};let o=n.slice(0,s),l=n.slice(s+1),c=o.indexOf("."),i=c===-1?void 0:o.slice(0,c),u=c===-1?o:o.slice(c+1);if(!u)return{cleanedSql:r,prismaQueryInfo:null};let p;try{p=H(JSON.parse(me.Buffer.from(l,"base64url").toString("utf8")))}catch{p=void 0}return{cleanedSql:r,prismaQueryInfo:{action:u,isRaw:!1,model:i,payload:p}}}function be(e){let t=5381;for(let r=0;r<e.length;r++)t=(t<<5)+t+e.charCodeAt(r)&4294967295;return(t>>>0).toString(36)}var O=new WeakMap;function Ee(e){let t=O.get(e);if(t&&!t.closed)return t.bridge;let r=pt(e),n={bridge:{close:()=>(n.closed||(n.closed=!0,n.sessions.clear(),n.subscribers.clear(),n.queryQueue.enqueue=n.originalEnqueue,n.queryQueue.clearQueueForHandler=n.originalClearQueueForHandler,O.delete(e)),Promise.resolve()),subscribe:s=>(n.subscribers.add(s),()=>{n.subscribers.delete(s)})},closed:!1,originalClearQueueForHandler:r.clearQueueForHandler.bind(r),originalEnqueue:r.enqueue.bind(r),queryQueue:r,sessions:new Map,subscribers:new Set};return r.clearQueueForHandler=s=>{n.sessions.delete(s),n.originalClearQueueForHandler(s)},r.enqueue=async(s,o,l)=>{let c=gt(n,s),i=bt(o);ft(c,i);let u=yt(c,i);if(!u)return await n.originalEnqueue(s,o,l);let p={commandTags:[],dataRowCount:0},y=new Pe.protocol.Parser,a=K.performance.now(),d=await n.originalEnqueue(s,o,D=>{y.parse(D,je=>{Tt(p,je)}),l(D)}),f=Math.max(0,K.performance.now()-a);return _t(n,{applicationName:u.applicationName,durationMs:f,query:u.query,responseStats:p}),d},O.set(e,n),n.bridge}async function Se(e){await O.get(e)?.bridge.close()}function pt(e){let t=e.queryQueue;if(!t||typeof t.enqueue!="function"||typeof t.clearQueueForHandler!="function")throw new Error("PGLiteSocketServer query queue is unavailable for query insights capture");return t}function gt(e,t){let r=e.sessions.get(t);if(r)return r;let n={applicationName:null,portals:new Map,statements:new Map};return e.sessions.set(t,n),n}function ft(e,t){if(t)switch(t.kind){case"startup":e.applicationName=t.applicationName;return;case"parse":e.statements.set(t.statementName,t.query);return;case"bind":{let r=e.statements.get(t.statementName);r&&e.portals.set(t.portalName,r);return}case"close":t.target==="portal"?e.portals.delete(t.name):e.statements.delete(t.name);return;default:return}}function yt(e,t){if(!t)return null;if(t.kind==="query")return{applicationName:e.applicationName,query:t.query};if(t.kind==="execute"){let r=e.portals.get(t.portalName);return r?{applicationName:e.applicationName,query:r}:null}return null}function bt(e){let t=Buffer.from(e);if(t.length<4)return null;let r=t.readInt32BE(0);if(t.length>=8&&r===t.length){let s=t.readInt32BE(4);if(s===196608||s===196608)return Pt(t)}if(t.length<5)return null;switch(String.fromCharCode(t[0]??0)){case"Q":return Et(t);case"P":return St(t);case"B":return wt(t);case"E":return ht(t);case"C":return Rt(t);default:return null}}function Pt(e){let t=8,r=null;for(;t<e.length-1;){let n=w(e,t);if(!n||n.value==="")break;t=n.nextOffset;let s=w(e,t);if(!s)break;t=s.nextOffset,n.value==="application_name"&&(r=s.value)}return{applicationName:r,kind:"startup"}}function Et(e){let t=w(e,5);return t?{kind:"query",query:t.value}:null}function St(e){let t=w(e,5);if(!t)return null;let r=w(e,t.nextOffset);return r?{kind:"parse",query:r.value,statementName:t.value}:null}function wt(e){let t=w(e,5);if(!t)return null;let r=w(e,t.nextOffset);return r?{kind:"bind",portalName:t.value,statementName:r.value}:null}function ht(e){let t=w(e,5);return t?{kind:"execute",portalName:t.value}:null}function Rt(e){if(e.length<7)return null;let t=e[5];if(t===void 0)return null;let r=w(e,6);return r?{kind:"close",name:r.value,target:t===80?"portal":"statement"}:null}function w(e,t){let r=e.indexOf(0,t);return r===-1?null:{nextOffset:r+1,value:e.toString("utf8",t,r)}}function Tt(e,t){if(t.name==="dataRow"){e.dataRowCount+=1;return}t.name==="commandComplete"&&typeof t.text=="string"&&t.text.length>0&&e.commandTags.push(t.text)}function _t(e,t){let r=ye(t.query),n=fe(r.cleanedSql);if(!n)return;let s=pe(r.cleanedSql),o={applicationName:t.applicationName,durationMs:t.durationMs,groupKey:ge(r.prismaQueryInfo),prismaQueryInfo:r.prismaQueryInfo,query:r.cleanedSql,queryId:s,reads:0,rowsReturned:At(t.responseStats),tables:n,timestamp:new Date().toISOString()};for(let l of e.subscribers)l([o])}function At(e){let t=e.commandTags.reduce((r,n)=>r+vt(n),0);return Math.max(t,e.dataRowCount)}function vt(e){let t=e.trim().split(/\s+/).at(-1);return!t||!/^\d+$/.test(t)?0:Number(t)}var A=require("fs"),_=require("fs/promises"),he=require("module"),Re=require("path"),h=require("url"),Dt=(0,he.createRequire)(b),Nt=["initdb.wasm","pglite.data","pglite.wasm"],Y="pglite-seed.tar.gz",Te={amcheck:"amcheck.tar.gz",bloom:"bloom.tar.gz",btree_gin:"btree_gin.tar.gz",btree_gist:"btree_gist.tar.gz",citext:"citext.tar.gz",cube:"cube.tar.gz",dict_int:"dict_int.tar.gz",dict_xsyn:"dict_xsyn.tar.gz",earthdistance:"earthdistance.tar.gz",file_fdw:"file_fdw.tar.gz",fuzzystrmatch:"fuzzystrmatch.tar.gz",hstore:"hstore.tar.gz",intarray:"intarray.tar.gz",isn:"isn.tar.gz",lo:"lo.tar.gz",ltree:"ltree.tar.gz",pageinspect:"pageinspect.tar.gz",pg_buffercache:"pg_buffercache.tar.gz",pg_freespacemap:"pg_freespacemap.tar.gz",pg_surgery:"pg_surgery.tar.gz",pg_trgm:"pg_trgm.tar.gz",pg_visibility:"pg_visibility.tar.gz",pg_walinspect:"pg_walinspect.tar.gz",seg:"seg.tar.gz",tablefunc:"tablefunc.tar.gz",tcn:"tcn.tar.gz",tsm_system_rows:"tsm_system_rows.tar.gz",tsm_system_time:"tsm_system_time.tar.gz",unaccent:"unaccent.tar.gz",uuid_ossp:"uuid-ossp.tar.gz",vector:"vector.tar.gz"},It=[...Nt.map(e=>({fileName:e,kind:"core",name:e})),{fileName:Y,kind:"core",name:Y},...Object.entries(Te).map(([e,t])=>({fileName:t,kind:"extension",name:e}))],C=new Map,xt=Symbol.for("@prisma/dev/bundled-pglite-runtime-asset-sources"),M=null;async function X(){await kt();let e=_e();if(e)return await Mt(e),await Lt(e);let t=Ct(),r=t.href,n=C.get(r);return n||(n=Bt(t),C.set(r,n)),await n}async function Lt(e){let t=`bundled:${e.wasmModule.href}:${e.fsBundle.href}`,r=C.get(t);return r||(r=Ot(e),C.set(t,r)),await r}async function Bt(e){let t=$(new URL("./runtime-assets/",b)),[r,n,s]=await Promise.all([(0,_.readFile)(U("pglite.data",e,t)),(0,_.readFile)(U(Y,e,t)),(0,_.readFile)(U("pglite.wasm",e,t))]),o=Ae();return{extensions:Object.fromEntries(Object.entries(Te).map(([l,c])=>[l,U(c,e,t)])),fsBundle:new Blob([Uint8Array.from(r)]),loadDataDir:new Blob([Uint8Array.from(n)]),wasmModule:await o.compile(s)}}async function Ot(e){let[t,r,n]=await Promise.all([J(e.fsBundle),J(e.loadDataDir),J(e.wasmModule)]),s=Ae();return{extensions:e.extensions,fsBundle:new Blob([Uint8Array.from(t)]),loadDataDir:new Blob([Uint8Array.from(r)]),wasmModule:await s.compile(n)}}async function Mt(e){if(e.initdbWasm.protocol!=="file:")return;let t=new URL("initdb.wasm",$(new URL("./",e.initdbWasm))),r=(0,h.fileURLToPath)(t);(0,A.existsSync)(r)||await(0,_.copyFile)((0,h.fileURLToPath)(e.initdbWasm),r)}function $(e){return e instanceof URL?we(e):we((0,h.pathToFileURL)(e))}function we(e){return e.href.endsWith("/")?e:new URL(`${e.href}/`)}function Ut(){let e=Dt.resolve("@electric-sql/pglite");return $((0,Re.dirname)(e))}function Ct(){let e=$(new URL("./",b));if($t(e))return e;if(Gt())return Ut();throw new Error("Unable to locate PGlite runtime assets. If you bundled @prisma/dev, copy them next to the bundle with copyPrismaDevRuntimeAssets().")}function $t(e){return It.every(t=>(0,A.existsSync)((0,h.fileURLToPath)(new URL(t.fileName,e))))}function _e(){return globalThis[xt]??null}async function kt(){!Qt()||_e()||(M||(M=import("./runtime-assets-manifest.bun.js").then(()=>{}).catch(e=>{throw M=null,e})),await M)}function Gt(){let e=(0,h.fileURLToPath)(new URL("../package.json",b));if(!(0,A.existsSync)(e))return!1;try{return JSON.parse((0,A.readFileSync)(e,"utf8")).name==="@prisma/dev"}catch{return!1}}function Qt(){return typeof globalThis.Bun<"u"}function Ae(){let e=globalThis.WebAssembly;if(!e)throw new Error("WebAssembly is not available in this runtime.");return e}async function J(e){if(e.protocol==="file:")return await(0,_.readFile)(e);let t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch runtime asset ${e.href}: ${t.status} ${t.statusText}`);return new Uint8Array(await t.arrayBuffer())}function U(e,t,r){let n=new URL(e,t);if((0,A.existsSync)((0,h.fileURLToPath)(n)))return n;if(r){let s=new URL(e,r);if((0,A.existsSync)((0,h.fileURLToPath)(s)))return s}return n}var ee=require("@electric-sql/pglite"),E="_prisma_dev_wal",Z="events",Ne="install_all_triggers",ve="capture_event",De="prisma_dev_wal_capture",I=new WeakMap,Ft=new Set(["ALTER","COMMIT","COPY","CREATE","DELETE","DROP","INSERT","MERGE","TRUNCATE","UPDATE"]);async function k(e,t){let r=I.get(e);if(r&&!r.closed)return r.bridge;let n=e.execProtocolRaw.bind(e),s=e.execProtocolRawStream.bind(e),o={bridge:{close:async()=>{o.closed||(o.closed=!0,o.subscribers.clear(),e.execProtocolRaw===l&&(e.execProtocolRaw=n),e.execProtocolRawStream===c&&(e.execProtocolRawStream=s),await o.pollPromise,I.delete(e))},poll:async()=>{await V(o,e)},subscribe:i=>(o.subscribers.add(i),()=>{o.subscribers.delete(i)})},closed:!1,ensureInfrastructurePromise:null,pendingPoll:!1,pollPromise:null,subscribers:new Set,suppressDepth:0},l=async(i,u)=>{let p=await n(i,u);return!o.closed&&o.suppressDepth===0&&te(p)&&V(o,e),p},c=async(i,u)=>{let p=[],y=new ee.protocol.Parser,a=u?.onRawData;await s(i,{...u,onRawData:d=>{y.parse(d,f=>{p.push(f)}),a?.(d)}}),!o.closed&&o.suppressDepth===0&&G(p)&&V(o,e)};return e.execProtocolRaw=l,e.execProtocolRawStream=c,I.set(e,o),await xe(o,e),o.bridge}async function Ie(e){let t=I.get(e);t&&await t.bridge.close()}function G(e){for(let t of e){if(t.name!=="commandComplete"||typeof t.text!="string")continue;let r=t.text.split(/\s+/,1)[0]?.toUpperCase();if(r&&Ft.has(r))return!0}return!1}function te(e){if(e.length===0)return!1;let t=[];return new ee.protocol.Parser().parse(e,n=>{t.push(n)}),G(t)}async function xe(e,t){e.ensureInfrastructurePromise??=re(e,t,async()=>{await t.exec(`CREATE SCHEMA IF NOT EXISTS "${E}"`),await t.exec(` CREATE TABLE IF NOT EXISTS "${E}"."${Z}" ( id BIGSERIAL PRIMARY KEY, txid BIGINT NOT NULL DEFAULT txid_current(), schema_name TEXT NOT NULL, table_name TEXT NOT NULL, op TEXT NOT NULL, row_data JSONB, old_row_data JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp() ) `),await t.exec(` CREATE OR REPLACE FUNCTION "${E}"."${ve}"() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_TABLE_SCHEMA = '${E}' THEN RETURN COALESCE(NEW, OLD); END IF; INSERT INTO "${E}"."${Z}" ( txid, schema_name, table_name, op, row_data, old_row_data ) VALUES ( txid_current(), TG_TABLE_SCHEMA, TG_TABLE_NAME, lower(TG_OP), CASE WHEN TG_OP IN ('INSERT', 'UPDATE') THEN to_jsonb(NEW) ELSE NULL END, CASE WHEN TG_OP IN ('UPDATE', 'DELETE') THEN to_jsonb(OLD) ELSE NULL END ); RETURN COALESCE(NEW, OLD); END; $$; `),await t.exec(` CREATE OR REPLACE FUNCTION "${E}"."${Ne}"() RETURNS void LANGUAGE plpgsql AS $$ DECLARE target REGCLASS; BEGIN FOR target IN SELECT c.oid::regclass FROM pg_class AS c JOIN pg_namespace AS n ON n.oid = c.relnamespace WHERE c.relkind IN ('r', 'p') AND n.nspname NOT IN ('${E}', 'information_schema', 'pg_catalog') AND n.nspname NOT LIKE 'pg_temp_%' AND n.nspname NOT LIKE 'pg_toast%' LOOP IF EXISTS ( SELECT 1 FROM pg_trigger WHERE tgrelid = target AND tgname = '${De}' ) THEN CONTINUE; END IF; EXECUTE format( 'CREATE TRIGGER %I AFTER INSERT OR UPDATE OR DELETE ON %s FOR EACH ROW EXECUTE FUNCTION "${E}"."${ve}"()', '${De}', target::text ); END LOOP; END; $$; `),await Le(e,t)}),await e.ensureInfrastructurePromise}async function Le(e,t){await re(e,t,async()=>{await t.query(`SELECT "${E}"."${Ne}"()`)})}async function qt(e,t){await xe(e,t),await Le(e,t);let r=await re(e,t,async()=>await t.query(` WITH drained AS ( DELETE FROM "${E}"."${Z}" RETURNING txid, schema_name, table_name, op, row_data, old_row_data, id ) SELECT txid, schema_name, table_name, op, row_data, old_row_data FROM drained ORDER BY id `));if(r.rows.length===0||e.subscribers.size===0)return;let n=r.rows.map(Wt);for(let s of e.subscribers)queueMicrotask(()=>{if(!e.closed&&e.subscribers.has(s))try{s(n)}catch(o){console.error("[WAL bridge] subscriber failed",o)}})}async function V(e,t){if(!e.closed){if(e.pollPromise){e.pendingPoll=!0,await e.pollPromise;return}e.pollPromise=(async()=>{do e.pendingPoll=!1,await qt(e,t);while(e.pendingPoll&&!e.closed)})().finally(()=>{e.pollPromise=null}),await e.pollPromise}}async function re(e,t,r){e.suppressDepth+=1;try{return await r()}finally{e.suppressDepth-=1,e.suppressDepth===0&&!e.closed&&I.get(t)!==e&&(e.closed=!0)}}function Wt(e){return{oldRecord:e.old_row_data,record:e.row_data,schema:e.schema_name,table:e.table_name,txid:String(e.txid),type:zt(e.op)}}function zt(e){switch(e.toLowerCase()){case"delete":return"delete";case"insert":return"insert";case"update":return"update";default:throw new Error(`Unsupported WAL bridge operation: ${e}`)}}var jt=10,Ue="127.0.0.1",Ce=128*1024*1024,$e=["-c","shared_buffers=16MB","-c","temp_buffers=1MB","-c","work_mem=1MB","-c","maintenance_work_mem=16MB","-c","wal_buffers=1MB"],m={connectionLimit:jt,connectTimeout:0,database:"template1",maxIdleConnectionLifetime:0,password:"postgres",poolTimeout:0,socketTimeout:0,sslMode:"disable",username:"postgres"},Ht=`postgres://${m.username}:${m.password}@localhost`,ne=new URLSearchParams({sslmode:m.sslMode}),ke=new URLSearchParams({...Object.fromEntries(ne.entries()),connection_limit:String(m.connectionLimit),connect_timeout:String(m.connectTimeout),max_idle_connection_lifetime:String(m.maxIdleConnectionLifetime),pool_timeout:String(m.poolTimeout),socket_timeout:String(m.socketTimeout)});async function Ge(e){let{rows:t}=await e.query("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = 'postgres') AS exists");t[0]?.exists?await e.exec(`ALTER ROLE ${m.username} WITH LOGIN SUPERUSER PASSWORD '${m.password}'`):await e.exec(`CREATE ROLE ${m.username} WITH LOGIN SUPERUSER PASSWORD '${m.password}'`),await e.exec(`SET ROLE ${m.username}`)}async function Kt(e,t){if(e==="shadow_database"&&!t.dryRun)return await Qe(t);let r=e==="database"?t.databasePort:t.shadowDatabasePort;return t.dryRun?qe(e,t,{db:null,port:r,server:null}):await Fe(e,t,{port:r,updateServerStatePort:!0})}async function Qe(e,t=async()=>await Fe("shadow_database",e,{port:0,updateServerStatePort:!1})){let{debug:r}=e,n=null,s=null,o=!1,l=new Set,c=(0,F.createServer)(u),i=await Jt(c,e.shadowDatabasePort);return e.shadowDatabasePort=i,r&&console.debug(`[shadow_database] lazy proxy listening on port ${i}`),{...m,attachWalEventBridge:()=>Promise.reject(new Error("WAL bridge is only available for the primary database server")),attachQueryInsightsBridge:()=>Promise.reject(new Error("Query insights are only available for the primary database server")),close:async()=>{o=!0;for(let d of l)d.destroy();l.clear();let a=[];try{await Yt(c),r&&console.debug(`[shadow_database] lazy proxy stopped on port ${i}`)}catch(d){console.error("[shadow_database] lazy proxy stop error",d),a.push(d)}try{await s?.catch(()=>null),await n?.close()}catch(d){console.error("[shadow_database] backend close error",d),a.push(d)}if(a.length>0)throw new AggregateError(a,"Failed to close shadow_database properly")},connectionString:Q(i,ne),dump:async()=>{},getPrimaryKeyColumns:()=>Promise.reject(new Error("Primary key resolution is only available for the primary database server")),port:i,prismaORMConnectionString:Q(i,ke),terminalCommand:`PGPASSWORD=${m.password} PGSSLMODE=${m.sslMode} psql -h localhost -p ${i} -U ${m.username} -d ${m.database}`};function u(a){l.add(a);let d=()=>{l.delete(a)};a.once("close",d),a.once("error",d),a.pause(),p(a)}async function p(a){try{let d=await y();if(o){a.destroy();return}let f=(0,F.createConnection)({host:Ue,port:d.port});l.add(f);let D=()=>{l.delete(f)};f.once("close",D),f.once("error",D),a.once("close",()=>f.destroy()),a.once("error",()=>f.destroy()),f.once("error",()=>a.destroy()),f.once("connect",()=>{r&&console.debug(`[shadow_database] proxying connection to lazy backend on port ${d.port}`),a.resume(),a.pipe(f),f.pipe(a)})}catch(d){r&&console.error("[shadow_database] failed to start lazy backend",d),a.destroy(d instanceof Error?d:void 0)}}async function y(){if(n)return n;if(o)throw new Error("shadow_database is closed");return s||(r&&console.debug("[shadow_database] starting lazy backend..."),s=t().then(a=>(n=a,r&&console.debug(`[shadow_database] lazy backend started on port ${a.port}`),a)).catch(a=>{throw s=null,a})),await s}}async function Fe(e,t,r){let{debug:n}=t,{port:s,updateServerStatePort:o}=r,c=await(e==="shadow_database"?Xt:We)(t.pgliteDataDirPath,n);n&&c.onNotification((a,d)=>{console.debug(`[${e}][${a}] ${d}`)});let{PGLiteSocketServer:i}=await import("@electric-sql/pglite-socket"),u=e==="shadow_database"?t.shadowDatabaseIdleTimeoutMillis:t.databaseIdleTimeoutMillis,p=new i({db:c,debug:n,idleTimeout:Number.isFinite(u)?u:0,inspect:n,maxConnections:m.connectionLimit,port:s});n&&(p.addEventListener("listening",a=>{let{detail:d}=a;console.debug(`[${e}] server listening on ${JSON.stringify(d)}`)}),p.addEventListener("connection",a=>{let{clientAddress:d,clientPort:f}=a.detail;console.debug(`[${e}] client connected from ${d}:${f}`)}),p.addEventListener("error",a=>{let{detail:d}=a;console.error(`[${e}] server error:`,d)}));try{await p.start()}catch(a){throw a instanceof Error&&"code"in a&&a.code==="EADDRINUSE"?new N(s):a}let y=Number(p.getServerConn().split(":").at(1));return o&&(t[e==="database"?"databasePort":"shadowDatabasePort"]=y),qe(e,t,{db:c,port:y,server:p})}function qe(e,t,r){let{debug:n}=t,{db:s,port:o,server:l}=r||{},c=new Map;return n&&console.debug(`[${e}] server started on port ${o}`),{...m,attachWalEventBridge:async()=>{if(e!=="database"||!s)throw new Error("WAL bridge is only available for the primary database server");return await k(s)},attachQueryInsightsBridge:()=>{if(e!=="database"||!l)throw new Error("Query insights are only available for the primary database server");return Promise.resolve(Ee(l))},close:async()=>{let i=[];try{await l?.stop(),n&&console.debug(`[${e}] server stopped on port ${o}`)}catch(u){console.error(`[${e}] server stop error`,u),i.push(u)}if(e==="database"){try{l&&await Se(l),n&&console.debug(`[${e}] closed query insights bridge`)}catch(u){console.error(`[${e}] query insights bridge close error`,u),i.push(u)}try{s&&await Ie(s),n&&console.debug(`[${e}] closed WAL bridge`)}catch(u){console.error(`[${e}] WAL bridge close error`,u),i.push(u)}try{await s?.syncToFs(),n&&console.debug(`[${e}] synced to filesystem`)}catch(u){console.error(`[${e}] sync error`,u),i.push(u)}}try{await s?.close(),n&&console.debug(`[${e}] closed`)}catch(u){console.error(`[${e}] close error`,u),i.push(u)}if(i.length>0)throw new AggregateError(i,`Failed to close ${e} properly`)},connectionString:Q(o,ne),dump:async i=>{e==="shadow_database"||!s||await ze({db:s,debug:n,destinationPath:i})},getPrimaryKeyColumns:async(i,u)=>{if(e==="shadow_database"||!s)throw new Error("Primary key resolution is only available for the primary database server");let p=`${i}.${u}`,y=c.get(p);return y||(y=Vt(s,i,u).catch(a=>{throw c.delete(p),a}),c.set(p,y)),await y},port:o,prismaORMConnectionString:Q(o,ke),terminalCommand:`PGPASSWORD=${m.password} PGSSLMODE=${m.sslMode} psql -h localhost -p ${o} -U ${m.username} -d ${m.database}`}}function Q(e,t){return`${Ht}:${e}/${m.database}?${t.toString()}`}async function We(e,t){let{PGlite:r}=await import("@electric-sql/pglite"),n=await X(),s=e==="memory://"||!await ie((0,Oe.join)(e,"PG_VERSION")),o=await r.create({database:m.database,dataDir:e,debug:t?5:void 0,extensions:n.extensions,fsBundle:n.fsBundle,initialMemory:Ce,loadDataDir:s?n.loadDataDir:void 0,relaxedDurability:!1,startParams:[...r.defaultStartParams,...$e],wasmModule:n.wasmModule});return await Ge(o),o}async function Jt(e,t){return await new Promise((r,n)=>{let s=c=>{if(l(),c.code==="EADDRINUSE"){n(new N(t));return}n(c)},o=()=>{let c=e.address();if(l(),!c||typeof c=="string"){n(new Error("Failed to determine TCP server port"));return}r(c.port)},l=()=>{e.off("error",s),e.off("listening",o)};e.once("error",s),e.once("listening",o),e.listen(t,Ue)})}async function Yt(e){await new Promise((t,r)=>{e.close(n=>{let s=n;if(s&&s.code!=="ERR_SERVER_NOT_RUNNING"){r(s);return}t()})})}async function Xt(e,t){let{PGlite:r}=await import("@electric-sql/pglite"),n=await X(),s=await r.create({database:m.database,dataDir:"memory://",debug:t?5:void 0,extensions:n.extensions,fsBundle:n.fsBundle,initialMemory:Ce,loadDataDir:n.loadDataDir,relaxedDurability:!1,startParams:[...r.defaultStartParams,...$e],wasmModule:n.wasmModule});return await Ge(s),s}async function Vt(e,t,r){let{rows:n}=await e.query(` SELECT attribute.attname AS column_name FROM pg_constraint pk_constraint INNER JOIN pg_class relation ON relation.oid = pk_constraint.conrelid INNER JOIN pg_namespace namespace ON namespace.oid = relation.relnamespace INNER JOIN unnest(pk_constraint.conkey) WITH ORDINALITY AS keys(attnum, ordinality) ON TRUE INNER JOIN pg_attribute attribute ON attribute.attrelid = relation.oid AND attribute.attnum = keys.attnum WHERE pk_constraint.contype = 'p' AND namespace.nspname = ${Be(t)} AND relation.relname = ${Be(r)} ORDER BY keys.ordinality `);return n.map(s=>s.column_name)}function Be(e){return`'${e.replaceAll("'","''")}'`}async function ze(e){let{dataDir:t,db:r,debug:n,destinationPath:s}=e,o=r||await We(t,n),{pgDump:l}=await import("@electric-sql/pglite-tools/pg_dump"),c=await l({args:["--schema-only","--no-owner"],fileName:s?(0,Me.filename)(s):void 0,pg:await o.clone()});return s?(n&&console.debug(`[DB] Dumping database to ${s}`),await ue(c,s)):(n&&console.debug("[DB] Dumping database to memory"),await c.text())}0&&(module.exports={attachWalEventBridge,dumpDB,shouldPollWalAfterMessages,shouldPollWalAfterResponse,startDBServer,startLazyShadowDBServer});