import{c as b}from"./chunk-KWCQYPJI.js";import{h as S}from"./chunk-EDFHV3AK.js";import{d as A,f as v}from"./chunk-DWY47FQV.js";import{createConnection as Z,createServer as ee}from"net";import{join as te}from"path";import{filename as re}from"pathe/utils";import{protocol as O}from"@electric-sql/pglite";var P="_prisma_dev_wal",y="events",B="install_all_triggers",L="capture_event",I="prisma_dev_wal_capture",w=new WeakMap,X=new Set(["ALTER","COMMIT","COPY","CREATE","DELETE","DROP","INSERT","MERGE","TRUNCATE","UPDATE"]);async function _(e,t){let n=w.get(e);if(n&&!n.closed)return n.bridge;let r=e.execProtocolRaw.bind(e),o=e.execProtocolRawStream.bind(e),s={bridge:{close:async()=>{s.closed||(s.closed=!0,s.subscribers.clear(),e.execProtocolRaw===E&&(e.execProtocolRaw=r),e.execProtocolRawStream===u&&(e.execProtocolRawStream=o),await s.pollPromise,w.delete(e))},poll:async()=>{await T(s,e)},subscribe:i=>(s.subscribers.add(i),()=>{s.subscribers.delete(i)})},closed:!1,ensureInfrastructurePromise:null,pendingPoll:!1,pollPromise:null,subscribers:new Set,suppressDepth:0},E=async(i,d)=>{let m=await r(i,d);return!s.closed&&s.suppressDepth===0&&x(m)&&T(s,e),m},u=async(i,d)=>{let m=[],g=new O.Parser,a=d?.onRawData;await o(i,{...d,onRawData:l=>{g.parse(l,p=>{m.push(p)}),a?.(l)}}),!s.closed&&s.suppressDepth===0&&R(m)&&T(s,e)};return e.execProtocolRaw=E,e.execProtocolRawStream=u,w.set(e,s),await $(s,e),s.bridge}async function C(e){let t=w.get(e);t&&await t.bridge.close()}function R(e){for(let t of e){if(t.name!=="commandComplete"||typeof t.text!="string")continue;let n=t.text.split(/\s+/,1)[0]?.toUpperCase();if(n&&X.has(n))return!0}return!1}function x(e){if(e.length===0)return!1;let t=[];return new O.Parser().parse(e,r=>{t.push(r)}),R(t)}async function $(e,t){e.ensureInfrastructurePromise??=N(e,t,async()=>{await t.exec(`CREATE SCHEMA IF NOT EXISTS "${P}"`),await t.exec(`
      CREATE TABLE IF NOT EXISTS "${P}"."${y}" (
        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 "${P}"."${L}"()
      RETURNS trigger
      LANGUAGE plpgsql
      AS $$
      BEGIN
        IF TG_TABLE_SCHEMA = '${P}' THEN
          RETURN COALESCE(NEW, OLD);
        END IF;

        INSERT INTO "${P}"."${y}" (
          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 "${P}"."${B}"()
      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 ('${P}', '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 = '${I}'
          ) THEN
            CONTINUE;
          END IF;

          EXECUTE format(
            'CREATE TRIGGER %I AFTER INSERT OR UPDATE OR DELETE ON %s FOR EACH ROW EXECUTE FUNCTION "${P}"."${L}"()',
            '${I}',
            target::text
          );
        END LOOP;
      END;
      $$;
    `),await M(e,t)}),await e.ensureInfrastructurePromise}async function M(e,t){await N(e,t,async()=>{await t.query(`SELECT "${P}"."${B}"()`)})}async function Q(e,t){await $(e,t),await M(e,t);let n=await N(e,t,async()=>await t.query(`
      WITH drained AS (
        DELETE FROM "${P}"."${y}"
        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(n.rows.length===0||e.subscribers.size===0)return;let r=n.rows.map(j);for(let o of e.subscribers)queueMicrotask(()=>{if(!e.closed&&e.subscribers.has(o))try{o(r)}catch(s){console.error("[WAL bridge] subscriber failed",s)}})}async function T(e,t){if(!e.closed){if(e.pollPromise){e.pendingPoll=!0,await e.pollPromise;return}e.pollPromise=(async()=>{do e.pendingPoll=!1,await Q(e,t);while(e.pendingPoll&&!e.closed)})().finally(()=>{e.pollPromise=null}),await e.pollPromise}}async function N(e,t,n){e.suppressDepth+=1;try{return await n()}finally{e.suppressDepth-=1,e.suppressDepth===0&&!e.closed&&w.get(t)!==e&&(e.closed=!0)}}function j(e){return{oldRecord:e.old_row_data,record:e.row_data,schema:e.schema_name,table:e.table_name,txid:String(e.txid),type:V(e.op)}}function V(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 oe=10,W="127.0.0.1",U=128*1024*1024,k=["-c","shared_buffers=16MB","-c","temp_buffers=1MB","-c","work_mem=1MB","-c","maintenance_work_mem=16MB","-c","wal_buffers=1MB"],c={connectionLimit:oe,connectTimeout:0,database:"template1",maxIdleConnectionLifetime:0,password:"postgres",poolTimeout:0,socketTimeout:0,sslMode:"disable",username:"postgres"},ae=`postgres://${c.username}:${c.password}@localhost`,D=new URLSearchParams({sslmode:c.sslMode}),F=new URLSearchParams({...Object.fromEntries(D.entries()),connection_limit:String(c.connectionLimit),connect_timeout:String(c.connectTimeout),max_idle_connection_lifetime:String(c.maxIdleConnectionLifetime),pool_timeout:String(c.poolTimeout),socket_timeout:String(c.socketTimeout)});async function H(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 ${c.username} WITH LOGIN SUPERUSER PASSWORD '${c.password}'`):await e.exec(`CREATE ROLE ${c.username} WITH LOGIN SUPERUSER PASSWORD '${c.password}'`),await e.exec(`SET ROLE ${c.username}`)}async function Te(e,t){if(e==="shadow_database"&&!t.dryRun)return await ne(t);let n=e==="database"?t.databasePort:t.shadowDatabasePort;return t.dryRun?Y(e,t,{db:null,port:n,server:null}):await q(e,t,{port:n,updateServerStatePort:!0})}async function ne(e,t=async()=>await q("shadow_database",e,{port:0,updateServerStatePort:!1})){let{debug:n}=e,r=null,o=null,s=!1,E=new Set,u=ee(d),i=await se(u,e.shadowDatabasePort);return e.shadowDatabasePort=i,n&&console.debug(`[shadow_database] lazy proxy listening on port ${i}`),{...c,attachWalEventBridge:()=>Promise.reject(new Error("WAL bridge is only available for the primary database server")),close:async()=>{s=!0;for(let l of E)l.destroy();E.clear();let a=[];try{await ie(u),n&&console.debug(`[shadow_database] lazy proxy stopped on port ${i}`)}catch(l){console.error("[shadow_database] lazy proxy stop error",l),a.push(l)}try{await o?.catch(()=>null),await r?.close()}catch(l){console.error("[shadow_database] backend close error",l),a.push(l)}if(a.length>0)throw new AggregateError(a,"Failed to close shadow_database properly")},connectionString:f(i,D),dump:async()=>{},getPrimaryKeyColumns:()=>Promise.reject(new Error("Primary key resolution is only available for the primary database server")),port:i,prismaORMConnectionString:f(i,F),terminalCommand:`PGPASSWORD=${c.password} PGSSLMODE=${c.sslMode} psql -h localhost -p ${i} -U ${c.username} -d ${c.database}`};function d(a){E.add(a);let l=()=>{E.delete(a)};a.once("close",l),a.once("error",l),a.pause(),m(a)}async function m(a){try{let l=await g();if(s){a.destroy();return}let p=Z({host:W,port:l.port});E.add(p);let h=()=>{E.delete(p)};p.once("close",h),p.once("error",h),a.once("close",()=>p.destroy()),a.once("error",()=>p.destroy()),p.once("error",()=>a.destroy()),p.once("connect",()=>{n&&console.debug(`[shadow_database] proxying connection to lazy backend on port ${l.port}`),a.resume(),a.pipe(p),p.pipe(a)})}catch(l){n&&console.error("[shadow_database] failed to start lazy backend",l),a.destroy(l instanceof Error?l:void 0)}}async function g(){if(r)return r;if(s)throw new Error("shadow_database is closed");return o||(n&&console.debug("[shadow_database] starting lazy backend..."),o=t().then(a=>(r=a,n&&console.debug(`[shadow_database] lazy backend started on port ${a.port}`),a)).catch(a=>{throw o=null,a})),await o}}async function q(e,t,n){let{debug:r}=t,{port:o,updateServerStatePort:s}=n,u=await(e==="shadow_database"?le:z)(t.pgliteDataDirPath,r);r&&u.onNotification((a,l)=>{console.debug(`[${e}][${a}] ${l}`)});let{PGLiteSocketServer:i}=await import("@electric-sql/pglite-socket"),d=e==="shadow_database"?t.shadowDatabaseIdleTimeoutMillis:t.databaseIdleTimeoutMillis,m=new i({db:u,debug:r,idleTimeout:Number.isFinite(d)?d:0,inspect:r,maxConnections:c.connectionLimit,port:o});r&&(m.addEventListener("listening",a=>{let{detail:l}=a;console.debug(`[${e}] server listening on ${JSON.stringify(l)}`)}),m.addEventListener("connection",a=>{let{clientAddress:l,clientPort:p}=a.detail;console.debug(`[${e}] client connected from ${l}:${p}`)}),m.addEventListener("error",a=>{let{detail:l}=a;console.error(`[${e}] server error:`,l)}));try{await m.start()}catch(a){throw a instanceof Error&&"code"in a&&a.code==="EADDRINUSE"?new S(o):a}let g=Number(m.getServerConn().split(":").at(1));return s&&(t[e==="database"?"databasePort":"shadowDatabasePort"]=g),Y(e,t,{db:u,port:g,server:m})}function Y(e,t,n){let{debug:r}=t,{db:o,port:s,server:E}=n||{},u=new Map;return r&&console.debug(`[${e}] server started on port ${s}`),{...c,attachWalEventBridge:async()=>{if(e!=="database"||!o)throw new Error("WAL bridge is only available for the primary database server");return await _(o)},close:async()=>{let i=[];try{await E?.stop(),r&&console.debug(`[${e}] server stopped on port ${s}`)}catch(d){console.error(`[${e}] server stop error`,d),i.push(d)}if(e==="database"){try{o&&await C(o),r&&console.debug(`[${e}] closed WAL bridge`)}catch(d){console.error(`[${e}] WAL bridge close error`,d),i.push(d)}try{await o?.syncToFs(),r&&console.debug(`[${e}] synced to filesystem`)}catch(d){console.error(`[${e}] sync error`,d),i.push(d)}}try{await o?.close(),r&&console.debug(`[${e}] closed`)}catch(d){console.error(`[${e}] close error`,d),i.push(d)}if(i.length>0)throw new AggregateError(i,`Failed to close ${e} properly`)},connectionString:f(s,D),dump:async i=>{e==="shadow_database"||!o||await de({db:o,debug:r,destinationPath:i})},getPrimaryKeyColumns:async(i,d)=>{if(e==="shadow_database"||!o)throw new Error("Primary key resolution is only available for the primary database server");let m=`${i}.${d}`,g=u.get(m);return g||(g=ce(o,i,d).catch(a=>{throw u.delete(m),a}),u.set(m,g)),await g},port:s,prismaORMConnectionString:f(s,F),terminalCommand:`PGPASSWORD=${c.password} PGSSLMODE=${c.sslMode} psql -h localhost -p ${s} -U ${c.username} -d ${c.database}`}}function f(e,t){return`${ae}:${e}/${c.database}?${t.toString()}`}async function z(e,t){let{PGlite:n}=await import("@electric-sql/pglite"),r=await b(),o=e==="memory://"||!await A(te(e,"PG_VERSION")),s=await n.create({database:c.database,dataDir:e,debug:t?5:void 0,extensions:r.extensions,fsBundle:r.fsBundle,initialMemory:U,loadDataDir:o?r.loadDataDir:void 0,relaxedDurability:!1,startParams:[...n.defaultStartParams,...k],wasmModule:r.wasmModule});return await H(s),s}async function se(e,t){return await new Promise((n,r)=>{let o=u=>{if(E(),u.code==="EADDRINUSE"){r(new S(t));return}r(u)},s=()=>{let u=e.address();if(E(),!u||typeof u=="string"){r(new Error("Failed to determine TCP server port"));return}n(u.port)},E=()=>{e.off("error",o),e.off("listening",s)};e.once("error",o),e.once("listening",s),e.listen(t,W)})}async function ie(e){await new Promise((t,n)=>{e.close(r=>{let o=r;if(o&&o.code!=="ERR_SERVER_NOT_RUNNING"){n(o);return}t()})})}async function le(e,t){let{PGlite:n}=await import("@electric-sql/pglite"),r=await b(),o=await n.create({database:c.database,dataDir:"memory://",debug:t?5:void 0,extensions:r.extensions,fsBundle:r.fsBundle,initialMemory:U,loadDataDir:r.loadDataDir,relaxedDurability:!1,startParams:[...n.defaultStartParams,...k],wasmModule:r.wasmModule});return await H(o),o}async function ce(e,t,n){let{rows:r}=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 = ${G(t)}
      AND relation.relname = ${G(n)}
    ORDER BY keys.ordinality
  `);return r.map(o=>o.column_name)}function G(e){return`'${e.replaceAll("'","''")}'`}async function de(e){let{dataDir:t,db:n,debug:r,destinationPath:o}=e,s=n||await z(t,r),{pgDump:E}=await import("@electric-sql/pglite-tools/pg_dump"),u=await E({args:["--schema-only","--no-owner"],fileName:o?re(o):void 0,pg:await s.clone()});return o?(r&&console.debug(`[DB] Dumping database to ${o}`),await v(u,o)):(r&&console.debug("[DB] Dumping database to memory"),await u.text())}export{_ as a,R as b,x as c,Te as d,ne as e,de as f};
