palgres 0.10.1 → 0.11.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/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- /*! palgres 0.10.1 — Palbase SDK License (see LICENSE) */
2
- import{a as ws,b as ys,c as Ge,l as kn,m as Ln}from"./chunks/KCXVL4CY.js";import{$ as Is,A as an,B as Y,C as wt,D as xe,E as ln,F as yt,G as $s,H as Ss,I as Rs,J as In,K as Tt,L as bs,M as Ns,N as As,O as xn,P as Os,Q as No,R as Ao,S as Oo,T as ko,U as Lo,V as Io,W as vn,X as ks,Y as Ls,Z as Cn,_ as _n,a as yo,aa as xs,b as To,c as ne,d as oe,e as Ne,f as $o,g as Ae,h as gt,i as So,j as Ke,k as He,l as ht,m as Et,n as Ve,o as Me,p as ae,q as gs,r as hs,s as Es,t as ue,u as On,v as on,w as Ts,x as Ro,y as bo,z as Xe}from"./chunks/C5MB2TN2.js";import{a as je,b as De,c as pt,d as D,e as be,f as rn,g as ms,h as ps,i as ft,j as ge,k as fs,l as Pe,o as he}from"./chunks/SCDFWCDV.js";import{createHash as Co}from"node:crypto";import{createHash as Rt}from"node:crypto";var b=t=>`"${t.replace(/"/g,'""')}"`,P=(t,e)=>`${b(t)}.${b(e)}`,M=t=>`'${t.replace(/'/g,"''")}'`;function de(t){if(t.includes("\0"))throw new TypeError("a NUL character cannot be sent to Postgres");return`E'${t.replace(/\\/g,"\\\\").replace(/'/g,"''")}'`}var ye=t=>t.map(b).join(", "),xo=new Set(["now","current_timestamp","current_date","current_time","localtimestamp","localtime","transaction_timestamp","statement_timestamp"]);function vs(t){return[...$t(t)].some(e=>e.call&&!xo.has(e.name.toLowerCase()))}function*$t(t){let e=0;for(;e<t.length;){let n=t[e];if(n==="'"){for(e++;e<t.length;)if(t[e]==="'"&&t[e+1]==="'")e+=2;else{if(t[e]==="'")break;e++}e++;continue}if(n==="$"){let s=/^\$[A-Za-z_]*\$/.exec(t.slice(e));if(s){let r=t.indexOf(s[0],e+s[0].length);e=r<0?t.length:r+s[0].length;continue}}if(n==='"'){let s=e+1,r="";for(;s<t.length;)if(t[s]==='"'&&t[s+1]==='"')r+='"',s+=2;else{if(t[s]==='"')break;r+=t[s++]}let o=s+1;yield{start:e,end:o,name:r,quoted:!0,call:/^\s*\(/.test(t.slice(o))},e=o;continue}if(/[A-Za-z_]/.test(n)&&(e===0||!/[A-Za-z0-9_$]/.test(t[e-1]))){let s=/^[A-Za-z_][A-Za-z0-9_$]*/.exec(t.slice(e)),r=e+s[0].length;yield{start:e,end:r,name:s[0],quoted:!1,call:/^\s*\(/.test(t.slice(r))},e=r;continue}e++}}function Oe(t,e){for(let n of $t(t))if(!n.call&&(n.quoted?n.name===e:n.name.toLowerCase()===e.toLowerCase()))return!0;return!1}function ke(t,e){if(e.size===0)return t;let n="",s=0;for(let r of $t(t)){if(r.call)continue;let o=e.get(r.quoted?r.name:vo(e,r.name)??"");o!==void 0&&(n+=t.slice(s,r.start)+b(o),s=r.end)}return n+t.slice(s)}function vo(t,e){if(t.has(e))return e;let n=e.toLowerCase();for(let s of t.keys())if(s.toLowerCase()===n)return s}var Dn=t=>`(NOT EXISTS (SELECT 1 FROM unnest(i.indclass::oid[]) AS oc(oid) JOIN pg_catalog.pg_opclass o ON o.oid = oc.oid WHERE NOT o.opcdefault)
1
+ /*! palgres 0.11.0 — Palbase SDK License (see LICENSE) */
2
+ import{a as Ds,b as Ps,c as Ye,l as Pn,m as Mn}from"./chunks/JYA2QXWY.js";import{$ as Vs,A as mn,B as Y,C as Lt,D as ke,E as ze,F as qn,G as qs,H as Fs,I as Us,J as Fn,K as Un,L as xt,M as Bs,N as Ws,O as pn,P as js,Q as Ko,R as Ho,S as Vo,T as Go,U as Xo,V as Yo,W as fn,X as Ks,Y as Hs,Z as Bn,_ as Wn,a as qo,aa as Gs,b as Fo,c as ne,d as oe,e as Ae,f as Uo,g as Oe,h as At,i as Bo,j as Ve,k as Ge,l as Ot,m as kt,n as Xe,o as Fe,p as ae,q as Cs,r as vs,s as _s,t as ue,u as Dn,v as dn,w as Ms,x as Wo,y as jo,z as Je}from"./chunks/FZ3ACJMC.js";import{a as ks,b as He,c as Me,d as Rt,e as D,f as Ne,g as un,h as Ls,i as xs,j as Nt,k as Ee,l as Is,m as qe,p as ye}from"./chunks/LOOM3LFG.js";import{createHash as Zo}from"node:crypto";function jn(t){return typeof t=="function"?t():Promise.resolve(t)}var Xs="pbe1.";function Qe(t,e,n){return t==="public"?`${e}.${n}`:`${t}.${e}.${n}`}var de="palgres.sealing",Kn=5e3,It=3*Kn,gn=class{going=new Map;get(e){return this.going.get(e)}get size(){return this.going.size}async read(e){let n;try{n=await e(`SELECT address, direction, phase FROM ${de}`)}catch(s){let r=s.code??s.errno;if(r!=="42P01"&&r!=="3F000")throw s;n=[]}this.going=new Map(n.map(s=>[s.address,{direction:s.direction,phase:s.phase}]))}},hn=t=>`"${t.replace(/"/g,'""')}"`;function Ys(t,e){let n=hn(t.column);return t.direction==="open"?{sql:`${n} LIKE 'pbe1.%'`,params:[]}:{sql:`(${n} NOT LIKE $1${t.lookup?` OR ${hn(t.lookup)} IS NULL`:""})`,params:[`pbe1.${e.currentKey()}.%`]}}async function Hn(t,e,n,s,r){let o=Ys(e,n),a=hn(e.column),i=s===null?"":` AND ctid > $${o.params.length+1}::tid`,c=await t(`SELECT ctid::text AS at, ${a} AS value FROM ${e.table} WHERE ${a} IS NOT NULL AND ${o.sql}${i} ORDER BY ctid LIMIT ${r}`,s===null?o.params:[...o.params,s]);if(c.length===0)return{done:0,last:null};let l=[],u=c.map(h=>{let p=Jo(n,e.address,h.value),E=[h.at,h.value,e.direction==="seal"?n.encrypt(e.address,p):p,...e.lookup?[n.lookup(e.address,p)]:[]],$=l.length+1;return l.push(...E),`(${E.map((f,d)=>`$${$+d}::text`).join(", ")})`}),g=[`${a} = v.next`,...e.lookup?[`${hn(e.lookup)} = v.lookup`]:[]],m=await t(`WITH done AS (UPDATE ${e.table} AS t SET ${g.join(", ")} FROM (VALUES ${u.join(", ")}) AS v(at, old, next${e.lookup?", lookup":""}) WHERE t.ctid = v.at::tid AND t.${a} = v.old RETURNING 1) SELECT count(*)::int AS n FROM done`,l);return{done:Number(m[0]?.n??0),last:c.length<r?null:c[c.length-1].at}}function Jo(t,e,n){if(!t.isEncrypted(n))return n;try{return t.decrypt(e,n)}catch{return n}}function Vn(t,e){if(typeof e=="string"&&e.startsWith(Xs))throw new TypeError(`${t} is going over between plain and encrypted: a value beginning ${Xs} would read as an encrypted one \u2014 it is written once the migration completes`)}async function Js(t,e,n){let s=Ys(e,n);return(await t(`SELECT 1 FROM ${e.table} WHERE ${hn(e.column)} IS NOT NULL AND ${s.sql} LIMIT 1`,s.params)).length>0}import{createHash as _t}from"node:crypto";var R=t=>`"${t.replace(/"/g,'""')}"`,P=(t,e)=>`${R(t)}.${R(e)}`,M=t=>`'${t.replace(/'/g,"''")}'`;function me(t){if(t.includes("\0"))throw new TypeError("a NUL character cannot be sent to Postgres");return`E'${t.replace(/\\/g,"\\\\").replace(/'/g,"''")}'`}var Te=t=>t.map(R).join(", "),zo=new Set(["now","current_timestamp","current_date","current_time","localtimestamp","localtime","transaction_timestamp","statement_timestamp"]);function zs(t){return[...Ct(t)].some(e=>e.call&&!zo.has(e.name.toLowerCase()))}function*Ct(t){let e=0;for(;e<t.length;){let n=t[e];if(n==="'"){for(e++;e<t.length;)if(t[e]==="'"&&t[e+1]==="'")e+=2;else{if(t[e]==="'")break;e++}e++;continue}if(n==="$"){let s=/^\$[A-Za-z_]*\$/.exec(t.slice(e));if(s){let r=t.indexOf(s[0],e+s[0].length);e=r<0?t.length:r+s[0].length;continue}}if(n==='"'){let s=e+1,r="";for(;s<t.length;)if(t[s]==='"'&&t[s+1]==='"')r+='"',s+=2;else{if(t[s]==='"')break;r+=t[s++]}let o=s+1;yield{start:e,end:o,name:r,quoted:!0,call:/^\s*\(/.test(t.slice(o))},e=o;continue}if(/[A-Za-z_]/.test(n)&&(e===0||!/[A-Za-z0-9_$]/.test(t[e-1]))){let s=/^[A-Za-z_][A-Za-z0-9_$]*/.exec(t.slice(e)),r=e+s[0].length;yield{start:e,end:r,name:s[0],quoted:!1,call:/^\s*\(/.test(t.slice(r))},e=r;continue}e++}}function Le(t,e){for(let n of Ct(t))if(!n.call&&(n.quoted?n.name===e:n.name.toLowerCase()===e.toLowerCase()))return!0;return!1}function xe(t,e){if(e.size===0)return t;let n="",s=0;for(let r of Ct(t)){if(r.call)continue;let o=e.get(r.quoted?r.name:Qo(e,r.name)??"");o!==void 0&&(n+=t.slice(s,r.start)+R(o),s=r.end)}return n+t.slice(s)}function Qo(t,e){if(t.has(e))return e;let n=e.toLowerCase();for(let s of t.keys())if(s.toLowerCase()===n)return s}var Gn=t=>`(NOT EXISTS (SELECT 1 FROM unnest(i.indclass::oid[]) AS oc(oid) JOIN pg_catalog.pg_opclass o ON o.oid = oc.oid WHERE NOT o.opcdefault)
3
3
  AND NOT i.indnullsnotdistinct AND ${t}.reloptions IS NULL
4
- AND NOT EXISTS (SELECT 1 FROM unnest(i.indcollation::oid[], i.indkey::int2[]) AS x(coll, att) JOIN pg_catalog.pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = x.att WHERE x.att > 0 AND x.coll <> a.attcollation))`;var J="palgres_search",Pn=(t,e)=>t.model===e.model&&t.dimensions===e.dimensions&&t.metric===e.metric&&t.from.length===e.from.length&&t.from.every((n,s)=>n===e.from[s]),Cs=48;function ve(t,e){let n=t.replaceAll(".","__");return`${n.length<=Cs?n:`${n.slice(0,32)}_${Rt("md5").update(n).digest("hex").slice(0,12)}`}__g${e}`}var _s=t=>({insert:`_palgres_search_g${t}_ins`,update:`_palgres_search_g${t}_upd`});function Mn(t,e){let n=Rt("sha256").update(JSON.stringify([t.schema,t.name,e])).digest("hex").slice(0,8),s=`_palgres_search_${t.name}_${n}`;return Buffer.byteLength(s)<=63?s:`_palgres_search_${Rt("sha256").update(`${t.schema}.${t.name}`).digest("hex").slice(0,16)}_${n}`}function qn(t,e){let n=e===void 0?"":`${b(e)}.`;return t.map(s=>`coalesce(${n}${b(s)}::text, '')`).join(" || ' ' || ")}var Fn=(t,e)=>`to_tsvector('simple', ${qn(t,e)})`;function cn(t,e){let n=t>ms?"halfvec":"vector",s={cosine:["cosine","<=>"],euclidean:["l2","<->"],inner_product:["ip","<#>"]}[e];return{type:n,opclass:`${n}_${s[0]}_ops`,operator:s[1]}}function Ds(t){let e=`${t.table.schema}.${t.table.name}`,n=P(t.table.schema,t.table.name),s=ve(e,t.gen),r=P(J,s),o=cn(t.search.dimensions,t.search.metric),a=b(t.pk.name),i=[t.roles.anon,t.roles.authenticated].map(b).join(", ");return[`INSERT INTO ${J}.generations (table_key, gen, model, dimensions, metric, from_columns, status, promoted_at) VALUES (${M(e)}, ${t.gen}, ${M(t.search.model)}, ${t.search.dimensions}, ${M(t.search.metric)}, ARRAY[${t.search.from.map(M).join(", ")}]::text[], ${M(t.status)}, ${t.status==="active"?"now()":"NULL"})`,`CREATE TABLE ${r} (
4
+ AND NOT EXISTS (SELECT 1 FROM unnest(i.indcollation::oid[], i.indkey::int2[]) AS x(coll, att) JOIN pg_catalog.pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = x.att WHERE x.att > 0 AND x.coll <> a.attcollation))`;var J="palgres_search",Xn=(t,e)=>t.model===e.model&&t.dimensions===e.dimensions&&t.metric===e.metric&&t.from.length===e.from.length&&t.from.every((n,s)=>n===e.from[s]),Qs=48;function ve(t,e){let n=t.replaceAll(".","__");return`${n.length<=Qs?n:`${n.slice(0,32)}_${_t("md5").update(n).digest("hex").slice(0,12)}`}__g${e}`}var Zs=t=>({insert:`_palgres_search_g${t}_ins`,update:`_palgres_search_g${t}_upd`});function Yn(t,e){let n=_t("sha256").update(JSON.stringify([t.schema,t.name,e])).digest("hex").slice(0,8),s=`_palgres_search_${t.name}_${n}`;return Buffer.byteLength(s)<=63?s:`_palgres_search_${_t("sha256").update(`${t.schema}.${t.name}`).digest("hex").slice(0,16)}_${n}`}function Jn(t,e){let n=e===void 0?"":`${R(e)}.`;return t.map(s=>`coalesce(${n}${R(s)}::text, '')`).join(" || ' ' || ")}var zn=(t,e)=>`to_tsvector('simple', ${Jn(t,e)})`;function En(t,e){let n=t>Ls?"halfvec":"vector",s={cosine:["cosine","<=>"],euclidean:["l2","<->"],inner_product:["ip","<#>"]}[e];return{type:n,opclass:`${n}_${s[0]}_ops`,operator:s[1]}}function er(t){let e=`${t.table.schema}.${t.table.name}`,n=P(t.table.schema,t.table.name),s=ve(e,t.gen),r=P(J,s),o=En(t.search.dimensions,t.search.metric),a=R(t.pk.name),i=[t.roles.anon,t.roles.authenticated].map(R).join(", ");return[`INSERT INTO ${J}.generations (table_key, gen, model, dimensions, metric, from_columns, status, promoted_at) VALUES (${M(e)}, ${t.gen}, ${M(t.search.model)}, ${t.search.dimensions}, ${M(t.search.metric)}, ARRAY[${t.search.from.map(M).join(", ")}]::text[], ${M(t.status)}, ${t.status==="active"?"now()":"NULL"})`,`CREATE TABLE ${r} (
5
5
  id ${t.pk.type} PRIMARY KEY REFERENCES ${n} (${a}) ON DELETE CASCADE,
6
- embedding ${b(t.types)}.${o.type}(${t.search.dimensions}) NOT NULL,
6
+ embedding ${R(t.types)}.${o.type}(${t.search.dimensions}) NOT NULL,
7
7
  model text NOT NULL,
8
8
  embedded_at timestamptz NOT NULL DEFAULT now()
9
- )`,`CREATE INDEX ON ${r} USING hnsw (embedding ${b(t.types)}.${o.opclass})`,`ALTER TABLE ${r} ENABLE ROW LEVEL SECURITY`,`CREATE POLICY ${b("_palgres_search_parent")} ON ${r} FOR SELECT TO ${i} USING (EXISTS (SELECT 1 FROM ${n} p WHERE p.${a} = ${b(s)}.id))`,`GRANT SELECT ON TABLE ${r} TO ${i}`,`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${r} TO ${b(t.roles.service)}`,`CREATE FUNCTION ${r}() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp AS $palgres$
9
+ )`,`CREATE INDEX ON ${r} USING hnsw (embedding ${R(t.types)}.${o.opclass})`,`ALTER TABLE ${r} ENABLE ROW LEVEL SECURITY`,`CREATE POLICY ${R("_palgres_search_parent")} ON ${r} FOR SELECT TO ${i} USING (EXISTS (SELECT 1 FROM ${n} p WHERE p.${a} = ${R(s)}.id))`,`GRANT SELECT ON TABLE ${r} TO ${i}`,`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${r} TO ${R(t.roles.service)}`,`CREATE FUNCTION ${r}() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp AS $palgres$
10
10
  BEGIN
11
11
  -- A generation left behind keeps its triggers until the next migration takes them: they do nothing.
12
12
  IF NOT EXISTS (SELECT 1 FROM ${J}.generations g WHERE g.table_key = ${M(e)} AND g.gen = ${t.gen} AND g.status <> 'retired') THEN
@@ -20,7 +20,7 @@ BEGIN
20
20
  DELETE FROM ${r} WHERE id = NEW.${a};
21
21
  END IF;
22
22
  RETURN NULL;
23
- END $palgres$`,`REVOKE ALL ON FUNCTION ${r}() FROM PUBLIC`,...Un({table:t.table,gen:t.gen,from:t.search.from,staleness:t.search.staleness},!1)]}function Un(t,e){let n=P(t.table.schema,t.table.name),s=`${P(J,ve(`${t.table.schema}.${t.table.name}`,t.gen))}(${M(t.staleness)})`,r=_s(t.gen),o=e?"CREATE OR REPLACE TRIGGER":"CREATE TRIGGER",a=t.from.map(i=>`OLD.${b(i)} IS DISTINCT FROM NEW.${b(i)}`).join(" OR ");return[`${o} ${b(r.insert)} AFTER INSERT ON ${n} FOR EACH ROW EXECUTE FUNCTION ${s}`,`${o} ${b(r.update)} AFTER UPDATE OF ${t.from.map(b).join(", ")} ON ${n} FOR EACH ROW WHEN (${a}) EXECUTE FUNCTION ${s}`]}function Ps(t,e,n){return`INSERT INTO ${J}.queue (table_key, gen, row_id) SELECT ${M(`${t.schema}.${t.name}`)}, ${e}, ${b(n)}::text FROM ${P(t.schema,t.name)} ON CONFLICT ON CONSTRAINT queue_one_pending DO NOTHING`}function Bn(t,e){let n=`${t.schema}.${t.name}`,s=P(t.schema,t.name),r=P(J,ve(n,e)),o=_s(e);return[`DROP TRIGGER IF EXISTS ${b(o.insert)} ON ${s}`,`DROP TRIGGER IF EXISTS ${b(o.update)} ON ${s}`,`DROP TABLE IF EXISTS ${r}`,`DROP FUNCTION IF EXISTS ${r}()`,`DELETE FROM ${J}.queue WHERE table_key = ${M(n)} AND gen = ${e}`,`DELETE FROM ${J}.generations WHERE table_key = ${M(n)} AND gen = ${e}`]}var Wn=t=>`palgres search 1 (${t.anon}, ${t.authenticated}, ${t.service})`;function Ms(t){let e=[t.anon,t.authenticated,t.service].map(b).join(", "),n=b(t.service),s=J;return[`CREATE SCHEMA IF NOT EXISTS ${s}`,`CREATE TABLE IF NOT EXISTS ${s}.generations (
23
+ END $palgres$`,`REVOKE ALL ON FUNCTION ${r}() FROM PUBLIC`,...Qn({table:t.table,gen:t.gen,from:t.search.from,staleness:t.search.staleness},!1)]}function Qn(t,e){let n=P(t.table.schema,t.table.name),s=`${P(J,ve(`${t.table.schema}.${t.table.name}`,t.gen))}(${M(t.staleness)})`,r=Zs(t.gen),o=e?"CREATE OR REPLACE TRIGGER":"CREATE TRIGGER",a=t.from.map(i=>`OLD.${R(i)} IS DISTINCT FROM NEW.${R(i)}`).join(" OR ");return[`${o} ${R(r.insert)} AFTER INSERT ON ${n} FOR EACH ROW EXECUTE FUNCTION ${s}`,`${o} ${R(r.update)} AFTER UPDATE OF ${t.from.map(R).join(", ")} ON ${n} FOR EACH ROW WHEN (${a}) EXECUTE FUNCTION ${s}`]}function nr(t,e,n){return`INSERT INTO ${J}.queue (table_key, gen, row_id) SELECT ${M(`${t.schema}.${t.name}`)}, ${e}, ${R(n)}::text FROM ${P(t.schema,t.name)} ON CONFLICT ON CONSTRAINT queue_one_pending DO NOTHING`}function Zn(t,e){let n=`${t.schema}.${t.name}`,s=P(t.schema,t.name),r=P(J,ve(n,e)),o=Zs(e);return[`DROP TRIGGER IF EXISTS ${R(o.insert)} ON ${s}`,`DROP TRIGGER IF EXISTS ${R(o.update)} ON ${s}`,`DROP TABLE IF EXISTS ${r}`,`DROP FUNCTION IF EXISTS ${r}()`,`DELETE FROM ${J}.queue WHERE table_key = ${M(n)} AND gen = ${e}`,`DELETE FROM ${J}.generations WHERE table_key = ${M(n)} AND gen = ${e}`]}var et=t=>`palgres search 1 (${t.anon}, ${t.authenticated}, ${t.service})`;function tr(t){let e=[t.anon,t.authenticated,t.service].map(R).join(", "),n=R(t.service),s=J;return[`CREATE SCHEMA IF NOT EXISTS ${s}`,`CREATE TABLE IF NOT EXISTS ${s}.generations (
24
24
  table_key text NOT NULL,
25
25
  gen integer NOT NULL,
26
26
  model text NOT NULL,
@@ -43,7 +43,7 @@ END $palgres$`,`REVOKE ALL ON FUNCTION ${r}() FROM PUBLIC`,...Un({table:t.table,
43
43
  CONSTRAINT queue_one_pending UNIQUE (table_key, gen, row_id),
44
44
  CONSTRAINT queue_due UNIQUE (next_attempt_at, enqueued_at, id)
45
45
  )`,`GRANT USAGE ON SCHEMA ${s} TO ${e}`,`GRANT SELECT ON TABLE ${s}.generations TO ${e}`,`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${s}.queue TO ${n}`,`GRANT USAGE, SELECT ON SEQUENCE ${s}.queue_id_seq TO ${n}`,`CREATE OR REPLACE FUNCTION ${s}.vectors(of_table text, gen integer) RETURNS text LANGUAGE sql IMMUTABLE SET search_path = pg_catalog, pg_temp AS $palgres$
46
- SELECT CASE WHEN length(b) <= ${Cs} THEN b ELSE left(b, 32) || '_' || left(md5(b), 12) END || '__g' || gen FROM (SELECT replace(of_table, '.', '__') AS b) x
46
+ SELECT CASE WHEN length(b) <= ${Qs} THEN b ELSE left(b, 32) || '_' || left(md5(b), 12) END || '__g' || gen FROM (SELECT replace(of_table, '.', '__') AS b) x
47
47
  $palgres$`,`CREATE OR REPLACE FUNCTION ${s}.promote(of_table text) RETURNS integer LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp AS $palgres$
48
48
  DECLARE
49
49
  g ${s}.generations%ROWTYPE;
@@ -69,30 +69,30 @@ BEGIN
69
69
  UPDATE ${s}.generations SET status = 'retired' WHERE table_key = of_table AND status = 'active';
70
70
  UPDATE ${s}.generations SET status = 'active', promoted_at = now() WHERE table_key = of_table AND gen = g.gen;
71
71
  RETURN g.gen;
72
- END $palgres$`,`REVOKE ALL ON FUNCTION ${s}.promote(text) FROM PUBLIC`,`GRANT EXECUTE ON FUNCTION ${s}.promote(text) TO ${n}`,`COMMENT ON SCHEMA ${s} IS ${M(Wn(t))}`]}var St=new Set,jn={listen(t){return St.add(t),()=>{St.delete(t)}},committed(){for(let t of St)t()}};var Ws=new Set(["tx","statement","backfill"]),Gn=1,Te=(t,e)=>`palgres_${t}_${e}`,js=t=>Co("sha256").update(t).digest("hex").slice(0,8),bt=(t,e)=>`${t.name}_${e}_${js(JSON.stringify([t.schema,t.name,e])).slice(0,6)}`,ie=(t,e,n)=>{let s=`_palgres_${t}_${e}_${n}`;return Buffer.byteLength(s)<=63?s:`_palgres_${t}_${e}_${js(n)}`},Nt={anon:"anon",backend_anon:"anon",authenticated:"authenticated",backend_authenticated:"authenticated",service_role:"service",backend_service_role:"service",public:"public"},qs=t=>!t.nullable&&t.default===void 0&&!t.identity&&!t.generated,Fs="the version serving now reads that value in the rows the new version writes";function Lt(t){return new kt(t).run()}var kt=class{from;to;fromN;n;input;changes=[];refusals=[];matches=new Map;fromMatched=new Set;prelude=[];creates=[];createFks=[];alters=[];backfills=[];online=[];settle=[];lateFks=[];searchStart=[];searchComplete=[];undoSearch=[];viewsAtComplete=null;namesAtComplete=!1;dropsColumnsAtComplete=!1;completeUnitDrops=[];raws=[];completeTables=[];completeIndexes=[];completeDrops=[];completeTypes=[];undoTables=[];undoOnline=[];fkDrops=[];undoFksGone=[];undoIndexesGone=[];undoFksBack=[];undoRawsGone=[];undoRawsBack=[];undoCreates=[];undoNewTables=[];layout={tables:[]};constructor(e){this.input=e,this.from=ge(e.from?.schema??pt());let n=new Map((e.from?.schema.raw??[]).map((r,o)=>[r.name,o]));this.from.raw.sort((r,o)=>(n.get(r.name)??0)-(n.get(o.name)??0)),this.to=ge(e.to);let s=new Map(e.to.raw.map((r,o)=>[r.name,o]));this.to.raw.sort((r,o)=>(s.get(r.name)??0)-(s.get(o.name)??0)),this.fromN=e.from?.n??null,this.n=e.next}run(){this.extensions(),this.schemas(),this.enums(),this.rawUnitsBefore(),this.matchTables();for(let r of this.to.tables){let o=this.matches.get(D(r));o?this.alterTable(o):this.createTable(r),this.search(r,o)}for(let r of this.from.tables)this.fromMatched.has(r)||this.dropTable(r);this.rawUnits(),this.enumDrops();let e=[...this.prelude,...this.creates.length+this.createFks.length>0?[{kind:"tx",sql:[...this.creates,...this.createFks],why:"the new tables and types"}]:[],...this.fkDrops,...this.alters,...this.backfills,...this.online,...this.settle,...this.lateFks,...this.searchStart,...this.raws,{kind:"tx",sql:this.views(),why:`version ${this.n}'s views`}],n=[...this.fromN!==null?[{kind:"tx",sql:this.dropViews(this.fromN,this.from),why:`version ${this.fromN}'s views`}]:[],...this.searchComplete,...this.viewsAtComplete?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.completeUnitDrops,...this.viewsAtComplete.drops,...this.completeTables.flatMap(r=>r.kind==="tx"?r.sql:[]),...this.viewsAtComplete.creates],why:"the tables, and the views that read them, at once"}]:[...this.completeUnitDrops.length>0?[{kind:"tx",sql:this.completeUnitDrops,why:"the triggers and rules gone"}]:[],...this.completeTables],...this.completeIndexes,...this.completeDrops.length>0?[{kind:"tx",sql:[`DROP TABLE IF EXISTS ${this.completeDrops.join(", ")}`],why:"the dropped tables"}]:[],...this.completeTypes.length>0?[{kind:"tx",sql:this.completeTypes,why:"the dropped types"}]:[]],s=[{kind:"tx",sql:this.dropViews(this.n,this.to),why:`version ${this.n}'s views`},...this.undoSearch,...this.undoFksGone,...this.undoRawsGone.length>0?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.undoRawsGone],why:"the units start made, taken back"}]:[],...[...this.undoTables].reverse(),...this.undoIndexesGone,...this.undoFksBack,...this.undoRawsBack.length>0?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.undoRawsBack],why:"the units start replaced, back"}]:[],...this.undoOnline,...this.undoNewTables.length+this.undoCreates.length>0?[{kind:"tx",sql:[...this.undoNewTables.length>0?[`DROP TABLE IF EXISTS ${this.undoNewTables.join(", ")}`]:[],...[...this.undoCreates].reverse()],why:"the new tables and types"}]:[]];return{format:Gn,from:this.fromN,to:this.n,changes:this.changes,refusals:this.refusals,start:e,complete:n,rollback:s,layout:this.layout}}refuse(e,n){this.refusals.push(`${e}: ${n}`)}extensions(){for(let e of this.to.extensions)this.from.extensions.includes(e)||(this.changes.push(`extension ${e}`),this.prelude.push({kind:"statement",sql:`CREATE EXTENSION IF NOT EXISTS ${b(e)}`,why:`extension ${e}`}))}schemas(){let e=new Set([...this.from.tables.map(a=>a.schema),...this.from.enums.map(a=>a.schema),...this.from.raw.flatMap(a=>a.schema?[a.schema]:[]),"public"]),n=[...new Set([...this.to.tables.map(a=>a.schema),...this.to.enums.map(a=>a.schema),...this.to.raw.flatMap(a=>a.schema?[a.schema]:[])])].filter(a=>!e.has(a)),{anon:s,authenticated:r,service:o}=this.input.roles;for(let a of n)this.changes.push(`schema ${a}`),this.creates.push(`CREATE SCHEMA IF NOT EXISTS ${b(a)}`,`GRANT USAGE ON SCHEMA ${b(a)} TO ${[s,r,o].map(b).join(", ")}`)}enums(){for(let e of this.to.enums){let n=this.from.enums.find(o=>o.schema===e.schema&&o.name===e.name),s=P(e.schema,e.name);if(!n){this.changes.push(`type ${e.schema}.${e.name}`),this.creates.push(`CREATE TYPE ${s} AS ENUM (${e.values.map(M).join(", ")})`),this.undoCreates.push(`DROP TYPE IF EXISTS ${s}`);continue}let r=n.values.filter(o=>!e.values.includes(o));r.length>0&&this.refuse(`type ${e.schema}.${e.name} loses ${r.join(", ")}`,"Postgres cannot take a value out of an enum; add a new type and move the column to it");for(let o of e.values)n.values.includes(o)||(this.changes.push(`type ${e.schema}.${e.name} gains '${o}'`),this.prelude.push({kind:"statement",sql:`ALTER TYPE ${s} ADD VALUE IF NOT EXISTS ${M(o)}`,why:`${e.name} gains ${o}`}))}}enumDrops(){for(let e of this.from.enums)this.to.enums.some(n=>n.schema===e.schema&&n.name===e.name)||(this.changes.push(`type ${e.schema}.${e.name} goes (at complete)`),this.completeTypes.push(`DROP TYPE IF EXISTS ${P(e.schema,e.name)}`))}matchTables(){let e=new Map(this.from.tables.map(n=>[D(n),n]));for(let n of this.to.tables)n.renamedFrom===void 0||n.renamedFrom===n.name||!e.has(`${n.schema}.${n.renamedFrom}`)||this.to.tables.some(s=>s!==n&&s.schema===n.schema&&s.name===n.renamedFrom)&&this.refuse(`table ${n.schema}.${n.renamedFrom} is renamed ${n.name}, and a new table takes the name ${n.renamedFrom} in the same deploy`,`rename it in this deploy, and make the new ${n.renamedFrom} in the next`);for(let n of this.to.tables){let s=e.get(D(n));if(n.renamedFrom!==void 0&&n.renamedFrom!==n.name){let r=e.get(`${n.schema}.${n.renamedFrom}`);s&&r&&this.refuse(`table ${D(n)} is renamed from ${n.renamedFrom}, but ${D(n)} is there already`,"remove renamedFrom, or rename to a free name"),!s&&r&&(s=r)}!s||this.fromMatched.has(s)||(this.fromMatched.add(s),this.matches.set(D(n),this.matchColumns(n,s)))}}matchColumns(e,n){let s=D(e),r=new Map(n.columns.map(c=>[c.name,c])),o={to:e,from:n,physical:n.name,renamed:new Map,cols:new Map,retyped:new Map,parked:new Map},a=new Set,i=new Set(e.columns.filter(c=>c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&r.has(c.renamedFrom)&&!r.has(c.name)).map(c=>c.renamedFrom));for(let c of e.columns){let l=i.has(c.name)?void 0:r.get(c.name);if(c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&r.has(c.renamedFrom)&&(r.has(c.name)?this.refuse(`column ${s}.${c.name} is renamed from ${c.renamedFrom}, but ${c.name} is there already`,"remove renamedFrom, or rename to a free name"):l=r.get(c.renamedFrom)),!l&&i.has(c.name)){let u=ie(this.n,"add",c.name);o.parked.set(c.name,u),o.cols.set(c.name,u);continue}if(!l||a.has(l.name)){o.cols.set(c.name,c.name);continue}if(a.add(l.name),l.name!==c.name&&o.renamed.set(l.name,c.name),be(l.type)!==be(c.type)){let u=ie(this.n,"new",c.name);o.retyped.set(c.name,{shadow:u,from:l,to:c}),o.cols.set(c.name,u)}else o.cols.set(c.name,l.name)}return o}inNewNames(e){let s=[...this.matches.values()].find(a=>a.from===e)?.renamed??new Map,r=a=>s.get(a)??a,o=a=>ke(a,s);return{...e,uniques:e.uniques.map(a=>({...a,columns:a.columns.map(r)})),indexes:e.indexes.map(a=>({...a,keys:a.keys.map(i=>"column"in i?{...i,column:r(i.column)}:{...i,expr:o(i.expr)}),include:a.include?.map(r),where:a.where===void 0?void 0:o(a.where)})),checks:e.checks.map(a=>({...a,expr:o(a.expr)})),foreignKeys:e.foreignKeys.map(a=>this.fkInNewNames(a,r)),policies:e.policies.map(a=>({...a,using:a.using===void 0?void 0:o(a.using),withCheck:a.withCheck===void 0?void 0:o(a.withCheck)})),primaryKey:e.primaryKey.map(r)}}fkInNewNames(e,n){let s=this.from.tables.find(o=>o.schema===e.refSchema&&o.name===e.refTable),r=s&&[...this.matches.values()].find(o=>o.from===s);return{...e,columns:e.columns.map(n),refTable:r?r.to.name:e.refTable,refColumns:e.refColumns.map(o=>r?.renamed.get(o)??o)}}where(e){let n=this.matches.get(D(e));return n?{table:n.physical,cols:n.cols}:{table:e.name,cols:new Map(e.columns.map(s=>[s.name,s.name]))}}grants(e){let{anon:n,authenticated:s,service:r}=this.input.roles;return[`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${e} TO ${[n,s,r].map(b).join(", ")}`]}typeSql(e){let n=/^([a-z_][a-z0-9_]*)\.([a-z_][a-z0-9_]*)((?:\[\])*)$/i.exec(e);return n?`${P(n[1],n[2])}${n[3]}`:e}columnSql(e){let n=`${b(e.name)} ${this.typeSql(e.type)}`;return e.identity&&(n+=` GENERATED ${e.identity==="always"?"ALWAYS":"BY DEFAULT"} AS IDENTITY`),e.generated&&(n+=` GENERATED ALWAYS AS (${e.generated.expr}) ${e.generated.stored?"STORED":"VIRTUAL"}`),e.default!==void 0&&(n+=` DEFAULT ${e.default}`),e.nullable||(n+=" NOT NULL"),n}sequences(e,n,s,r){let{anon:o,authenticated:a,service:i}=this.input.roles;for(let c of _o(n.default)){let l=new RegExp(String.raw`\bCREATE\s+SEQUENCE\s+(?:IF\s+NOT\s+EXISTS\s+)?${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?![\w$"])`,"i");if(this.to.raw.some(u=>l.test(u.sql))){r.push(`GRANT USAGE, SELECT ON SEQUENCE ${c} TO ${[o,a,i].map(b).join(", ")}`);continue}s.push(`CREATE SEQUENCE IF NOT EXISTS ${c}`),r.push(`ALTER SEQUENCE ${c} OWNED BY ${P(e.schema,e.name)}.${b(n.name)}`,`GRANT USAGE, SELECT ON SEQUENCE ${c} TO ${[o,a,i].map(b).join(", ")}`)}}createTable(e){let n=P(e.schema,e.name),s=new Map(e.columns.map(c=>[c.name,c.name]));this.changes.push(`table ${D(e)}`);let r=[];for(let c of e.columns)this.sequences(e,c,this.creates,r);let o=e.columns.map(c=>this.columnSql(c)),a=new Set,i=[];e.primaryKey.length>0&&(o.push(`PRIMARY KEY (${ye(e.primaryKey)})`),a.add(e.primaryKey.join("\0")));for(let c of e.uniques){let l=c.columns.join("\0");a.has(l)?i.push(`ALTER TABLE ${n} ADD CONSTRAINT ${b(c.name)} UNIQUE (${ye(c.columns)})`):o.push(`CONSTRAINT ${b(c.name)} UNIQUE (${ye(c.columns)})`),a.add(l)}for(let c of e.checks)o.push(`CONSTRAINT ${b(c.name)} CHECK (${c.expr})`);this.creates.push(`CREATE TABLE ${n} (
72
+ END $palgres$`,`REVOKE ALL ON FUNCTION ${s}.promote(text) FROM PUBLIC`,`GRANT EXECUTE ON FUNCTION ${s}.promote(text) TO ${n}`,`COMMENT ON SCHEMA ${s} IS ${M(et(t))}`]}var vt=new Set,nt={listen(t){return vt.add(t),()=>{vt.delete(t)}},committed(){for(let t of vt)t()}};var ir=new Set(["tx","statement","backfill","seal","settle"]),Ut=2;function ea(...t){return t.some(e=>e.some(n=>n.kind==="seal"||n.kind==="settle"))?2:1}var $e=(t,e)=>`palgres_${t}_${e}`,lr=t=>Zo("sha256").update(t).digest("hex").slice(0,8),Dt=(t,e)=>`${t.name}_${e}_${lr(JSON.stringify([t.schema,t.name,e])).slice(0,6)}`,ie=(t,e,n)=>{let s=`_palgres_${t}_${e}_${n}`;return Buffer.byteLength(s)<=63?s:`_palgres_${t}_${e}_${lr(n)}`},Pt={anon:"anon",backend_anon:"anon",authenticated:"authenticated",backend_authenticated:"authenticated",service_role:"service",backend_service_role:"service",public:"public"},sr=t=>!t.nullable&&t.default===void 0&&!t.identity&&!t.generated,rr="the version serving now reads that value in the rows the new version writes";function Bt(t){return new Ft(t).run()}var Ft=class{from;to;fromN;n;input;changes=[];refusals=[];matches=new Map;fromMatched=new Set;prelude=[];creates=[];createFks=[];alters=[];backfills=[];online=[];settle=[];lateFks=[];searchStart=[];searchComplete=[];undoSearch=[];viewsAtComplete=null;namesAtComplete=!1;dropsColumnsAtComplete=!1;completeUnitDrops=[];raws=[];sealingStart=[];sealingComplete=[];sealingUndo=[];completeTables=[];completeIndexes=[];completeDrops=[];completeTypes=[];undoTables=[];undoOnline=[];fkDrops=[];undoFksGone=[];undoIndexesGone=[];undoFksBack=[];undoRawsGone=[];undoRawsBack=[];undoCreates=[];undoNewTables=[];layout={tables:[]};constructor(e){this.input=e,this.from=Ee(e.from?.schema??Rt());let n=new Map((e.from?.schema.raw??[]).map((r,o)=>[r.name,o]));this.from.raw.sort((r,o)=>(n.get(r.name)??0)-(n.get(o.name)??0)),this.to=Ee(e.to);let s=new Map(e.to.raw.map((r,o)=>[r.name,o]));this.to.raw.sort((r,o)=>(s.get(r.name)??0)-(s.get(o.name)??0)),this.fromN=e.from?.n??null,this.n=e.next}run(){this.extensions(),this.schemas(),this.enums(),this.rawUnitsBefore(),this.matchTables();for(let r of this.to.tables){let o=this.matches.get(D(r));o?(this.alterTable(o),this.encryption(o)):this.createTable(r),this.search(r,o)}for(let r of this.from.tables)this.fromMatched.has(r)||this.dropTable(r);this.rawUnits(),this.enumDrops();let e=[...this.prelude,...this.creates.length+this.createFks.length>0?[{kind:"tx",sql:[...this.creates,...this.createFks],why:"the new tables and types"}]:[],...this.fkDrops,...this.alters,...this.backfills,...this.online,...this.settle,...this.lateFks,...this.searchStart,...this.raws,...this.sealingStart,{kind:"tx",sql:this.views(),why:`version ${this.n}'s views`}],n=[...this.sealingComplete,...this.fromN!==null?[{kind:"tx",sql:this.dropViews(this.fromN,this.from),why:`version ${this.fromN}'s views`}]:[],...this.searchComplete,...this.viewsAtComplete?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.completeUnitDrops,...this.viewsAtComplete.drops,...this.completeTables.flatMap(r=>r.kind==="tx"?r.sql:[]),...this.viewsAtComplete.creates],why:"the tables, and the views that read them, at once"}]:[...this.completeUnitDrops.length>0?[{kind:"tx",sql:this.completeUnitDrops,why:"the triggers and rules gone"}]:[],...this.completeTables],...this.completeIndexes,...this.completeDrops.length>0?[{kind:"tx",sql:[`DROP TABLE IF EXISTS ${this.completeDrops.join(", ")}`],why:"the dropped tables"}]:[],...this.completeTypes.length>0?[{kind:"tx",sql:this.completeTypes,why:"the dropped types"}]:[]],s=[...this.sealingUndo,{kind:"tx",sql:this.dropViews(this.n,this.to),why:`version ${this.n}'s views`},...this.undoSearch,...this.undoFksGone,...this.undoRawsGone.length>0?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.undoRawsGone],why:"the units start made, taken back"}]:[],...[...this.undoTables].reverse(),...this.undoIndexesGone,...this.undoFksBack,...this.undoRawsBack.length>0?[{kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.undoRawsBack],why:"the units start replaced, back"}]:[],...this.undoOnline,...this.undoNewTables.length+this.undoCreates.length>0?[{kind:"tx",sql:[...this.undoNewTables.length>0?[`DROP TABLE IF EXISTS ${this.undoNewTables.join(", ")}`]:[],...[...this.undoCreates].reverse()],why:"the new tables and types"}]:[]];return{format:ea(e,n,s),from:this.fromN,to:this.n,changes:this.changes,refusals:this.refusals,start:e,complete:n,rollback:s,layout:this.layout}}refuse(e,n){this.refusals.push(`${e}: ${n}`)}encryption(e){let n=D(e.to),s=this.input.hasRows(D(e.from)),r=new Map(e.from.columns.map(a=>[a.name,a])),o=new Map([...e.renamed].map(([a,i])=>[i,a]));for(let a of e.to.columns){if(a.lookupOf!==void 0)continue;let i=r.get(o.get(a.name)??a.name);if(i===void 0||e.parked.has(a.name))continue;let c=a.encrypted!==void 0,l=i.encrypted!==void 0;if(!c&&!l)continue;if(s&&(i.name!==a.name||e.from.name!==e.to.name)){this.refuse(`column ${n}.${a.name} is encrypted and is renamed (or its table is) while the table holds rows: its values are bound to ${Qe(e.from.schema,e.from.name,i.name)}`,"keep its name; to move the values, add a new encrypted column, write them into it from the app, and ignore the old one");continue}if(c===l)continue;if(e.retyped.has(a.name)){this.refuse(`column ${n}.${a.name} changes its type and its encryption in one deploy`,"change one, deploy, then the other");continue}if(!s)continue;let u=Qe(e.to.schema,e.to.name,a.name);if(c&&a.encrypted?.lookup){let p=a.encrypted.lookup,E=e.to.uniques.some(f=>f.columns.includes(p))||e.to.indexes.some(f=>f.unique&&f.keys.some(d=>"column"in d&&d.column===p)),$=e.from.uniques.some(f=>f.columns.length===1&&f.columns[0]===i.name)||e.from.indexes.some(f=>f.unique&&f.keys.length===1&&"column"in f.keys[0]&&f.keys[0].column===i.name);if(E&&!$){this.refuse(`column ${n}.${a.name} becomes encrypted and unique in one deploy while the table holds rows`,"make it .unique() first and deploy \u2014 the rows are checked while they are plain \u2014 then encrypt it");continue}}let g=c?"seal":"open",m=M(u);this.changes.push(`column ${n}.${a.name} ${c?"becomes encrypted: its rows are sealed":"stops being encrypted: its rows are opened"} at complete`),this.sealingStart.push({kind:"tx",sql:[`INSERT INTO ${de} (address, direction, phase) VALUES (${m}, ${M(g)}, 'mixed') ON CONFLICT (address) DO UPDATE SET direction = EXCLUDED.direction, phase = 'mixed'`],why:`${u} goes over: the old version's form kept while it serves`}),g==="open"&&this.sealingStart.push({kind:"settle",ms:It,why:`the version serving reads that ${u} goes over`});let h=c&&a.encrypted?.lookup?e.cols.get(a.encrypted.lookup)??a.encrypted.lookup:null;if(this.sealingComplete.push({kind:"tx",sql:[`UPDATE ${de} SET phase = 'final' WHERE address = ${m}`],why:`${u}: the old version is gone, the new form is written`},{kind:"seal",table:P(e.from.schema,e.physical),column:i.name,lookup:h,address:u,direction:g,why:`${u}'s rows ${c?"sealed":"opened"}`},{kind:"tx",sql:[`DELETE FROM ${de} WHERE address = ${m}`],why:`${u} has gone over`}),g==="open"){let p=i.encrypted?.lookup??null;this.sealingUndo.push({kind:"seal",table:P(e.from.schema,e.physical),column:i.name,lookup:p,address:u,direction:"seal",why:`${u}'s rows the abandoned version wrote plain, sealed again`})}this.sealingUndo.push({kind:"tx",sql:[`DELETE FROM ${de} WHERE address = ${m}`],why:`${u} no longer goes over`})}}extensions(){for(let e of this.to.extensions)this.from.extensions.includes(e)||(this.changes.push(`extension ${e}`),this.prelude.push({kind:"statement",sql:`CREATE EXTENSION IF NOT EXISTS ${R(e)}`,why:`extension ${e}`}))}schemas(){let e=new Set([...this.from.tables.map(a=>a.schema),...this.from.enums.map(a=>a.schema),...this.from.raw.flatMap(a=>a.schema?[a.schema]:[]),"public"]),n=[...new Set([...this.to.tables.map(a=>a.schema),...this.to.enums.map(a=>a.schema),...this.to.raw.flatMap(a=>a.schema?[a.schema]:[])])].filter(a=>!e.has(a)),{anon:s,authenticated:r,service:o}=this.input.roles;for(let a of n)this.changes.push(`schema ${a}`),this.creates.push(`CREATE SCHEMA IF NOT EXISTS ${R(a)}`,`GRANT USAGE ON SCHEMA ${R(a)} TO ${[s,r,o].map(R).join(", ")}`)}enums(){for(let e of this.to.enums){let n=this.from.enums.find(o=>o.schema===e.schema&&o.name===e.name),s=P(e.schema,e.name);if(!n){this.changes.push(`type ${e.schema}.${e.name}`),this.creates.push(`CREATE TYPE ${s} AS ENUM (${e.values.map(M).join(", ")})`),this.undoCreates.push(`DROP TYPE IF EXISTS ${s}`);continue}let r=n.values.filter(o=>!e.values.includes(o));r.length>0&&this.refuse(`type ${e.schema}.${e.name} loses ${r.join(", ")}`,"Postgres cannot take a value out of an enum; add a new type and move the column to it");for(let o of e.values)n.values.includes(o)||(this.changes.push(`type ${e.schema}.${e.name} gains '${o}'`),this.prelude.push({kind:"statement",sql:`ALTER TYPE ${s} ADD VALUE IF NOT EXISTS ${M(o)}`,why:`${e.name} gains ${o}`}))}}enumDrops(){for(let e of this.from.enums)this.to.enums.some(n=>n.schema===e.schema&&n.name===e.name)||(this.changes.push(`type ${e.schema}.${e.name} goes (at complete)`),this.completeTypes.push(`DROP TYPE IF EXISTS ${P(e.schema,e.name)}`))}matchTables(){let e=new Map(this.from.tables.map(n=>[D(n),n]));for(let n of this.to.tables)n.renamedFrom===void 0||n.renamedFrom===n.name||!e.has(`${n.schema}.${n.renamedFrom}`)||this.to.tables.some(s=>s!==n&&s.schema===n.schema&&s.name===n.renamedFrom)&&this.refuse(`table ${n.schema}.${n.renamedFrom} is renamed ${n.name}, and a new table takes the name ${n.renamedFrom} in the same deploy`,`rename it in this deploy, and make the new ${n.renamedFrom} in the next`);for(let n of this.to.tables){let s=e.get(D(n));if(n.renamedFrom!==void 0&&n.renamedFrom!==n.name){let r=e.get(`${n.schema}.${n.renamedFrom}`);s&&r&&this.refuse(`table ${D(n)} is renamed from ${n.renamedFrom}, but ${D(n)} is there already`,"remove renamedFrom, or rename to a free name"),!s&&r&&(s=r)}!s||this.fromMatched.has(s)||(this.fromMatched.add(s),this.matches.set(D(n),this.matchColumns(n,s)))}}matchColumns(e,n){let s=D(e),r=new Map(n.columns.map(c=>[c.name,c])),o={to:e,from:n,physical:n.name,renamed:new Map,cols:new Map,retyped:new Map,parked:new Map},a=new Set,i=new Set(e.columns.filter(c=>c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&r.has(c.renamedFrom)&&!r.has(c.name)).map(c=>c.renamedFrom));for(let c of e.columns){let l=i.has(c.name)?void 0:r.get(c.name);if(c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&r.has(c.renamedFrom)&&(r.has(c.name)?this.refuse(`column ${s}.${c.name} is renamed from ${c.renamedFrom}, but ${c.name} is there already`,"remove renamedFrom, or rename to a free name"):l=r.get(c.renamedFrom)),!l&&i.has(c.name)){let u=ie(this.n,"add",c.name);o.parked.set(c.name,u),o.cols.set(c.name,u);continue}if(!l||a.has(l.name)){o.cols.set(c.name,c.name);continue}if(a.add(l.name),l.name!==c.name&&o.renamed.set(l.name,c.name),Ne(l.type)!==Ne(c.type)){let u=ie(this.n,"new",c.name);o.retyped.set(c.name,{shadow:u,from:l,to:c}),o.cols.set(c.name,u)}else o.cols.set(c.name,l.name)}return o}inNewNames(e){let s=[...this.matches.values()].find(a=>a.from===e)?.renamed??new Map,r=a=>s.get(a)??a,o=a=>xe(a,s);return{...e,uniques:e.uniques.map(a=>({...a,columns:a.columns.map(r)})),indexes:e.indexes.map(a=>({...a,keys:a.keys.map(i=>"column"in i?{...i,column:r(i.column)}:{...i,expr:o(i.expr)}),include:a.include?.map(r),where:a.where===void 0?void 0:o(a.where)})),checks:e.checks.map(a=>({...a,expr:o(a.expr)})),foreignKeys:e.foreignKeys.map(a=>this.fkInNewNames(a,r)),policies:e.policies.map(a=>({...a,using:a.using===void 0?void 0:o(a.using),withCheck:a.withCheck===void 0?void 0:o(a.withCheck)})),primaryKey:e.primaryKey.map(r)}}fkInNewNames(e,n){let s=this.from.tables.find(o=>o.schema===e.refSchema&&o.name===e.refTable),r=s&&[...this.matches.values()].find(o=>o.from===s);return{...e,columns:e.columns.map(n),refTable:r?r.to.name:e.refTable,refColumns:e.refColumns.map(o=>r?.renamed.get(o)??o)}}where(e){let n=this.matches.get(D(e));return n?{table:n.physical,cols:n.cols}:{table:e.name,cols:new Map(e.columns.map(s=>[s.name,s.name]))}}grants(e){let{anon:n,authenticated:s,service:r}=this.input.roles;return[`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${e} TO ${[n,s,r].map(R).join(", ")}`]}typeSql(e){let n=/^([a-z_][a-z0-9_]*)\.([a-z_][a-z0-9_]*)((?:\[\])*)$/i.exec(e);return n?`${P(n[1],n[2])}${n[3]}`:e}columnSql(e){let n=`${R(e.name)} ${this.typeSql(e.type)}`;return e.identity&&(n+=` GENERATED ${e.identity==="always"?"ALWAYS":"BY DEFAULT"} AS IDENTITY`),e.generated&&(n+=` GENERATED ALWAYS AS (${e.generated.expr}) ${e.generated.stored?"STORED":"VIRTUAL"}`),e.default!==void 0&&(n+=` DEFAULT ${e.default}`),e.nullable||(n+=" NOT NULL"),n}sequences(e,n,s,r){let{anon:o,authenticated:a,service:i}=this.input.roles;for(let c of na(n.default)){let l=new RegExp(String.raw`\bCREATE\s+SEQUENCE\s+(?:IF\s+NOT\s+EXISTS\s+)?${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?![\w$"])`,"i");if(this.to.raw.some(u=>l.test(u.sql))){r.push(`GRANT USAGE, SELECT ON SEQUENCE ${c} TO ${[o,a,i].map(R).join(", ")}`);continue}s.push(`CREATE SEQUENCE IF NOT EXISTS ${c}`),r.push(`ALTER SEQUENCE ${c} OWNED BY ${P(e.schema,e.name)}.${R(n.name)}`,`GRANT USAGE, SELECT ON SEQUENCE ${c} TO ${[o,a,i].map(R).join(", ")}`)}}createTable(e){let n=P(e.schema,e.name),s=new Map(e.columns.map(c=>[c.name,c.name]));this.changes.push(`table ${D(e)}`);let r=[];for(let c of e.columns)this.sequences(e,c,this.creates,r);let o=e.columns.map(c=>this.columnSql(c)),a=new Set,i=[];e.primaryKey.length>0&&(o.push(`PRIMARY KEY (${Te(e.primaryKey)})`),a.add(e.primaryKey.join("\0")));for(let c of e.uniques){let l=c.columns.join("\0");a.has(l)?i.push(`ALTER TABLE ${n} ADD CONSTRAINT ${R(c.name)} UNIQUE (${Te(c.columns)})`):o.push(`CONSTRAINT ${R(c.name)} UNIQUE (${Te(c.columns)})`),a.add(l)}for(let c of e.checks)o.push(`CONSTRAINT ${R(c.name)} CHECK (${c.expr})`);this.creates.push(`CREATE TABLE ${n} (
73
73
  ${o.join(`,
74
74
  `)}
75
- )`,...i,...r);for(let c of e.indexes)this.creates.push(this.indexSql(e.schema,e.name,c,s,!1));for(let c of e.foreignKeys){let l=`${c.refSchema}.${c.refTable}`;this.from.tables.some(u=>D(u)===l)&&l!==D(e)?(this.lateFks.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSql(c,s)} NOT VALID`],why:`foreign key ${c.name}`}),this.lateFks.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${b(c.name)}`,why:`foreign key ${c.name}`}),this.undoFksGone.push({kind:"tx",sql:[`ALTER TABLE IF EXISTS ${n} DROP CONSTRAINT IF EXISTS ${b(c.name)}`],why:`foreign key ${c.name}`})):this.createFks.push(`ALTER TABLE ${n} ADD ${this.fkSql(c,s)}`)}this.creates.push(...At(n,e.rls,!1));for(let c of e.policies)this.readsOthersRenamed(e,c,D(e))||this.createFks.push(this.policySql(n,c,s));this.creates.push(...this.grants(n)),this.undoNewTables.push(n),this.addLayout(e,e.name,s)}dropTable(e){if(!e.ignored&&this.input.hasRows(D(e))){this.refuse(`table ${D(e)} is gone from the schema and has rows`,"mark it ignored first (defineTable(\u2026, { ignored: true })) and deploy; remove it in the deploy after that, when its data may go");return}this.changes.push(`table ${D(e)} goes (at complete)`),this.searchGone(e,e.name),this.completeDrops.push(P(e.schema,e.name))}addLayout(e,n,s){e.ignored||this.layout.tables.push({schema:e.schema,name:e.name,physical:n,columns:e.columns.filter(r=>!r.ignored).map(r=>({name:r.name,physical:s.get(r.name)}))})}alterTable(e){let{to:n,from:s}=e,r=P(n.schema,e.physical),o=D(n),a={tx:[],undo:[],undoColumns:[],complete:[]},i=this.input.hasRows(D(s));n.name!==s.name&&this.changes.push(`table ${n.schema}.${s.name} is renamed ${n.name} (at complete)`);let c=new Map(s.columns.map(g=>[g.name,g])),l=new Set;for(let g of n.columns){let p=e.cols.get(g.name),h=e.retyped.get(g.name),m=h?.from??(e.parked.has(g.name)?void 0:c.get(p));if(!m){this.addColumn(n,r,p===g.name?g:{...g,name:p},a);continue}if(l.add(m.name),h){this.retype(e,r,g.name,h,a);continue}m.name!==g.name&&(this.changes.push(`column ${o}.${m.name} is renamed ${g.name} (at complete)`),a.complete.push(`ALTER TABLE ${r} RENAME COLUMN ${b(m.name)} TO ${b(g.name)}`),a.names=!0),g.ignored&&!m.ignored&&this.insertsWithout(o,g),this.alterColumn(n,r,m,g,a)}for(let g of s.columns)if(!l.has(g.name)){if(!g.ignored&&i){let p=qs(g)?` \u2014 and, being NOT NULL with no default, with one (.default(\u2026)): ${Fs}`:"";this.refuse(`column ${D(s)}.${g.name} is gone from the schema and the table has rows`,`mark it ignored first (.ignored())${p}, and deploy; remove it in the deploy after that, when its data may go`);continue}g.ignored||this.insertsWithout(o,g),this.changes.push(`column ${D(s)}.${g.name} goes (at complete)`),a.complete.push(`ALTER TABLE ${r} DROP COLUMN IF EXISTS ${b(g.name)}`),a.names=!0,a.dropsColumns=!0}this.constraints(e,r,a),this.policies(e,r,a),s.rls!==n.rls&&(this.changes.push(`table ${o}: row-level security ${n.rls?"on":"off"}`),a.tx.push(...At(r,n.rls,!0)),a.undo.push(...At(r,s.rls,!0))),this.inNewNames(s).primaryKey.join()!==n.primaryKey.join()&&this.refuse(`the primary key of ${o} changes`,"a primary key cannot change while both versions write the table; add a unique constraint instead"),a.tx.length>0&&this.alters.push({kind:"tx",sql:a.tx,why:`table ${o}`});let u=[...a.undo,...a.undoColumns];u.length>0&&this.undoTables.push({kind:"tx",sql:u,why:`table ${o}`});for(let[g,p]of e.parked)this.changes.push(`column ${o}.${g} is made as ${p}, and takes its name at complete`),a.complete.push(`ALTER TABLE ${r} RENAME COLUMN ${b(p)} TO ${b(g)}`),a.names=!0;n.name!==s.name&&(a.complete.push(`ALTER TABLE ${r} RENAME TO ${b(n.name)}`),a.names=!0),a.names&&(this.namesAtComplete=!0),a.dropsColumns&&(this.dropsColumnsAtComplete=!0),a.complete.length>0&&this.completeTables.push({kind:"tx",sql:a.complete,why:`table ${o}`}),this.addLayout(n,e.physical,e.cols)}sequenceRenamed(e,n){let[s,r]=Vn(e.default),[o,a]=Vn(n.default);if(s===void 0||o===void 0||r!==void 0||a!==void 0||(s.schema??null)!==(o.schema??null)||s.name===o.name)return;let i=h=>h.replace(Hs,"nextval()");if(i(e.default)!==i(n.default))return;let c=h=>m=>m.name===h.name&&(m.schema??null)===(h.schema??null),l=h=>this.from.tables.flatMap(m=>m.columns).filter(m=>Vn(m.default).some(c(h))).length;if(l(s)!==1||l(o)!==0)return;let u=h=>h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=o.schema===void 0?String.raw`[^".\s]+`:u(o.schema),p=new RegExp(String.raw`\bSEQUENCE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"?${g}"?\.)?"?${u(o.name)}"?(?![\w$"])`,"i");if(!this.from.raw.some(h=>p.test(h.sql)))return{from:s.schema===void 0?b(s.name):P(s.schema,s.name),to:o.name}}insertsWithout(e,n){qs(n)&&this.refuse(`column ${e}.${n.name} is NOT NULL with no default, and the new version inserts rows without it`,`give it a default (.default(\u2026)): ${Fs} \u2014 or make it nullable in this deploy, if that version can read it empty`)}addColumn(e,n,s,r){let o=[];this.sequences(e,s,r.tx,o),this.addColumnItself(e,n,s,r),r.tx.push(...o)}addColumnItself(e,n,s,r){let o=D(e),a=b(s.name);if(this.changes.push(`column ${o}.${s.name}`),r.undoColumns.push(`ALTER TABLE ${n} DROP COLUMN IF EXISTS ${a}`),s.identity){this.input.hasRows(D(this.matches.get(o).from))?this.refuse(`column ${o}.${s.name} is an identity column added to a table with rows`,"Postgres would rewrite the table under a lock; add a bigint column with a default and fill it"):r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(s.generated){s.generated.stored&&this.input.hasRows(D(this.matches.get(o).from))?this.refuse(`column ${o}.${s.name} is a stored generated column added to a table with rows`,"Postgres would rewrite the table under a lock: add it virtual (.generated(expr)), or as a plain column a trigger keeps"):r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(this.input.hasRows(D(this.matches.get(o).from))&&this.checkedDomain(s.type)){this.refuse(`column ${o}.${s.name} is of ${s.type}, a domain with a CHECK, added to a table with rows`,"Postgres would rewrite the table under a lock to check every row: add it as the domain's base type with a CHECK (added NOT VALID, then validated), or before the table has rows");return}if(!(s.default!==void 0&&vs(s.default))&&(s.nullable||s.default!==void 0)){r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(!s.nullable&&s.default===void 0&&s.fill===void 0){this.refuse(`column ${o}.${s.name} is NOT NULL with no default`,"the version serving now inserts rows without it: give it a default (.default(\u2026)) or the value for those rows (.fillWith(sql))");return}r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${a} ${this.typeSql(s.type)}`),s.default!==void 0?(r.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${a} SET DEFAULT ${s.default}`),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(e),set:`${a} = ${s.default}`,where:`${a} IS NULL`,why:`${o}.${s.name} takes its default`})):this.fill(e,n,s.name,s.fill,r),s.nullable||this.notNull(e,n,s.name,r)}fill(e,n,s,r,o){let a=D(e),i=P(e.schema,ie(this.n,"fill",bt(e,s))),c=b(ie(this.n,"fill",s)),l=b(s),u=this.where(e),g=ke(r,un(u.cols));o.tx.push(`CREATE OR REPLACE FUNCTION ${i}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
75
+ )`,...i,...r);for(let c of e.indexes)this.creates.push(this.indexSql(e.schema,e.name,c,s,!1));for(let c of e.foreignKeys){let l=`${c.refSchema}.${c.refTable}`;this.from.tables.some(u=>D(u)===l)&&l!==D(e)?(this.lateFks.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSql(c,s)} NOT VALID`],why:`foreign key ${c.name}`}),this.lateFks.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${R(c.name)}`,why:`foreign key ${c.name}`}),this.undoFksGone.push({kind:"tx",sql:[`ALTER TABLE IF EXISTS ${n} DROP CONSTRAINT IF EXISTS ${R(c.name)}`],why:`foreign key ${c.name}`})):this.createFks.push(`ALTER TABLE ${n} ADD ${this.fkSql(c,s)}`)}this.creates.push(...Mt(n,e.rls,!1));for(let c of e.policies)this.readsOthersRenamed(e,c,D(e))||this.createFks.push(this.policySql(n,c,s));this.creates.push(...this.grants(n)),this.undoNewTables.push(n),this.addLayout(e,e.name,s)}dropTable(e){if(!e.ignored&&this.input.hasRows(D(e))){this.refuse(`table ${D(e)} is gone from the schema and has rows`,"mark it ignored first (defineTable(\u2026, { ignored: true })) and deploy; remove it in the deploy after that, when its data may go");return}this.changes.push(`table ${D(e)} goes (at complete)`),this.searchGone(e,e.name),this.completeDrops.push(P(e.schema,e.name))}addLayout(e,n,s){e.ignored||this.layout.tables.push({schema:e.schema,name:e.name,physical:n,columns:e.columns.filter(r=>!r.ignored).map(r=>({name:r.name,physical:s.get(r.name)}))})}alterTable(e){let{to:n,from:s}=e,r=P(n.schema,e.physical),o=D(n),a={tx:[],undo:[],undoColumns:[],complete:[]},i=this.input.hasRows(D(s));n.name!==s.name&&this.changes.push(`table ${n.schema}.${s.name} is renamed ${n.name} (at complete)`);let c=new Map(s.columns.map(g=>[g.name,g])),l=new Set;for(let g of n.columns){let m=e.cols.get(g.name),h=e.retyped.get(g.name),p=h?.from??(e.parked.has(g.name)?void 0:c.get(m));if(!p){this.addColumn(n,r,m===g.name?g:{...g,name:m},a);continue}if(l.add(p.name),h){this.retype(e,r,g.name,h,a);continue}p.name!==g.name&&(this.changes.push(`column ${o}.${p.name} is renamed ${g.name} (at complete)`),a.complete.push(`ALTER TABLE ${r} RENAME COLUMN ${R(p.name)} TO ${R(g.name)}`),a.names=!0),g.ignored&&!p.ignored&&this.insertsWithout(o,g),this.alterColumn(n,r,p,g,a)}for(let g of s.columns)if(!l.has(g.name)){if(!g.ignored&&i&&g.lookupOf===void 0){let m=sr(g)?` \u2014 and, being NOT NULL with no default, with one (.default(\u2026)): ${rr}`:"";this.refuse(`column ${D(s)}.${g.name} is gone from the schema and the table has rows`,`mark it ignored first (.ignored())${m}, and deploy; remove it in the deploy after that, when its data may go`);continue}g.ignored||this.insertsWithout(o,g),this.changes.push(`column ${D(s)}.${g.name} goes (at complete)`),a.complete.push(`ALTER TABLE ${r} DROP COLUMN IF EXISTS ${R(g.name)}`),a.names=!0,a.dropsColumns=!0}this.constraints(e,r,a),this.policies(e,r,a),s.rls!==n.rls&&(this.changes.push(`table ${o}: row-level security ${n.rls?"on":"off"}`),a.tx.push(...Mt(r,n.rls,!0)),a.undo.push(...Mt(r,s.rls,!0))),this.inNewNames(s).primaryKey.join()!==n.primaryKey.join()&&this.refuse(`the primary key of ${o} changes`,"a primary key cannot change while both versions write the table; add a unique constraint instead"),a.tx.length>0&&this.alters.push({kind:"tx",sql:a.tx,why:`table ${o}`});let u=[...a.undo,...a.undoColumns];u.length>0&&this.undoTables.push({kind:"tx",sql:u,why:`table ${o}`});for(let[g,m]of e.parked)this.changes.push(`column ${o}.${g} is made as ${m}, and takes its name at complete`),a.complete.push(`ALTER TABLE ${r} RENAME COLUMN ${R(m)} TO ${R(g)}`),a.names=!0;n.name!==s.name&&(a.complete.push(`ALTER TABLE ${r} RENAME TO ${R(n.name)}`),a.names=!0),a.names&&(this.namesAtComplete=!0),a.dropsColumns&&(this.dropsColumnsAtComplete=!0),a.complete.length>0&&this.completeTables.push({kind:"tx",sql:a.complete,why:`table ${o}`}),this.addLayout(n,e.physical,e.cols)}sequenceRenamed(e,n){let[s,r]=rt(e.default),[o,a]=rt(n.default);if(s===void 0||o===void 0||r!==void 0||a!==void 0||(s.schema??null)!==(o.schema??null)||s.name===o.name)return;let i=h=>h.replace(ur,"nextval()");if(i(e.default)!==i(n.default))return;let c=h=>p=>p.name===h.name&&(p.schema??null)===(h.schema??null),l=h=>this.from.tables.flatMap(p=>p.columns).filter(p=>rt(p.default).some(c(h))).length;if(l(s)!==1||l(o)!==0)return;let u=h=>h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=o.schema===void 0?String.raw`[^".\s]+`:u(o.schema),m=new RegExp(String.raw`\bSEQUENCE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"?${g}"?\.)?"?${u(o.name)}"?(?![\w$"])`,"i");if(!this.from.raw.some(h=>m.test(h.sql)))return{from:s.schema===void 0?R(s.name):P(s.schema,s.name),to:o.name}}insertsWithout(e,n){sr(n)&&this.refuse(`column ${e}.${n.name} is NOT NULL with no default, and the new version inserts rows without it`,`give it a default (.default(\u2026)): ${rr} \u2014 or make it nullable in this deploy, if that version can read it empty`)}addColumn(e,n,s,r){let o=[];this.sequences(e,s,r.tx,o),this.addColumnItself(e,n,s,r),r.tx.push(...o)}addColumnItself(e,n,s,r){let o=D(e),a=R(s.name);if(this.changes.push(`column ${o}.${s.name}`),r.undoColumns.push(`ALTER TABLE ${n} DROP COLUMN IF EXISTS ${a}`),s.identity){this.input.hasRows(D(this.matches.get(o).from))?this.refuse(`column ${o}.${s.name} is an identity column added to a table with rows`,"Postgres would rewrite the table under a lock; add a bigint column with a default and fill it"):r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(s.generated){s.generated.stored&&this.input.hasRows(D(this.matches.get(o).from))?this.refuse(`column ${o}.${s.name} is a stored generated column added to a table with rows`,"Postgres would rewrite the table under a lock: add it virtual (.generated(expr)), or as a plain column a trigger keeps"):r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(this.input.hasRows(D(this.matches.get(o).from))&&this.checkedDomain(s.type)){this.refuse(`column ${o}.${s.name} is of ${s.type}, a domain with a CHECK, added to a table with rows`,"Postgres would rewrite the table under a lock to check every row: add it as the domain's base type with a CHECK (added NOT VALID, then validated), or before the table has rows");return}if(!(s.default!==void 0&&zs(s.default))&&(s.nullable||s.default!==void 0)){r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${this.columnSql(s)}`);return}if(!s.nullable&&s.default===void 0&&s.fill===void 0){this.refuse(`column ${o}.${s.name} is NOT NULL with no default`,"the version serving now inserts rows without it: give it a default (.default(\u2026)) or the value for those rows (.fillWith(sql))");return}r.tx.push(`ALTER TABLE ${n} ADD COLUMN ${a} ${this.typeSql(s.type)}`),s.default!==void 0?(r.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${a} SET DEFAULT ${s.default}`),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(e),set:`${a} = ${s.default}`,where:`${a} IS NULL`,why:`${o}.${s.name} takes its default`})):this.fill(e,n,s.name,s.fill,r),s.nullable||this.notNull(e,n,s.name,r)}fill(e,n,s,r,o){let a=D(e),i=P(e.schema,ie(this.n,"fill",Dt(e,s))),c=R(ie(this.n,"fill",s)),l=R(s),u=this.where(e),g=xe(r,yn(u.cols));o.tx.push(`CREATE OR REPLACE FUNCTION ${i}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
76
76
  BEGIN
77
77
  IF NEW.${l} IS NULL THEN
78
78
  NEW.${l} := (SELECT (
79
79
  ${g}
80
- ) FROM (SELECT (NEW).*) AS ${b(u.table)});
80
+ ) FROM (SELECT (NEW).*) AS ${R(u.table)});
81
81
  END IF;
82
82
  RETURN NEW;
83
- END $palgres$`,`CREATE TRIGGER ${c} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${i}()`);let p=[`DROP TRIGGER IF EXISTS ${c} ON ${n}`,`DROP FUNCTION IF EXISTS ${i}()`];o.undo.push(...p),o.complete.unshift(...p),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(e),set:`${l} = (
83
+ END $palgres$`,`CREATE TRIGGER ${c} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${i}()`);let m=[`DROP TRIGGER IF EXISTS ${c} ON ${n}`,`DROP FUNCTION IF EXISTS ${i}()`];o.undo.push(...m),o.complete.unshift(...m),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(e),set:`${l} = (
84
84
  ${g}
85
- )`,where:`${l} IS NULL`,why:`${a}.${s} is filled`})}relaxNotNull(e,n,s,r){let o=b(s);r.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${o} DROP NOT NULL`);let a=b(ie(this.n,"nn",s)),i=`EXISTS (SELECT 1 FROM pg_constraint WHERE conname = ${M(a.slice(1,-1))} AND conrelid = ${M(n)}::regclass`;this.undoOnline.push({kind:"tx",sql:[`DO $palgres$ BEGIN IF NOT ${i}) THEN ALTER TABLE ${n} ADD CONSTRAINT ${a} CHECK (${o} IS NOT NULL) NOT VALID; END IF; END $palgres$`],why:`${e}.${s} NOT NULL again`},{kind:"statement",sql:`DO $palgres$ BEGIN IF ${i}) THEN ALTER TABLE ${n} VALIDATE CONSTRAINT ${a}; END IF; EXCEPTION WHEN check_violation THEN ALTER TABLE ${n} DROP CONSTRAINT ${a}; RAISE WARNING 'palgres: % stays nullable: NULL was written since', ${M(`${e}.${s}`)}; END $palgres$`,why:`${e}.${s} has no NULL`},{kind:"tx",sql:[`DO $palgres$ BEGIN IF ${i} AND convalidated) THEN ALTER TABLE ${n} ALTER COLUMN ${o} SET NOT NULL; END IF; END $palgres$`,`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${a}`],why:`${e}.${s} is NOT NULL`})}notNull(e,n,s,r){let o=b(ie(this.n,"nn",s)),a=b(s);this.online.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD CONSTRAINT ${o} CHECK (${a} IS NOT NULL) NOT VALID`],why:`${D(e)}.${s} is held NOT NULL`}),r.undo.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${o}`),this.online.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${o}`,why:`${D(e)}.${s} has no NULL`}),this.settle.push({kind:"tx",sql:[`ALTER TABLE ${n} ALTER COLUMN ${a} SET NOT NULL`,`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${o}`],why:`${D(e)}.${s} is NOT NULL`})}alterColumn(e,n,s,r,o){let a=D(e),i=b(s.name);if(s.nullable&&!r.nullable){let c=r.fill??r.default;c===void 0?this.refuse(`column ${a}.${r.name} becomes NOT NULL`,"the version serving now may still write NULL: give the value for those rows and writes (.fillWith(sql))"):(this.changes.push(`column ${a}.${r.name} becomes NOT NULL`),this.fill(e,n,s.name,c,o),this.notNull(e,n,s.name,o),o.undo.push(`ALTER TABLE ${n} ALTER COLUMN ${i} DROP NOT NULL`))}if(!s.nullable&&r.nullable&&(this.changes.push(`column ${a}.${r.name} becomes nullable`),this.relaxNotNull(a,n,s.name,o)),(s.default??null)!==(r.default??null)){let c=this.sequenceRenamed(s,r);c!==void 0?(this.changes.push(`sequence ${c.from} becomes ${c.to} (at complete)`),o.complete.push(`ALTER SEQUENCE ${c.from} RENAME TO ${b(c.to)}`)):r.default!==void 0?(this.changes.push(`column ${a}.${r.name} defaults to ${r.default}`),o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET DEFAULT ${r.default}`),o.undo.push(s.default!==void 0?`ALTER TABLE ${n} ALTER COLUMN ${i} SET DEFAULT ${s.default}`:`ALTER TABLE ${n} ALTER COLUMN ${i} DROP DEFAULT`)):(this.changes.push(`column ${a}.${r.name} loses its default (at complete)`),o.complete.push(`ALTER TABLE ${n} ALTER COLUMN ${b(r.name)} DROP DEFAULT`))}(s.identity??null)!==(r.identity??null)&&this.refuse(`column ${a}.${r.name} changes identity`,"an identity cannot change while both versions write; add a new column"),this.regenerate(e,n,s,r,o)}regenerate(e,n,s,r,o){let a=D(e),i=b(s.name),c=s.generated,l=r.generated;if(!(!c&&!l)&&!(c&&l&&c.expr===l.expr&&c.stored===l.stored)){if(!c&&l){this.refuse(`column ${a}.${r.name} becomes a generated column`,"Postgres cannot make a column generated: add a new generated column and ignore the old one");return}if(c&&!l){if(!c.stored){this.refuse(`column ${a}.${r.name} stops being a virtual generated column`,"a virtual column holds no values to keep: add a plain column filled with .fillWith(expr) and ignore this one");return}this.changes.push(`column ${a}.${r.name} is no longer generated (it keeps its values; the old version's writes are computed until complete, and a rollback leaves it plain, computed so)`);let u=P(e.schema,ie(this.n,"gen",bt(e,s.name))),g=b(ie(this.n,"gen",s.name)),p=this.where(e);o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} DROP EXPRESSION IF EXISTS`,`CREATE OR REPLACE FUNCTION ${u}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
85
+ )`,where:`${l} IS NULL`,why:`${a}.${s} is filled`})}relaxNotNull(e,n,s,r){let o=R(s);r.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${o} DROP NOT NULL`);let a=R(ie(this.n,"nn",s)),i=`EXISTS (SELECT 1 FROM pg_constraint WHERE conname = ${M(a.slice(1,-1))} AND conrelid = ${M(n)}::regclass`;this.undoOnline.push({kind:"tx",sql:[`DO $palgres$ BEGIN IF NOT ${i}) THEN ALTER TABLE ${n} ADD CONSTRAINT ${a} CHECK (${o} IS NOT NULL) NOT VALID; END IF; END $palgres$`],why:`${e}.${s} NOT NULL again`},{kind:"statement",sql:`DO $palgres$ BEGIN IF ${i}) THEN ALTER TABLE ${n} VALIDATE CONSTRAINT ${a}; END IF; EXCEPTION WHEN check_violation THEN ALTER TABLE ${n} DROP CONSTRAINT ${a}; RAISE WARNING 'palgres: % stays nullable: NULL was written since', ${M(`${e}.${s}`)}; END $palgres$`,why:`${e}.${s} has no NULL`},{kind:"tx",sql:[`DO $palgres$ BEGIN IF ${i} AND convalidated) THEN ALTER TABLE ${n} ALTER COLUMN ${o} SET NOT NULL; END IF; END $palgres$`,`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${a}`],why:`${e}.${s} is NOT NULL`})}notNull(e,n,s,r){let o=R(ie(this.n,"nn",s)),a=R(s);this.online.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD CONSTRAINT ${o} CHECK (${a} IS NOT NULL) NOT VALID`],why:`${D(e)}.${s} is held NOT NULL`}),r.undo.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${o}`),this.online.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${o}`,why:`${D(e)}.${s} has no NULL`}),this.settle.push({kind:"tx",sql:[`ALTER TABLE ${n} ALTER COLUMN ${a} SET NOT NULL`,`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${o}`],why:`${D(e)}.${s} is NOT NULL`})}alterColumn(e,n,s,r,o){let a=D(e),i=R(s.name);if(s.nullable&&!r.nullable){let c=r.fill??r.default;c===void 0?this.refuse(`column ${a}.${r.name} becomes NOT NULL`,"the version serving now may still write NULL: give the value for those rows and writes (.fillWith(sql))"):(this.changes.push(`column ${a}.${r.name} becomes NOT NULL`),this.fill(e,n,s.name,c,o),this.notNull(e,n,s.name,o),o.undo.push(`ALTER TABLE ${n} ALTER COLUMN ${i} DROP NOT NULL`))}if(!s.nullable&&r.nullable&&(this.changes.push(`column ${a}.${r.name} becomes nullable`),this.relaxNotNull(a,n,s.name,o)),(s.default??null)!==(r.default??null)){let c=this.sequenceRenamed(s,r);c!==void 0?(this.changes.push(`sequence ${c.from} becomes ${c.to} (at complete)`),o.complete.push(`ALTER SEQUENCE ${c.from} RENAME TO ${R(c.to)}`)):r.default!==void 0?(this.changes.push(`column ${a}.${r.name} defaults to ${r.default}`),o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET DEFAULT ${r.default}`),o.undo.push(s.default!==void 0?`ALTER TABLE ${n} ALTER COLUMN ${i} SET DEFAULT ${s.default}`:`ALTER TABLE ${n} ALTER COLUMN ${i} DROP DEFAULT`)):(this.changes.push(`column ${a}.${r.name} loses its default (at complete)`),o.complete.push(`ALTER TABLE ${n} ALTER COLUMN ${R(r.name)} DROP DEFAULT`))}(s.identity??null)!==(r.identity??null)&&this.refuse(`column ${a}.${r.name} changes identity`,"an identity cannot change while both versions write; add a new column"),this.regenerate(e,n,s,r,o)}regenerate(e,n,s,r,o){let a=D(e),i=R(s.name),c=s.generated,l=r.generated;if(!(!c&&!l)&&!(c&&l&&c.expr===l.expr&&c.stored===l.stored)){if(!c&&l){this.refuse(`column ${a}.${r.name} becomes a generated column`,"Postgres cannot make a column generated: add a new generated column and ignore the old one");return}if(c&&!l){if(!c.stored){this.refuse(`column ${a}.${r.name} stops being a virtual generated column`,"a virtual column holds no values to keep: add a plain column filled with .fillWith(expr) and ignore this one");return}this.changes.push(`column ${a}.${r.name} is no longer generated (it keeps its values; the old version's writes are computed until complete, and a rollback leaves it plain, computed so)`);let u=P(e.schema,ie(this.n,"gen",Dt(e,s.name))),g=R(ie(this.n,"gen",s.name)),m=this.where(e);o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} DROP EXPRESSION IF EXISTS`,`CREATE OR REPLACE FUNCTION ${u}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
86
86
  BEGIN
87
- IF position(${M(Te(this.n,""))} in replace(current_setting('search_path'), '"', '')) <> 1 THEN
87
+ IF position(${M($e(this.n,""))} in replace(current_setting('search_path'), '"', '')) <> 1 THEN
88
88
  NEW.${i} := (SELECT (
89
- ${ke(c.expr,un(p.cols))}
90
- ) FROM (SELECT (NEW).*) AS ${b(p.table)});
89
+ ${xe(c.expr,yn(m.cols))}
90
+ ) FROM (SELECT (NEW).*) AS ${R(m.table)});
91
91
  END IF;
92
92
  RETURN NEW;
93
- END $palgres$`,`CREATE TRIGGER ${g} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${u}()`),o.complete.unshift(`DROP TRIGGER IF EXISTS ${g} ON ${n}`,`DROP FUNCTION IF EXISTS ${u}()`);return}if(c.stored!==l.stored){this.refuse(`column ${a}.${r.name} changes between stored and virtual`,"Postgres would compute every row again: add a new generated column and ignore the old one");return}if(l.stored&&this.input.hasRows(D(this.matches.get(a).from))){this.refuse(`column ${a}.${r.name} changes its stored expression on a table with rows`,"Postgres would compute every row again under a lock: add a new generated column and ignore the old one");return}this.changes.push(`column ${a}.${r.name} is generated as ${l.expr}`),o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET EXPRESSION AS (${l.expr})`),o.undo.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET EXPRESSION AS (${c.expr})`)}}retype(e,n,s,r,o){let a=e.to,i=D(a),c=[...a.checks.filter(m=>Oe(m.expr,s)).map(m=>`check ${m.name}`),...a.policies.filter(m=>Oe(`${m.using??""} ${m.withCheck??""}`,s)).map(m=>`policy ${m.name}`),...a.indexes.filter(m=>m.keys.some(y=>"expr"in y&&Oe(y.expr,s))||m.where!==void 0&&Oe(m.where,s)).map(m=>`index ${m.name}`),...a.primaryKey.includes(s)?["the primary key"]:[],...this.to.tables.flatMap(m=>m.foreignKeys.filter(y=>y.refSchema===a.schema&&y.refTable===a.name&&y.refColumns.includes(s)).map(y=>`foreign key ${D(m)}.${y.name}`))];if(c.length>0){this.refuse(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}, and ${c.join(", ")} use it`,`add a column of the new type with .fillWith("${s}::${r.to.type}"), move them to it, and ignore the old one`);return}let l=this.conversion(r.from.type,r.to.type);if("refused"in l){this.refuse(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}: ${l.refused}`,"add a column of the new type with .fillWith(\u2026) saying the value, move to it, and ignore the old one");return}if(r.from.nullable&&!r.to.nullable){this.refuse(`column ${i}.${s} changes type and becomes NOT NULL in one deploy`,"change its type in this deploy and make it NOT NULL (with .fillWith) in the next");return}this.changes.push(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}`);let u=b(r.from.name),g=b(r.shadow),p=P(a.schema,ie(this.n,"sync",bt(a,s))),h=b(ie(this.n,"sync",s));o.tx.push(`ALTER TABLE ${n} ADD COLUMN ${g} ${this.typeSql(r.to.type)}`,`CREATE OR REPLACE FUNCTION ${p}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
93
+ END $palgres$`,`CREATE TRIGGER ${g} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${u}()`),o.complete.unshift(`DROP TRIGGER IF EXISTS ${g} ON ${n}`,`DROP FUNCTION IF EXISTS ${u}()`);return}if(c.stored!==l.stored){this.refuse(`column ${a}.${r.name} changes between stored and virtual`,"Postgres would compute every row again: add a new generated column and ignore the old one");return}if(l.stored&&this.input.hasRows(D(this.matches.get(a).from))){this.refuse(`column ${a}.${r.name} changes its stored expression on a table with rows`,"Postgres would compute every row again under a lock: add a new generated column and ignore the old one");return}this.changes.push(`column ${a}.${r.name} is generated as ${l.expr}`),o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET EXPRESSION AS (${l.expr})`),o.undo.push(`ALTER TABLE ${n} ALTER COLUMN ${i} SET EXPRESSION AS (${c.expr})`)}}retype(e,n,s,r,o){let a=e.to,i=D(a),c=[...a.checks.filter(p=>Le(p.expr,s)).map(p=>`check ${p.name}`),...a.policies.filter(p=>Le(`${p.using??""} ${p.withCheck??""}`,s)).map(p=>`policy ${p.name}`),...a.indexes.filter(p=>p.keys.some(E=>"expr"in E&&Le(E.expr,s))||p.where!==void 0&&Le(p.where,s)).map(p=>`index ${p.name}`),...a.primaryKey.includes(s)?["the primary key"]:[],...this.to.tables.flatMap(p=>p.foreignKeys.filter(E=>E.refSchema===a.schema&&E.refTable===a.name&&E.refColumns.includes(s)).map(E=>`foreign key ${D(p)}.${E.name}`))];if(c.length>0){this.refuse(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}, and ${c.join(", ")} use it`,`add a column of the new type with .fillWith("${s}::${r.to.type}"), move them to it, and ignore the old one`);return}let l=this.conversion(r.from.type,r.to.type);if("refused"in l){this.refuse(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}: ${l.refused}`,"add a column of the new type with .fillWith(\u2026) saying the value, move to it, and ignore the old one");return}if(r.from.nullable&&!r.to.nullable){this.refuse(`column ${i}.${s} changes type and becomes NOT NULL in one deploy`,"change its type in this deploy and make it NOT NULL (with .fillWith) in the next");return}this.changes.push(`column ${i}.${s} changes type from ${r.from.type} to ${r.to.type}`);let u=R(r.from.name),g=R(r.shadow),m=P(a.schema,ie(this.n,"sync",Dt(a,s))),h=R(ie(this.n,"sync",s));o.tx.push(`ALTER TABLE ${n} ADD COLUMN ${g} ${this.typeSql(r.to.type)}`,`CREATE OR REPLACE FUNCTION ${m}() RETURNS trigger LANGUAGE plpgsql AS $palgres$
94
94
  DECLARE
95
- next boolean := position(${M(Te(this.n,""))} in replace(current_setting('search_path'), '"', '')) = 1;
95
+ next boolean := position(${M($e(this.n,""))} in replace(current_setting('search_path'), '"', '')) = 1;
96
96
  BEGIN
97
97
  -- The writer's own column, taken across \u2014 on an update only when it
98
98
  -- changed: a value the other version wrote is not cast back over (a cast
@@ -112,32 +112,32 @@ BEGIN
112
112
  NEW.${g} := ${l.on(`NEW.${u}`)};
113
113
  END IF;
114
114
  RETURN NEW;
115
- END $palgres$`,`CREATE TRIGGER ${h} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${p}()`),r.to.default!==void 0&&o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${g} SET DEFAULT ${r.to.default}`),!r.from.nullable&&r.to.nullable&&this.relaxNotNull(i,n,r.from.name,o),o.undo.push(`DROP TRIGGER IF EXISTS ${h} ON ${n}`,`DROP FUNCTION IF EXISTS ${p}()`),o.undoColumns.push(`ALTER TABLE ${n} DROP COLUMN IF EXISTS ${g}`),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(a),set:`${u} = ${u}`,where:`${g} IS NULL AND ${u} IS NOT NULL`,why:`${i}.${s} in its new type`}),r.to.nullable||this.notNull(a,n,r.shadow,o),o.complete.push(`DROP TRIGGER IF EXISTS ${h} ON ${n}`,`DROP FUNCTION IF EXISTS ${p}()`,`ALTER TABLE ${n} DROP COLUMN ${u}`,`ALTER TABLE ${n} RENAME COLUMN ${g} TO ${b(s)}`),o.names=!0,o.dropsColumns=!0}checkedDomain(e){if(this.input.checkedDomain(this.typeSql(e))===!0)return!0;let n=be(e).replace(/^public\./,""),s=o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(String.raw`\bCREATE\s+DOMAIN\s+(?:"?public"?\.)?"?${s(n.replace(/^"|"$/g,""))}"?\s[\s\S]*\b(?:CHECK|NOT\s+NULL)\b`,"i");return this.to.raw.some(o=>r.test(o.sql))}conversion(e,n){let s=h=>/(\[\])*$/.exec(h)[0],r=h=>h.slice(0,h.length-s(h).length);if(s(e)!==s(n))return{refused:"one is an array and the other is not, or of another depth"};let o=s(e),a=h=>{let m=be(r(h));return[...this.to.enums,...this.from.enums].find(y=>rn(y.schema,y.name)===m||y.schema==="public"&&rn(y.schema,y.name)===`public.${m}`)},i=h=>/^(text|citext|public\.citext|character varying(\(\d+\))?|character(\(\d+\))?)$/.test(be(r(h))),c=h=>m=>`${m}::${this.typeSql(h)}`,l=a(e),u=a(n);if(l&&u){let h=(f,d)=>f.filter(T=>!d.includes(T)),m=h(l.values,u.values),y=h(u.values,l.values);if(m.length>0||y.length>0)return{refused:`the enums' labels differ (${[...m.map(f=>`-${f}`),...y.map(f=>`+${f}`)].join(", ")}), and a label one version writes the other's column cannot hold`};let S=f=>d=>`${d}::text${o}::${this.typeSql(f)}`;return{on:S(n),back:S(e)}}if(l||u)return i(l?n:e)?{on:c(n),back:c(e)}:{refused:`Postgres has no cast between an enum and ${l?n:e}`};let g=this.input.castable(this.typeSql(e),this.typeSql(n)),p=this.input.castable(this.typeSql(n),this.typeSql(e));return g===!1||p===!1?{refused:`Postgres has no cast from ${g===!1?e:n} to ${g===!1?n:e}`}:{on:c(n),back:c(e)}}constraints(e,n,s){let{to:r}=e,o=this.inNewNames(e.from),a=e.from,i=D(r),c=E=>E.some(w=>e.retyped.has(w)),l=E=>E.some(w=>e.retyped.has(w)),u=(E,w)=>c(w)?ie(this.n,"c",E):E,g=(E,w,O)=>{E!==w&&s.complete.push(O?`ALTER TABLE ${n} RENAME CONSTRAINT ${b(E)} TO ${b(w)}`:`ALTER INDEX ${P(r.schema,E)} RENAME TO ${b(w)}`)},p=(E,w,O,k)=>{let N=[],A=[];for(let R of w){let L=E.find($=>$.name===R.name);L?(!k(L,R)||c(O(R)))&&(l(O(L))||A.push(L),N.push(R)):N.push(R)}for(let R of E)!w.some(L=>L.name===R.name)&&!l(O(R))&&A.push(R);return{added:N,gone:A}},h=(E,w)=>E.find(O=>O.name===w),m=E=>a.uniques.some(w=>w.name===E)||a.indexes.some(w=>w.name===E),y=p(o.uniques,r.uniques,E=>E.columns,(E,w)=>E.columns.join()===w.columns.join());this.renamedTwins(y,(E,w)=>E.columns.join()===w.columns.join()&&!c(w.columns),(E,w)=>{this.changes.push(`unique ${i}.${E.name} is renamed ${w.name} (at complete)`),s.complete.push(`ALTER TABLE ${n} RENAME CONSTRAINT ${b(E.name)} TO ${b(w.name)}`)});for(let E of y.gone)this.changes.push(`unique ${i}.${E.name} goes (at complete)`),s.complete.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(E.name)}`);for(let E of y.added){let w=m(E.name)?ie(this.n,"c",E.name):u(E.name,E.columns),O=P(r.schema,w);this.changes.push(`unique ${i}.${E.name}`),this.online.push({kind:"statement",sql:`CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS ${b(w)} ON ${n} (${ye(E.columns.map(k=>e.cols.get(k)))})`,why:`unique ${E.name}`}),this.settle.push({kind:"tx",sql:[`DO $palgres$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = ${M(w)} AND conrelid = ${M(n)}::regclass) THEN ALTER TABLE ${n} ADD CONSTRAINT ${b(w)} UNIQUE USING INDEX ${b(w)}; END IF; END $palgres$`],why:`unique ${E.name}`}),s.undo.unshift(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(w)}`,`DROP INDEX IF EXISTS ${O}`),g(w,E.name,!0)}let S=p(o.checks,r.checks,E=>r.columns.filter(w=>Oe(E.expr,w.name)).map(w=>w.name),(E,w)=>E.expr.trim()===w.expr.trim());for(let E of S.gone)this.changes.push(`check ${i}.${E.name} goes`),s.tx.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(E.name)}`),s.undo.push(`ALTER TABLE ${n} ADD CONSTRAINT ${b(E.name)} CHECK (${h(a.checks,E.name).expr}) NOT VALID`);for(let E of S.added)this.changes.push(`check ${i}.${E.name}`),s.tx.push(`ALTER TABLE ${n} ADD CONSTRAINT ${b(E.name)} CHECK (${ke(E.expr,un(e.cols))}) NOT VALID`),this.online.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${b(E.name)}`,why:`check ${E.name}`}),s.undo.unshift(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(E.name)}`);let f=p(o.foreignKeys,r.foreignKeys,E=>E.columns,(E,w)=>Kn(E)===Kn(w));for(let E of f.gone)this.changes.push(`foreign key ${i}.${E.name} goes`),this.fkDrops.push({kind:"tx",sql:[`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(E.name)}`],why:`foreign key ${E.name} goes`}),this.undoFksBack.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSqlOld(h(a.foreignKeys,E.name))} NOT VALID`],why:`foreign key ${E.name} again`});for(let E of f.added){let w=u(E.name,E.columns);this.changes.push(`foreign key ${i}.${E.name}`),this.lateFks.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSql({...E,name:w},e.cols)} NOT VALID`],why:`foreign key ${E.name}`}),this.lateFks.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${b(w)}`,why:`foreign key ${E.name}`}),this.undoFksGone.push({kind:"tx",sql:[`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${b(w)}`],why:`foreign key ${E.name}`}),g(w,E.name,!0)}for(let E of r.foreignKeys){let w=o.foreignKeys.find(O=>O.name===E.name);!w||Kn(w)!==Kn(E)||c(E.columns)||(w.deferrable??!1)===(E.deferrable??!1)||(this.changes.push(`foreign key ${i}.${E.name} is ${E.deferrable?"":"not "}deferrable (in the catalog, no row read again; ${i} locked a moment, the lock given way to while others hold it and tried again)`),s.tx.push(`ALTER TABLE ${n} ALTER CONSTRAINT ${b(E.name)} ${E.deferrable?"DEFERRABLE":"NOT DEFERRABLE"}`),s.undo.push(`ALTER TABLE ${n} ALTER CONSTRAINT ${b(E.name)} ${E.deferrable?"NOT DEFERRABLE":"DEFERRABLE"}`))}let d=E=>[...E.keys.flatMap(w=>"column"in w?[w.column]:[]),...E.include??[]],T=p(o.indexes,r.indexes,d,(E,w)=>Hn(E)===Hn(w));this.renamedTwins(T,(E,w)=>Hn(E)===Hn(w)&&!c(d(w)),(E,w)=>{this.changes.push(`index ${i}.${E.name} is renamed ${w.name} (at complete)`),s.complete.push(`ALTER INDEX ${P(r.schema,E.name)} RENAME TO ${b(w.name)}`)});for(let E of T.added){if(!E.unique)continue;let w=d(E).slice(0,E.keys.length),O=T.gone.find(N=>N.unique&&d(N).slice(0,N.keys.length).join()===w.join());if(!O)continue;let k=this.to.tables.flatMap(N=>N.foreignKeys.filter(A=>A.refSchema===r.schema&&A.refTable===r.name&&A.refColumns.join()===w.join()).map(A=>`${D(N)}.${A.name}`));k.length>0&&this.refuse(`unique index ${i}.${O.name} is built again as ${E.name}, and foreign key ${k.join(", ")} reference its columns`,"Postgres binds a foreign key to the first unique index over its columns \u2014 the old one, which then cannot go: change the index in one deploy and the foreign keys in another, or give the new index other key columns")}for(let E of T.gone)T.added.some(w=>w.name===E.name)?(this.changes.push(`index ${i}.${E.name} is built again (the old one goes at complete)`),s.complete.push(`DROP INDEX IF EXISTS ${P(r.schema,E.name)}`)):(this.changes.push(`index ${i}.${E.name} goes (at complete)`),this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,E.name)}`,why:`index ${E.name}`}));for(let E of T.added){let w=m(E.name)?ie(this.n,"i",E.name):u(E.name,d(E));this.changes.push(`index ${i}.${E.name}`),this.online.push({kind:"statement",sql:this.indexSql(r.schema,e.physical,{...E,name:w},e.cols,!0),why:`index ${E.name}`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,w)}`,why:`index ${E.name}`}),g(w,E.name,!1)}}renamedTwins(e,n,s){for(let r of[...e.gone]){let o=e.added.find(a=>a.name!==r.name&&n(r,a)&&!e.gone.some(i=>i.name===a.name));o&&(e.gone.splice(e.gone.indexOf(r),1),e.added.splice(e.added.indexOf(o),1),s(r,o))}}indexSql(e,n,s,r,o){let a=un(r),i=s.keys.map(l=>{let u="column"in l?b(r.get(l.column)??l.column):`(${ke(l.expr,a)})`;return l.desc&&(u+=" DESC"),l.nulls&&(u+=` NULLS ${l.nulls.toUpperCase()}`),u}),c=`CREATE ${s.unique?"UNIQUE ":""}INDEX ${o?"CONCURRENTLY ":""}IF NOT EXISTS ${b(s.name)} ON ${P(e,n)}`;return s.method&&s.method!=="btree"&&(c+=` USING ${s.method}`),c+=` (${i.join(", ")})`,s.include?.length&&(c+=` INCLUDE (${ye(s.include.map(l=>r.get(l)??l))})`),s.where!==void 0&&(c+=` WHERE ${ke(s.where,a)}`),c}fkSql(e,n){let s=this.to.tables.find(o=>o.schema===e.refSchema&&o.name===e.refTable),r=s?this.where(s):{table:e.refTable,cols:new Map};return`CONSTRAINT ${b(e.name)} FOREIGN KEY (${ye(e.columns.map(o=>n.get(o)??o))}) REFERENCES ${P(e.refSchema,r.table)} (${ye(e.refColumns.map(o=>r.cols.get(o)??o))})${e.match==="full"?" MATCH FULL":""} ON DELETE ${e.onDelete.toUpperCase()} ON UPDATE ${e.onUpdate.toUpperCase()}${e.deferrable?" DEFERRABLE":""}`}fkSqlOld(e){return`CONSTRAINT ${b(e.name)} FOREIGN KEY (${ye(e.columns)}) REFERENCES ${P(e.refSchema,e.refTable)} (${ye(e.refColumns)})${e.match==="full"?" MATCH FULL":""} ON DELETE ${e.onDelete.toUpperCase()} ON UPDATE ${e.onUpdate.toUpperCase()}${e.deferrable?" DEFERRABLE":""}`}generations(e){return[...this.input.generations?.(e)??[]].sort((n,s)=>n.gen-s.gen)}search(e,n){let s=D(e),r=e.search,o=n?.from.search;if(r===void 0){n&&this.searchGone(n.from,n.physical);return}let a=ps(`table ${s}`,e,r);if(a.length>0){this.refusals.push(...a);return}let i=e.columns.find(T=>T.name===e.primaryKey[0]),c=this.generations(n?D(n.from):s),l=c.filter(T=>T.status!=="retired"),u=l.find(T=>T.status==="active"),g=l.at(-1),p=g===void 0?[]:Pn(g,r)?l:u?[u]:[],h=g===void 0?"active":Pn(g,r)||u!==void 0&&Pn(u,r)?void 0:"filling";if(n){let T="take search out of the table and deploy, make the change in the next deploy, and declare search again in the one after \u2014 every row is embedded again then";e.name!==n.from.name&&this.refuse(`table ${e.schema}.${n.from.name} is renamed ${e.name} while it declares search`,T);let E=new Set;for(let w of new Set([i.name,...r.from])){let O=w===i.name?"search keeps each row's vector by it":"search reads it";if(n.retyped.has(w))this.refuse(`column ${s}.${w} changes type, and ${O}`,T);else if((n.cols.get(w)??w)!==w)this.refuse(`column ${s}.${w} ${n.parked.has(w)?"takes a name another column leaves in this deploy":`is renamed from ${n.cols.get(w)}`}, and ${O}`,T);else continue;E.add(n.retyped.get(w)?.from.name??n.cols.get(w)??w)}for(let w of p)for(let O of w.from){if(E.has(O))continue;e.columns.some(N=>N.name===O)&&!n.retyped.has(O)&&(n.cols.get(O)??O)===O||this.refuse(`column ${s}.${O} goes or changes, and the vectors that serve search of ${s} now (generation ${w.gen}) are made from it`,"they serve until the new ones are complete: leave the column as it is in this deploy, and change it in a deploy after that")}}let m={schema:e.schema,name:n?n.physical:e.name},y=P(m.schema,m.name);if(h!==void 0){let T=(c.at(-1)?.gen??0)+1;this.changes.push(h==="active"?`search of ${s}: its rows are embedded with ${r.model} (${r.dimensions} dimensions) in the background; found by their words until then`:`search of ${s}: every row is embedded again with ${r.model} (${r.dimensions} dimensions) in the background; the vectors there serve until the new ones are complete`),this.searchStart.push({kind:"tx",sql:Ds({table:m,gen:T,search:r,status:h,pk:{name:i.name,type:this.typeSql(i.type)},roles:this.input.roles,types:this.input.vectorSchema??"public"}),why:`search of ${s}: generation ${T}`}),n&&this.searchStart.push({kind:"statement",sql:Ps(m,T,i.name),why:`search of ${s}: its rows queued`}),this.undoSearch.push({kind:"tx",sql:Bn(m,T),why:`search of ${s}: generation ${T}`})}if(o!==void 0&&o.staleness!==r.staleness&&p.length>0){this.changes.push(`search of ${s}: a changed row's old vector ${r.staleness==="null"?"goes":"stays"} until the row is embedded again`);for(let T of p)this.searchStart.push({kind:"tx",sql:Un({table:m,gen:T.gen,from:T.from,staleness:r.staleness},!0),why:`search of ${s}: generation ${T.gen}'s triggers`}),this.undoSearch.push({kind:"tx",sql:Un({table:m,gen:T.gen,from:T.from,staleness:o.staleness},!0),why:`search of ${s}: generation ${T.gen}'s triggers`})}for(let T of c)p.includes(T)||(this.changes.push(`search of ${s}: generation ${T.gen}'s vectors, ${T.status==="retired"?"left behind":"never full"}, go (at complete)`),this.searchComplete.push({kind:"tx",sql:Bn(m,T.gen),why:`search of ${s}: generation ${T.gen}`}));let S=Mn(m,r.from),f=o===void 0?void 0:Mn(m,o.from);if(S===f)return;let d=T=>`CREATE INDEX ${T?"CONCURRENTLY ":""}IF NOT EXISTS ${b(S)} ON ${y} USING gin (${Fn(r.from)})`;o!==void 0&&this.changes.push(`search of ${s} reads ${r.from.join(", ")}`),n?(this.online.push({kind:"statement",sql:d(!0),why:`search of ${s}: its words`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(m.schema,S)}`,why:`search of ${s}: its words`})):this.creates.push(d(!1)),f!==void 0&&this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(m.schema,f)}`,why:`search of ${s}: the words it read`})}searchGone(e,n){let s=this.generations(D(e));if(e.search===void 0&&s.length===0)return;let r={schema:e.schema,name:n},o=D(e);this.changes.push(`search of ${o} goes (at complete)`);for(let a of s)this.searchComplete.push({kind:"tx",sql:Bn(r,a.gen),why:`search of ${o}: generation ${a.gen}`});e.search!==void 0&&this.searchComplete.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,Mn(r,e.search.from))}`,why:`search of ${o}: the words it read`})}policyRoles(e,n){let s=new Set;for(let r of e.to){if(r.startsWith("role:")&&r.length>5){s.add(b(r.slice(5)));continue}let o=Nt[r];if(!o){this.refuse(`policy ${n}.${e.name} is for role ${r}`,`a policy is for ${Object.keys(Nt).join(", ")}`);continue}s.add(o==="public"?"PUBLIC":b(this.input.roles[o]))}return[...s].join(", ")}policySql(e,n,s){let r=un(s),o=`CREATE POLICY ${b(n.name)} ON ${e} AS ${n.restrictive?"RESTRICTIVE":"PERMISSIVE"} FOR ${n.for.toUpperCase()} TO ${this.policyRoles(n,e)}`;return n.using!==void 0&&(o+=` USING (${ke(n.using,r)})`),n.withCheck!==void 0&&(o+=` WITH CHECK (${ke(n.withCheck,r)})`),o}policies(e,n,s){let{to:r}=e,o=this.inNewNames(e.from),a=D(r),i=l=>JSON.stringify([l.for,[...new Set(l.to.map(u=>Nt[u]??u))].sort(),l.using??null,l.withCheck??null,l.restrictive??!1]),c=l=>e.from.policies.find(u=>u.name===l);for(let l of r.policies){let u=o.policies.find(g=>g.name===l.name);u&&i(u)===i(l)||this.readsOthersRenamed(r,l,a)||(this.changes.push(`policy ${a}.${l.name}${u?" changes":""}`),s.undo.push(`DROP POLICY IF EXISTS ${b(l.name)} ON ${n}`),u&&(s.tx.push(`DROP POLICY IF EXISTS ${b(l.name)} ON ${n}`),s.undo.push(this.policySql(n,c(l.name),Us(e.from)))),s.tx.push(this.policySql(n,l,e.cols)))}for(let l of o.policies)r.policies.some(u=>u.name===l.name)||(this.changes.push(`policy ${a}.${l.name} goes`),s.tx.push(`DROP POLICY IF EXISTS ${b(l.name)} ON ${n}`),s.undo.push(this.policySql(n,c(l.name),Us(e.from))))}readsOthersRenamed(e,n,s){let r=`${n.using??""} ${n.withCheck??""}`;for(let o of this.to.tables){if(o===e)continue;let a=this.from.tables.find(c=>c.schema===o.schema&&c.name===(o.renamedFrom??o.name));if(!a)continue;let i=[...o.name!==a.name&&Oe(r,o.name)?[`${o.schema}.${o.name}`]:[],...Oe(r,o.name)?o.columns.filter(c=>c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&a.columns.some(l=>l.name===c.renamedFrom)&&Oe(r,c.name)).map(c=>`${o.schema}.${o.name}.${c.name}`):[]];if(i.length>0)return this.refuse(`policy ${s}.${n.name} reads ${i.join(", ")}, renamed in this deploy`,"Postgres has the new name only from complete on: rename in this deploy, change the policy in the next"),!0}return!1}rawUnitsBefore(){let e=!0;for(let n of this.to.raw){if(!n.before)continue;let s=this.from.raw.find(r=>r.name===n.name);if(!(s&&s.sql.trim()===n.sql.trim())){if(s&&/^\s*CREATE\s+(?:DOMAIN|TYPE|SEQUENCE)\b/i.test(s.sql)){this.refuse(`raw ${n.name} changes`,"Postgres cannot drop a domain or a type a column uses, and a sequence made again starts over: say the change as an ALTER (ALTER DOMAIN \u2026 ADD CONSTRAINT \u2026 NOT VALID, ALTER TYPE, ALTER SEQUENCE) in a unit of its own, or make a new one and move the columns to it");continue}this.changes.push(`raw ${n.name}${s?" changes":""}`),e&&this.creates.push("SET LOCAL check_function_bodies = off"),e=!1,this.creates.push(...this.rawApply(n,s)),!s&&n.drop!==void 0&&this.undoCreates.push(n.drop),s&&this.undoRawsBack.push(...this.rawApply(s,n))}}}rawApply(e,n){return!n||/^\s*CREATE\s+OR\s+REPLACE\b/i.test(e.sql)||n.drop===void 0?[e.sql]:[n.drop,e.sql]}rawUnits(){let e=this.to.raw.filter(l=>!l.before),n=l=>/^\s*CREATE\s+(?:OR\s+REPLACE\s+)?(?:MATERIALIZED\s+)?VIEW\b/i.test(l),s=this.namesAtComplete,r=this.dropsColumnsAtComplete,o=e.findIndex(l=>{let u=this.from.raw.find(g=>g.name===l.name);return n(l.sql)?r&&u!==void 0?!0:u===void 0?s:u.sql.trim()!==l.sql.trim():!1}),a=new Set,i=new Set,c=null;if(o>=0){let l=e.slice(o),u=p=>n(p)||/^\s*CREATE\s+(?:OR\s+REPLACE\s+)?(?:FUNCTION|PROCEDURE)\b/i.test(p)||Ot.test(p),g=[];for(let p of[...this.from.raw].reverse()){if(p.before||p.drop===void 0)continue;let h=l.some(y=>y.name===p.name),m=!this.to.raw.some(y=>y.name===p.name);(h&&u(p.sql)||m&&n(p.sql))&&g.push(p.drop),m&&n(p.sql)&&i.add(p.name)}for(let p of l){let h=this.from.raw.find(m=>m.name===p.name);(!h||h.sql.trim()!==p.sql.trim())&&this.changes.push(`raw ${p.name}${h?" changes":""}`),a.add(p.name)}if(s){this.viewsAtComplete={drops:g,creates:l.map(p=>p.sql)};for(let p of l){let h=this.changes.findIndex(m=>m===`raw ${p.name}`||m===`raw ${p.name} changes`);h>=0&&(this.changes[h]+=" (at complete)")}}else{c={kind:"tx",sql:["SET LOCAL check_function_bodies = off",...g,...l.map(p=>p.sql)],why:`raw ${l[0].name} and what follows it, made again`};for(let p of[...l].reverse())p.drop!==void 0&&this.undoRawsGone.push(p.drop);for(let p of this.from.raw){if(p.before||p.drop===void 0)continue;let h=l.some(y=>y.name===p.name),m=!this.to.raw.some(y=>y.name===p.name);(h&&u(p.sql)||m&&n(p.sql))&&this.undoRawsBack.push(p.sql)}}}for(let l of this.to.raw){if(l.before||(c!==null&&l.name===e[o].name&&this.raws.push(c),a.has(l.name)))continue;let u=this.from.raw.find(p=>p.name===l.name),g=Bs(l.sql);if(!(u&&u.sql.trim()===l.sql.trim())){if(u&&g){this.refuse(`raw index ${l.name} changes under its name`,"an index is built CONCURRENTLY next to the one serving, so under a name of its own: give the new one its own name (the old one goes at complete)");continue}if(this.changes.push(`raw ${l.name}${u?" changes":""}`),g)this.raws.push({kind:"statement",sql:g.create,why:`raw ${l.name}`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${g.qualified(l,this.to)}`,why:`raw ${l.name}`});else{if(l.drop===void 0&&(Ot.test(l.sql)||n(l.sql))){this.refuse(`raw ${l.name} has no drop`,"a rollback could not take it back, and the old version would write and read past it: give it its drop (raw(name, up, { drop }))");continue}this.raws.push({kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.rawApply(l,u)],why:`raw ${l.name}`}),l.drop!==void 0&&this.undoRawsGone.unshift(l.drop),u&&this.undoRawsBack.push(...l.drop!==void 0?[u.sql]:this.rawApply(u,l))}}}for(let l of[...this.from.raw].reverse()){if(this.to.raw.some(g=>g.name===l.name))continue;if(i.has(l.name)){this.changes.push(`raw ${l.name} goes (with the views made again)`);continue}let u=Bs(l.sql);if(!u){if(l.drop===void 0){this.refuse(`raw ${l.name} is gone from the schema`,"Palgres does not know how to take back what its SQL made: keep it, or give the unit its drop (raw(name, up, { drop })) and remove it in the deploy after that");continue}this.changes.push(`raw ${l.name} goes (at complete)`),Ot.test(l.sql)?this.completeUnitDrops.push(l.drop):this.completeIndexes.push({kind:"tx",sql:[l.drop],why:`raw ${l.name}`});continue}this.changes.push(`raw index ${l.name} goes (at complete)`),this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${u.qualified(l,this.from)}`,why:`raw ${l.name}`})}}views(){let{anon:e,authenticated:n,service:s}=this.input.roles,r=[e,n,s].map(b).join(", "),o=[];for(let a of[...new Set(this.layout.tables.map(i=>i.schema))]){let i=b(Te(this.n,a));o.push(`DROP SCHEMA IF EXISTS ${i} CASCADE`,`CREATE SCHEMA ${i}`,`GRANT USAGE ON SCHEMA ${i} TO ${r}`)}for(let a of this.layout.tables){let i=a.columns.map(l=>l.physical===l.name?b(l.name):`${b(l.physical)} AS ${b(l.name)}`).join(", "),c=P(Te(this.n,a.schema),a.name);o.push(`CREATE VIEW ${c} WITH (security_invoker = true) AS SELECT ${i} FROM ${P(a.schema,a.physical)}`),o.push(`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${c} TO ${r}`)}return o}dropViews(e,n){let s=[...new Set(n.tables.map(r=>r.schema))];return s.length>0?s.map(r=>`DROP SCHEMA IF EXISTS ${b(Te(e,r))} CASCADE`):["SELECT 1"]}keyOf(e){let n=this.where(e);return e.primaryKey.map(s=>{let r=this.matches.get(D(e))?.retyped.get(s);return r?r.from.name:n.cols.get(s)??s})}};function Us(t){return new Map(t.columns.map(e=>[e.name,e.name]))}function un(t){return new Map([...t].filter(([e,n])=>e!==n))}function At(t,e,n){return e?[`ALTER TABLE ${t} ENABLE ROW LEVEL SECURITY`]:n?[`ALTER TABLE ${t} DISABLE ROW LEVEL SECURITY`]:[]}function Kn(t){return JSON.stringify([t.columns,t.refSchema,t.refTable,t.refColumns,t.onDelete,t.onUpdate,t.match??"simple"])}function Hn(t){return JSON.stringify([t.keys,t.unique,t.where??null,t.method??"btree",t.include??[]])}var Ot=/^\s*(?:CREATE\s+(?:OR\s+REPLACE\s+)?(?:TRIGGER|CONSTRAINT\s+TRIGGER|RULE)\b|DO\s+\$\w*\$\s+BEGIN\s+IF\s+NOT\s+\(EXISTS\s+\(SELECT\s+1\s+FROM\s+pg_catalog\.pg_trigger)/i,Ks=/^\s*CREATE\s+(UNIQUE\s+)?INDEX\s+(?:CONCURRENTLY\s+)?(?:IF\s+NOT\s+EXISTS\s+)?("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*)\s+ON\s+/i;function _o(t){return Vn(t).map(e=>e.schema===void 0?b(e.name):P(e.schema,e.name))}var Hs=/\bnextval\('((?:[^']|'')+)'(?:::regclass)?\)/gi;function Vn(t){if(t===void 0)return[];let e=[];for(let n of t.matchAll(Hs)){let s=n[1].replace(/''/g,"'"),r='("(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)',o=new RegExp(`^(?:${r}\\.)?${r}$`).exec(s);if(!o)continue;let a=i=>i.startsWith('"')?i.slice(1,-1).replace(/""/g,'"'):i.toLowerCase();e.push(o[1]===void 0?{name:a(o[2])}:{schema:a(o[1]),name:a(o[2])})}return e}function It(t){let e=t.sql.trim().replace(/;\s*$/,""),n=Ks.exec(e);return!n||e.includes(";")?void 0:n[2].replace(/^"|"$/g,"")}function Bs(t){let e=t.trim().replace(/;\s*$/,""),n=Ks.exec(e);if(!n||e.includes(";"))return;let s=n[2].replace(/^"|"$/g,""),r=e.slice(n[0].length);return{unique:!!n[1],create:`CREATE ${n[1]?"UNIQUE ":""}INDEX CONCURRENTLY IF NOT EXISTS ${b(s)} ON ${r}`,qualified:(o,a)=>{let i=/^\s*(?:ONLY\s+)?("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*)(?:\.("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*))?/i.exec(r),c=u=>u.replace(/^"|"$/g,""),l=i?.[2]?c(i[1]):o.table?.split(".")[0]??a.tables.find(u=>u.name===c(i?.[1]??""))?.schema??"public";return P(l,s)}}}import{randomBytes as Ko}from"node:crypto";var qe=(t,e)=>JSON.stringify(t)===JSON.stringify(e),dn=t=>new Map(t.map(e=>[e.name,e])),Ye=t=>({type:t.type,nullable:t.nullable,default:t.default??null,identity:t.identity??null,generated:t.generated??null});function Do(t,e){if(t.name===e)return t;let{renamedFrom:n,...s}=t;return{...s,name:e}}function xt(t,e,n){let s=ge(n),r=[],o=[...t.unmanaged],a=new Map(t.schema.tables.map(f=>[D(f),f])),i=new Map(e.schema.tables.map(f=>[D(f),f])),c=new Set,l=[],u=new Set(s.raw.map(f=>It(f)).filter(f=>f!==void 0));for(let f of s.tables){let d=a.get(D(f))??(f.renamedFrom!==void 0?a.get(`${f.schema}.${f.renamedFrom}`):void 0);if(!d)continue;c.add(D(d));let T=i.get(D(f));if(!T)throw new Error(`palgres: the shadow database has no ${D(f)}: the schema did not make it`);let E=dn(T.columns),w=d.columns.map(k=>{let N=f.columns.find(R=>R.name===k.name)??f.columns.find(R=>R.renamedFrom===k.name&&!d.columns.some(L=>L.name===R.name)),A=N&&E.get(N.name);return N&&A&&qe(Ye(k),Ye(A))?Do(N,k.name):k}),O=(k,N,A)=>{let R=dn(N),L=dn(A);return k.map($=>{let C=R.get($.name),q=L.get($.name);return q&&C&&qe($,C)?q:$})};l.push({schema:d.schema,name:d.name,...f.ignored!==void 0?{ignored:f.ignored}:{},...f.renamedFrom!==void 0&&f.name===d.name?{renamedFrom:f.renamedFrom}:{},columns:w,primaryKey:d.primaryKey,uniques:O(d.uniques,T.uniques,f.uniques),indexes:O(d.indexes.filter(k=>!u.has(k.name)),T.indexes,f.indexes),checks:O(d.checks,T.checks,f.checks),foreignKeys:O(d.foreignKeys.filter(k=>a.has(`${k.refSchema}.${k.refTable}`)&&s.tables.some(N=>N.schema===k.refSchema&&N.name===k.refTable||N.schema===k.refSchema&&N.renamedFrom===k.refTable)?!0:(o.push(`foreign key ${D(d)}.${k.name} references ${k.refSchema}.${k.refTable}, outside the schema \u2014 kept as it is; drop it when its target goes`),!1)),T.foreignKeys,f.foreignKeys),rls:d.rls,policies:O(d.policies,T.policies,f.policies)})}for(let f of a.keys())c.has(f)||o.push(`table ${f}: not in the schema \u2014 kept as it is`);for(let f of t.forced)c.has(f)||o.push(`table ${f}: row-level security FORCEd on its owner \u2014 kept as it is`);let g=new Map(t.schema.tables.flatMap(f=>f.indexes.map(d=>[`${f.schema}.${d.name}`,{t:f,i:d}]))),p=new Map(e.schema.tables.flatMap(f=>f.indexes.map(d=>[`${f.schema}.${d.name}`,{t:f,i:d}]))),h=[],m=!0;for(let[f,d]of e.objects){let T=t.objects.get(f);T===void 0?m=!1:T!==d&&r.push(`${f} is not what the schema's raw SQL makes: drop it, and the migration makes it as the schema says`)}for(let f of s.raw){let d=It(f);if(d===void 0){m&&h.push(f);continue}let T=[...p.keys()].find(O=>O.endsWith(`.${d}`)),E=T&&p.get(T),w=T&&g.get(T);if(!E||!w){let O=[...e.objects.keys()].find(k=>k.startsWith("index ")&&k.endsWith(`.${d}`));O!==void 0&&t.objects.get(O)===e.objects.get(O)&&h.push(f);continue}qe(w.i,E.i)&&D(w.t)===D(E.t)?h.push(f):r.push(`index ${T} is not what the schema's raw unit ${f.name} makes: drop it, and the migration makes it as the schema says`)}let y=[];for(let f of s.enums){let d=t.schema.enums.find(T=>T.schema===f.schema&&T.name===f.name);d&&y.push(qe(d.values,f.values)?f:d)}let S=s.extensions.filter(f=>t.schema.extensions.includes(f));return{schema:ge({tables:l,enums:y,extensions:S,raw:h}),unforce:t.forced.filter(f=>c.has(f)),refusals:r,unmanaged:o}}function Po(t,e){let n=[],s=new Map(t.schema.tables.map(r=>[D(r),r]));for(let r of e.schema.tables){let o=D(r),a=s.get(o);if(!a){n.push(`table ${o} is missing`);continue}for(let u of r.columns)a.columns.some(g=>g.name===u.name)||n.push(`column ${o}.${u.name} is missing`);for(let u of a.columns)r.columns.some(g=>g.name===u.name)||n.push(`column ${o}.${u.name}: not declared`);for(let u of r.columns){let g=a.columns.find(p=>p.name===u.name);g&&!qe(Ye(g),Ye(u))&&n.push(`column ${o}.${u.name}: ${JSON.stringify(Ye(g))}, declared ${JSON.stringify(Ye(u))}`)}qe(a.primaryKey,r.primaryKey)||n.push(`table ${o}: primary key (${a.primaryKey.join(", ")}), declared (${r.primaryKey.join(", ")})`),a.rls!==r.rls&&n.push(`table ${o}: row-level security ${a.rls?"on":"off"}, declared ${r.rls?"on":"off"}`);let i={uniques:"unique",indexes:"index",checks:"check",foreignKeys:"foreign key",policies:"policy"},c=(u,g)=>e.schema.tables.some(p=>p.schema===u&&p.name===g),l={...a,foreignKeys:a.foreignKeys.filter(u=>c(u.refSchema,u.refTable))};for(let[u,g]of Object.entries(i)){let p=dn(l[u]),h=dn(r[u]);for(let[m,y]of h)qe(p.get(m),y)||n.push(`${g} ${o}.${m}: ${p.has(m)?`${JSON.stringify(p.get(m))}, declared ${JSON.stringify(y)}`:"missing"}`);for(let m of p.keys())h.has(m)||n.push(`${g} ${o}.${m}: not declared`)}}return n}function Ce(t,e){let n=t.join("_").replace(/[^A-Za-z0-9_]/g,"_").replace(/^([^A-Za-z_])/,"_$1");if(Buffer.byteLength(n)>55){let r=0;for(let o of t.join("."))r=Math.imul(r,31)+o.charCodeAt(0)>>>0;n=`${n.slice(0,46)}_${r.toString(36)}`}let s=n;for(let r=2;e.has(s);r++)s=`${n}_${r}`;return e.add(s),s}function Mo(t){let e="$palgres$";for(let n=1;t.includes(e);n++)e=`$palgres${n}$`;return e}var vt=(t,e)=>{let n=Mo(e+t);return`DO ${n} BEGIN IF NOT (${t}) THEN ${e}; END IF; END ${n}`};async function Vs(t,e,n,s){let r=new Set,o=[],a=[],i=[],c=await t(`SELECT n.nspname AS schema, t.typname AS name, pg_catalog.format_type(t.typbasetype, t.typtypmod) AS base,
115
+ END $palgres$`,`CREATE TRIGGER ${h} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW EXECUTE FUNCTION ${m}()`),r.to.default!==void 0&&o.tx.push(`ALTER TABLE ${n} ALTER COLUMN ${g} SET DEFAULT ${r.to.default}`),!r.from.nullable&&r.to.nullable&&this.relaxNotNull(i,n,r.from.name,o),o.undo.push(`DROP TRIGGER IF EXISTS ${h} ON ${n}`,`DROP FUNCTION IF EXISTS ${m}()`),o.undoColumns.push(`ALTER TABLE ${n} DROP COLUMN IF EXISTS ${g}`),this.backfills.push({kind:"backfill",table:n,key:this.keyOf(a),set:`${u} = ${u}`,where:`${g} IS NULL AND ${u} IS NOT NULL`,why:`${i}.${s} in its new type`}),r.to.nullable||this.notNull(a,n,r.shadow,o),o.complete.push(`DROP TRIGGER IF EXISTS ${h} ON ${n}`,`DROP FUNCTION IF EXISTS ${m}()`,`ALTER TABLE ${n} DROP COLUMN ${u}`,`ALTER TABLE ${n} RENAME COLUMN ${g} TO ${R(s)}`),o.names=!0,o.dropsColumns=!0}checkedDomain(e){if(this.input.checkedDomain(this.typeSql(e))===!0)return!0;let n=Ne(e).replace(/^public\./,""),s=o=>o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(String.raw`\bCREATE\s+DOMAIN\s+(?:"?public"?\.)?"?${s(n.replace(/^"|"$/g,""))}"?\s[\s\S]*\b(?:CHECK|NOT\s+NULL)\b`,"i");return this.to.raw.some(o=>r.test(o.sql))}conversion(e,n){let s=h=>/(\[\])*$/.exec(h)[0],r=h=>h.slice(0,h.length-s(h).length);if(s(e)!==s(n))return{refused:"one is an array and the other is not, or of another depth"};let o=s(e),a=h=>{let p=Ne(r(h));return[...this.to.enums,...this.from.enums].find(E=>un(E.schema,E.name)===p||E.schema==="public"&&un(E.schema,E.name)===`public.${p}`)},i=h=>/^(text|citext|public\.citext|character varying(\(\d+\))?|character(\(\d+\))?)$/.test(Ne(r(h))),c=h=>p=>`${p}::${this.typeSql(h)}`,l=a(e),u=a(n);if(l&&u){let h=(f,d)=>f.filter(T=>!d.includes(T)),p=h(l.values,u.values),E=h(u.values,l.values);if(p.length>0||E.length>0)return{refused:`the enums' labels differ (${[...p.map(f=>`-${f}`),...E.map(f=>`+${f}`)].join(", ")}), and a label one version writes the other's column cannot hold`};let $=f=>d=>`${d}::text${o}::${this.typeSql(f)}`;return{on:$(n),back:$(e)}}if(l||u)return i(l?n:e)?{on:c(n),back:c(e)}:{refused:`Postgres has no cast between an enum and ${l?n:e}`};let g=this.input.castable(this.typeSql(e),this.typeSql(n)),m=this.input.castable(this.typeSql(n),this.typeSql(e));return g===!1||m===!1?{refused:`Postgres has no cast from ${g===!1?e:n} to ${g===!1?n:e}`}:{on:c(n),back:c(e)}}constraints(e,n,s){let{to:r}=e,o=this.inNewNames(e.from),a=e.from,i=D(r),c=y=>y.some(w=>e.retyped.has(w)),l=y=>y.some(w=>e.retyped.has(w)),u=(y,w)=>c(w)?ie(this.n,"c",y):y,g=(y,w,O)=>{y!==w&&s.complete.push(O?`ALTER TABLE ${n} RENAME CONSTRAINT ${R(y)} TO ${R(w)}`:`ALTER INDEX ${P(r.schema,y)} RENAME TO ${R(w)}`)},m=(y,w,O,k)=>{let N=[],A=[];for(let b of w){let L=y.find(S=>S.name===b.name);L?(!k(L,b)||c(O(b)))&&(l(O(L))||A.push(L),N.push(b)):N.push(b)}for(let b of y)!w.some(L=>L.name===b.name)&&!l(O(b))&&A.push(b);return{added:N,gone:A}},h=(y,w)=>y.find(O=>O.name===w),p=y=>a.uniques.some(w=>w.name===y)||a.indexes.some(w=>w.name===y),E=m(o.uniques,r.uniques,y=>y.columns,(y,w)=>y.columns.join()===w.columns.join());this.renamedTwins(E,(y,w)=>y.columns.join()===w.columns.join()&&!c(w.columns),(y,w)=>{this.changes.push(`unique ${i}.${y.name} is renamed ${w.name} (at complete)`),s.complete.push(`ALTER TABLE ${n} RENAME CONSTRAINT ${R(y.name)} TO ${R(w.name)}`)});for(let y of E.gone)this.changes.push(`unique ${i}.${y.name} goes (at complete)`),s.complete.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(y.name)}`);for(let y of E.added){let w=p(y.name)?ie(this.n,"c",y.name):u(y.name,y.columns),O=P(r.schema,w);this.changes.push(`unique ${i}.${y.name}`),this.online.push({kind:"statement",sql:`CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS ${R(w)} ON ${n} (${Te(y.columns.map(k=>e.cols.get(k)))})`,why:`unique ${y.name}`}),this.settle.push({kind:"tx",sql:[`DO $palgres$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = ${M(w)} AND conrelid = ${M(n)}::regclass) THEN ALTER TABLE ${n} ADD CONSTRAINT ${R(w)} UNIQUE USING INDEX ${R(w)}; END IF; END $palgres$`],why:`unique ${y.name}`}),s.undo.unshift(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(w)}`,`DROP INDEX IF EXISTS ${O}`),g(w,y.name,!0)}let $=m(o.checks,r.checks,y=>r.columns.filter(w=>Le(y.expr,w.name)).map(w=>w.name),(y,w)=>y.expr.trim()===w.expr.trim());for(let y of $.gone)this.changes.push(`check ${i}.${y.name} goes`),s.tx.push(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(y.name)}`),s.undo.push(`ALTER TABLE ${n} ADD CONSTRAINT ${R(y.name)} CHECK (${h(a.checks,y.name).expr}) NOT VALID`);for(let y of $.added)this.changes.push(`check ${i}.${y.name}`),s.tx.push(`ALTER TABLE ${n} ADD CONSTRAINT ${R(y.name)} CHECK (${xe(y.expr,yn(e.cols))}) NOT VALID`),this.online.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${R(y.name)}`,why:`check ${y.name}`}),s.undo.unshift(`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(y.name)}`);let f=m(o.foreignKeys,r.foreignKeys,y=>y.columns,(y,w)=>tt(y)===tt(w));for(let y of f.gone)this.changes.push(`foreign key ${i}.${y.name} goes`),this.fkDrops.push({kind:"tx",sql:[`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(y.name)}`],why:`foreign key ${y.name} goes`}),this.undoFksBack.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSqlOld(h(a.foreignKeys,y.name))} NOT VALID`],why:`foreign key ${y.name} again`});for(let y of f.added){let w=u(y.name,y.columns);this.changes.push(`foreign key ${i}.${y.name}`),this.lateFks.push({kind:"tx",sql:[`ALTER TABLE ${n} ADD ${this.fkSql({...y,name:w},e.cols)} NOT VALID`],why:`foreign key ${y.name}`}),this.lateFks.push({kind:"statement",sql:`ALTER TABLE ${n} VALIDATE CONSTRAINT ${R(w)}`,why:`foreign key ${y.name}`}),this.undoFksGone.push({kind:"tx",sql:[`ALTER TABLE ${n} DROP CONSTRAINT IF EXISTS ${R(w)}`],why:`foreign key ${y.name}`}),g(w,y.name,!0)}for(let y of r.foreignKeys){let w=o.foreignKeys.find(O=>O.name===y.name);!w||tt(w)!==tt(y)||c(y.columns)||(w.deferrable??!1)===(y.deferrable??!1)||(this.changes.push(`foreign key ${i}.${y.name} is ${y.deferrable?"":"not "}deferrable (in the catalog, no row read again; ${i} locked a moment, the lock given way to while others hold it and tried again)`),s.tx.push(`ALTER TABLE ${n} ALTER CONSTRAINT ${R(y.name)} ${y.deferrable?"DEFERRABLE":"NOT DEFERRABLE"}`),s.undo.push(`ALTER TABLE ${n} ALTER CONSTRAINT ${R(y.name)} ${y.deferrable?"NOT DEFERRABLE":"DEFERRABLE"}`))}let d=y=>[...y.keys.flatMap(w=>"column"in w?[w.column]:[]),...y.include??[]],T=m(o.indexes,r.indexes,d,(y,w)=>st(y)===st(w));this.renamedTwins(T,(y,w)=>st(y)===st(w)&&!c(d(w)),(y,w)=>{this.changes.push(`index ${i}.${y.name} is renamed ${w.name} (at complete)`),s.complete.push(`ALTER INDEX ${P(r.schema,y.name)} RENAME TO ${R(w.name)}`)});for(let y of T.added){if(!y.unique)continue;let w=d(y).slice(0,y.keys.length),O=T.gone.find(N=>N.unique&&d(N).slice(0,N.keys.length).join()===w.join());if(!O)continue;let k=this.to.tables.flatMap(N=>N.foreignKeys.filter(A=>A.refSchema===r.schema&&A.refTable===r.name&&A.refColumns.join()===w.join()).map(A=>`${D(N)}.${A.name}`));k.length>0&&this.refuse(`unique index ${i}.${O.name} is built again as ${y.name}, and foreign key ${k.join(", ")} reference its columns`,"Postgres binds a foreign key to the first unique index over its columns \u2014 the old one, which then cannot go: change the index in one deploy and the foreign keys in another, or give the new index other key columns")}for(let y of T.gone)T.added.some(w=>w.name===y.name)?(this.changes.push(`index ${i}.${y.name} is built again (the old one goes at complete)`),s.complete.push(`DROP INDEX IF EXISTS ${P(r.schema,y.name)}`)):(this.changes.push(`index ${i}.${y.name} goes (at complete)`),this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,y.name)}`,why:`index ${y.name}`}));for(let y of T.added){let w=p(y.name)?ie(this.n,"i",y.name):u(y.name,d(y));this.changes.push(`index ${i}.${y.name}`),this.online.push({kind:"statement",sql:this.indexSql(r.schema,e.physical,{...y,name:w},e.cols,!0),why:`index ${y.name}`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,w)}`,why:`index ${y.name}`}),g(w,y.name,!1)}}renamedTwins(e,n,s){for(let r of[...e.gone]){let o=e.added.find(a=>a.name!==r.name&&n(r,a)&&!e.gone.some(i=>i.name===a.name));o&&(e.gone.splice(e.gone.indexOf(r),1),e.added.splice(e.added.indexOf(o),1),s(r,o))}}indexSql(e,n,s,r,o){let a=yn(r),i=s.keys.map(l=>{let u="column"in l?R(r.get(l.column)??l.column):`(${xe(l.expr,a)})`;return l.desc&&(u+=" DESC"),l.nulls&&(u+=` NULLS ${l.nulls.toUpperCase()}`),u}),c=`CREATE ${s.unique?"UNIQUE ":""}INDEX ${o?"CONCURRENTLY ":""}IF NOT EXISTS ${R(s.name)} ON ${P(e,n)}`;return s.method&&s.method!=="btree"&&(c+=` USING ${s.method}`),c+=` (${i.join(", ")})`,s.include?.length&&(c+=` INCLUDE (${Te(s.include.map(l=>r.get(l)??l))})`),s.where!==void 0&&(c+=` WHERE ${xe(s.where,a)}`),c}fkSql(e,n){let s=this.to.tables.find(o=>o.schema===e.refSchema&&o.name===e.refTable),r=s?this.where(s):{table:e.refTable,cols:new Map};return`CONSTRAINT ${R(e.name)} FOREIGN KEY (${Te(e.columns.map(o=>n.get(o)??o))}) REFERENCES ${P(e.refSchema,r.table)} (${Te(e.refColumns.map(o=>r.cols.get(o)??o))})${e.match==="full"?" MATCH FULL":""} ON DELETE ${e.onDelete.toUpperCase()} ON UPDATE ${e.onUpdate.toUpperCase()}${e.deferrable?" DEFERRABLE":""}`}fkSqlOld(e){return`CONSTRAINT ${R(e.name)} FOREIGN KEY (${Te(e.columns)}) REFERENCES ${P(e.refSchema,e.refTable)} (${Te(e.refColumns)})${e.match==="full"?" MATCH FULL":""} ON DELETE ${e.onDelete.toUpperCase()} ON UPDATE ${e.onUpdate.toUpperCase()}${e.deferrable?" DEFERRABLE":""}`}generations(e){return[...this.input.generations?.(e)??[]].sort((n,s)=>n.gen-s.gen)}search(e,n){let s=D(e),r=e.search,o=n?.from.search;if(r===void 0){n&&this.searchGone(n.from,n.physical);return}let a=xs(`table ${s}`,e,r);if(a.length>0){this.refusals.push(...a);return}let i=e.columns.find(T=>T.name===e.primaryKey[0]),c=this.generations(n?D(n.from):s),l=c.filter(T=>T.status!=="retired"),u=l.find(T=>T.status==="active"),g=l.at(-1),m=g===void 0?[]:Xn(g,r)?l:u?[u]:[],h=g===void 0?"active":Xn(g,r)||u!==void 0&&Xn(u,r)?void 0:"filling";if(n){let T="take search out of the table and deploy, make the change in the next deploy, and declare search again in the one after \u2014 every row is embedded again then";e.name!==n.from.name&&this.refuse(`table ${e.schema}.${n.from.name} is renamed ${e.name} while it declares search`,T);let y=new Set;for(let w of new Set([i.name,...r.from])){let O=w===i.name?"search keeps each row's vector by it":"search reads it";if(n.retyped.has(w))this.refuse(`column ${s}.${w} changes type, and ${O}`,T);else if((n.cols.get(w)??w)!==w)this.refuse(`column ${s}.${w} ${n.parked.has(w)?"takes a name another column leaves in this deploy":`is renamed from ${n.cols.get(w)}`}, and ${O}`,T);else continue;y.add(n.retyped.get(w)?.from.name??n.cols.get(w)??w)}for(let w of m)for(let O of w.from){if(y.has(O))continue;e.columns.some(N=>N.name===O)&&!n.retyped.has(O)&&(n.cols.get(O)??O)===O||this.refuse(`column ${s}.${O} goes or changes, and the vectors that serve search of ${s} now (generation ${w.gen}) are made from it`,"they serve until the new ones are complete: leave the column as it is in this deploy, and change it in a deploy after that")}}let p={schema:e.schema,name:n?n.physical:e.name},E=P(p.schema,p.name);if(h!==void 0){let T=(c.at(-1)?.gen??0)+1;this.changes.push(h==="active"?`search of ${s}: its rows are embedded with ${r.model} (${r.dimensions} dimensions) in the background; found by their words until then`:`search of ${s}: every row is embedded again with ${r.model} (${r.dimensions} dimensions) in the background; the vectors there serve until the new ones are complete`),this.searchStart.push({kind:"tx",sql:er({table:p,gen:T,search:r,status:h,pk:{name:i.name,type:this.typeSql(i.type)},roles:this.input.roles,types:this.input.vectorSchema??"public"}),why:`search of ${s}: generation ${T}`}),n&&this.searchStart.push({kind:"statement",sql:nr(p,T,i.name),why:`search of ${s}: its rows queued`}),this.undoSearch.push({kind:"tx",sql:Zn(p,T),why:`search of ${s}: generation ${T}`})}if(o!==void 0&&o.staleness!==r.staleness&&m.length>0){this.changes.push(`search of ${s}: a changed row's old vector ${r.staleness==="null"?"goes":"stays"} until the row is embedded again`);for(let T of m)this.searchStart.push({kind:"tx",sql:Qn({table:p,gen:T.gen,from:T.from,staleness:r.staleness},!0),why:`search of ${s}: generation ${T.gen}'s triggers`}),this.undoSearch.push({kind:"tx",sql:Qn({table:p,gen:T.gen,from:T.from,staleness:o.staleness},!0),why:`search of ${s}: generation ${T.gen}'s triggers`})}for(let T of c)m.includes(T)||(this.changes.push(`search of ${s}: generation ${T.gen}'s vectors, ${T.status==="retired"?"left behind":"never full"}, go (at complete)`),this.searchComplete.push({kind:"tx",sql:Zn(p,T.gen),why:`search of ${s}: generation ${T.gen}`}));let $=Yn(p,r.from),f=o===void 0?void 0:Yn(p,o.from);if($===f)return;let d=T=>`CREATE INDEX ${T?"CONCURRENTLY ":""}IF NOT EXISTS ${R($)} ON ${E} USING gin (${zn(r.from)})`;o!==void 0&&this.changes.push(`search of ${s} reads ${r.from.join(", ")}`),n?(this.online.push({kind:"statement",sql:d(!0),why:`search of ${s}: its words`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(p.schema,$)}`,why:`search of ${s}: its words`})):this.creates.push(d(!1)),f!==void 0&&this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(p.schema,f)}`,why:`search of ${s}: the words it read`})}searchGone(e,n){let s=this.generations(D(e));if(e.search===void 0&&s.length===0)return;let r={schema:e.schema,name:n},o=D(e);this.changes.push(`search of ${o} goes (at complete)`);for(let a of s)this.searchComplete.push({kind:"tx",sql:Zn(r,a.gen),why:`search of ${o}: generation ${a.gen}`});e.search!==void 0&&this.searchComplete.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${P(r.schema,Yn(r,e.search.from))}`,why:`search of ${o}: the words it read`})}policyRoles(e,n){let s=new Set;for(let r of e.to){if(r.startsWith("role:")&&r.length>5){s.add(R(r.slice(5)));continue}let o=Pt[r];if(!o){this.refuse(`policy ${n}.${e.name} is for role ${r}`,`a policy is for ${Object.keys(Pt).join(", ")}`);continue}s.add(o==="public"?"PUBLIC":R(this.input.roles[o]))}return[...s].join(", ")}policySql(e,n,s){let r=yn(s),o=`CREATE POLICY ${R(n.name)} ON ${e} AS ${n.restrictive?"RESTRICTIVE":"PERMISSIVE"} FOR ${n.for.toUpperCase()} TO ${this.policyRoles(n,e)}`;return n.using!==void 0&&(o+=` USING (${xe(n.using,r)})`),n.withCheck!==void 0&&(o+=` WITH CHECK (${xe(n.withCheck,r)})`),o}policies(e,n,s){let{to:r}=e,o=this.inNewNames(e.from),a=D(r),i=l=>JSON.stringify([l.for,[...new Set(l.to.map(u=>Pt[u]??u))].sort(),l.using??null,l.withCheck??null,l.restrictive??!1]),c=l=>e.from.policies.find(u=>u.name===l);for(let l of r.policies){let u=o.policies.find(g=>g.name===l.name);u&&i(u)===i(l)||this.readsOthersRenamed(r,l,a)||(this.changes.push(`policy ${a}.${l.name}${u?" changes":""}`),s.undo.push(`DROP POLICY IF EXISTS ${R(l.name)} ON ${n}`),u&&(s.tx.push(`DROP POLICY IF EXISTS ${R(l.name)} ON ${n}`),s.undo.push(this.policySql(n,c(l.name),or(e.from)))),s.tx.push(this.policySql(n,l,e.cols)))}for(let l of o.policies)r.policies.some(u=>u.name===l.name)||(this.changes.push(`policy ${a}.${l.name} goes`),s.tx.push(`DROP POLICY IF EXISTS ${R(l.name)} ON ${n}`),s.undo.push(this.policySql(n,c(l.name),or(e.from))))}readsOthersRenamed(e,n,s){let r=`${n.using??""} ${n.withCheck??""}`;for(let o of this.to.tables){if(o===e)continue;let a=this.from.tables.find(c=>c.schema===o.schema&&c.name===(o.renamedFrom??o.name));if(!a)continue;let i=[...o.name!==a.name&&Le(r,o.name)?[`${o.schema}.${o.name}`]:[],...Le(r,o.name)?o.columns.filter(c=>c.renamedFrom!==void 0&&c.renamedFrom!==c.name&&a.columns.some(l=>l.name===c.renamedFrom)&&Le(r,c.name)).map(c=>`${o.schema}.${o.name}.${c.name}`):[]];if(i.length>0)return this.refuse(`policy ${s}.${n.name} reads ${i.join(", ")}, renamed in this deploy`,"Postgres has the new name only from complete on: rename in this deploy, change the policy in the next"),!0}return!1}rawUnitsBefore(){let e=!0;for(let n of this.to.raw){if(!n.before)continue;let s=this.from.raw.find(r=>r.name===n.name);if(!(s&&s.sql.trim()===n.sql.trim())){if(s&&/^\s*CREATE\s+(?:DOMAIN|TYPE|SEQUENCE)\b/i.test(s.sql)){this.refuse(`raw ${n.name} changes`,"Postgres cannot drop a domain or a type a column uses, and a sequence made again starts over: say the change as an ALTER (ALTER DOMAIN \u2026 ADD CONSTRAINT \u2026 NOT VALID, ALTER TYPE, ALTER SEQUENCE) in a unit of its own, or make a new one and move the columns to it");continue}this.changes.push(`raw ${n.name}${s?" changes":""}`),e&&this.creates.push("SET LOCAL check_function_bodies = off"),e=!1,this.creates.push(...this.rawApply(n,s)),!s&&n.drop!==void 0&&this.undoCreates.push(n.drop),s&&this.undoRawsBack.push(...this.rawApply(s,n))}}}rawApply(e,n){return!n||/^\s*CREATE\s+OR\s+REPLACE\b/i.test(e.sql)||n.drop===void 0?[e.sql]:[n.drop,e.sql]}rawUnits(){let e=this.to.raw.filter(l=>!l.before),n=l=>/^\s*CREATE\s+(?:OR\s+REPLACE\s+)?(?:MATERIALIZED\s+)?VIEW\b/i.test(l),s=this.namesAtComplete,r=this.dropsColumnsAtComplete,o=e.findIndex(l=>{let u=this.from.raw.find(g=>g.name===l.name);return n(l.sql)?r&&u!==void 0?!0:u===void 0?s:u.sql.trim()!==l.sql.trim():!1}),a=new Set,i=new Set,c=null;if(o>=0){let l=e.slice(o),u=m=>n(m)||/^\s*CREATE\s+(?:OR\s+REPLACE\s+)?(?:FUNCTION|PROCEDURE)\b/i.test(m)||qt.test(m),g=[];for(let m of[...this.from.raw].reverse()){if(m.before||m.drop===void 0)continue;let h=l.some(E=>E.name===m.name),p=!this.to.raw.some(E=>E.name===m.name);(h&&u(m.sql)||p&&n(m.sql))&&g.push(m.drop),p&&n(m.sql)&&i.add(m.name)}for(let m of l){let h=this.from.raw.find(p=>p.name===m.name);(!h||h.sql.trim()!==m.sql.trim())&&this.changes.push(`raw ${m.name}${h?" changes":""}`),a.add(m.name)}if(s){this.viewsAtComplete={drops:g,creates:l.map(m=>m.sql)};for(let m of l){let h=this.changes.findIndex(p=>p===`raw ${m.name}`||p===`raw ${m.name} changes`);h>=0&&(this.changes[h]+=" (at complete)")}}else{c={kind:"tx",sql:["SET LOCAL check_function_bodies = off",...g,...l.map(m=>m.sql)],why:`raw ${l[0].name} and what follows it, made again`};for(let m of[...l].reverse())m.drop!==void 0&&this.undoRawsGone.push(m.drop);for(let m of this.from.raw){if(m.before||m.drop===void 0)continue;let h=l.some(E=>E.name===m.name),p=!this.to.raw.some(E=>E.name===m.name);(h&&u(m.sql)||p&&n(m.sql))&&this.undoRawsBack.push(m.sql)}}}for(let l of this.to.raw){if(l.before||(c!==null&&l.name===e[o].name&&this.raws.push(c),a.has(l.name)))continue;let u=this.from.raw.find(m=>m.name===l.name),g=ar(l.sql);if(!(u&&u.sql.trim()===l.sql.trim())){if(u&&g){this.refuse(`raw index ${l.name} changes under its name`,"an index is built CONCURRENTLY next to the one serving, so under a name of its own: give the new one its own name (the old one goes at complete)");continue}if(this.changes.push(`raw ${l.name}${u?" changes":""}`),g)this.raws.push({kind:"statement",sql:g.create,why:`raw ${l.name}`}),this.undoIndexesGone.unshift({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${g.qualified(l,this.to)}`,why:`raw ${l.name}`});else{if(l.drop===void 0&&(qt.test(l.sql)||n(l.sql))){this.refuse(`raw ${l.name} has no drop`,"a rollback could not take it back, and the old version would write and read past it: give it its drop (raw(name, up, { drop }))");continue}this.raws.push({kind:"tx",sql:["SET LOCAL check_function_bodies = off",...this.rawApply(l,u)],why:`raw ${l.name}`}),l.drop!==void 0&&this.undoRawsGone.unshift(l.drop),u&&this.undoRawsBack.push(...l.drop!==void 0?[u.sql]:this.rawApply(u,l))}}}for(let l of[...this.from.raw].reverse()){if(this.to.raw.some(g=>g.name===l.name))continue;if(i.has(l.name)){this.changes.push(`raw ${l.name} goes (with the views made again)`);continue}let u=ar(l.sql);if(!u){if(l.drop===void 0){this.refuse(`raw ${l.name} is gone from the schema`,"Palgres does not know how to take back what its SQL made: keep it, or give the unit its drop (raw(name, up, { drop })) and remove it in the deploy after that");continue}this.changes.push(`raw ${l.name} goes (at complete)`),qt.test(l.sql)?this.completeUnitDrops.push(l.drop):this.completeIndexes.push({kind:"tx",sql:[l.drop],why:`raw ${l.name}`});continue}this.changes.push(`raw index ${l.name} goes (at complete)`),this.completeIndexes.push({kind:"statement",sql:`DROP INDEX CONCURRENTLY IF EXISTS ${u.qualified(l,this.from)}`,why:`raw ${l.name}`})}}views(){let{anon:e,authenticated:n,service:s}=this.input.roles,r=[e,n,s].map(R).join(", "),o=[];for(let a of[...new Set(this.layout.tables.map(i=>i.schema))]){let i=R($e(this.n,a));o.push(`DROP SCHEMA IF EXISTS ${i} CASCADE`,`CREATE SCHEMA ${i}`,`GRANT USAGE ON SCHEMA ${i} TO ${r}`)}for(let a of this.layout.tables){let i=a.columns.map(l=>l.physical===l.name?R(l.name):`${R(l.physical)} AS ${R(l.name)}`).join(", "),c=P($e(this.n,a.schema),a.name);o.push(`CREATE VIEW ${c} WITH (security_invoker = true) AS SELECT ${i} FROM ${P(a.schema,a.physical)}`),o.push(`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${c} TO ${r}`)}return o}dropViews(e,n){let s=[...new Set(n.tables.map(r=>r.schema))];return s.length>0?s.map(r=>`DROP SCHEMA IF EXISTS ${R($e(e,r))} CASCADE`):["SELECT 1"]}keyOf(e){let n=this.where(e);return e.primaryKey.map(s=>{let r=this.matches.get(D(e))?.retyped.get(s);return r?r.from.name:n.cols.get(s)??s})}};function or(t){return new Map(t.columns.map(e=>[e.name,e.name]))}function yn(t){return new Map([...t].filter(([e,n])=>e!==n))}function Mt(t,e,n){return e?[`ALTER TABLE ${t} ENABLE ROW LEVEL SECURITY`]:n?[`ALTER TABLE ${t} DISABLE ROW LEVEL SECURITY`]:[]}function tt(t){return JSON.stringify([t.columns,t.refSchema,t.refTable,t.refColumns,t.onDelete,t.onUpdate,t.match??"simple"])}function st(t){return JSON.stringify([t.keys,t.unique,t.where??null,t.method??"btree",t.include??[]])}var qt=/^\s*(?:CREATE\s+(?:OR\s+REPLACE\s+)?(?:TRIGGER|CONSTRAINT\s+TRIGGER|RULE)\b|DO\s+\$\w*\$\s+BEGIN\s+IF\s+NOT\s+\(EXISTS\s+\(SELECT\s+1\s+FROM\s+pg_catalog\.pg_trigger)/i,cr=/^\s*CREATE\s+(UNIQUE\s+)?INDEX\s+(?:CONCURRENTLY\s+)?(?:IF\s+NOT\s+EXISTS\s+)?("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*)\s+ON\s+/i;function na(t){return rt(t).map(e=>e.schema===void 0?R(e.name):P(e.schema,e.name))}var ur=/\bnextval\('((?:[^']|'')+)'(?:::regclass)?\)/gi;function rt(t){if(t===void 0)return[];let e=[];for(let n of t.matchAll(ur)){let s=n[1].replace(/''/g,"'"),r='("(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)',o=new RegExp(`^(?:${r}\\.)?${r}$`).exec(s);if(!o)continue;let a=i=>i.startsWith('"')?i.slice(1,-1).replace(/""/g,'"'):i.toLowerCase();e.push(o[1]===void 0?{name:a(o[2])}:{schema:a(o[1]),name:a(o[2])})}return e}function Wt(t){let e=t.sql.trim().replace(/;\s*$/,""),n=cr.exec(e);return!n||e.includes(";")?void 0:n[2].replace(/^"|"$/g,"")}function ar(t){let e=t.trim().replace(/;\s*$/,""),n=cr.exec(e);if(!n||e.includes(";"))return;let s=n[2].replace(/^"|"$/g,""),r=e.slice(n[0].length);return{unique:!!n[1],create:`CREATE ${n[1]?"UNIQUE ":""}INDEX CONCURRENTLY IF NOT EXISTS ${R(s)} ON ${r}`,qualified:(o,a)=>{let i=/^\s*(?:ONLY\s+)?("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*)(?:\.("[^"]+"|[A-Za-z_][A-Za-z0-9_$]*))?/i.exec(r),c=u=>u.replace(/^"|"$/g,""),l=i?.[2]?c(i[1]):o.table?.split(".")[0]??a.tables.find(u=>u.name===c(i?.[1]??""))?.schema??"public";return P(l,s)}}}import{randomBytes as da}from"node:crypto";var Ue=(t,e)=>JSON.stringify(t)===JSON.stringify(e),wn=t=>new Map(t.map(e=>[e.name,e])),Ze=t=>({type:t.type,nullable:t.nullable,default:t.default??null,identity:t.identity??null,generated:t.generated??null});function ta(t,e){if(t.name===e)return t;let{renamedFrom:n,...s}=t;return{...s,name:e}}function jt(t,e,n){let s=Ee(n),r=[],o=[...t.unmanaged],a=new Map(t.schema.tables.map(f=>[D(f),f])),i=new Map(e.schema.tables.map(f=>[D(f),f])),c=new Set,l=[],u=new Set(s.raw.map(f=>Wt(f)).filter(f=>f!==void 0));for(let f of s.tables){let d=a.get(D(f))??(f.renamedFrom!==void 0?a.get(`${f.schema}.${f.renamedFrom}`):void 0);if(!d)continue;c.add(D(d));let T=i.get(D(f));if(!T)throw new Error(`palgres: the shadow database has no ${D(f)}: the schema did not make it`);let y=wn(T.columns),w=d.columns.map(k=>{let N=f.columns.find(b=>b.name===k.name)??f.columns.find(b=>b.renamedFrom===k.name&&!d.columns.some(L=>L.name===b.name)),A=N&&y.get(N.name);return N&&A&&Ue(Ze(k),Ze(A))?ta(N,k.name):k}),O=(k,N,A)=>{let b=wn(N),L=wn(A);return k.map(S=>{let v=b.get(S.name),q=L.get(S.name);return q&&v&&Ue(S,v)?q:S})};l.push({schema:d.schema,name:d.name,...f.ignored!==void 0?{ignored:f.ignored}:{},...f.renamedFrom!==void 0&&f.name===d.name?{renamedFrom:f.renamedFrom}:{},columns:w,primaryKey:d.primaryKey,uniques:O(d.uniques,T.uniques,f.uniques),indexes:O(d.indexes.filter(k=>!u.has(k.name)),T.indexes,f.indexes),checks:O(d.checks,T.checks,f.checks),foreignKeys:O(d.foreignKeys.filter(k=>a.has(`${k.refSchema}.${k.refTable}`)&&s.tables.some(N=>N.schema===k.refSchema&&N.name===k.refTable||N.schema===k.refSchema&&N.renamedFrom===k.refTable)?!0:(o.push(`foreign key ${D(d)}.${k.name} references ${k.refSchema}.${k.refTable}, outside the schema \u2014 kept as it is; drop it when its target goes`),!1)),T.foreignKeys,f.foreignKeys),rls:d.rls,policies:O(d.policies,T.policies,f.policies)})}for(let f of a.keys())c.has(f)||o.push(`table ${f}: not in the schema \u2014 kept as it is`);for(let f of t.forced)c.has(f)||o.push(`table ${f}: row-level security FORCEd on its owner \u2014 kept as it is`);let g=new Map(t.schema.tables.flatMap(f=>f.indexes.map(d=>[`${f.schema}.${d.name}`,{t:f,i:d}]))),m=new Map(e.schema.tables.flatMap(f=>f.indexes.map(d=>[`${f.schema}.${d.name}`,{t:f,i:d}]))),h=[],p=!0;for(let[f,d]of e.objects){let T=t.objects.get(f);T===void 0?p=!1:T!==d&&r.push(`${f} is not what the schema's raw SQL makes: drop it, and the migration makes it as the schema says`)}for(let f of s.raw){let d=Wt(f);if(d===void 0){p&&h.push(f);continue}let T=[...m.keys()].find(O=>O.endsWith(`.${d}`)),y=T&&m.get(T),w=T&&g.get(T);if(!y||!w){let O=[...e.objects.keys()].find(k=>k.startsWith("index ")&&k.endsWith(`.${d}`));O!==void 0&&t.objects.get(O)===e.objects.get(O)&&h.push(f);continue}Ue(w.i,y.i)&&D(w.t)===D(y.t)?h.push(f):r.push(`index ${T} is not what the schema's raw unit ${f.name} makes: drop it, and the migration makes it as the schema says`)}let E=[];for(let f of s.enums){let d=t.schema.enums.find(T=>T.schema===f.schema&&T.name===f.name);d&&E.push(Ue(d.values,f.values)?f:d)}let $=s.extensions.filter(f=>t.schema.extensions.includes(f));return{schema:Ee({tables:l,enums:E,extensions:$,raw:h}),unforce:t.forced.filter(f=>c.has(f)),refusals:r,unmanaged:o}}function sa(t,e){let n=[],s=new Map(t.schema.tables.map(r=>[D(r),r]));for(let r of e.schema.tables){let o=D(r),a=s.get(o);if(!a){n.push(`table ${o} is missing`);continue}for(let u of r.columns)a.columns.some(g=>g.name===u.name)||n.push(`column ${o}.${u.name} is missing`);for(let u of a.columns)r.columns.some(g=>g.name===u.name)||n.push(`column ${o}.${u.name}: not declared`);for(let u of r.columns){let g=a.columns.find(m=>m.name===u.name);g&&!Ue(Ze(g),Ze(u))&&n.push(`column ${o}.${u.name}: ${JSON.stringify(Ze(g))}, declared ${JSON.stringify(Ze(u))}`)}Ue(a.primaryKey,r.primaryKey)||n.push(`table ${o}: primary key (${a.primaryKey.join(", ")}), declared (${r.primaryKey.join(", ")})`),a.rls!==r.rls&&n.push(`table ${o}: row-level security ${a.rls?"on":"off"}, declared ${r.rls?"on":"off"}`);let i={uniques:"unique",indexes:"index",checks:"check",foreignKeys:"foreign key",policies:"policy"},c=(u,g)=>e.schema.tables.some(m=>m.schema===u&&m.name===g),l={...a,foreignKeys:a.foreignKeys.filter(u=>c(u.refSchema,u.refTable))};for(let[u,g]of Object.entries(i)){let m=wn(l[u]),h=wn(r[u]);for(let[p,E]of h)Ue(m.get(p),E)||n.push(`${g} ${o}.${p}: ${m.has(p)?`${JSON.stringify(m.get(p))}, declared ${JSON.stringify(E)}`:"missing"}`);for(let p of m.keys())h.has(p)||n.push(`${g} ${o}.${p}: not declared`)}}return n}function _e(t,e){let n=t.join("_").replace(/[^A-Za-z0-9_]/g,"_").replace(/^([^A-Za-z_])/,"_$1");if(Buffer.byteLength(n)>55){let r=0;for(let o of t.join("."))r=Math.imul(r,31)+o.charCodeAt(0)>>>0;n=`${n.slice(0,46)}_${r.toString(36)}`}let s=n;for(let r=2;e.has(s);r++)s=`${n}_${r}`;return e.add(s),s}function ra(t){let e="$palgres$";for(let n=1;t.includes(e);n++)e=`$palgres${n}$`;return e}var Kt=(t,e)=>{let n=ra(e+t);return`DO ${n} BEGIN IF NOT (${t}) THEN ${e}; END IF; END ${n}`};async function dr(t,e,n,s){let r=new Set,o=[],a=[],i=[],c=await t(`SELECT n.nspname AS schema, t.typname AS name, pg_catalog.format_type(t.typbasetype, t.typtypmod) AS base,
116
116
  CASE WHEN t.typcollation <> 0 AND t.typcollation <> (SELECT b.typcollation FROM pg_catalog.pg_type b WHERE b.oid = t.typbasetype) THEN (SELECT format('%I.%I', cn.nspname, co.collname) FROM pg_catalog.pg_collation co JOIN pg_catalog.pg_namespace cn ON cn.oid = co.collnamespace WHERE co.oid = t.typcollation) END AS collation,
117
117
  pg_catalog.pg_get_expr(t.typdefaultbin, 0) AS default, t.typnotnull AS notnull,
118
118
  (SELECT json_agg(json_build_object('name', c.conname, 'def', pg_catalog.pg_get_constraintdef(c.oid, true)) ORDER BY c.conname) FROM pg_catalog.pg_constraint c WHERE c.contypid = t.oid AND c.contype = 'c') AS checks
119
119
  FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
120
120
  WHERE n.nspname IN ${e} AND t.typtype = 'd'
121
121
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = t.oid AND d.deptype = 'e')
122
- ORDER BY t.oid`);for(let d of c){let T=[`AS ${d.base}`];d.collation!==null&&T.push(`COLLATE ${d.collation}`),d.default!==null&&T.push(`DEFAULT ${d.default}`),d.notnull&&T.push("NOT NULL");for(let w of d.checks??[])T.push(`CONSTRAINT ${b(w.name)} ${w.def}`);let E=`domain ${d.schema}.${d.name}`;s.set(E,T.join(" ")),o.push({schema:d.schema,key:E,listed:`type ${d.schema}.${d.name} (`,kind:"domain",name:Ce(["domain",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!0,create:vt(`EXISTS (SELECT 1 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = ${Fe(d.schema)} AND t.typname = ${Fe(d.name)})`,`CREATE DOMAIN ${P(d.schema,d.name)} ${T.join(" ")}`),drop:`DROP DOMAIN IF EXISTS ${P(d.schema,d.name)}`})}let l=await t(`SELECT n.nspname AS schema, t.typname AS name,
122
+ ORDER BY t.oid`);for(let d of c){let T=[`AS ${d.base}`];d.collation!==null&&T.push(`COLLATE ${d.collation}`),d.default!==null&&T.push(`DEFAULT ${d.default}`),d.notnull&&T.push("NOT NULL");for(let w of d.checks??[])T.push(`CONSTRAINT ${R(w.name)} ${w.def}`);let y=`domain ${d.schema}.${d.name}`;s.set(y,T.join(" ")),o.push({schema:d.schema,key:y,listed:`type ${d.schema}.${d.name} (`,kind:"domain",name:_e(["domain",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!0,create:Kt(`EXISTS (SELECT 1 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = ${Be(d.schema)} AND t.typname = ${Be(d.name)})`,`CREATE DOMAIN ${P(d.schema,d.name)} ${T.join(" ")}`),drop:`DROP DOMAIN IF EXISTS ${P(d.schema,d.name)}`})}let l=await t(`SELECT n.nspname AS schema, t.typname AS name,
123
123
  (SELECT json_agg(json_build_object('name', a.attname, 'type', pg_catalog.format_type(a.atttypid, a.atttypmod)) ORDER BY a.attnum) FROM pg_catalog.pg_attribute a WHERE a.attrelid = t.typrelid AND a.attnum > 0 AND NOT a.attisdropped) AS attrs,
124
124
  EXISTS (SELECT 1 FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_type at ON at.oid = a.atttypid JOIN pg_catalog.pg_class rc ON rc.oid = at.typrelid WHERE a.attrelid = t.typrelid AND rc.relkind <> 'c') AS "usesTable"
125
125
  FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace JOIN pg_catalog.pg_class c ON c.oid = t.typrelid
126
126
  WHERE n.nspname IN ${e} AND t.typtype = 'c' AND c.relkind = 'c'
127
127
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = t.oid AND d.deptype = 'e')
128
- ORDER BY t.oid`);for(let d of l){let T=(d.attrs??[]).map(O=>`${b(O.name)} ${O.type}`).join(", "),E=`type ${d.schema}.${d.name}`;s.set(E,T);let w={schema:d.schema,key:E,listed:`type ${d.schema}.${d.name} (`,kind:"type",name:Ce(["type",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!d.usesTable,create:vt(`EXISTS (SELECT 1 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = ${Fe(d.schema)} AND t.typname = ${Fe(d.name)})`,`CREATE TYPE ${P(d.schema,d.name)} AS (${T})`),drop:`DROP TYPE IF EXISTS ${P(d.schema,d.name)}`};(w.before?o:a).push(w)}let u=await t(`SELECT n.nspname AS schema, c.relname AS name, pg_catalog.format_type(s.seqtypid, NULL) AS type, s.seqstart::text AS start, s.seqincrement::text AS increment,
128
+ ORDER BY t.oid`);for(let d of l){let T=(d.attrs??[]).map(O=>`${R(O.name)} ${O.type}`).join(", "),y=`type ${d.schema}.${d.name}`;s.set(y,T);let w={schema:d.schema,key:y,listed:`type ${d.schema}.${d.name} (`,kind:"type",name:_e(["type",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!d.usesTable,create:Kt(`EXISTS (SELECT 1 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE n.nspname = ${Be(d.schema)} AND t.typname = ${Be(d.name)})`,`CREATE TYPE ${P(d.schema,d.name)} AS (${T})`),drop:`DROP TYPE IF EXISTS ${P(d.schema,d.name)}`};(w.before?o:a).push(w)}let u=await t(`SELECT n.nspname AS schema, c.relname AS name, pg_catalog.format_type(s.seqtypid, NULL) AS type, s.seqstart::text AS start, s.seqincrement::text AS increment,
129
129
  s.seqmin::text AS min, s.seqmax::text AS max, s.seqcache::text AS cache, s.seqcycle AS cycle
130
130
  FROM pg_catalog.pg_sequence s JOIN pg_catalog.pg_class c ON c.oid = s.seqrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
131
131
  WHERE n.nspname IN ${e}
132
132
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = c.oid AND d.deptype IN ('a', 'i', 'e'))
133
- ORDER BY c.oid`);for(let d of u){let T=`AS ${d.type} INCREMENT BY ${d.increment} MINVALUE ${d.min} MAXVALUE ${d.max} START WITH ${d.start} CACHE ${d.cache}${d.cycle?" CYCLE":" NO CYCLE"}`,E=`sequence ${d.schema}.${d.name}`;s.set(E,T),o.push({schema:d.schema,key:E,listed:`sequence ${d.schema}.${d.name} (`,kind:"sequence",name:Ce(["sequence",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!0,create:`CREATE SEQUENCE IF NOT EXISTS ${P(d.schema,d.name)} ${T}`,drop:`DROP SEQUENCE IF EXISTS ${P(d.schema,d.name)}`})}let g=await t(`SELECT n.nspname AS schema, p.proname AS name, pg_catalog.pg_get_function_identity_arguments(p.oid) AS args, p.prokind AS kind, pg_catalog.pg_get_functiondef(p.oid) AS def,
133
+ ORDER BY c.oid`);for(let d of u){let T=`AS ${d.type} INCREMENT BY ${d.increment} MINVALUE ${d.min} MAXVALUE ${d.max} START WITH ${d.start} CACHE ${d.cache}${d.cycle?" CYCLE":" NO CYCLE"}`,y=`sequence ${d.schema}.${d.name}`;s.set(y,T),o.push({schema:d.schema,key:y,listed:`sequence ${d.schema}.${d.name} (`,kind:"sequence",name:_e(["sequence",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!0,create:`CREATE SEQUENCE IF NOT EXISTS ${P(d.schema,d.name)} ${T}`,drop:`DROP SEQUENCE IF EXISTS ${P(d.schema,d.name)}`})}let g=await t(`SELECT n.nspname AS schema, p.proname AS name, pg_catalog.pg_get_function_identity_arguments(p.oid) AS args, p.prokind AS kind, pg_catalog.pg_get_functiondef(p.oid) AS def,
134
134
  EXISTS (SELECT 1 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_class rc ON rc.oid = t.typrelid
135
135
  WHERE rc.relkind <> 'c' AND (t.oid = p.prorettype OR t.oid = ANY (p.proargtypes::oid[]) OR t.oid = ANY (coalesce(p.proallargtypes, '{}'::oid[]))
136
136
  OR t.typarray = p.prorettype)) AS "usesRelation"
137
137
  FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
138
138
  WHERE n.nspname IN ${e} AND p.proname NOT LIKE '\\_palgres\\_%' AND p.prokind IN ('f', 'p', 'w')
139
139
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
140
- ORDER BY p.oid`);for(let d of g){let T=`function ${d.schema}.${d.name}(${d.args})`,E={schema:d.schema,key:T,listed:`function ${d.schema}.${d.name}(${d.args})`,kind:"function",name:Ce(["fn",d.schema==="public"?d.name:`${d.schema}_${d.name}`,d.args===""?"":d.args.replace(/\s+/g,"_")].filter(Boolean),r),before:!d.usesRelation,create:d.def.trim(),drop:`DROP ${d.kind==="p"?"PROCEDURE":"FUNCTION"} IF EXISTS ${P(d.schema,d.name)}(${d.args})`};(E.before?o:i).push(E)}let p=await t(`SELECT n.nspname AS schema, p.proname AS name, pg_catalog.pg_get_function_identity_arguments(p.oid) AS args,
140
+ ORDER BY p.oid`);for(let d of g){let T=`function ${d.schema}.${d.name}(${d.args})`,y={schema:d.schema,key:T,listed:`function ${d.schema}.${d.name}(${d.args})`,kind:"function",name:_e(["fn",d.schema==="public"?d.name:`${d.schema}_${d.name}`,d.args===""?"":d.args.replace(/\s+/g,"_")].filter(Boolean),r),before:!d.usesRelation,create:d.def.trim(),drop:`DROP ${d.kind==="p"?"PROCEDURE":"FUNCTION"} IF EXISTS ${P(d.schema,d.name)}(${d.args})`};(y.before?o:i).push(y)}let m=await t(`SELECT n.nspname AS schema, p.proname AS name, pg_catalog.pg_get_function_identity_arguments(p.oid) AS args,
141
141
  a.aggtransfn::regprocedure::text AS sfunc, pg_catalog.format_type(a.aggtranstype, NULL) AS stype,
142
142
  CASE WHEN a.aggfinalfn <> 0 THEN a.aggfinalfn::regproc::text END AS final, CASE WHEN a.aggcombinefn <> 0 THEN a.aggcombinefn::regproc::text END AS combine,
143
143
  a.agginitval AS init, CASE WHEN a.aggsortop <> 0 THEN a.aggsortop::regoperator::text END AS sortop, p.proparallel AS parallel,
@@ -145,22 +145,22 @@ END $palgres$`,`CREATE TRIGGER ${h} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW
145
145
  FROM pg_catalog.pg_aggregate a JOIN pg_catalog.pg_proc p ON p.oid = a.aggfnoid JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
146
146
  WHERE n.nspname IN ${e} AND a.aggkind = 'n' AND a.aggmtransfn = 0
147
147
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
148
- ORDER BY p.oid`);for(let d of p){let T=d.sfunc.replace(/\(.*\)$/,""),E=[`SFUNC = ${T}`,`STYPE = ${d.stype}`];d.final!==null&&E.push(`FINALFUNC = ${d.final}`),d.combine!==null&&E.push(`COMBINEFUNC = ${d.combine}`),d.init!==null&&E.push(`INITCOND = ${Fe(d.init)}`),d.sortop!==null&&E.push(`SORTOP = ${d.sortop.replace(/\(.*\)$/,"")}`),E.push(`PARALLEL = ${d.parallel==="s"?"SAFE":d.parallel==="r"?"RESTRICTED":"UNSAFE"}`);let w=`aggregate ${d.schema}.${d.name}(${d.args})`;s.set(w,E.join(", "));let O={schema:d.schema,key:w,listed:`function ${d.schema}.${d.name}(${d.args})`,kind:"function",name:Ce(["agg",d.schema==="public"?d.name:`${d.schema}_${d.name}`,d.args.replace(/\s+/g,"_")].filter(Boolean),r),before:!d.usesRelation&&!i.some(k=>k.key.startsWith(`function ${T}(`)||d.final!==null&&k.key.startsWith(`function ${d.final}(`)),create:`CREATE OR REPLACE AGGREGATE ${P(d.schema,d.name)}(${d.args}) (${E.join(", ")})`,drop:`DROP AGGREGATE IF EXISTS ${P(d.schema,d.name)}(${d.args})`};(O.before?o:i).push(O)}let h=await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name, c.relkind AS kind, pg_catalog.pg_get_viewdef(c.oid, true) AS def, c.reloptions AS options,
148
+ ORDER BY p.oid`);for(let d of m){let T=d.sfunc.replace(/\(.*\)$/,""),y=[`SFUNC = ${T}`,`STYPE = ${d.stype}`];d.final!==null&&y.push(`FINALFUNC = ${d.final}`),d.combine!==null&&y.push(`COMBINEFUNC = ${d.combine}`),d.init!==null&&y.push(`INITCOND = ${Be(d.init)}`),d.sortop!==null&&y.push(`SORTOP = ${d.sortop.replace(/\(.*\)$/,"")}`),y.push(`PARALLEL = ${d.parallel==="s"?"SAFE":d.parallel==="r"?"RESTRICTED":"UNSAFE"}`);let w=`aggregate ${d.schema}.${d.name}(${d.args})`;s.set(w,y.join(", "));let O={schema:d.schema,key:w,listed:`function ${d.schema}.${d.name}(${d.args})`,kind:"function",name:_e(["agg",d.schema==="public"?d.name:`${d.schema}_${d.name}`,d.args.replace(/\s+/g,"_")].filter(Boolean),r),before:!d.usesRelation&&!i.some(k=>k.key.startsWith(`function ${T}(`)||d.final!==null&&k.key.startsWith(`function ${d.final}(`)),create:`CREATE OR REPLACE AGGREGATE ${P(d.schema,d.name)}(${d.args}) (${y.join(", ")})`,drop:`DROP AGGREGATE IF EXISTS ${P(d.schema,d.name)}(${d.args})`};(O.before?o:i).push(O)}let h=await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name, c.relkind AS kind, pg_catalog.pg_get_viewdef(c.oid, true) AS def, c.reloptions AS options,
149
149
  (SELECT array_agg(DISTINCT format('%s.%s', rn.nspname, rc.relname)) FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_depend d ON d.classid = 'pg_catalog.pg_rewrite'::regclass AND d.objid = r.oid
150
150
  JOIN pg_catalog.pg_class rc ON rc.oid = d.refobjid JOIN pg_catalog.pg_namespace rn ON rn.oid = rc.relnamespace
151
151
  WHERE r.ev_class = c.oid AND d.refclassid = 'pg_catalog.pg_class'::regclass AND d.refobjid <> c.oid) AS reads
152
152
  FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
153
153
  WHERE n.nspname IN ${e} AND c.relkind IN ('v', 'm')
154
154
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = c.oid AND d.deptype = 'e')
155
- ORDER BY c.oid`),m=new Set(n),y=[...h];for(let d=!0;d&&y.length>0;){d=!1;for(let T=0;T<y.length;T++){let E=y[T];if(!(E.reads??[]).every(A=>m.has(A)))continue;y.splice(T--,1),d=!0,m.add(`${E.schema}.${E.name}`);let w=E.def.trim().replace(/;$/,""),O=E.options?.length?` WITH (${E.options.join(", ")})`:"",k=E.kind==="m",N=`${k?"materialized view":"view"} ${E.schema}.${E.name}`;s.set(N,JSON.stringify({options:E.options??[],query:w})),a.push({schema:E.schema,key:N,listed:`${k?"materialized view":"view"} ${E.schema}.${E.name}`,kind:k?"materialized view":"view",name:Ce([k?"matview":"view",E.schema==="public"?E.name:`${E.schema}_${E.name}`],r),before:!1,create:k?`CREATE MATERIALIZED VIEW IF NOT EXISTS ${P(E.schema,E.name)}${O} AS ${w}`:`CREATE OR REPLACE VIEW ${P(E.schema,E.name)}${O} AS ${w}`,drop:`DROP ${k?"MATERIALIZED VIEW":"VIEW"} IF EXISTS ${P(E.schema,E.name)}`})}}a.push(...i);let S=await t(`SELECT n.nspname AS schema, c.relname AS table, ic.relname AS name, pg_catalog.pg_get_indexdef(i.indexrelid) AS def
155
+ ORDER BY c.oid`),p=new Set(n),E=[...h];for(let d=!0;d&&E.length>0;){d=!1;for(let T=0;T<E.length;T++){let y=E[T];if(!(y.reads??[]).every(A=>p.has(A)))continue;E.splice(T--,1),d=!0,p.add(`${y.schema}.${y.name}`);let w=y.def.trim().replace(/;$/,""),O=y.options?.length?` WITH (${y.options.join(", ")})`:"",k=y.kind==="m",N=`${k?"materialized view":"view"} ${y.schema}.${y.name}`;s.set(N,JSON.stringify({options:y.options??[],query:w})),a.push({schema:y.schema,key:N,listed:`${k?"materialized view":"view"} ${y.schema}.${y.name}`,kind:k?"materialized view":"view",name:_e([k?"matview":"view",y.schema==="public"?y.name:`${y.schema}_${y.name}`],r),before:!1,create:k?`CREATE MATERIALIZED VIEW IF NOT EXISTS ${P(y.schema,y.name)}${O} AS ${w}`:`CREATE OR REPLACE VIEW ${P(y.schema,y.name)}${O} AS ${w}`,drop:`DROP ${k?"MATERIALIZED VIEW":"VIEW"} IF EXISTS ${P(y.schema,y.name)}`})}}a.push(...i);let $=await t(`SELECT n.nspname AS schema, c.relname AS table, ic.relname AS name, pg_catalog.pg_get_indexdef(i.indexrelid) AS def
156
156
  FROM pg_catalog.pg_index i JOIN pg_catalog.pg_class ic ON ic.oid = i.indexrelid JOIN pg_catalog.pg_class c ON c.oid = i.indrelid
157
157
  JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace JOIN pg_catalog.pg_am am ON am.oid = ic.relam
158
158
  WHERE n.nspname IN ${e} AND i.indisvalid AND ic.relname NOT LIKE '\\_palgres\\_search\\_%' AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_constraint k WHERE k.conindid = i.indexrelid AND k.contype IN ('p', 'u', 'x'))
159
- AND (c.relkind = 'm' OR (c.relkind = 'r' AND (am.amname NOT IN ('btree', 'hash', 'gin', 'gist', 'brin') OR NOT ${Dn("ic")})))
160
- ORDER BY ic.oid`);for(let d of S){if(!m.has(`${d.schema}.${d.table}`))continue;let T=`index ${d.schema}.${d.name}`;s.set(T,d.def),a.push({schema:d.schema,key:T,listed:`index ${d.schema}.${d.name} `,kind:"index",name:Ce(["index",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!1,create:d.def.replace(/^CREATE (UNIQUE )?INDEX /,"CREATE $1INDEX IF NOT EXISTS "),drop:`DROP INDEX IF EXISTS ${P(d.schema,d.name)}`})}let f=await t(`SELECT n.nspname AS schema, c.relname AS table, t.tgname AS name, pg_catalog.pg_get_triggerdef(t.oid, true) AS def, t.tgconstraint <> 0 AS constraint
159
+ AND (c.relkind = 'm' OR (c.relkind = 'r' AND (am.amname NOT IN ('btree', 'hash', 'gin', 'gist', 'brin') OR NOT ${Gn("ic")})))
160
+ ORDER BY ic.oid`);for(let d of $){if(!p.has(`${d.schema}.${d.table}`))continue;let T=`index ${d.schema}.${d.name}`;s.set(T,d.def),a.push({schema:d.schema,key:T,listed:`index ${d.schema}.${d.name} `,kind:"index",name:_e(["index",d.schema==="public"?d.name:`${d.schema}_${d.name}`],r),before:!1,create:d.def.replace(/^CREATE (UNIQUE )?INDEX /,"CREATE $1INDEX IF NOT EXISTS "),drop:`DROP INDEX IF EXISTS ${P(d.schema,d.name)}`})}let f=await t(`SELECT n.nspname AS schema, c.relname AS table, t.tgname AS name, pg_catalog.pg_get_triggerdef(t.oid, true) AS def, t.tgconstraint <> 0 AS constraint
161
161
  FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
162
162
  WHERE n.nspname IN ${e} AND NOT t.tgisinternal AND t.tgname NOT LIKE '\\_palgres\\_%'
163
- ORDER BY t.oid`);for(let d of f){if(!m.has(`${d.schema}.${d.table}`))continue;let T=`trigger ${d.schema}.${d.table}.${d.name}`;a.push({schema:d.schema,key:T,listed:`trigger ${d.name} on ${d.schema}.${d.table} `,kind:"trigger",name:Ce(["trigger",d.schema==="public"?d.table:`${d.schema}_${d.table}`,d.name],r),before:!1,create:d.constraint?vt(`EXISTS (SELECT 1 FROM pg_catalog.pg_trigger x WHERE x.tgrelid = ${Fe(`${b(d.schema)}.${b(d.table)}`)}::regclass AND x.tgname = ${Fe(d.name)})`,d.def):d.def.replace(/^CREATE TRIGGER /,"CREATE OR REPLACE TRIGGER "),drop:`DROP TRIGGER IF EXISTS ${b(d.name)} ON ${P(d.schema,d.table)}`})}return[...o,...a]}var Fe=t=>`'${t.replace(/'/g,"''")}'`;var Xn={a:"no action",r:"restrict",c:"cascade",n:"set null",d:"set default"},qo={ALL:"all",SELECT:"select",INSERT:"insert",UPDATE:"update",DELETE:"delete"};async function Yn(t,e,n){let s=await t.reserve();try{return await Fo(async r=>await s.unsafe(r),e,n)}finally{s.release()}}async function Fo(t,e,n){let s=[],r=[],o=new Map,a=`(${e.map(M).join(", ")})`;await t("BEGIN READ ONLY");try{await t("SET LOCAL search_path = ''");let i=await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name, c.relkind AS kind, c.relrowsecurity AS rls, c.relforcerowsecurity AS forced, c.relispartition AS partition,
163
+ ORDER BY t.oid`);for(let d of f){if(!p.has(`${d.schema}.${d.table}`))continue;let T=`trigger ${d.schema}.${d.table}.${d.name}`;a.push({schema:d.schema,key:T,listed:`trigger ${d.name} on ${d.schema}.${d.table} `,kind:"trigger",name:_e(["trigger",d.schema==="public"?d.table:`${d.schema}_${d.table}`,d.name],r),before:!1,create:d.constraint?Kt(`EXISTS (SELECT 1 FROM pg_catalog.pg_trigger x WHERE x.tgrelid = ${Be(`${R(d.schema)}.${R(d.table)}`)}::regclass AND x.tgname = ${Be(d.name)})`,d.def):d.def.replace(/^CREATE TRIGGER /,"CREATE OR REPLACE TRIGGER "),drop:`DROP TRIGGER IF EXISTS ${R(d.name)} ON ${P(d.schema,d.table)}`})}return[...o,...a]}var Be=t=>`'${t.replace(/'/g,"''")}'`;var ot={a:"no action",r:"restrict",c:"cascade",n:"set null",d:"set default"},oa={ALL:"all",SELECT:"select",INSERT:"insert",UPDATE:"update",DELETE:"delete"};async function at(t,e,n){let s=await t.reserve();try{return await aa(async r=>await s.unsafe(r),e,n)}finally{s.release()}}async function aa(t,e,n){let s=[],r=[],o=new Map,a=`(${e.map(M).join(", ")})`;await t("BEGIN READ ONLY");try{await t("SET LOCAL search_path = ''");let i=await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name, c.relkind AS kind, c.relrowsecurity AS rls, c.relforcerowsecurity AS forced, c.relispartition AS partition,
164
164
  EXISTS (SELECT 1 FROM pg_catalog.pg_inherits i WHERE i.inhrelid = c.oid OR i.inhparent = c.oid) AS inherits,
165
165
  (SELECT e.extname FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_extension e ON e.oid = d.refobjid
166
166
  WHERE d.classid = 'pg_catalog.pg_class'::regclass AND d.objid = c.oid AND d.refclassid = 'pg_catalog.pg_extension'::regclass AND d.deptype = 'e' LIMIT 1) AS extension
@@ -174,36 +174,36 @@ END $palgres$`,`CREATE TRIGGER ${h} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW
174
174
  LEFT JOIN pg_catalog.pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum
175
175
  LEFT JOIN pg_catalog.pg_collation co ON co.oid = a.attcollation
176
176
  WHERE a.attrelid IN ${f} AND a.attnum > 0 AND NOT a.attisdropped
177
- ORDER BY a.attrelid, a.attnum`);for(let $ of d){let C=l.get($.rel),q=`${C.schema}.${C.name}.${$.name}`,U=$.generated==="s"||$.generated==="v"?{expr:$.default??"",stored:$.generated==="s"}:void 0;$.collation!==null&&s.push(`column ${q}: collation ${$.collation} \u2014 kept, the model does not say it`);let v={name:$.name,type:be($.type),nullable:!$.notnull};U?v.generated=U:$.identity==="a"||$.identity==="d"?v.identity=$.identity==="a"?"always":"by default":$.default!==null&&(v.default=$.default),C.columns.push(v)}let T=await t(`SELECT c.conrelid::int AS rel, c.conname AS name, c.contype AS type, pg_catalog.pg_get_constraintdef(c.oid, true) AS def,
177
+ ORDER BY a.attrelid, a.attnum`);for(let S of d){let v=l.get(S.rel),q=`${v.schema}.${v.name}.${S.name}`,U=S.generated==="s"||S.generated==="v"?{expr:S.default??"",stored:S.generated==="s"}:void 0;S.collation!==null&&s.push(`column ${q}: collation ${S.collation} \u2014 kept, the model does not say it`);let C={name:S.name,type:Ne(S.type),nullable:!S.notnull};U?C.generated=U:S.identity==="a"||S.identity==="d"?C.identity=S.identity==="a"?"always":"by default":S.default!==null&&(C.default=S.default),v.columns.push(C)}let T=await t(`SELECT c.conrelid::int AS rel, c.conname AS name, c.contype AS type, pg_catalog.pg_get_constraintdef(c.oid, true) AS def,
178
178
  (SELECT array_agg(a.attname ORDER BY k.i) FROM unnest(c.conkey) WITH ORDINALITY AS k(attnum, i) JOIN pg_catalog.pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k.attnum) AS cols,
179
179
  c.confrelid::int AS refrel,
180
180
  (SELECT array_agg(a.attname ORDER BY k.i) FROM unnest(c.confkey) WITH ORDINALITY AS k(attnum, i) JOIN pg_catalog.pg_attribute a ON a.attrelid = c.confrelid AND a.attnum = k.attnum) AS refcols,
181
181
  c.confdeltype AS del, c.confupdtype AS upd, c.confmatchtype AS match, c.condeferrable AS deferrable, c.condeferred AS deferred, i.relname AS index
182
182
  FROM pg_catalog.pg_constraint c LEFT JOIN pg_catalog.pg_class i ON i.oid = c.conindid
183
183
  WHERE c.conrelid IN ${f}
184
- ORDER BY c.conrelid, c.conname`),E=new Map,w=[...new Set(T.filter($=>$.refrel).map($=>$.refrel))];if(w.length>0)for(let $ of await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.oid IN (${w.join(", ")})`))E.set($.oid,{schema:$.schema,name:$.name});let O=new Set;for(let $ of T){let C=l.get($.rel),q=`${C.schema}.${C.name}`;$.index&&($.type==="p"||$.type==="u"||$.type==="x")&&O.add(`${C.schema}.${$.index}`);let U=$.type==="f"&&!$.deferred&&je(Xn[$.del],Xn[$.upd]);if($.deferrable&&$.type!=="n"&&!U){s.push(`constraint ${q}.${$.name}: deferrable \u2014 kept as it is, the model does not say it`);continue}switch($.type){case"p":C.primaryKey=$.cols??[];break;case"u":if(/NULLS NOT DISTINCT/i.test($.def)){s.push(`constraint ${q}.${$.name}: UNIQUE NULLS NOT DISTINCT \u2014 kept as it is`);break}C.uniques.push({name:$.name,columns:$.cols??[]});break;case"c":{let v=/^CHECK \((.*)\)( NOT VALID)?$/s.exec($.def);if(!v||/\bNO INHERIT\b/.test($.def)){s.push(`constraint ${q}.${$.name}: ${$.def} \u2014 kept as it is`);break}C.checks.push({name:$.name,expr:v[1]});break}case"f":{let v=$.refrel===null?void 0:E.get($.refrel);if(!v||$.match==="p"){s.push(`constraint ${q}.${$.name}: ${$.def} \u2014 kept as it is`);break}let I={name:$.name,columns:$.cols??[],refSchema:v.schema,refTable:v.name,refColumns:$.refcols??[],onDelete:Xn[$.del],onUpdate:Xn[$.upd]};$.match==="f"&&(I.match="full"),$.deferrable&&(I.deferrable=!0),C.foreignKeys.push(I);break}case"n":break;default:s.push(`constraint ${q}.${$.name}: ${$.def} \u2014 kept as it is`)}}let k=await t(`SELECT i.indrelid::int AS rel, n.nspname AS schema, c.relname AS name, i.indisunique AS unique, am.amname AS method, i.indnkeyatts::int AS keyatts,
184
+ ORDER BY c.conrelid, c.conname`),y=new Map,w=[...new Set(T.filter(S=>S.refrel).map(S=>S.refrel))];if(w.length>0)for(let S of await t(`SELECT c.oid::int AS oid, n.nspname AS schema, c.relname AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.oid IN (${w.join(", ")})`))y.set(S.oid,{schema:S.schema,name:S.name});let O=new Set;for(let S of T){let v=l.get(S.rel),q=`${v.schema}.${v.name}`;S.index&&(S.type==="p"||S.type==="u"||S.type==="x")&&O.add(`${v.schema}.${S.index}`);let U=S.type==="f"&&!S.deferred&&He(ot[S.del],ot[S.upd]);if(S.deferrable&&S.type!=="n"&&!U){s.push(`constraint ${q}.${S.name}: deferrable \u2014 kept as it is, the model does not say it`);continue}switch(S.type){case"p":v.primaryKey=S.cols??[];break;case"u":if(/NULLS NOT DISTINCT/i.test(S.def)){s.push(`constraint ${q}.${S.name}: UNIQUE NULLS NOT DISTINCT \u2014 kept as it is`);break}v.uniques.push({name:S.name,columns:S.cols??[]});break;case"c":{let C=/^CHECK \((.*)\)( NOT VALID)?$/s.exec(S.def);if(!C||/\bNO INHERIT\b/.test(S.def)){s.push(`constraint ${q}.${S.name}: ${S.def} \u2014 kept as it is`);break}v.checks.push({name:S.name,expr:C[1]});break}case"f":{let C=S.refrel===null?void 0:y.get(S.refrel);if(!C||S.match==="p"){s.push(`constraint ${q}.${S.name}: ${S.def} \u2014 kept as it is`);break}let x={name:S.name,columns:S.cols??[],refSchema:C.schema,refTable:C.name,refColumns:S.refcols??[],onDelete:ot[S.del],onUpdate:ot[S.upd]};S.match==="f"&&(x.match="full"),S.deferrable&&(x.deferrable=!0),v.foreignKeys.push(x);break}case"n":break;default:s.push(`constraint ${q}.${S.name}: ${S.def} \u2014 kept as it is`)}}let k=await t(`SELECT i.indrelid::int AS rel, n.nspname AS schema, c.relname AS name, i.indisunique AS unique, am.amname AS method, i.indnkeyatts::int AS keyatts,
185
185
  -- indkey and indoption count from 0, and Bun cannot read an array that does not start at 1 ("[0:1]={\u2026}").
186
186
  ARRAY(SELECT k::int FROM unnest(i.indkey::int2[]) AS k) AS attnums, ARRAY(SELECT o::int FROM unnest(i.indoption::int2[]) AS o) AS options,
187
187
  ARRAY(SELECT pg_catalog.pg_get_indexdef(i.indexrelid, k, true) FROM generate_series(1, i.indnatts) AS k) AS exprs,
188
188
  pg_catalog.pg_get_expr(i.indpred, i.indrelid, true) AS where,
189
- ${Dn("c")} AS "defaultOps",
189
+ ${Gn("c")} AS "defaultOps",
190
190
  i.indisvalid AS valid
191
191
  FROM pg_catalog.pg_index i JOIN pg_catalog.pg_class c ON c.oid = i.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace JOIN pg_catalog.pg_am am ON am.oid = c.relam
192
192
  WHERE i.indrelid IN ${f} AND c.relname NOT LIKE '\\_palgres\\_search\\_%'
193
- ORDER BY i.indrelid, c.relname`);for(let $ of k){let C=l.get($.rel);if(O.has(`${$.schema}.${$.name}`))continue;let q=`${C.schema}.${C.name}`;if(!$.valid){s.push(`index ${$.schema}.${$.name}: INVALID (a build that did not finish) \u2014 drop it, or Palgres would take it for built`);continue}if(!["btree","hash","gin","gist","brin"].includes($.method)||!$.defaultOps){s.push(`index ${$.schema}.${$.name} of ${q}: ${$.method}${$.defaultOps?"":" with an operator class, a collation, NULLS NOT DISTINCT or storage options of its own"} \u2014 kept as it is`);continue}let U=[];for(let I=0;I<$.keyatts;I++){let x=($.options[I]&1)!==0,B=($.options[I]&2)!==0,F={};x&&(F.desc=!0),B!==x&&(F.nulls=B?"first":"last");let W=$.attnums[I];U.push(W===0?{expr:$.exprs[I],...F}:{column:$.exprs[I].replace(/^"(.*)"$/,"$1").replace(/""/g,'"'),...F})}let v={name:$.name,keys:U,unique:$.unique};$.method!=="btree"&&(v.method=$.method),$.where!==null&&(v.where=$.where),$.keyatts<$.attnums.length&&(v.include=$.exprs.slice($.keyatts).map(I=>I.replace(/^"(.*)"$/,"$1").replace(/""/g,'"'))),C.indexes.push(v)}let N=await t(`SELECT schemaname AS schema, tablename AS table, policyname AS name, permissive, roles::text[] AS roles, cmd, qual, with_check AS check
194
- FROM pg_catalog.pg_policies WHERE schemaname IN ${a} ORDER BY schemaname, tablename, policyname`),A=new Map([[n.anon,"anon"],[n.authenticated,"authenticated"],[n.service,"service_role"],["public","public"]]);for(let $ of N){let C=c.find(v=>v.schema===$.schema&&v.name===$.table);if(!C)continue;let q=$.roles.map(v=>A.get(v)??`role:${v}`),U={name:$.name,for:qo[$.cmd],to:q};$.qual!==null&&(U.using=$.qual),$.check!==null&&(U.withCheck=$.check),$.permissive==="RESTRICTIVE"&&(U.restrictive=!0),C.policies.push(U)}let R=await t(`SELECT format('%s.%s', n.nspname, c.relname) AS table, t.tgname AS name, pg_catalog.pg_get_triggerdef(t.oid, true) AS def FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
195
- WHERE t.tgrelid IN ${f} AND NOT t.tgisinternal AND t.tgname NOT LIKE '\\_palgres\\_%' ORDER BY 1, 2`);for(let $ of R)s.push(`trigger ${$.name} on ${$.table} \u2014 kept as it is`),o.set(`trigger ${$.table}.${$.name}`,$.def);let L=await t(`SELECT format('%s.%s', schemaname, tablename) AS table, rulename AS name FROM pg_catalog.pg_rules WHERE schemaname IN ${a} ORDER BY 1, 2`);for(let $ of L)s.push(`rule ${$.name} on ${$.table} \u2014 kept as it is`)}let g=await t(`SELECT n.nspname AS schema, t.typname AS name, t.typtype AS kind,
193
+ ORDER BY i.indrelid, c.relname`);for(let S of k){let v=l.get(S.rel);if(O.has(`${S.schema}.${S.name}`))continue;let q=`${v.schema}.${v.name}`;if(!S.valid){s.push(`index ${S.schema}.${S.name}: INVALID (a build that did not finish) \u2014 drop it, or Palgres would take it for built`);continue}if(!["btree","hash","gin","gist","brin"].includes(S.method)||!S.defaultOps){s.push(`index ${S.schema}.${S.name} of ${q}: ${S.method}${S.defaultOps?"":" with an operator class, a collation, NULLS NOT DISTINCT or storage options of its own"} \u2014 kept as it is`);continue}let U=[];for(let x=0;x<S.keyatts;x++){let I=(S.options[x]&1)!==0,B=(S.options[x]&2)!==0,F={};I&&(F.desc=!0),B!==I&&(F.nulls=B?"first":"last");let W=S.attnums[x];U.push(W===0?{expr:S.exprs[x],...F}:{column:S.exprs[x].replace(/^"(.*)"$/,"$1").replace(/""/g,'"'),...F})}let C={name:S.name,keys:U,unique:S.unique};S.method!=="btree"&&(C.method=S.method),S.where!==null&&(C.where=S.where),S.keyatts<S.attnums.length&&(C.include=S.exprs.slice(S.keyatts).map(x=>x.replace(/^"(.*)"$/,"$1").replace(/""/g,'"'))),v.indexes.push(C)}let N=await t(`SELECT schemaname AS schema, tablename AS table, policyname AS name, permissive, roles::text[] AS roles, cmd, qual, with_check AS check
194
+ FROM pg_catalog.pg_policies WHERE schemaname IN ${a} ORDER BY schemaname, tablename, policyname`),A=new Map([[n.anon,"anon"],[n.authenticated,"authenticated"],[n.service,"service_role"],["public","public"]]);for(let S of N){let v=c.find(C=>C.schema===S.schema&&C.name===S.table);if(!v)continue;let q=S.roles.map(C=>A.get(C)??`role:${C}`),U={name:S.name,for:oa[S.cmd],to:q};S.qual!==null&&(U.using=S.qual),S.check!==null&&(U.withCheck=S.check),S.permissive==="RESTRICTIVE"&&(U.restrictive=!0),v.policies.push(U)}let b=await t(`SELECT format('%s.%s', n.nspname, c.relname) AS table, t.tgname AS name, pg_catalog.pg_get_triggerdef(t.oid, true) AS def FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
195
+ WHERE t.tgrelid IN ${f} AND NOT t.tgisinternal AND t.tgname NOT LIKE '\\_palgres\\_%' ORDER BY 1, 2`);for(let S of b)s.push(`trigger ${S.name} on ${S.table} \u2014 kept as it is`),o.set(`trigger ${S.table}.${S.name}`,S.def);let L=await t(`SELECT format('%s.%s', schemaname, tablename) AS table, rulename AS name FROM pg_catalog.pg_rules WHERE schemaname IN ${a} ORDER BY 1, 2`);for(let S of L)s.push(`rule ${S.name} on ${S.table} \u2014 kept as it is`)}let g=await t(`SELECT n.nspname AS schema, t.typname AS name, t.typtype AS kind,
196
196
  CASE WHEN t.typtype = 'e' THEN ARRAY(SELECT e.enumlabel::text FROM pg_catalog.pg_enum e WHERE e.enumtypid = t.oid ORDER BY e.enumsortorder) END AS values
197
197
  FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
198
198
  WHERE n.nspname IN ${a} AND t.typtype IN ('e', 'd', 'c', 'r', 'm')
199
199
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_class c WHERE c.reltype = t.oid)
200
- ORDER BY 1, 2`),p=[];for(let f of g)f.kind==="e"?p.push({schema:f.schema,name:f.name,values:f.values??[]}):s.push(`type ${f.schema}.${f.name} (${f.kind==="d"?"domain":f.kind==="c"?"composite":"range"}) \u2014 kept as it is`);let h=await t(`SELECT format('%s.%s(%s)', n.nspname, p.proname, pg_catalog.pg_get_function_identity_arguments(p.oid)) AS name, CASE WHEN p.prokind IN ('f', 'p', 'w') THEN pg_catalog.pg_get_functiondef(p.oid) ELSE '' END AS def FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
200
+ ORDER BY 1, 2`),m=[];for(let f of g)f.kind==="e"?m.push({schema:f.schema,name:f.name,values:f.values??[]}):s.push(`type ${f.schema}.${f.name} (${f.kind==="d"?"domain":f.kind==="c"?"composite":"range"}) \u2014 kept as it is`);let h=await t(`SELECT format('%s.%s(%s)', n.nspname, p.proname, pg_catalog.pg_get_function_identity_arguments(p.oid)) AS name, CASE WHEN p.prokind IN ('f', 'p', 'w') THEN pg_catalog.pg_get_functiondef(p.oid) ELSE '' END AS def FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
201
201
  WHERE n.nspname IN ${a} AND p.proname NOT LIKE '\\_palgres\\_%'
202
202
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = p.oid AND d.deptype = 'e')
203
- ORDER BY 1`);for(let f of h)s.push(`function ${f.name} \u2014 kept as it is`),o.set(`function ${f.name}`,f.def);let m=await t(`SELECT format('%s.%s', n.nspname, c.relname) AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
203
+ ORDER BY 1`);for(let f of h)s.push(`function ${f.name} \u2014 kept as it is`),o.set(`function ${f.name}`,f.def);let p=await t(`SELECT format('%s.%s', n.nspname, c.relname) AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
204
204
  WHERE n.nspname IN ${a} AND c.relkind = 'S'
205
205
  AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend d WHERE d.objid = c.oid AND d.deptype IN ('a', 'i'))
206
- ORDER BY 1`);for(let f of m)s.push(`sequence ${f.name} (owned by no column) \u2014 kept as it is`);let y=(await t("SELECT extname AS name FROM pg_catalog.pg_extension WHERE extname <> 'plpgsql' ORDER BY 1")).map(f=>f.name),S=await Vs(t,a,new Set(c.map(f=>`${f.schema}.${f.name}`)),o);return{schema:{tables:c,enums:p,extensions:y,raw:[]},unmanaged:s,forced:r,objects:o,units:S}}finally{await t("ROLLBACK")}}var Le={SHARE:1,"SHARE ROW EXCLUSIVE":2,"ACCESS EXCLUSIVE":3},fe=String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)`,me=String.raw`${fe}(?:\s*\.\s*${fe}){0,2}`,z=t=>new RegExp(t,"i");function Xs(t){let e={needs:[],made:[]};for(let n of t)for(let s of zn(n))Ys(s,e);return e}function Gs(t){return t.startsWith('"')?t.slice(1,-1).replace(/""/g,'"'):t.toLowerCase()}var pe=t=>[...t.matchAll(new RegExp(fe,"g"))].map(e=>e[0]).join("."),Uo=z(String.raw`\b(?:ALTER\s+TABLE|DROP\s+TABLE|CREATE\s+(?:OR\s+REPLACE\s+)?(?:CONSTRAINT\s+)?TRIGGER|DROP\s+TRIGGER|(?:CREATE|ALTER|DROP)\s+POLICY|CREATE\s+(?:UNIQUE\s+)?INDEX|DROP\s+INDEX|CREATE\s+(?:OR\s+REPLACE\s+)?RULE|DROP\s+RULE|TRUNCATE|CREATE\s+(?:UNLOGGED\s+|TEMP(?:ORARY)?\s+)?TABLE|DROP\s+VIEW|CREATE\s+OR\s+REPLACE\s+VIEW|ALTER\s+VIEW)\b`);function Ys(t,e){let n;if(n=/^DO\s+(?:LANGUAGE\s+\w+\s+)?(\$[A-Za-z_0-9]*\$)([\s\S]*?)\1/i.exec(t)){for(let s of zn(n[2],!0)){let r=Uo.exec(s);r&&Ys(s.slice(r.index),e)}return}if(n=z(String.raw`^ALTER\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:ONLY\s+)?(${me})\s*\*?\s*([\s\S]*)$`).exec(t))return Wo(pe(n[1]),n[2],e);if(n=z(String.raw`^DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of Jn(n[1]))e.needs.push({of:"relation",name:s,mode:"ACCESS EXCLUSIVE"},{of:"table",name:s});return}if(n=z(String.raw`^DROP\s+VIEW\s+(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of Jn(n[1]))e.needs.push({of:"view",name:s});return}if(n=z(String.raw`^(?:CREATE\s+OR\s+REPLACE\s+(?:(?:TEMP|TEMPORARY)\s+)?(?:RECURSIVE\s+)?VIEW|ALTER\s+VIEW\s+(?:IF\s+EXISTS\s+)?)\s*(${me})`).exec(t)){e.needs.push({of:"view",name:pe(n[1])});return}if(n=z(String.raw`^CREATE\s+(?:OR\s+REPLACE\s+)?(?:CONSTRAINT\s+)?TRIGGER\s+${fe}\s+[\s\S]*?\bON\s+(?:ONLY\s+)?(${me})`).exec(t)){e.needs.push({of:"relation",name:pe(n[1]),mode:"SHARE ROW EXCLUSIVE"});return}if(n=z(String.raw`^(?:DROP\s+TRIGGER|(?:CREATE|ALTER|DROP)\s+POLICY|DROP\s+RULE)\s+(?:IF\s+EXISTS\s+)?${fe}\s+ON\s+(${me})`).exec(t)){e.needs.push({of:"relation",name:pe(n[1]),mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:OR\s+REPLACE\s+)?RULE\s+${fe}\s+AS\s+ON\s+\w+\s+TO\s+(${me})`).exec(t)){e.needs.push({of:"relation",name:pe(n[1]),mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?!CONCURRENTLY\b)(?:IF\s+NOT\s+EXISTS\s+)?(?:${fe}\s+)?ON\s+(?:ONLY\s+)?(${me})`).exec(t)){e.needs.push({of:"relation",name:pe(n[1]),mode:"SHARE"});return}if(n=z(String.raw`^DROP\s+INDEX\s+(?!CONCURRENTLY\b)(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of Jn(n[1]))e.needs.push({of:"index",name:s});return}if(n=z(String.raw`^TRUNCATE\s+(?:TABLE\s+)?([\s\S]*?)(?:\s+(?:RESTART|CONTINUE|CASCADE|RESTRICT)\b[\s\S]*)?$`).exec(t)){for(let s of Jn(n[1]))e.needs.push({of:"relation",name:s,mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:(?:GLOBAL|LOCAL)\s+)?(?:TEMP(?:ORARY)?\s+|UNLOGGED\s+)?TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(${me})([\s\S]*)$`).exec(t)){e.made.push(pe(n[1]));let s=z(String.raw`^\s*PARTITION\s+OF\s+(${me})`).exec(n[2]);s&&e.needs.push({of:"relation",name:pe(s[1]),mode:"ACCESS EXCLUSIVE"});for(let r of Js(n[2]))e.needs.push({of:"relation",name:r,mode:"SHARE ROW EXCLUSIVE"})}}var Bo=[/^VALIDATE\s+CONSTRAINT\b/i,z(String.raw`^(?:ALTER\s+(?:COLUMN\s+)?${fe}\s+)?SET\s+STATISTICS\b`),z(String.raw`^(?:ALTER\s+(?:COLUMN\s+)?${fe}\s+)?(?:SET|RESET)\s*\(`),/^CLUSTER\s+ON\b/i,/^SET\s+WITHOUT\s+CLUSTER\b/i];function Wo(t,e,n){let s=null,r=[];for(let o of zn(e,!1,",")){let a,i="ACCESS EXCLUSIVE";z(String.raw`^ADD\s+(?:CONSTRAINT\s+${fe}\s+)?FOREIGN\s+KEY\b`).test(o)||/^(?:ENABLE|DISABLE)\s+(?:REPLICA\s+|ALWAYS\s+)?TRIGGER\b/i.test(o)?i="SHARE ROW EXCLUSIVE":Bo.some(c=>c.test(o))?i=null:(a=z(String.raw`^ATTACH\s+PARTITION\s+(${me})`).exec(o))?(i=null,r.push({of:"relation",name:pe(a[1]),mode:"ACCESS EXCLUSIVE"})):(a=z(String.raw`^DETACH\s+PARTITION\s+(${me})`).exec(o))?r.push({of:"relation",name:pe(a[1]),mode:"ACCESS EXCLUSIVE"}):(a=z(String.raw`^DROP\s+CONSTRAINT\s+(?:IF\s+EXISTS\s+)?(${fe})`).exec(o))?r.push({of:"constraint",table:t,name:Gs(a[1])}):(a=z(String.raw`^DROP\s+(?:COLUMN\s+)?(?:IF\s+EXISTS\s+)?(${fe})`).exec(o))&&r.push({of:"column",table:t,name:Gs(a[1])});for(let c of Js(o))r.push({of:"relation",name:c,mode:"SHARE ROW EXCLUSIVE"});i!==null&&(s===null||Le[i]>Le[s])&&(s=i)}s!==null&&n.needs.push({of:"relation",name:t,mode:s}),n.needs.push(...r)}function Js(t){return[...t.matchAll(new RegExp(String.raw`\bREFERENCES\s+(${me})`,"gi"))].map(e=>pe(e[1]))}function Jn(t){return zn(t,!1,",").map(e=>z(String.raw`^(?:ONLY\s+)?(${me})\s*\*?$`).exec(e)?.[1]).filter(e=>e!==void 0).map(pe)}async function zs(t,e){if(e.length===0)return[];let n=e.map((c,l)=>c.of==="relation"?{i:l,of:c.of,rel:c.name,mode:c.mode}:c.of==="constraint"||c.of==="column"?{i:l,of:c.of,rel:c.table,name:c.name}:{i:l,of:c.of,rel:c.name}),s=await t(`WITH r AS (SELECT n.*, to_regclass(n.rel)::oid AS oid FROM jsonb_to_recordset(${M(JSON.stringify(n))}::jsonb) AS n(i int, "of" text, rel text, name text, mode text)),
206
+ ORDER BY 1`);for(let f of p)s.push(`sequence ${f.name} (owned by no column) \u2014 kept as it is`);let E=(await t("SELECT extname AS name FROM pg_catalog.pg_extension WHERE extname <> 'plpgsql' ORDER BY 1")).map(f=>f.name),$=await dr(t,a,new Set(c.map(f=>`${f.schema}.${f.name}`)),o);return{schema:{tables:c,enums:m,extensions:E,raw:[]},unmanaged:s,forced:r,objects:o,units:$}}finally{await t("ROLLBACK")}}var Ie={SHARE:1,"SHARE ROW EXCLUSIVE":2,"ACCESS EXCLUSIVE":3},ge=String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)`,pe=String.raw`${ge}(?:\s*\.\s*${ge}){0,2}`,z=t=>new RegExp(t,"i");function pr(t){let e={needs:[],made:[]};for(let n of t)for(let s of lt(n))fr(s,e);return e}function mr(t){return t.startsWith('"')?t.slice(1,-1).replace(/""/g,'"'):t.toLowerCase()}var fe=t=>[...t.matchAll(new RegExp(ge,"g"))].map(e=>e[0]).join("."),ia=z(String.raw`\b(?:ALTER\s+TABLE|DROP\s+TABLE|CREATE\s+(?:OR\s+REPLACE\s+)?(?:CONSTRAINT\s+)?TRIGGER|DROP\s+TRIGGER|(?:CREATE|ALTER|DROP)\s+POLICY|CREATE\s+(?:UNIQUE\s+)?INDEX|DROP\s+INDEX|CREATE\s+(?:OR\s+REPLACE\s+)?RULE|DROP\s+RULE|TRUNCATE|CREATE\s+(?:UNLOGGED\s+|TEMP(?:ORARY)?\s+)?TABLE|DROP\s+VIEW|CREATE\s+OR\s+REPLACE\s+VIEW|ALTER\s+VIEW)\b`);function fr(t,e){let n;if(n=/^DO\s+(?:LANGUAGE\s+\w+\s+)?(\$[A-Za-z_0-9]*\$)([\s\S]*?)\1/i.exec(t)){for(let s of lt(n[2],!0)){let r=ia.exec(s);r&&fr(s.slice(r.index),e)}return}if(n=z(String.raw`^ALTER\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:ONLY\s+)?(${pe})\s*\*?\s*([\s\S]*)$`).exec(t))return ca(fe(n[1]),n[2],e);if(n=z(String.raw`^DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of it(n[1]))e.needs.push({of:"relation",name:s,mode:"ACCESS EXCLUSIVE"},{of:"table",name:s});return}if(n=z(String.raw`^DROP\s+VIEW\s+(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of it(n[1]))e.needs.push({of:"view",name:s});return}if(n=z(String.raw`^(?:CREATE\s+OR\s+REPLACE\s+(?:(?:TEMP|TEMPORARY)\s+)?(?:RECURSIVE\s+)?VIEW|ALTER\s+VIEW\s+(?:IF\s+EXISTS\s+)?)\s*(${pe})`).exec(t)){e.needs.push({of:"view",name:fe(n[1])});return}if(n=z(String.raw`^CREATE\s+(?:OR\s+REPLACE\s+)?(?:CONSTRAINT\s+)?TRIGGER\s+${ge}\s+[\s\S]*?\bON\s+(?:ONLY\s+)?(${pe})`).exec(t)){e.needs.push({of:"relation",name:fe(n[1]),mode:"SHARE ROW EXCLUSIVE"});return}if(n=z(String.raw`^(?:DROP\s+TRIGGER|(?:CREATE|ALTER|DROP)\s+POLICY|DROP\s+RULE)\s+(?:IF\s+EXISTS\s+)?${ge}\s+ON\s+(${pe})`).exec(t)){e.needs.push({of:"relation",name:fe(n[1]),mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:OR\s+REPLACE\s+)?RULE\s+${ge}\s+AS\s+ON\s+\w+\s+TO\s+(${pe})`).exec(t)){e.needs.push({of:"relation",name:fe(n[1]),mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:UNIQUE\s+)?INDEX\s+(?!CONCURRENTLY\b)(?:IF\s+NOT\s+EXISTS\s+)?(?:${ge}\s+)?ON\s+(?:ONLY\s+)?(${pe})`).exec(t)){e.needs.push({of:"relation",name:fe(n[1]),mode:"SHARE"});return}if(n=z(String.raw`^DROP\s+INDEX\s+(?!CONCURRENTLY\b)(?:IF\s+EXISTS\s+)?([\s\S]*?)(?:\s+(?:CASCADE|RESTRICT))?\s*$`).exec(t)){for(let s of it(n[1]))e.needs.push({of:"index",name:s});return}if(n=z(String.raw`^TRUNCATE\s+(?:TABLE\s+)?([\s\S]*?)(?:\s+(?:RESTART|CONTINUE|CASCADE|RESTRICT)\b[\s\S]*)?$`).exec(t)){for(let s of it(n[1]))e.needs.push({of:"relation",name:s,mode:"ACCESS EXCLUSIVE"});return}if(n=z(String.raw`^CREATE\s+(?:(?:GLOBAL|LOCAL)\s+)?(?:TEMP(?:ORARY)?\s+|UNLOGGED\s+)?TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(${pe})([\s\S]*)$`).exec(t)){e.made.push(fe(n[1]));let s=z(String.raw`^\s*PARTITION\s+OF\s+(${pe})`).exec(n[2]);s&&e.needs.push({of:"relation",name:fe(s[1]),mode:"ACCESS EXCLUSIVE"});for(let r of gr(n[2]))e.needs.push({of:"relation",name:r,mode:"SHARE ROW EXCLUSIVE"})}}var la=[/^VALIDATE\s+CONSTRAINT\b/i,z(String.raw`^(?:ALTER\s+(?:COLUMN\s+)?${ge}\s+)?SET\s+STATISTICS\b`),z(String.raw`^(?:ALTER\s+(?:COLUMN\s+)?${ge}\s+)?(?:SET|RESET)\s*\(`),/^CLUSTER\s+ON\b/i,/^SET\s+WITHOUT\s+CLUSTER\b/i];function ca(t,e,n){let s=null,r=[];for(let o of lt(e,!1,",")){let a,i="ACCESS EXCLUSIVE";z(String.raw`^ADD\s+(?:CONSTRAINT\s+${ge}\s+)?FOREIGN\s+KEY\b`).test(o)||/^(?:ENABLE|DISABLE)\s+(?:REPLICA\s+|ALWAYS\s+)?TRIGGER\b/i.test(o)?i="SHARE ROW EXCLUSIVE":la.some(c=>c.test(o))?i=null:(a=z(String.raw`^ATTACH\s+PARTITION\s+(${pe})`).exec(o))?(i=null,r.push({of:"relation",name:fe(a[1]),mode:"ACCESS EXCLUSIVE"})):(a=z(String.raw`^DETACH\s+PARTITION\s+(${pe})`).exec(o))?r.push({of:"relation",name:fe(a[1]),mode:"ACCESS EXCLUSIVE"}):(a=z(String.raw`^DROP\s+CONSTRAINT\s+(?:IF\s+EXISTS\s+)?(${ge})`).exec(o))?r.push({of:"constraint",table:t,name:mr(a[1])}):(a=z(String.raw`^DROP\s+(?:COLUMN\s+)?(?:IF\s+EXISTS\s+)?(${ge})`).exec(o))&&r.push({of:"column",table:t,name:mr(a[1])});for(let c of gr(o))r.push({of:"relation",name:c,mode:"SHARE ROW EXCLUSIVE"});i!==null&&(s===null||Ie[i]>Ie[s])&&(s=i)}s!==null&&n.needs.push({of:"relation",name:t,mode:s}),n.needs.push(...r)}function gr(t){return[...t.matchAll(new RegExp(String.raw`\bREFERENCES\s+(${pe})`,"gi"))].map(e=>fe(e[1]))}function it(t){return lt(t,!1,",").map(e=>z(String.raw`^(?:ONLY\s+)?(${pe})\s*\*?$`).exec(e)?.[1]).filter(e=>e!==void 0).map(fe)}async function hr(t,e){if(e.length===0)return[];let n=e.map((c,l)=>c.of==="relation"?{i:l,of:c.of,rel:c.name,mode:c.mode}:c.of==="constraint"||c.of==="column"?{i:l,of:c.of,rel:c.table,name:c.name}:{i:l,of:c.of,rel:c.name}),s=await t(`WITH r AS (SELECT n.*, to_regclass(n.rel)::oid AS oid FROM jsonb_to_recordset(${M(JSON.stringify(n))}::jsonb) AS n(i int, "of" text, rel text, name text, mode text)),
207
207
  got AS (
208
208
  SELECT r.i, r.oid AS rel, r.mode FROM r WHERE r.of IN ('relation', 'view') AND r.oid IS NOT NULL
209
209
  UNION ALL
@@ -224,18 +224,18 @@ END $palgres$`,`CREATE TRIGGER ${h} BEFORE INSERT OR UPDATE ON ${n} FOR EACH ROW
224
224
  FROM got g JOIN pg_catalog.pg_class k ON k.oid = g.rel
225
225
  WHERE k.relkind IN ('r', 'p', 'v')
226
226
  AND (pg_catalog.pg_has_role(k.relowner, 'USAGE') OR pg_catalog.has_table_privilege(g.rel, 'UPDATE, DELETE, TRUNCATE, MAINTAIN'))
227
- ORDER BY g.i`),r=new Map,o=new Map;for(let c of s){let l=String(c.oid),u=c.mode;if(c.kind==="v"){o.has(l)||o.set(l,{lock:{oid:l,name:String(c.name),mode:"ACCESS EXCLUSIVE"},reads:c.reads.map(String)});continue}let g=r.get(l);g?Le[u]>Le[g.mode]&&(g.mode=u):r.set(l,{oid:l,name:String(c.name),mode:u})}let a=c=>r.get(c)?.mode==="ACCESS EXCLUSIVE";return[...[...o.values()].filter(c=>c.reads.length>0&&c.reads.every(a)).map(c=>c.lock),...r.values()]}async function Qs(t,e,n){if(e.length===0)return new Set;let s=e.map(o=>`(${M(o.oid)}::oid, ${M(o.mode)})`).join(", "),r=await t(`SELECT DISTINCT h.relation::text AS oid
227
+ ORDER BY g.i`),r=new Map,o=new Map;for(let c of s){let l=String(c.oid),u=c.mode;if(c.kind==="v"){o.has(l)||o.set(l,{lock:{oid:l,name:String(c.name),mode:"ACCESS EXCLUSIVE"},reads:c.reads.map(String)});continue}let g=r.get(l);g?Ie[u]>Ie[g.mode]&&(g.mode=u):r.set(l,{oid:l,name:String(c.name),mode:u})}let a=c=>r.get(c)?.mode==="ACCESS EXCLUSIVE";return[...[...o.values()].filter(c=>c.reads.length>0&&c.reads.every(a)).map(c=>c.lock),...r.values()]}async function Er(t,e,n){if(e.length===0)return new Set;let s=e.map(o=>`(${M(o.oid)}::oid, ${M(o.mode)})`).join(", "),r=await t(`SELECT DISTINCT h.relation::text AS oid
228
228
  FROM pg_catalog.pg_locks h JOIN (VALUES ${s}) AS want(rel, mode) ON want.rel = h.relation
229
229
  JOIN pg_catalog.pg_locks w ON w.pid = h.pid AND NOT w.granted
230
230
  WHERE h.locktype = 'relation' AND h.granted AND h.pid <> pg_backend_pid()
231
231
  AND (want.mode = 'ACCESS EXCLUSIVE' OR h.mode NOT IN ('AccessShareLock', 'RowShareLock'))
232
- AND w.waitstart < clock_timestamp() - make_interval(secs => ${Math.max(0,n)/1e3})`);return new Set(r.map(o=>String(o.oid)))}var jo={ShareLock:"SHARE",ShareRowExclusiveLock:"SHARE ROW EXCLUSIVE",ExclusiveLock:"ACCESS EXCLUSIVE",AccessExclusiveLock:"ACCESS EXCLUSIVE"};async function Zs(t,e){let n=e.length===0?"":`AND l.relation NOT IN (SELECT o FROM unnest(ARRAY[${e.map(o=>`to_regclass(${M(o)})::oid`).join(", ")}]) AS o WHERE o IS NOT NULL)`,s=await t(`SELECT l.relation::text AS oid, l.relation::regclass::text AS name, l.mode
232
+ AND w.waitstart < clock_timestamp() - make_interval(secs => ${Math.max(0,n)/1e3})`);return new Set(r.map(o=>String(o.oid)))}var ua={ShareLock:"SHARE",ShareRowExclusiveLock:"SHARE ROW EXCLUSIVE",ExclusiveLock:"ACCESS EXCLUSIVE",AccessExclusiveLock:"ACCESS EXCLUSIVE"};async function yr(t,e){let n=e.length===0?"":`AND l.relation NOT IN (SELECT o FROM unnest(ARRAY[${e.map(o=>`to_regclass(${M(o)})::oid`).join(", ")}]) AS o WHERE o IS NOT NULL)`,s=await t(`SELECT l.relation::text AS oid, l.relation::regclass::text AS name, l.mode
233
233
  FROM pg_catalog.pg_locks l JOIN pg_catalog.pg_class c ON c.oid = l.relation
234
234
  WHERE l.pid = pg_backend_pid() AND l.locktype = 'relation' AND l.granted AND c.relkind IN ('r', 'p')
235
- AND l.mode IN ('ShareLock', 'ShareRowExclusiveLock', 'ExclusiveLock', 'AccessExclusiveLock') ${n}`),r=new Map;for(let o of s){let a=String(o.oid),i=jo[String(o.mode)],c=r.get(a);c?Le[i]>Le[c.mode]&&(c.mode=i):r.set(a,{oid:a,name:String(o.name),mode:i})}return[...r.values()]}function zn(t,e=!1,n=";"){let s=[],r="",o=0,a=0,i=t.length;for(;a<i;){let c=t[a];if(c==="-"&&t[a+1]==="-"){for(;a<i&&t[a]!==`
236
- `;)a++;r+=" ";continue}if(c==="/"&&t[a+1]==="*"){let l=0;do t[a]==="/"&&t[a+1]==="*"?(l++,a+=2):t[a]==="*"&&t[a+1]==="/"?(l--,a+=2):a++;while(a<i&&l>0);r+=" ";continue}if(c==="'"){let l=/[Ee]/.test(t[a-1]??"")&&!/[A-Za-z0-9_$]/.test(t[a-2]??""),u=a+1;for(;u<i;)if(l&&t[u]==="\\")u+=2;else if(t[u]==="'"&&t[u+1]==="'")u+=2;else{if(t[u]==="'")break;u++}r+=e?`'${" ".repeat(Math.max(0,u-a-1))}'`:t.slice(a,u+1),a=u+1;continue}if(c==='"'){let l=a+1;for(;l<i&&!(t[l]==='"'&&t[l+1]!=='"');)l+=t[l]==='"'?2:1;r+=t.slice(a,l+1),a=l+1;continue}if(c==="$"&&!/[A-Za-z0-9_$]/.test(t[a-1]??"")){let l=/^\$[A-Za-z_][A-Za-z0-9_]*\$|^\$\$/.exec(t.slice(a));if(l){let u=t.indexOf(l[0],a+l[0].length),g=u<0?i:u+l[0].length;r+=t.slice(a,g),a=g;continue}}if(c==="("?o++:c===")"&&o--,c===n&&o===0){r.trim()&&s.push(r.trim()),r="",a++;continue}r+=c,a++}return r.trim()&&s.push(r.trim()),s}var $e=class extends Error{refusals;constructor(e){super(`palgres: the migration is refused:
235
+ AND l.mode IN ('ShareLock', 'ShareRowExclusiveLock', 'ExclusiveLock', 'AccessExclusiveLock') ${n}`),r=new Map;for(let o of s){let a=String(o.oid),i=ua[String(o.mode)],c=r.get(a);c?Ie[i]>Ie[c.mode]&&(c.mode=i):r.set(a,{oid:a,name:String(o.name),mode:i})}return[...r.values()]}function lt(t,e=!1,n=";"){let s=[],r="",o=0,a=0,i=t.length;for(;a<i;){let c=t[a];if(c==="-"&&t[a+1]==="-"){for(;a<i&&t[a]!==`
236
+ `;)a++;r+=" ";continue}if(c==="/"&&t[a+1]==="*"){let l=0;do t[a]==="/"&&t[a+1]==="*"?(l++,a+=2):t[a]==="*"&&t[a+1]==="/"?(l--,a+=2):a++;while(a<i&&l>0);r+=" ";continue}if(c==="'"){let l=/[Ee]/.test(t[a-1]??"")&&!/[A-Za-z0-9_$]/.test(t[a-2]??""),u=a+1;for(;u<i;)if(l&&t[u]==="\\")u+=2;else if(t[u]==="'"&&t[u+1]==="'")u+=2;else{if(t[u]==="'")break;u++}r+=e?`'${" ".repeat(Math.max(0,u-a-1))}'`:t.slice(a,u+1),a=u+1;continue}if(c==='"'){let l=a+1;for(;l<i&&!(t[l]==='"'&&t[l+1]!=='"');)l+=t[l]==='"'?2:1;r+=t.slice(a,l+1),a=l+1;continue}if(c==="$"&&!/[A-Za-z0-9_$]/.test(t[a-1]??"")){let l=/^\$[A-Za-z_][A-Za-z0-9_]*\$|^\$\$/.exec(t.slice(a));if(l){let u=t.indexOf(l[0],a+l[0].length),g=u<0?i:u+l[0].length;r+=t.slice(a,g),a=g;continue}}if(c==="("?o++:c===")"&&o--,c===n&&o===0){r.trim()&&s.push(r.trim()),r="",a++;continue}r+=c,a++}return r.trim()&&s.push(r.trim()),s}var he=class extends Error{refusals;constructor(e){super(`palgres: the migration is refused:
237
237
  - ${e.join(`
238
- - `)}`),this.name="MigrationRefused",this.refusals=e}},pn=class extends Error{from;to;openedBy;constructor(e,n,s=null){super(`palgres: the migration from version ${e??"none"} to ${n}${s?`, opened by ${s},`:""} is still open: complete it or roll it back first`),this.name="MigrationOpen",this.from=e,this.to=n,this.openedBy=s}},fn=class extends Error{version;constructor(e,n,s){super(`palgres: ${n} connection(s) of version ${e} are still open after ${s} ms`),this.name="VersionStillConnected",this.version=e}},Ct=1e4,er=`CREATE OR REPLACE FUNCTION palgres.defer_keys(keys text[], deferred boolean) RETURNS void
238
+ - `)}`),this.name="MigrationRefused",this.refusals=e}},$n=class extends Error{from;to;openedBy;constructor(e,n,s=null){super(`palgres: the migration from version ${e??"none"} to ${n}${s?`, opened by ${s},`:""} is still open: complete it or roll it back first`),this.name="MigrationOpen",this.from=e,this.to=n,this.openedBy=s}},Sn=class extends Error{version;constructor(e,n,s){super(`palgres: ${n} connection(s) of version ${e} are still open after ${s} ms`),this.name="VersionStillConnected",this.version=e}},Ht=1e4,wr=`CREATE OR REPLACE FUNCTION palgres.defer_keys(keys text[], deferred boolean) RETURNS void
239
239
  LANGUAGE plpgsql SET search_path = pg_catalog, pg_temp AS $palgres$
240
240
  DECLARE
241
241
  named text;
@@ -246,26 +246,26 @@ BEGIN
246
246
  IF named IS NOT NULL THEN
247
247
  EXECUTE 'SET CONSTRAINTS ' || named || CASE WHEN deferred THEN ' DEFERRED' ELSE ' IMMEDIATE' END;
248
248
  END IF;
249
- END $palgres$`,mn=class extends Error{constructor(e,n){super(`palgres: ${e} was not had in the step's time`,{cause:n}),this.name="LockNotHad"}},gn=class extends Error{constructor(e,n){super(`palgres: rows of ${e} to fill were held by writers through ${n} passes`),this.name="RowsHeld"}},Ho=new Set(["55P03","40P01","40001","57014","25006"]);function Vo(t){if(ue(t)!==void 0)return!0;let e=t;for(let n=0;n<4&&typeof e=="object"&&e!==null;n++){if(e instanceof fn||e instanceof gn)return!0;let s=ae(e);if(s!==void 0)return Ho.has(s)||s.startsWith("53");e=e.cause}return!1}var Je={anon:"anon",authenticated:"authenticated",service:"service_role"},Qn=t=>`palgres:v${t}`,nr="palgres.migrate",Dt=class t{pool;roles;openedBy;lockTimeoutMs;statementWaitMs;lockTimeoutFor(e){return e>=3?Math.max(this.lockTimeoutMs,1500):this.lockTimeoutMs}attempts;batchSize;disconnectTimeoutMs;log;shadow;constructor(e,n={}){this.pool=e,this.roles={...Je,...n.roles},this.lockTimeoutMs=n.lockTimeoutMs??500,this.statementWaitMs=n.statementWaitMs??6e5,this.attempts=n.attempts??10,this.batchSize=n.batchSize??1e3,this.disconnectTimeoutMs=n.disconnectTimeoutMs??6e4,this.log=n.log??(()=>{}),this.shadow=n.shadow,this.openedBy=n.openedBy??"deploy"}async status(){return this.session(async e=>{let n=await this.active(e),s=await this.open(e);return{active:n&&{n:n.n,digest:n.digest,state:"active"},open:s&&{from:s.from_n,to:s.to_n,phase:s.phase,opened_by:s.opened_by}}},!1)}async plan(e){tr(e);let n=Pe(e),s=async(r,o)=>{let a;try{a=await this.adopt(r,e)}catch(l){if(!(l instanceof $e))throw l;return{from:null,to:1,changes:[],refusals:l.refusals,start:[],complete:[],rollback:[],layout:{tables:[]}}}let i=o?[]:await this.authRefusals(r);if(!a){let l=await this.planFrom(r,null,e);return{...l,refusals:[...i,...l.refusals]}}if(a.version.digest===n)return{from:null,to:a.version.n,changes:[],refusals:i,start:[],complete:[],rollback:[],layout:a.layout,adoption:a.adoption};let c=await this.planFrom(r,a.version,e);return{...c,refusals:[...i,...c.refusals],adoption:a.adoption}};return this.session(async r=>{let o=await this.active(r);return o?this.planFrom(r,o,e):s(r,!0)},!1,r=>s(r,!1))}async start(e){tr(e);let n=Pe(e);return this.session(async s=>{let r=await this.open(s);if(r){if((await this.version(s,r.to_n))?.digest!==n)throw new pn(r.from_n,r.to_n,r.opened_by);if(r.phase==="started")return{state:"resumed",from:r.from_n,to:r.to_n,changes:r.plan.changes,completed:!1};if(r.phase!=="starting")throw new pn(r.from_n,r.to_n);return this.log(`palgres: resuming the start of version ${r.to_n}`),await this.runStart(s,r),{state:"resumed",from:r.from_n,to:r.to_n,changes:r.plan.changes,completed:!1}}let o=await this.active(s);if(o?.digest===n)return{state:"in-sync",version:o.n};let a=o?null:await this.adopt(s,e),i=async()=>{s.ledger===!1&&(await this.ownAuth(s),await this.ensure(s),s.ledger=!0)};if(a){if(a.version.digest===n)return await i(),await a.record(),{state:"adopted",version:a.version.n,adoption:a.adoption};o=a.version}let c=a?.adoption,l=await this.planFrom(s,o,e);if(l.refusals.length>0)throw new $e(l.refusals);await i(),await a?.record(),await this.tx(s,["ALTER TABLE palgres.migration ADD COLUMN IF NOT EXISTS opened_by text",er,`INSERT INTO palgres.versions (n, digest, schema, layout, state, direct) VALUES (${l.to}, ${M(n)}, ${M(JSON.stringify(fs(e)))}::jsonb, ${M(JSON.stringify(l.layout))}::jsonb, 'starting', ${rr(l.layout)})`,`INSERT INTO palgres.migration (from_n, to_n, plan, phase, opened_by) VALUES (${l.from??"NULL"}, ${l.to}, ${M(JSON.stringify(l))}::jsonb, 'starting', ${M(this.openedBy)})`]),this.log(`palgres: version ${l.from??"none"} \u2192 ${l.to}:
249
+ END $palgres$`,Tn=class extends Error{constructor(e,n){super(`palgres: ${e} was not had in the step's time`,{cause:n}),this.name="LockNotHad"}},en=class extends Error{constructor(e,n){super(`palgres: rows of ${e} to fill were held by writers through ${n} passes`),this.name="RowsHeld"}},ma=new Set(["55P03","40P01","40001","57014","25006"]);function pa(t){if(ue(t)!==void 0)return!0;let e=t;for(let n=0;n<4&&typeof e=="object"&&e!==null;n++){if(e instanceof Sn||e instanceof en)return!0;let s=ae(e);if(s!==void 0)return ma.has(s)||s.startsWith("53");e=e.cause}return!1}var nn={anon:"anon",authenticated:"authenticated",service:"service_role"},ct=t=>`palgres:v${t}`,Tr="palgres.migrate",Gt=class t{pool;roles;openedBy;lockTimeoutMs;statementWaitMs;lockTimeoutFor(e){return e>=3?Math.max(this.lockTimeoutMs,1500):this.lockTimeoutMs}attempts;batchSize;disconnectTimeoutMs;log;shadow;fieldsSource;fields;constructor(e,n={}){this.fieldsSource=n.fields,this.pool=e,this.roles={...nn,...n.roles},this.lockTimeoutMs=n.lockTimeoutMs??500,this.statementWaitMs=n.statementWaitMs??6e5,this.attempts=n.attempts??10,this.batchSize=n.batchSize??1e3,this.disconnectTimeoutMs=n.disconnectTimeoutMs??6e4,this.log=n.log??(()=>{}),this.shadow=n.shadow,this.openedBy=n.openedBy??"deploy"}async status(){return this.session(async e=>{let n=await this.active(e),s=await this.open(e);return{active:n&&{n:n.n,digest:n.digest,state:"active"},open:s&&{from:s.from_n,to:s.to_n,phase:s.phase,opened_by:s.opened_by}}},!1)}async plan(e){$r(e);let n=qe(e),s=async(r,o)=>{let a;try{a=await this.adopt(r,e)}catch(l){if(!(l instanceof he))throw l;return{from:null,to:1,changes:[],refusals:l.refusals,start:[],complete:[],rollback:[],layout:{tables:[]}}}let i=o?[]:await this.authRefusals(r);if(!a){let l=await this.planFrom(r,null,e);return{...l,refusals:[...i,...l.refusals]}}if(a.version.digest===n)return{from:null,to:a.version.n,changes:[],refusals:i,start:[],complete:[],rollback:[],layout:a.layout,adoption:a.adoption};let c=await this.planFrom(r,a.version,e);return{...c,refusals:[...i,...c.refusals],adoption:a.adoption}};return this.session(async r=>{let o=await this.active(r);return o?this.planFrom(r,o,e):s(r,!0)},!1,r=>s(r,!1))}async start(e){$r(e);let n=qe(e);return this.session(async s=>{let r=await this.open(s);if(r){if((await this.version(s,r.to_n))?.digest!==n)throw new $n(r.from_n,r.to_n,r.opened_by);if(r.phase==="started")return{state:"resumed",from:r.from_n,to:r.to_n,changes:r.plan.changes,completed:!1};if(r.phase!=="starting")throw new $n(r.from_n,r.to_n);return this.log(`palgres: resuming the start of version ${r.to_n}`),await this.runStart(s,r),{state:"resumed",from:r.from_n,to:r.to_n,changes:r.plan.changes,completed:!1}}let o=await this.active(s);if(o?.digest===n)return{state:"in-sync",version:o.n};let a=o?null:await this.adopt(s,e),i=async()=>{s.ledger===!1&&(await this.ownAuth(s),await this.ensure(s),s.ledger=!0)};if(a){if(a.version.digest===n)return await i(),await a.record(),{state:"adopted",version:a.version.n,adoption:a.adoption};o=a.version}let c=a?.adoption,l=await this.planFrom(s,o,e);if(l.refusals.length>0)throw new he(l.refusals);await this.cipherFor(l),await i(),await a?.record(),await this.tx(s,["ALTER TABLE palgres.migration ADD COLUMN IF NOT EXISTS opened_by text",wr,`INSERT INTO palgres.versions (n, digest, schema, layout, state, direct) VALUES (${l.to}, ${M(n)}, ${M(JSON.stringify(Is(e)))}::jsonb, ${M(JSON.stringify(l.layout))}::jsonb, 'starting', ${br(l.layout)})`,`INSERT INTO palgres.migration (from_n, to_n, plan, phase, opened_by) VALUES (${l.from??"NULL"}, ${l.to}, ${M(JSON.stringify(l))}::jsonb, 'starting', ${M(this.openedBy)})`]),this.log(`palgres: version ${l.from??"none"} \u2192 ${l.to}:
250
250
  ${l.changes.join(`
251
- `)||"(no change but the views)"}`);let u={from_n:l.from,to_n:l.to,plan:l,done:{},phase:"starting",opened_by:this.openedBy};return await this.runStart(s,u),l.from===null?(await this.runComplete(s,{...u,phase:"started"}),{state:"started",from:null,to:l.to,changes:l.changes,completed:!0}):{state:"started",from:l.from,to:l.to,changes:l.changes,completed:!1,...c?{adoption:c}:{}}})}async complete(){return this.session(async e=>{let n=await this.open(e);if(!n)return{state:"none"};if(n.phase==="starting"||n.phase==="rolling_back")throw new Error(`palgres: version ${n.to_n} is ${n.phase==="starting"?"still starting: run start again to finish it":"being rolled back: run rollback again"}`);return n.from_n!==null&&await this.waitGone(e,n.from_n),await this.runComplete(e,n),{state:"completed",version:n.to_n}})}async rollback(){return this.session(async e=>{let n=await this.open(e);if(!n)return{state:"none"};if(n.phase==="completing")throw new Error(`palgres: version ${n.to_n} is completing: what the old version used is going; run complete again`);return await this.waitGone(e,n.to_n),n.phase!=="rolling_back"&&(await this.tx(e,["UPDATE palgres.migration SET phase = 'rolling_back', updated_at = now()"]),n.phase="rolling_back"),await this.runSteps(e,n,"rollback",[`UPDATE palgres.versions SET state = 'abandoned', retired_at = now() WHERE n = ${n.to_n}`,"DELETE FROM palgres.migration"]),this.log(`palgres: version ${n.to_n} rolled back; ${n.from_n??"no version"} serves`),{state:"rolled-back",version:n.from_n}})}async runStart(e,n){await this.runSteps(e,n,"start",[`UPDATE palgres.versions SET state = 'active', ready_at = now() WHERE n = ${n.to_n}`,"UPDATE palgres.migration SET phase = 'started', updated_at = now()"])}async runComplete(e,n){n.phase!=="completing"&&(await this.tx(e,["UPDATE palgres.migration SET phase = 'completing', updated_at = now()"]),n.phase="completing"),await this.runSteps(e,n,"complete",[...n.from_n!==null?[`UPDATE palgres.versions SET state = 'retired', retired_at = now() WHERE n = ${n.from_n}`]:[],`UPDATE palgres.versions SET direct = true WHERE n = ${n.to_n}`,"DELETE FROM palgres.migration"]),this.log(`palgres: version ${n.to_n} serves alone`)}async runSteps(e,n,s,r){let o=n.plan[s],a=n.done[s]??0;for(let i=a;i<o.length;i++){let c=o[i],l=`UPDATE palgres.migration SET done = done || ${M(JSON.stringify({[s]:i+1}))}::jsonb, updated_at = now()`,u=i===o.length-1;if(this.log(`palgres: ${s} ${i+1}/${o.length}: ${c.why}`),c.kind==="tx"){await this.tx(e,[...c.sql,...u?r:[l]]);continue}if(c.kind==="statement")await this.statement(e,c.sql);else if(c.kind==="backfill")await this.backfill(e,n,i,c);else throw new $e([`version ${n.to_n}'s migration has a step of a kind this Palgres does not run (${JSON.stringify(c.kind)})`]);await this.tx(e,u?r:[l])}o.length===0&&await this.tx(e,r)}async tx(e,n){let s=n.every(u=>/^(?:UPDATE|INSERT\s+INTO|DELETE\s+FROM)\s+palgres\./i.test(u)),{needs:r,made:o}=s?{needs:[],made:[]}:Xs(n),a=await zs(e.query,r),{holding:i,statementTimeout:c}=await this.settings(e),l=0;await this.retrying(e,async u=>{await e.query("BEGIN");try{let g=this.lockTimeoutFor(u);await e.query(`SET LOCAL lock_timeout = ${g}`);let p=Date.now()+i,h=m=>e.query(`SELECT set_config('lock_timeout', '${Math.max(1,Math.floor(m))}', true)`);if(!s&&a.length>0){let m=Date.now();p=m+i;let y=[a[l],...a.filter((f,d)=>d!==l)],S=new Set;for(let[f,d]of y.entries()){let T=Math.max(1,Math.floor(p-Date.now())),E=f>0&&(p-Date.now()<1||S.has(d.oid));f>0&&await e.query(`SELECT set_config('lock_timeout', '${T}', true), set_config('statement_timeout', '${T}', true)`);try{await e.query(`LOCK TABLE ${d.name} IN ${d.mode} MODE${E?" NOWAIT":""}`)}catch(w){let O=ae(w);throw(O==="55P03"||O==="57014")&&(l=a.indexOf(d),this.log(`palgres: ${d.name} is held by others (${d.mode} not had${E?" at once":` in ${f===0?g:T} ms`}): the step gives way`)),O==="57014"?new mn(d.name,w):w}f===0&&y.length>1&&(S=await Qs(e.query,y.slice(1),Date.now()-m))}await e.query(`SET LOCAL statement_timeout = ${M(c)}`)}for(let[m,y]of n.entries())!s&&a.length===0&&m===0?p=Date.now()+i:s||await h(p-Date.now()),await e.query(y);s||await this.notTakenFirst(e,a,o),await e.query("COMMIT")}catch(g){throw await e.query("ROLLBACK").catch(()=>{}),g}})}async settings(e){if(e.deadlockMs===void 0||e.statementTimeout===void 0){let[n]=await e.query("SELECT (SELECT setting::int FROM pg_catalog.pg_settings WHERE name = 'deadlock_timeout') AS ms, current_setting('statement_timeout') AS st");e.deadlockMs=Number(n?.ms??1e3),e.statementTimeout=String(n?.st??"0")}return{holding:Math.max(1,Math.min(this.lockTimeoutMs,Math.floor(e.deadlockMs/2))),statementTimeout:e.statementTimeout}}async notTakenFirst(e,n,s){for(let r of await Zs(e.query,s)){let o=n.find(a=>a.oid===r.oid);o&&Le[o.mode]>=Le[r.mode]||this.log(`palgres: ${r.name} was locked ${r.mode} by a statement, ${o?`more strongly than the step took it first (${o.mode})`:"not taken first"}`)}}async statement(e,n){let s=/^CREATE (?:UNIQUE )?INDEX CONCURRENTLY IF NOT EXISTS ("(?:[^"]|"")+") ON /.exec(n);await this.retrying(e,async()=>{if(s){let r=await e.query(`SELECT n.nspname AS schema FROM pg_index i JOIN pg_class c ON c.oid = i.indexrelid JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = ${M(sr(s[1]))} AND NOT i.indisvalid`);for(let o of r)await e.query(`DROP INDEX CONCURRENTLY IF EXISTS ${P(String(o.schema),sr(s[1]))}`)}await e.query(`SET lock_timeout = ${this.statementWaitMs}`);try{await e.query(n)}finally{await e.query("RESET lock_timeout")}})}async backfill(e,n,s,r){let{holding:o}=await this.settings(e),a=r.key.length>0,i=n.done.cursor?.step===s?n.done.cursor:void 0,c=i?.last??(a?null:0),l=i?.inclusive??!1,u=a?0:await this.pages(e,r.table),g=a?await this.highest(e,r):null,p=!1,h=i?.skippedFrom??null,m=h===null?[]:null,y=null,S=0,f=0,d=0;for(;;){let T=y?.splice(0,this.batchSize),E=T!==void 0,w=E?T.length===0:p?!1:a?g===null:Number(c)>=u,O;if(w||await this.retrying(e,async()=>{await e.query("BEGIN");try{await e.query(`SET LOCAL lock_timeout = ${o}`),await e.query("SET LOCAL statement_timeout = 30000");let N=(await e.query(a?this.keyedBatch(r,T??null,c,l,g,p):this.pageBatch(r,T??null,p?u:Number(c),p)))[0],A=N.left??[],R=E?!0:a?Number(N.seen)>0:!p,L={gone:Number(N.gone),seen:R,last:E||p&&!a?c:a?N.last??c:Number(c)+this.pagesPerBatch(),left:A},$=h??(A.length>0?a?A[0]:!0:y||T?a?T[0]??null:!0:null);await e.query(`UPDATE palgres.migration SET done = done || ${M(JSON.stringify({cursor:{step:s,last:L.last,inclusive:T?l:!1,skippedFrom:$}}))}::jsonb, updated_at = now()`),await e.query("COMMIT"),O=L}catch(N){throw await e.query("ROLLBACK").catch(()=>{}),N}}),O&&(S+=O.gone,f+=O.gone,E||(c=O.last,l=!1),O.left.length>0&&(h??=a?O.left[0]:!0,m!==null&&(m=m.length+O.left.length>Ct?null:[...m,...O.left])),O.seen))continue;if(!E&&!p){p=!0;continue}if(h===null)break;if(f>0)d=0;else if(++d>=this.attempts)throw new gn(r.table,d);let k=Math.min(250*2**Math.max(0,d-1),5e3);this.log(`palgres: ${m===null?"rows":`${m.length} row(s)`} of ${r.table} held by writers; gone over again in ${k} ms`),await new Promise(N=>setTimeout(N,k)),m!==null?y=m:a?(y=null,c=h,l=!0,g=await this.highest(e,r)):(y=null,c=0,u=await this.pages(e,r.table)),h=null,m=[],f=0,p=!1}this.log(`palgres: ${S} row(s)`)}async highest(e,n){let s=n.key.map(b).join(", ");return(await e.query(`SELECT (SELECT to_jsonb(x) FROM (SELECT ${s} FROM ${n.table} ORDER BY ${s} DESC LIMIT 1) x) AS k`))[0].k??null}pagesPerBatch(){return Math.max(1,Math.ceil(this.batchSize/50))}async pages(e,n){return Number((await e.query(`SELECT (pg_catalog.pg_relation_size(${M(n)}::regclass) / current_setting('block_size')::int)::int AS n`))[0].n)}keyedBatch(e,n,s,r,o,a){let i="_palgres_t",c=e.key.map(b).join(", "),l=e.key.map(f=>`${i}.${b(f)}`).join(", "),u=e.key.map((f,d)=>b(`_palgres_k${d}`)),g=e.key.map((f,d)=>`${i}.${b(f)} AS ${u[d]}`).join(", "),p=f=>e.key.map((d,T)=>`${f}.${u[T]} AS ${b(d)}`).join(", "),h=f=>`(SELECT ${c} FROM jsonb_populate_record(NULL::${e.table}, ${M(JSON.stringify(f))}::jsonb))`,m=s===null?"true":`(${l}) ${r?">=":">"} ${h(s)}`,y=n!==null?`(${l}) IN (SELECT ${c} FROM jsonb_populate_recordset(NULL::${e.table}, ${M(JSON.stringify(n))}::jsonb))`:a?`${m} AND (${e.where})`:`${m} AND (${l}) <= ${h(o)}`,S=n!==null?y:`${m} AND (${l}) <= (SELECT ${u.join(", ")} FROM edge)`;return`WITH win AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${y} ORDER BY ${l} LIMIT ${this.batchSize}),
251
+ `)||"(no change but the views)"}`);let u={from_n:l.from,to_n:l.to,plan:l,done:{},phase:"starting",opened_by:this.openedBy};return await this.runStart(s,u),l.from===null?(await this.runComplete(s,{...u,phase:"started"}),{state:"started",from:null,to:l.to,changes:l.changes,completed:!0}):{state:"started",from:l.from,to:l.to,changes:l.changes,completed:!1,...c?{adoption:c}:{}}})}async complete(){return this.session(async e=>{let n=await this.open(e);if(!n)return{state:"none"};if(n.phase==="starting"||n.phase==="rolling_back")throw new Error(`palgres: version ${n.to_n} is ${n.phase==="starting"?"still starting: run start again to finish it":"being rolled back: run rollback again"}`);return await this.cipherFor(n.plan),n.from_n!==null&&await this.waitGone(e,n.from_n),await this.runComplete(e,n),{state:"completed",version:n.to_n}})}async rollback(){return this.session(async e=>{let n=await this.open(e);if(!n)return{state:"none"};if(n.phase==="completing")throw new Error(`palgres: version ${n.to_n} is completing: what the old version used is going; run complete again`);return await this.cipherFor(n.plan),await this.waitGone(e,n.to_n),n.phase!=="rolling_back"&&(await this.tx(e,["UPDATE palgres.migration SET phase = 'rolling_back', updated_at = now()"]),n.phase="rolling_back"),await this.runSteps(e,n,"rollback",[`UPDATE palgres.versions SET state = 'abandoned', retired_at = now() WHERE n = ${n.to_n}`,"DELETE FROM palgres.migration"]),this.log(`palgres: version ${n.to_n} rolled back; ${n.from_n??"no version"} serves`),{state:"rolled-back",version:n.from_n}})}async runStart(e,n){await this.runSteps(e,n,"start",[`UPDATE palgres.versions SET state = 'active', ready_at = now() WHERE n = ${n.to_n}`,"UPDATE palgres.migration SET phase = 'started', updated_at = now()"])}async runComplete(e,n){n.phase!=="completing"&&(await this.tx(e,["UPDATE palgres.migration SET phase = 'completing', updated_at = now()"]),n.phase="completing"),await this.runSteps(e,n,"complete",[...n.from_n!==null?[`UPDATE palgres.versions SET state = 'retired', retired_at = now() WHERE n = ${n.from_n}`]:[],`UPDATE palgres.versions SET direct = true WHERE n = ${n.to_n}`,"DELETE FROM palgres.migration"]),this.log(`palgres: version ${n.to_n} serves alone`)}async runSteps(e,n,s,r){let o=n.plan[s],a=n.done[s]??0;for(let i=a;i<o.length;i++){let c=o[i],l=`UPDATE palgres.migration SET done = done || ${M(JSON.stringify({[s]:i+1}))}::jsonb, updated_at = now()`,u=i===o.length-1;if(this.log(`palgres: ${s} ${i+1}/${o.length}: ${c.why}`),c.kind==="tx"){await this.tx(e,[...c.sql,...u?r:[l]]);continue}if(c.kind==="statement")await this.statement(e,c.sql);else if(c.kind==="backfill")await this.backfill(e,n,i,c);else if(c.kind==="seal")await this.seal(e,c);else if(c.kind==="settle")await new Promise(g=>setTimeout(g,c.ms));else throw new he([`version ${n.to_n}'s migration has a step of a kind this Palgres does not run (${JSON.stringify(c.kind)})`]);await this.tx(e,u?r:[l])}o.length===0&&await this.tx(e,r)}async tx(e,n){let s=n.every(u=>/^(?:UPDATE|INSERT\s+INTO|DELETE\s+FROM)\s+palgres\./i.test(u)),{needs:r,made:o}=s?{needs:[],made:[]}:pr(n),a=await hr(e.query,r),{holding:i,statementTimeout:c}=await this.settings(e),l=0;await this.retrying(e,async u=>{await e.query("BEGIN");try{let g=this.lockTimeoutFor(u);await e.query(`SET LOCAL lock_timeout = ${g}`);let m=Date.now()+i,h=p=>e.query(`SELECT set_config('lock_timeout', '${Math.max(1,Math.floor(p))}', true)`);if(!s&&a.length>0){let p=Date.now();m=p+i;let E=[a[l],...a.filter((f,d)=>d!==l)],$=new Set;for(let[f,d]of E.entries()){let T=Math.max(1,Math.floor(m-Date.now())),y=f>0&&(m-Date.now()<1||$.has(d.oid));f>0&&await e.query(`SELECT set_config('lock_timeout', '${T}', true), set_config('statement_timeout', '${T}', true)`);try{await e.query(`LOCK TABLE ${d.name} IN ${d.mode} MODE${y?" NOWAIT":""}`)}catch(w){let O=ae(w);throw(O==="55P03"||O==="57014")&&(l=a.indexOf(d),this.log(`palgres: ${d.name} is held by others (${d.mode} not had${y?" at once":` in ${f===0?g:T} ms`}): the step gives way`)),O==="57014"?new Tn(d.name,w):w}f===0&&E.length>1&&($=await Er(e.query,E.slice(1),Date.now()-p))}await e.query(`SET LOCAL statement_timeout = ${M(c)}`)}for(let[p,E]of n.entries())!s&&a.length===0&&p===0?m=Date.now()+i:s||await h(m-Date.now()),await e.query(E);s||await this.notTakenFirst(e,a,o),await e.query("COMMIT")}catch(g){throw await e.query("ROLLBACK").catch(()=>{}),g}})}async settings(e){if(e.deadlockMs===void 0||e.statementTimeout===void 0){let[n]=await e.query("SELECT (SELECT setting::int FROM pg_catalog.pg_settings WHERE name = 'deadlock_timeout') AS ms, current_setting('statement_timeout') AS st");e.deadlockMs=Number(n?.ms??1e3),e.statementTimeout=String(n?.st??"0")}return{holding:Math.max(1,Math.min(this.lockTimeoutMs,Math.floor(e.deadlockMs/2))),statementTimeout:e.statementTimeout}}async notTakenFirst(e,n,s){for(let r of await yr(e.query,s)){let o=n.find(a=>a.oid===r.oid);o&&Ie[o.mode]>=Ie[r.mode]||this.log(`palgres: ${r.name} was locked ${r.mode} by a statement, ${o?`more strongly than the step took it first (${o.mode})`:"not taken first"}`)}}async statement(e,n){let s=/^CREATE (?:UNIQUE )?INDEX CONCURRENTLY IF NOT EXISTS ("(?:[^"]|"")+") ON /.exec(n);await this.retrying(e,async()=>{if(s){let r=await e.query(`SELECT n.nspname AS schema FROM pg_index i JOIN pg_class c ON c.oid = i.indexrelid JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = ${M(Sr(s[1]))} AND NOT i.indisvalid`);for(let o of r)await e.query(`DROP INDEX CONCURRENTLY IF EXISTS ${P(String(o.schema),Sr(s[1]))}`)}await e.query(`SET lock_timeout = ${this.statementWaitMs}`);try{await e.query(n)}finally{await e.query("RESET lock_timeout")}})}async backfill(e,n,s,r){let{holding:o}=await this.settings(e),a=r.key.length>0,i=n.done.cursor?.step===s?n.done.cursor:void 0,c=i?.last??(a?null:0),l=i?.inclusive??!1,u=a?0:await this.pages(e,r.table),g=a?await this.highest(e,r):null,m=!1,h=i?.skippedFrom??null,p=h===null?[]:null,E=null,$=0,f=0,d=0;for(;;){let T=E?.splice(0,this.batchSize),y=T!==void 0,w=y?T.length===0:m?!1:a?g===null:Number(c)>=u,O;if(w||await this.retrying(e,async()=>{await e.query("BEGIN");try{await e.query(`SET LOCAL lock_timeout = ${o}`),await e.query("SET LOCAL statement_timeout = 30000");let N=(await e.query(a?this.keyedBatch(r,T??null,c,l,g,m):this.pageBatch(r,T??null,m?u:Number(c),m)))[0],A=N.left??[],b=y?!0:a?Number(N.seen)>0:!m,L={gone:Number(N.gone),seen:b,last:y||m&&!a?c:a?N.last??c:Number(c)+this.pagesPerBatch(),left:A},S=h??(A.length>0?a?A[0]:!0:E||T?a?T[0]??null:!0:null);await e.query(`UPDATE palgres.migration SET done = done || ${M(JSON.stringify({cursor:{step:s,last:L.last,inclusive:T?l:!1,skippedFrom:S}}))}::jsonb, updated_at = now()`),await e.query("COMMIT"),O=L}catch(N){throw await e.query("ROLLBACK").catch(()=>{}),N}}),O&&($+=O.gone,f+=O.gone,y||(c=O.last,l=!1),O.left.length>0&&(h??=a?O.left[0]:!0,p!==null&&(p=p.length+O.left.length>Ht?null:[...p,...O.left])),O.seen))continue;if(!y&&!m){m=!0;continue}if(h===null)break;if(f>0)d=0;else if(++d>=this.attempts)throw new en(r.table,d);let k=Math.min(250*2**Math.max(0,d-1),5e3);this.log(`palgres: ${p===null?"rows":`${p.length} row(s)`} of ${r.table} held by writers; gone over again in ${k} ms`),await new Promise(N=>setTimeout(N,k)),p!==null?E=p:a?(E=null,c=h,l=!0,g=await this.highest(e,r)):(E=null,c=0,u=await this.pages(e,r.table)),h=null,p=[],f=0,m=!1}this.log(`palgres: ${$} row(s)`)}async highest(e,n){let s=n.key.map(R).join(", ");return(await e.query(`SELECT (SELECT to_jsonb(x) FROM (SELECT ${s} FROM ${n.table} ORDER BY ${s} DESC LIMIT 1) x) AS k`))[0].k??null}pagesPerBatch(){return Math.max(1,Math.ceil(this.batchSize/50))}async pages(e,n){return Number((await e.query(`SELECT (pg_catalog.pg_relation_size(${M(n)}::regclass) / current_setting('block_size')::int)::int AS n`))[0].n)}keyedBatch(e,n,s,r,o,a){let i="_palgres_t",c=e.key.map(R).join(", "),l=e.key.map(f=>`${i}.${R(f)}`).join(", "),u=e.key.map((f,d)=>R(`_palgres_k${d}`)),g=e.key.map((f,d)=>`${i}.${R(f)} AS ${u[d]}`).join(", "),m=f=>e.key.map((d,T)=>`${f}.${u[T]} AS ${R(d)}`).join(", "),h=f=>`(SELECT ${c} FROM jsonb_populate_record(NULL::${e.table}, ${M(JSON.stringify(f))}::jsonb))`,p=s===null?"true":`(${l}) ${r?">=":">"} ${h(s)}`,E=n!==null?`(${l}) IN (SELECT ${c} FROM jsonb_populate_recordset(NULL::${e.table}, ${M(JSON.stringify(n))}::jsonb))`:a?`${p} AND (${e.where})`:`${p} AND (${l}) <= ${h(o)}`,$=n!==null?E:`${p} AND (${l}) <= (SELECT ${u.join(", ")} FROM edge)`;return`WITH win AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${E} ORDER BY ${l} LIMIT ${this.batchSize}),
252
252
  edge AS (SELECT * FROM win ORDER BY ${u.join(" DESC, ")} DESC LIMIT 1),
253
- batch AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${S} AND (${e.where}) FOR NO KEY UPDATE OF ${i} SKIP LOCKED),
254
- done AS (UPDATE ${e.table} SET ${e.set} FROM batch WHERE (${e.key.map(f=>`${e.table}.${b(f)}`).join(", ")}) = (${u.map(f=>`batch.${f}`).join(", ")}) AND (${e.where}) RETURNING NOT (${e.where}) AS gone),
255
- left_ AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${S} AND (${e.where}) AND NOT EXISTS (SELECT 1 FROM batch b WHERE (${u.map(f=>`b.${f}`).join(", ")}) = (${l})))
253
+ batch AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${$} AND (${e.where}) FOR NO KEY UPDATE OF ${i} SKIP LOCKED),
254
+ done AS (UPDATE ${e.table} SET ${e.set} FROM batch WHERE (${e.key.map(f=>`${e.table}.${R(f)}`).join(", ")}) = (${u.map(f=>`batch.${f}`).join(", ")}) AND (${e.where}) RETURNING NOT (${e.where}) AS gone),
255
+ left_ AS (SELECT ${g} FROM ${e.table} ${i} WHERE ${$} AND (${e.where}) AND NOT EXISTS (SELECT 1 FROM batch b WHERE (${u.map(f=>`b.${f}`).join(", ")}) = (${l})))
256
256
  SELECT (SELECT count(*) FROM win)::int AS seen, (SELECT count(*) FROM done WHERE gone)::int AS gone,
257
- (SELECT to_jsonb(x) FROM (SELECT ${p("edge")} FROM edge) x) AS last,
258
- (SELECT jsonb_agg(to_jsonb(x)) FROM (SELECT ${p("left_")} FROM left_ ORDER BY ${u.join(", ")} LIMIT ${Ct+1}) x) AS left`}pageBatch(e,n,s,r){let o=n!==null?`ctid = ANY (${M(`{${n.map(a=>`"${String(a)}"`).join(",")}}`)}::tid[])`:r?`ctid >= '(${s},0)'::tid`:`ctid >= '(${s},0)'::tid AND ctid < '(${s+this.pagesPerBatch()},0)'::tid`;return`WITH batch AS (SELECT ctid AS c FROM ${e.table} WHERE ${o} AND (${e.where}) FOR NO KEY UPDATE SKIP LOCKED),
257
+ (SELECT to_jsonb(x) FROM (SELECT ${m("edge")} FROM edge) x) AS last,
258
+ (SELECT jsonb_agg(to_jsonb(x)) FROM (SELECT ${m("left_")} FROM left_ ORDER BY ${u.join(", ")} LIMIT ${Ht+1}) x) AS left`}pageBatch(e,n,s,r){let o=n!==null?`ctid = ANY (${M(`{${n.map(a=>`"${String(a)}"`).join(",")}}`)}::tid[])`:r?`ctid >= '(${s},0)'::tid`:`ctid >= '(${s},0)'::tid AND ctid < '(${s+this.pagesPerBatch()},0)'::tid`;return`WITH batch AS (SELECT ctid AS c FROM ${e.table} WHERE ${o} AND (${e.where}) FOR NO KEY UPDATE SKIP LOCKED),
259
259
  done AS (UPDATE ${e.table} SET ${e.set} WHERE ctid = ANY (ARRAY(SELECT c FROM batch)) AND (${e.where}) RETURNING NOT (${e.where}) AS gone),
260
260
  left_ AS (SELECT ctid AS c FROM ${e.table} WHERE ${o} AND (${e.where}) AND ctid <> ALL (ARRAY(SELECT c FROM batch)))
261
- SELECT (SELECT count(*) FROM done WHERE gone)::int AS gone, (SELECT array_agg(c::text) FROM (SELECT c FROM left_ LIMIT ${Ct+1}) x) AS left`}async retrying(e,n){for(let s=1;;s++)try{await n(s);return}catch(r){let o=r instanceof mn?"57014":ae(r);if(o!=="55P03"&&o!=="40P01"&&!(r instanceof mn)||s>=this.attempts)throw r;let a=Math.min(250*2**(s-1),5e3);this.log(`palgres: a lock was busy (${o}); again in ${a} ms`),await new Promise(i=>setTimeout(i,a))}}async waitGone(e,n){let s=Date.now()+this.disconnectTimeoutMs;for(;;){let r=await e.query(`SELECT count(*)::int AS n FROM pg_stat_activity WHERE application_name = ${M(Qn(n))} AND datname = current_database() AND pid <> pg_backend_pid()`),o=Number(r[0].n);if(o===0)return;if(Date.now()>=s)throw new fn(n,o,this.disconnectTimeoutMs);await new Promise(a=>setTimeout(a,500))}}async adopt(e,n){let s=[...new Set([...n.tables.map(h=>h.schema),...n.raw.flatMap(h=>h.schema?[h.schema]:[])])],r=await Yn(this.pool,s,this.roles);if(!n.tables.some(h=>r.schema.tables.some(m=>m.schema===h.schema&&(m.name===h.name||m.name===h.renamedFrom))))return null;if(!this.shadow)throw new Error("palgres: the database holds tables of the schema and no Palgres version: taking it over needs a shadow database (MigratorOptions.shadow) to read the schema as Postgres writes it");let a=await this.made(e,n,s,r),i=xt(r,a,n);if(i.refusals.length>0)throw new $e(i.refusals);let c=[this.roles.anon,this.roles.authenticated,this.roles.service].map(b).join(", "),l={tables:i.schema.tables.filter(h=>!h.ignored).map(h=>({schema:h.schema,name:h.name,physical:h.name,columns:h.columns.filter(m=>!m.ignored).map(m=>({name:m.name,physical:m.name}))}))},u=i.schema.tables.map(h=>P(h.schema,h.name)),g=Pe(i.schema),p=async()=>{await this.tx(e,[...i.unforce.map(h=>`ALTER TABLE ${P(h.slice(0,h.indexOf(".")),h.slice(h.indexOf(".")+1))} NO FORCE ROW LEVEL SECURITY`),...[...new Set(i.schema.tables.map(h=>h.schema))].map(h=>`GRANT USAGE ON SCHEMA ${b(h)} TO ${c}`),...u.map(h=>`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${h} TO ${c}`),`DO $palgres$ DECLARE s regclass; BEGIN
261
+ SELECT (SELECT count(*) FROM done WHERE gone)::int AS gone, (SELECT array_agg(c::text) FROM (SELECT c FROM left_ LIMIT ${Ht+1}) x) AS left`}async retrying(e,n){for(let s=1;;s++)try{await n(s);return}catch(r){let o=r instanceof Tn?"57014":ae(r);if(o!=="55P03"&&o!=="40P01"&&!(r instanceof Tn)||s>=this.attempts)throw r;let a=Math.min(250*2**(s-1),5e3);this.log(`palgres: a lock was busy (${o}); again in ${a} ms`),await new Promise(i=>setTimeout(i,a))}}async cipherFor(e){let n=[...new Set([...e.complete,...e.rollback].filter(s=>s.kind==="seal").map(s=>s.address))];if(!(n.length===0||this.fields!==void 0)){if(this.fieldsSource===void 0)throw new he([`${n.join(", ")} ${n.length===1?"becomes":"become"} encrypted or stop being while the table holds rows: the migration seals or opens the rows with the project's field keys \u2014 Migrator({ fields })`]);this.fields=await jn(this.fieldsSource)}}async seal(e,n){let s=this.fields;if(s===void 0)throw new he([`${n.address}'s rows are sealed or opened with the project's field keys \u2014 Migrator({ fields })`]);await this.waitBegunBefore(e,n.address);let{holding:r}=await this.settings(e);for(let o=1;;o++){let a=null,i=0;do await this.retrying(e,async()=>{await e.query("BEGIN");try{await e.query(`SET LOCAL lock_timeout = ${r}`),await e.query("SET LOCAL statement_timeout = 30000");let l=await Hn((u,g)=>e.query(u,g),n,s,a,this.batchSize);await e.query("COMMIT"),i+=l.done,a=l.last}catch(l){throw await e.query("ROLLBACK").catch(()=>{}),l}});while(a!==null);let c=await Js((l,u)=>e.query(l,u),n,s);if(this.log(`palgres: ${n.address}: pass ${o}, ${i} row(s) ${n.direction==="seal"?"sealed":"opened"}${c?", some written meanwhile":""}`),!c)return;if(o>=this.attempts)throw new en(n.table,o);await new Promise(l=>setTimeout(l,Math.min(250*2**(o-1),5e3)))}}async waitBegunBefore(e,n){let s=(await e.query("SELECT coalesce(array_agg(x)::text[], ARRAY[]::text[]) AS xids FROM pg_snapshot_xip(pg_current_snapshot()) AS x"))[0].xids,r=Date.now()+this.statementWaitMs;for(let o=s;o.length>0;){if(o=(await e.query("SELECT coalesce(array_agg(x::text), ARRAY[]::text[]) AS xids FROM unnest($1::xid8[]) AS x WHERE pg_xact_status(x) = 'in progress'",[`{${o.join(",")}}`]))[0].xids,o.length===0)return;if(Date.now()>=r)throw new Error(`palgres: ${n}: ${o.length} transaction(s) open when its phase turned final are still open after ${this.statementWaitMs} ms \u2014 run complete again`);await new Promise(i=>setTimeout(i,200))}}async waitGone(e,n){let s=Date.now()+this.disconnectTimeoutMs;for(;;){let r=await e.query(`SELECT count(*)::int AS n FROM pg_stat_activity WHERE application_name = ${M(ct(n))} AND datname = current_database() AND pid <> pg_backend_pid()`),o=Number(r[0].n);if(o===0)return;if(Date.now()>=s)throw new Sn(n,o,this.disconnectTimeoutMs);await new Promise(a=>setTimeout(a,500))}}async adopt(e,n){let s=[...new Set([...n.tables.map(h=>h.schema),...n.raw.flatMap(h=>h.schema?[h.schema]:[])])],r=await at(this.pool,s,this.roles);if(!n.tables.some(h=>r.schema.tables.some(p=>p.schema===h.schema&&(p.name===h.name||p.name===h.renamedFrom))))return null;if(!this.shadow)throw new Error("palgres: the database holds tables of the schema and no Palgres version: taking it over needs a shadow database (MigratorOptions.shadow) to read the schema as Postgres writes it");let a=await this.made(e,n,s,r),i=jt(r,a,n);if(i.refusals.length>0)throw new he(i.refusals);let c=[this.roles.anon,this.roles.authenticated,this.roles.service].map(R).join(", "),l={tables:i.schema.tables.filter(h=>!h.ignored).map(h=>({schema:h.schema,name:h.name,physical:h.name,columns:h.columns.filter(p=>!p.ignored).map(p=>({name:p.name,physical:p.name}))}))},u=i.schema.tables.map(h=>P(h.schema,h.name)),g=qe(i.schema),m=async()=>{await this.tx(e,[...i.unforce.map(h=>`ALTER TABLE ${P(h.slice(0,h.indexOf(".")),h.slice(h.indexOf(".")+1))} NO FORCE ROW LEVEL SECURITY`),...[...new Set(i.schema.tables.map(h=>h.schema))].map(h=>`GRANT USAGE ON SCHEMA ${R(h)} TO ${c}`),...u.map(h=>`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ${h} TO ${c}`),`DO $palgres$ DECLARE s regclass; BEGIN
262
262
  FOR s IN SELECT d.objid::regclass FROM pg_depend d JOIN pg_class c ON c.oid = d.objid AND c.relkind = 'S'
263
263
  WHERE d.deptype = 'a' AND d.refobjid = ANY (ARRAY[${u.length>0?u.map(h=>`${M(h)}::regclass`).join(", "):"NULL::regclass"}]::oid[]) LOOP
264
264
  EXECUTE format('GRANT USAGE, SELECT ON SEQUENCE %s TO ${c.replace(/'/g,"''")}', s);
265
265
  END LOOP; END $palgres$`,`INSERT INTO palgres.versions (n, digest, schema, layout, state, direct, ready_at) VALUES (1, ${M(g)}, ${M(JSON.stringify(i.schema))}::jsonb, ${M(JSON.stringify(l))}::jsonb, 'active', true, now())`]),this.log(`palgres: takes the database over as version 1 (${i.schema.tables.length} table(s))${i.unforce.length>0?`; FORCE row-level security off on ${i.unforce.join(", ")}`:""}${i.unmanaged.length>0?`
266
266
  left as it is:
267
267
  ${i.unmanaged.join(`
268
- `)}`:""}`)};return{version:{n:1,digest:g,state:"active",schema:i.schema},adoption:{unforced:i.unforce,unmanaged:i.unmanaged},layout:l,record:p}}async made(e,n,s,r){let o=`palgres_shadow_${Ko(6).toString("hex")}`;await e.query(`CREATE DATABASE ${b(o)}`);try{let a=this.shadow(o);try{await new t(a,{roles:this.roles,lockTimeoutMs:this.lockTimeoutMs}).start(n);let i=await Yn(a,s,this.roles);return await Yo(a,r,i),i}finally{await a.end()}}finally{await e.query(`DROP DATABASE IF EXISTS ${b(o)} WITH (FORCE)`)}}async planFrom(e,n,s){let r=new Set;for(let f of n?.schema.tables??[])(await e.query(`SELECT EXISTS (SELECT 1 FROM ${P(f.schema,f.name)}) AS any`))[0].any&&r.add(D(f));let o=new Map,a=[],i=(f,d)=>{let T=`${f}\0${d}`;return o.has(T)||(o.set(T,void 0),a.push([f,d])),o.get(T)},l=(await e.query("SELECT to_regclass('palgres.versions') IS NOT NULL AS there"))[0]?.there===!0?Number((await e.query("SELECT coalesce(max(n), 0) AS n FROM palgres.versions"))[0].n):0,u=Math.max(l,n?.n??0)+1,g=new Map,p=f=>(g.has(f)||g.set(f,void 0),g.get(f)),h=new Map;if((await e.query(`SELECT to_regclass('${J}.generations') IS NOT NULL AS there`))[0]?.there===!0)for(let f of await e.query(`SELECT table_key, gen, model, dimensions, metric, from_columns, status FROM ${J}.generations ORDER BY table_key, gen`)){let d=String(f.table_key);h.has(d)||h.set(d,[]),h.get(d).push({gen:Number(f.gen),model:String(f.model),dimensions:Number(f.dimensions),metric:f.metric,from:f.from_columns.map(String),status:f.status})}let m=(await e.query("SELECT n.nspname AS schema FROM pg_catalog.pg_extension e JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace WHERE e.extname = 'vector'"))[0]?.schema,y=()=>Lt({from:n&&{n:n.n,schema:n.schema},next:u,to:s,hasRows:f=>r.has(f),castable:i,checkedDomain:p,roles:this.roles,generations:f=>h.get(f)??[],vectorSchema:typeof m=="string"?m:"public"}),S=y();if(a.length===0&&g.size===0)return S;for(let[f,d]of a)o.set(`${f}\0${d}`,await this.casts(e,f,d));for(let f of g.keys())g.set(f,await this.checkedDomain(e,f));return y()}async checkedDomain(e,n){let s=await e.query(`SELECT t.typtype = 'd' AND (t.typnotnull OR EXISTS (SELECT 1 FROM pg_catalog.pg_constraint c WHERE c.contypid = t.oid)) AS checked FROM pg_catalog.pg_type t WHERE t.oid = pg_catalog.to_regtype(${M(n)})`);return s.length===0?void 0:s[0].checked===!0}async casts(e,n,s){try{return await e.query(`SELECT CAST(NULL::${n} AS ${s})`),!0}catch(r){let o=ae(r);if(o==="42846")return!1;if(o==="42704")return;throw r}}async active(e){if(e.ledger===!1)return null;let n=await e.query("SELECT n, digest, schema FROM palgres.versions WHERE state = 'active' ORDER BY n DESC LIMIT 1"),s=await this.open(e),o=(s?await e.query(`SELECT n, digest, schema FROM palgres.versions WHERE n = ${s.from_n??-1}`):n)[0];return o?{n:Number(o.n),digest:String(o.digest),state:"active",schema:_t(o.schema)}:null}async version(e,n){if(e.ledger===!1)return null;let s=await e.query(`SELECT n, digest, state FROM palgres.versions WHERE n = ${n}`);return s[0]?{n,digest:String(s[0].digest),state:s[0].state}:null}async open(e){if(e.ledger===!1)return null;let s=(await e.query("SELECT from_n, to_n, plan, done, phase, to_jsonb(m) ->> 'opened_by' AS opened_by FROM palgres.migration m"))[0];return s?{from_n:s.from_n===null?null:Number(s.from_n),to_n:Number(s.to_n),plan:Xo(_t(s.plan),Number(s.to_n)),done:_t(s.done),phase:s.phase,opened_by:typeof s.opened_by=="string"?s.opened_by:null}:null}async session(e,n=!0,s){let r=await this.pool.reserve(),o={query:async a=>await r.unsafe(a)};try{if(await o.query("SET application_name = 'palgres:migrate'"),await o.query("SET search_path = public, pg_temp"),n){await o.query(`SELECT pg_advisory_lock(hashtextextended(${M(nr)}, 0))`);let a=(await o.query(`SELECT to_regclass('palgres.versions') IS NOT NULL AS there, (SELECT pg_catalog.obj_description(n.oid, 'pg_namespace') FROM pg_catalog.pg_namespace n WHERE n.nspname = '${J}') AS search`))[0];o.ledger=a.there===!0,o.searchLedger=typeof a.search=="string"?a.search:null,o.ledger&&await this.ensure(o)}else if((await o.query("SELECT to_regclass('palgres.migration') IS NULL AS none"))[0].none)return await(s?s(o):e(Go));return await e(o)}finally{n&&await o.query(`SELECT pg_advisory_unlock(hashtextextended(${M(nr)}, 0))`).catch(()=>{}),r.release()}}async ownAuth(e){let n=await this.authRefusals(e);if(n.length>0)throw new $e(n)}async authRefusals(e){let n={jwt:["SELECT coalesce(nullif(current_setting('request.jwt.claims', true), '')::jsonb, '{}'::jsonb)"],uid:["SELECT nullif(auth.jwt() ->> 'sub', '')","SELECT current_setting('request.jwt.claims', true)::jsonb ->> 'sub'"],role:["SELECT nullif(auth.jwt() ->> 'role', '')"]},s=a=>a.replace(/\s+/g," ").trim();return(await e.query("SELECT p.proname AS name, p.prosrc AS src, pg_catalog.format_type(p.prorettype, NULL) AS returns FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = 'auth' AND p.proname IN ('jwt', 'uid', 'role') AND p.pronargs = 0")).filter(a=>!(n[String(a.name)]??[]).some(i=>s(i)===s(String(a.src)))).map(a=>`auth.${a.name}() is the database's own (returns ${a.returns}: ${s(String(a.src)).slice(0,120)}): Palgres makes it read the request's claims (request.jwt.claims), and the app there now would read its caller otherwise \u2014 rename yours, or make it read the claims as Palgres does, before the take-over`)}async ensure(e){let n=[this.roles.anon,this.roles.authenticated,this.roles.service],s=await e.query(`SELECT r FROM unnest(ARRAY[${n.map(M).join(", ")}]) AS r WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = r)`);if(s.length>0)throw new Error(`palgres: the database has no role ${s.map(o=>o.r).join(", ")} \u2014 the app's roles are made with the database`);let r=n.map(b).join(", ");await this.tx(e,["CREATE SCHEMA IF NOT EXISTS palgres",`CREATE TABLE IF NOT EXISTS palgres.versions (
268
+ `)}`:""}`)};return{version:{n:1,digest:g,state:"active",schema:i.schema},adoption:{unforced:i.unforce,unmanaged:i.unmanaged},layout:l,record:m}}async made(e,n,s,r){let o=`palgres_shadow_${da(6).toString("hex")}`;await e.query(`CREATE DATABASE ${R(o)}`);try{let a=this.shadow(o);try{await new t(a,{roles:this.roles,lockTimeoutMs:this.lockTimeoutMs}).start(n);let i=await at(a,s,this.roles);return await ha(a,r,i),i}finally{await a.end()}}finally{await e.query(`DROP DATABASE IF EXISTS ${R(o)} WITH (FORCE)`)}}async planFrom(e,n,s){let r=new Set;for(let f of n?.schema.tables??[])(await e.query(`SELECT EXISTS (SELECT 1 FROM ${P(f.schema,f.name)}) AS any`))[0].any&&r.add(D(f));let o=new Map,a=[],i=(f,d)=>{let T=`${f}\0${d}`;return o.has(T)||(o.set(T,void 0),a.push([f,d])),o.get(T)},l=(await e.query("SELECT to_regclass('palgres.versions') IS NOT NULL AS there"))[0]?.there===!0?Number((await e.query("SELECT coalesce(max(n), 0) AS n FROM palgres.versions"))[0].n):0,u=Math.max(l,n?.n??0)+1,g=new Map,m=f=>(g.has(f)||g.set(f,void 0),g.get(f)),h=new Map;if((await e.query(`SELECT to_regclass('${J}.generations') IS NOT NULL AS there`))[0]?.there===!0)for(let f of await e.query(`SELECT table_key, gen, model, dimensions, metric, from_columns, status FROM ${J}.generations ORDER BY table_key, gen`)){let d=String(f.table_key);h.has(d)||h.set(d,[]),h.get(d).push({gen:Number(f.gen),model:String(f.model),dimensions:Number(f.dimensions),metric:f.metric,from:f.from_columns.map(String),status:f.status})}let p=(await e.query("SELECT n.nspname AS schema FROM pg_catalog.pg_extension e JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace WHERE e.extname = 'vector'"))[0]?.schema,E=()=>Bt({from:n&&{n:n.n,schema:n.schema},next:u,to:s,hasRows:f=>r.has(f),castable:i,checkedDomain:m,roles:this.roles,generations:f=>h.get(f)??[],vectorSchema:typeof p=="string"?p:"public"}),$=E();if(a.length===0&&g.size===0)return $;for(let[f,d]of a)o.set(`${f}\0${d}`,await this.casts(e,f,d));for(let f of g.keys())g.set(f,await this.checkedDomain(e,f));return E()}async checkedDomain(e,n){let s=await e.query(`SELECT t.typtype = 'd' AND (t.typnotnull OR EXISTS (SELECT 1 FROM pg_catalog.pg_constraint c WHERE c.contypid = t.oid)) AS checked FROM pg_catalog.pg_type t WHERE t.oid = pg_catalog.to_regtype(${M(n)})`);return s.length===0?void 0:s[0].checked===!0}async casts(e,n,s){try{return await e.query(`SELECT CAST(NULL::${n} AS ${s})`),!0}catch(r){let o=ae(r);if(o==="42846")return!1;if(o==="42704")return;throw r}}async active(e){if(e.ledger===!1)return null;let n=await e.query("SELECT n, digest, schema FROM palgres.versions WHERE state = 'active' ORDER BY n DESC LIMIT 1"),s=await this.open(e),o=(s?await e.query(`SELECT n, digest, schema FROM palgres.versions WHERE n = ${s.from_n??-1}`):n)[0];return o?{n:Number(o.n),digest:String(o.digest),state:"active",schema:Vt(o.schema)}:null}async version(e,n){if(e.ledger===!1)return null;let s=await e.query(`SELECT n, digest, state FROM palgres.versions WHERE n = ${n}`);return s[0]?{n,digest:String(s[0].digest),state:s[0].state}:null}async open(e){if(e.ledger===!1)return null;let s=(await e.query("SELECT from_n, to_n, plan, done, phase, to_jsonb(m) ->> 'opened_by' AS opened_by FROM palgres.migration m"))[0];return s?{from_n:s.from_n===null?null:Number(s.from_n),to_n:Number(s.to_n),plan:ga(Vt(s.plan),Number(s.to_n)),done:Vt(s.done),phase:s.phase,opened_by:typeof s.opened_by=="string"?s.opened_by:null}:null}async session(e,n=!0,s){let r=await this.pool.reserve(),o={query:async(a,i)=>await r.unsafe(a,i)};try{if(await o.query("SET application_name = 'palgres:migrate'"),await o.query("SET search_path = public, pg_temp"),n){await o.query(`SELECT pg_advisory_lock(hashtextextended(${M(Tr)}, 0))`);let a=(await o.query(`SELECT to_regclass('palgres.versions') IS NOT NULL AS there, (SELECT pg_catalog.obj_description(n.oid, 'pg_namespace') FROM pg_catalog.pg_namespace n WHERE n.nspname = '${J}') AS search`))[0];o.ledger=a.there===!0,o.searchLedger=typeof a.search=="string"?a.search:null,o.ledger&&await this.ensure(o)}else if((await o.query("SELECT to_regclass('palgres.migration') IS NULL AS none"))[0].none)return await(s?s(o):e(fa));return await e(o)}finally{n&&await o.query(`SELECT pg_advisory_unlock(hashtextextended(${M(Tr)}, 0))`).catch(()=>{}),r.release()}}async ownAuth(e){let n=await this.authRefusals(e);if(n.length>0)throw new he(n)}async authRefusals(e){let n={jwt:["SELECT coalesce(nullif(current_setting('request.jwt.claims', true), '')::jsonb, '{}'::jsonb)"],uid:["SELECT nullif(auth.jwt() ->> 'sub', '')","SELECT current_setting('request.jwt.claims', true)::jsonb ->> 'sub'"],role:["SELECT nullif(auth.jwt() ->> 'role', '')"]},s=a=>a.replace(/\s+/g," ").trim();return(await e.query("SELECT p.proname AS name, p.prosrc AS src, pg_catalog.format_type(p.prorettype, NULL) AS returns FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = 'auth' AND p.proname IN ('jwt', 'uid', 'role') AND p.pronargs = 0")).filter(a=>!(n[String(a.name)]??[]).some(i=>s(i)===s(String(a.src)))).map(a=>`auth.${a.name}() is the database's own (returns ${a.returns}: ${s(String(a.src)).slice(0,120)}): Palgres makes it read the request's claims (request.jwt.claims), and the app there now would read its caller otherwise \u2014 rename yours, or make it read the claims as Palgres does, before the take-over`)}async ensure(e){let n=[this.roles.anon,this.roles.authenticated,this.roles.service],s=await e.query(`SELECT r FROM unnest(ARRAY[${n.map(M).join(", ")}]) AS r WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = r)`);if(s.length>0)throw new Error(`palgres: the database has no role ${s.map(o=>o.r).join(", ")} \u2014 the app's roles are made with the database`);let r=n.map(R).join(", ");await this.tx(e,["CREATE SCHEMA IF NOT EXISTS palgres",`CREATE TABLE IF NOT EXISTS palgres.versions (
269
269
  n integer PRIMARY KEY,
270
270
  digest text NOT NULL,
271
271
  schema jsonb NOT NULL,
@@ -284,11 +284,15 @@ END $palgres$`,mn=class extends Error{constructor(e,n){super(`palgres: ${e} was
284
284
  phase text NOT NULL CHECK (phase IN ('starting', 'started', 'completing', 'rolling_back')),
285
285
  updated_at timestamptz NOT NULL DEFAULT now(),
286
286
  opened_by text
287
- )`,"GRANT USAGE ON SCHEMA palgres TO PUBLIC","GRANT SELECT (n, digest, state, direct) ON palgres.versions TO PUBLIC",er,"CREATE SCHEMA IF NOT EXISTS auth","CREATE OR REPLACE FUNCTION auth.jwt() RETURNS jsonb LANGUAGE sql STABLE AS $palgres$ SELECT coalesce(nullif(current_setting('request.jwt.claims', true), '')::jsonb, '{}'::jsonb) $palgres$","CREATE OR REPLACE FUNCTION auth.uid() RETURNS text LANGUAGE sql STABLE AS $palgres$ SELECT nullif(auth.jwt() ->> 'sub', '') $palgres$","CREATE OR REPLACE FUNCTION auth.role() RETURNS text LANGUAGE sql STABLE AS $palgres$ SELECT nullif(auth.jwt() ->> 'role', '') $palgres$",`GRANT USAGE ON SCHEMA auth TO ${r}`,`GRANT EXECUTE ON FUNCTION auth.jwt(), auth.uid(), auth.role() TO ${r}`,...e.searchLedger===Wn(this.roles)?[]:Ms(this.roles)]),e.searchLedger=Wn(this.roles)}},Go={query:async()=>[]};function Xo(t,e){let n=t.format??1;if(!Number.isInteger(n)||n<1||n>Gn)throw new $e([`version ${e}'s migration was planned by a newer Palgres (plan format ${String(t.format)}; this one runs ${Gn} and before): release the version that planned it, or one after, to go on with it`]);for(let s of["start","complete","rollback"])for(let r of t[s]??[])if(!Ws.has(r.kind))throw new $e([`version ${e}'s migration has a step of a kind this Palgres does not run (${JSON.stringify(r.kind)}, in its ${s}): release the version that planned it, or one after, to go on with it`]);return t}function tr(t){let e=ft(ge(t));if(e.length>0)throw new De(e)}function _t(t){return typeof t=="string"?JSON.parse(t):t}function sr(t){return t.slice(1,-1).replace(/""/g,'"')}function Pt(t,e="public"){return`${b(Te(t,e))}, ${b(e)}, pg_temp`}function rr(t){return t.tables.every(e=>e.physical===e.name&&e.columns.every(n=>n.physical===n.name))}async function Yo(t,e,n){for(let[s,r]of n.objects){if(!s.startsWith("view ")&&!s.startsWith("materialized view "))continue;let o=e.objects.get(s);if(o===void 0||o===r)continue;let{options:a,query:i}=JSON.parse(o),c=await t.reserve();try{await c.unsafe("BEGIN"),await c.unsafe("SET LOCAL search_path = ''"),await c.unsafe(`CREATE TEMP VIEW palgres_fixpoint AS ${i}`);let l=await c.unsafe("SELECT pg_catalog.pg_get_viewdef('pg_temp.palgres_fixpoint'::regclass, true) AS def");JSON.stringify({options:a,query:l[0].def.trim().replace(/;$/,"")})===r&&e.objects.set(s,r)}catch{}finally{await Promise.resolve(c.unsafe("ROLLBACK")).catch(()=>{}),c.release()}}}function ar(t,e){return{version:t,direct:e,searchPath:e?`${b("public")}, pg_temp`:Pt(t),applicationName:Qn(t),schema:n=>e?n:Te(t,n)}}var Zn=class extends Error{digest;constructor(e){super(`palgres: this schema (${e}) has no version in the database yet \u2014 the deploy migrates it before the app serves (PALBASE_DB_MIGRATE=start)`),this.name="VersionNotMigrated",this.digest=e}};async function Jo(t,e,n={}){let s=Pe(e),r=Date.now()+(n.waitMs??0);for(;;){let o;try{o=await t.unsafe("SELECT n, direct FROM palgres.versions WHERE digest = $1 AND state = 'active'",[s])}catch(a){let i=ae(a);if(i!=="42P01"&&i!=="3F000"){if(ue(a)===void 0||Date.now()>=r)throw a;n.onUnreachable?.(a),await new Promise(c=>setTimeout(c,1e3));continue}o=[]}if(o.length>0)return ar(Number(o[0].n),o[0].direct===!0);if(Date.now()>=r)throw new Zn(s);await new Promise(a=>setTimeout(a,500))}}function hn(t,e,n){let s=or.get(t);s||or.set(t,s=new Map);let r=s.get(e);return r===void 0&&(r=`SELECT set_config('role', ${de(e)}, true), set_config('search_path', ${de(t.searchPath)}, true), set_config('application_name', ${de(t.applicationName)}, false), set_config('request.jwt.claims', `,s.set(e,r)),`${r}${de(JSON.stringify(n))}, true)`}var or=new WeakMap;async function zo(t,e,n,s,r="service_role"){if(typeof s!="string"||s==="")throw new TypeError("forgetUser: the user id is a non-empty string");let o=[];for(let a of ge(n).tables)for(let i of a.columns){if(!i.user)continue;let c=a.ignored===!0||i.ignored===!0;o.push({view:P(c?a.schema:e.schema(a.schema),a.name),column:i.name,onDelete:i.user.onDelete})}return o.length===0?{deleted:0,detached:0}:t.begin(async a=>{await a.unsafe(hn(e,r,{role:r})),await a.unsafe("SET CONSTRAINTS ALL DEFERRED");let i=0,c=0;for(let l of o.filter(u=>u.onDelete==="set null")){let u=await a.unsafe(`WITH t AS (UPDATE ${l.view} SET ${b(l.column)} = NULL WHERE ${b(l.column)} = $1 RETURNING 1) SELECT count(*)::int AS n FROM t`,[s]);c+=Number(u[0].n)}for(let l of o.filter(u=>u.onDelete==="cascade")){let u=await a.unsafe(`WITH t AS (DELETE FROM ${l.view} WHERE ${b(l.column)} = $1 RETURNING 1) SELECT count(*)::int AS n FROM t`,[s]);i+=Number(u[0].n)}return{deleted:i,detached:c}})}var Qo=new Set("break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield let static implements interface package private protected public await arguments eval".split(" ")),Zo=new Set(["defineSchema","defineTable","uuid","text","integer","bigint","numeric","boolean","timestamp","date","jsonb","policy","raw","foreignKey","enumType","sqlType","AnyColumn","TableHandle"]),Mt=t=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(t),lr=/^[A-Za-z_$][A-Za-z0-9_$]*$/,j=t=>JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"),ea=t=>t.replace(/[\r\n\u2028\u2029]+/g," "),cr=t=>t==="__proto__"?`[${j(t)}]`:lr.test(t)?t:j(t),ir={uuid:"uuid()",text:"text()",integer:"integer()",bigint:"bigint()",numeric:"numeric()",boolean:"boolean()","timestamp with time zone":"timestamp()",date:"date()",jsonb:"jsonb()"},na=new Set(["uuid","text","integer","bigint","numeric","boolean","timestamp with time zone","date"]);function ta(t){let e=/^'((?:[^']|'')*)'(?:::[a-z_ ."]+(?:\[\])?)?$/i.exec(t);return e?e[1].replace(/''/g,"'"):void 0}function sa(t,e={}){let n=e.from??"palbase/backend",s=[],r=new Map,o=new Map(t.enums.map(m=>[rn(m.schema,m.name),m])),a=new Map,i=new Set;for(let m of t.tables){let y=lr.test(m.name)&&!Qo.has(m.name)&&!Zo.has(m.name)?m.name:`t_${m.name.replace(/[^A-Za-z0-9_$]/g,"_")}`;for(m.schema!=="public"&&i.has(y)&&(y=`${m.schema}_${y}`);i.has(y);)y=`${y}_`;i.add(y),a.set(D(m),y)}let c=e.units??[],l=oa(t),u=ra(t),g=[...new Set([...t.tables.map(m=>m.schema),...c.map(m=>m.schema)])].sort(),p=new Map,h=new Set;for(let m of g.filter(Mt)){let y=m;for(let S=2;h.has(y.toLowerCase());S++)y=`${m}_${S}`;h.add(y.toLowerCase()),p.set(m,y)}for(let m of g){if(!Mt(m)){s.push(`schema ${JSON.stringify(m)} is not a plain name: not pulled`);continue}let y=t.tables.filter(A=>A.schema===m),S=new Set(["defineSchema","defineTable"]),f=new Map,d=y.map(A=>aa(A,t,o,a,S,f,s,l,u)),T=c.filter(A=>A.schema===m);T.length>0&&S.add("raw");let E=T.map(A=>` raw(${j(A.name)}, ${j(A.create)}, { drop: ${j(A.drop)}${A.before?", before: true":""} }),`),w=[`import { ${[...S].sort().join(", ")} } from ${j(n)};`];for(let[A,R]of[...f].sort())w.push(`import { ${[...R].sort().join(", ")} } from ${j(`./${p.get(A)}.ts`)};`);let O=m==="public"&&t.extensions.length>0?`, extensions: [${t.extensions.map(j).join(", ")}]`:"",k=(e.unmanaged??[]).filter(A=>A.includes(` ${m}.`)&&!c.some(R=>A.startsWith(R.listed))),N=k.length>0?`// Left as it is in the database, outside this file:
288
- ${k.map(A=>`// ${ea(A)}`).join(`
287
+ )`,"GRANT USAGE ON SCHEMA palgres TO PUBLIC","GRANT SELECT (n, digest, state, direct) ON palgres.versions TO PUBLIC",`CREATE TABLE IF NOT EXISTS ${de} (
288
+ address text PRIMARY KEY,
289
+ direction text NOT NULL CHECK (direction IN ('seal', 'open')),
290
+ phase text NOT NULL CHECK (phase IN ('mixed', 'final'))
291
+ )`,`GRANT SELECT ON ${de} TO PUBLIC`,wr,"CREATE SCHEMA IF NOT EXISTS auth","CREATE OR REPLACE FUNCTION auth.jwt() RETURNS jsonb LANGUAGE sql STABLE AS $palgres$ SELECT coalesce(nullif(current_setting('request.jwt.claims', true), '')::jsonb, '{}'::jsonb) $palgres$","CREATE OR REPLACE FUNCTION auth.uid() RETURNS text LANGUAGE sql STABLE AS $palgres$ SELECT nullif(auth.jwt() ->> 'sub', '') $palgres$","CREATE OR REPLACE FUNCTION auth.role() RETURNS text LANGUAGE sql STABLE AS $palgres$ SELECT nullif(auth.jwt() ->> 'role', '') $palgres$",`GRANT USAGE ON SCHEMA auth TO ${r}`,`GRANT EXECUTE ON FUNCTION auth.jwt(), auth.uid(), auth.role() TO ${r}`,...e.searchLedger===et(this.roles)?[]:tr(this.roles)]),e.searchLedger=et(this.roles)}},fa={query:async()=>[]};function ga(t,e){let n=t.format??1;if(!Number.isInteger(n)||n<1||n>Ut)throw new he([`version ${e}'s migration was planned by a newer Palgres (plan format ${String(t.format)}; this one runs ${Ut} and before): release the version that planned it, or one after, to go on with it`]);for(let s of["start","complete","rollback"])for(let r of t[s]??[])if(!ir.has(r.kind))throw new he([`version ${e}'s migration has a step of a kind this Palgres does not run (${JSON.stringify(r.kind)}, in its ${s}): release the version that planned it, or one after, to go on with it`]);return t}function $r(t){let e=Nt(Ee(t));if(e.length>0)throw new Me(e)}function Vt(t){return typeof t=="string"?JSON.parse(t):t}function Sr(t){return t.slice(1,-1).replace(/""/g,'"')}function Xt(t,e="public"){return`${R($e(t,e))}, ${R(e)}, pg_temp`}function br(t){return t.tables.every(e=>e.physical===e.name&&e.columns.every(n=>n.physical===n.name))}async function ha(t,e,n){for(let[s,r]of n.objects){if(!s.startsWith("view ")&&!s.startsWith("materialized view "))continue;let o=e.objects.get(s);if(o===void 0||o===r)continue;let{options:a,query:i}=JSON.parse(o),c=await t.reserve();try{await c.unsafe("BEGIN"),await c.unsafe("SET LOCAL search_path = ''"),await c.unsafe(`CREATE TEMP VIEW palgres_fixpoint AS ${i}`);let l=await c.unsafe("SELECT pg_catalog.pg_get_viewdef('pg_temp.palgres_fixpoint'::regclass, true) AS def");JSON.stringify({options:a,query:l[0].def.trim().replace(/;$/,"")})===r&&e.objects.set(s,r)}catch{}finally{await Promise.resolve(c.unsafe("ROLLBACK")).catch(()=>{}),c.release()}}}function Nr(t,e){return{version:t,direct:e,searchPath:e?`${R("public")}, pg_temp`:Xt(t),applicationName:ct(t),schema:n=>e?n:$e(t,n)}}var ut=class extends Error{digest;constructor(e){super(`palgres: this schema (${e}) has no version in the database yet \u2014 the deploy migrates it before the app serves (PALBASE_DB_MIGRATE=start)`),this.name="VersionNotMigrated",this.digest=e}};async function Ea(t,e,n={}){let s=qe(e),r=Date.now()+(n.waitMs??0);for(;;){let o;try{o=await t.unsafe("SELECT n, direct FROM palgres.versions WHERE digest = $1 AND state = 'active'",[s])}catch(a){let i=ae(a);if(i!=="42P01"&&i!=="3F000"){if(ue(a)===void 0||Date.now()>=r)throw a;n.onUnreachable?.(a),await new Promise(c=>setTimeout(c,1e3));continue}o=[]}if(o.length>0)return Nr(Number(o[0].n),o[0].direct===!0);if(Date.now()>=r)throw new ut(s);await new Promise(a=>setTimeout(a,500))}}function bn(t,e,n){let s=Rr.get(t);s||Rr.set(t,s=new Map);let r=s.get(e);return r===void 0&&(r=`SELECT set_config('role', ${me(e)}, true), set_config('search_path', ${me(t.searchPath)}, true), set_config('application_name', ${me(t.applicationName)}, false), set_config('request.jwt.claims', `,s.set(e,r)),`${r}${me(JSON.stringify(n))}, true)`}var Rr=new WeakMap;async function ya(t,e,n,s,r="service_role"){if(typeof s!="string"||s==="")throw new TypeError("forgetUser: the user id is a non-empty string");let o=[];for(let a of Ee(n).tables)for(let i of a.columns){if(!i.user)continue;let c=a.ignored===!0||i.ignored===!0;o.push({view:P(c?a.schema:e.schema(a.schema),a.name),column:i.name,onDelete:i.user.onDelete})}return o.length===0?{deleted:0,detached:0}:t.begin(async a=>{await a.unsafe(bn(e,r,{role:r})),await a.unsafe("SET CONSTRAINTS ALL DEFERRED");let i=0,c=0;for(let l of o.filter(u=>u.onDelete==="set null")){let u=await a.unsafe(`WITH t AS (UPDATE ${l.view} SET ${R(l.column)} = NULL WHERE ${R(l.column)} = $1 RETURNING 1) SELECT count(*)::int AS n FROM t`,[s]);c+=Number(u[0].n)}for(let l of o.filter(u=>u.onDelete==="cascade")){let u=await a.unsafe(`WITH t AS (DELETE FROM ${l.view} WHERE ${R(l.column)} = $1 RETURNING 1) SELECT count(*)::int AS n FROM t`,[s]);i+=Number(u[0].n)}return{deleted:i,detached:c}})}var wa=new Set("break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield let static implements interface package private protected public await arguments eval".split(" ")),Ta=new Set(["defineSchema","defineTable","uuid","text","integer","bigint","numeric","boolean","timestamp","date","jsonb","policy","raw","foreignKey","enumType","sqlType","AnyColumn","TableHandle"]),Yt=t=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(t),Or=/^[A-Za-z_$][A-Za-z0-9_$]*$/,j=t=>JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"),$a=t=>t.replace(/[\r\n\u2028\u2029]+/g," "),kr=t=>t==="__proto__"?`[${j(t)}]`:Or.test(t)?t:j(t),Ar={uuid:"uuid()",text:"text()",integer:"integer()",bigint:"bigint()",numeric:"numeric()",boolean:"boolean()","timestamp with time zone":"timestamp()",date:"date()",jsonb:"jsonb()"},Sa=new Set(["uuid","text","integer","bigint","numeric","boolean","timestamp with time zone","date"]);function ba(t){let e=/^'((?:[^']|'')*)'(?:::[a-z_ ."]+(?:\[\])?)?$/i.exec(t);return e?e[1].replace(/''/g,"'"):void 0}function Ra(t,e={}){let n=e.from??"palbase/backend",s=[],r=new Map,o=new Map(t.enums.map(p=>[un(p.schema,p.name),p])),a=new Map,i=new Set;for(let p of t.tables){let E=Or.test(p.name)&&!wa.has(p.name)&&!Ta.has(p.name)?p.name:`t_${p.name.replace(/[^A-Za-z0-9_$]/g,"_")}`;for(p.schema!=="public"&&i.has(E)&&(E=`${p.schema}_${E}`);i.has(E);)E=`${E}_`;i.add(E),a.set(D(p),E)}let c=e.units??[],l=Aa(t),u=Na(t),g=[...new Set([...t.tables.map(p=>p.schema),...c.map(p=>p.schema)])].sort(),m=new Map,h=new Set;for(let p of g.filter(Yt)){let E=p;for(let $=2;h.has(E.toLowerCase());$++)E=`${p}_${$}`;h.add(E.toLowerCase()),m.set(p,E)}for(let p of g){if(!Yt(p)){s.push(`schema ${JSON.stringify(p)} is not a plain name: not pulled`);continue}let E=t.tables.filter(A=>A.schema===p),$=new Set(["defineSchema","defineTable"]),f=new Map,d=E.map(A=>Oa(A,t,o,a,$,f,s,l,u)),T=c.filter(A=>A.schema===p);T.length>0&&$.add("raw");let y=T.map(A=>` raw(${j(A.name)}, ${j(A.create)}, { drop: ${j(A.drop)}${A.before?", before: true":""} }),`),w=[`import { ${[...$].sort().join(", ")} } from ${j(n)};`];for(let[A,b]of[...f].sort())w.push(`import { ${[...b].sort().join(", ")} } from ${j(`./${m.get(A)}.ts`)};`);let O=p==="public"&&t.extensions.length>0?`, extensions: [${t.extensions.map(j).join(", ")}]`:"",k=(e.unmanaged??[]).filter(A=>A.includes(` ${p}.`)&&!c.some(b=>A.startsWith(b.listed))),N=k.length>0?`// Left as it is in the database, outside this file:
292
+ ${k.map(A=>`// ${$a(A)}`).join(`
289
293
  `)}
290
294
 
291
- `:"";r.set(`db/${p.get(m)}.ts`,`// Written by palgres pull from the database, ${new Date().toISOString().slice(0,10)}.
295
+ `:"";r.set(`db/${m.get(p)}.ts`,`// Written by palgres pull from the database, ${new Date().toISOString().slice(0,10)}.
292
296
  ${N}${w.join(`
293
297
  `)}
294
298
 
@@ -296,48 +300,48 @@ ${d.join(`
296
300
 
297
301
  `)}${d.length>0?`
298
302
 
299
- `:""}export default defineSchema(${j(m)}, {
300
- tables: [${y.map(A=>a.get(D(A))).join(", ")}],${O?`
301
- ${O.slice(2)},`:""}${E.length>0?`
303
+ `:""}export default defineSchema(${j(p)}, {
304
+ tables: [${E.map(A=>a.get(D(A))).join(", ")}],${O?`
305
+ ${O.slice(2)},`:""}${y.length>0?`
302
306
  raw: [
303
- ${E.join(`
307
+ ${y.join(`
304
308
  `)}
305
309
  ],`:""}
306
310
  });
307
- `)}return{files:r,notes:s}}function ur(t,e){let n=r=>`${t.schema==="public"?t.name:`${t.schema}_${t.name}`}_${r}_fkey`,s=new Map;for(let r of t.foreignKeys)r.columns.length===1&&r.name===n(r.columns[0])&&r.match!=="full"&&!qt(e,r)&&s.set(r.columns[0],r);return s}var qt=(t,e)=>!Mt(e.refSchema)||!t.tables.some(n=>n.schema===e.refSchema&&n.name===e.refTable);function ra(t){let e=new Map(t.tables.map(u=>[D(u),u.foreignKeys.filter(g=>!qt(t,g)).map(g=>`${g.refSchema}.${g.refTable}`)])),n=new Map,s=new Map,r=new Map,o=[],a=new Set,i=0,c=0,l=u=>{n.set(u,i),s.set(u,i),i++,o.push(u),a.add(u);for(let p of e.get(u)??[])n.has(p)?a.has(p)&&s.set(u,Math.min(s.get(u),n.get(p))):(l(p),s.set(u,Math.min(s.get(u),s.get(p))));if(s.get(u)!==n.get(u))return;let g;do g=o.pop(),a.delete(g),r.set(g,c);while(g!==u);c++};for(let u of e.keys())n.has(u)||l(u);return(u,g,p)=>r.get(D(u))===r.get(`${g}.${p}`)}function oa(t){let e=i=>i.endsWith("_id")?i.slice(0,-3):i,n=new Map,s=[];for(let i of t.tables)for(let[c,l]of ur(i,t))s.push({fk:`${D(i)}.${c}`,child:D(i),column:c,target:`${l.refSchema}.${l.refTable}`,childName:i.name});let r=new Map,o=(i,c)=>r.set(`${i}\0${c}`,(r.get(`${i}\0${c}`)??0)+1);for(let i of s)o(i.child,e(i.column)),i.target!==i.child&&o(i.target,i.childName);let a=(i,c)=>(r.get(`${i}\0${c}`)??0)>1;for(let i of s){let c={};a(i.child,e(i.column))&&(c.as=i.column),i.target!==i.child&&a(i.target,i.childName)&&(c.reverseAs=`${i.childName}_${e(i.column)}`),(c.as!==void 0||c.reverseAs!==void 0)&&n.set(i.fk,c)}return n}function aa(t,e,n,s,r,o,a,i,c){let l=D(t),u=[],g=t.primaryKey.length===1?t.primaryKey[0]:void 0,p=new Set(t.uniques.filter(w=>w.columns.length===1&&w.name===`${t.name}_${w.columns[0]}_key`).map(w=>w.columns[0])),h=ur(t,e),m=w=>qt(e,w);for(let w of t.foreignKeys)m(w)&&a.push(`foreign key ${l}.${w.name} references ${w.refSchema}.${w.refTable}, outside the pulled schemas: left out, kept in the database as it is`);for(let w of t.foreignKeys)m(w)||!je(w.onDelete,w.onUpdate)||w.deferrable||a.push(`foreign key ${l}.${w.name} is checked at once, so the files say deferrable: false \u2014 remove it to let the next migration make the key deferrable: forgetting a user needs that where the user's rows cascade onto a row with more than one key with an action`);let y=new Set(t.indexes.map(w=>w.name)),S={name(w,O){let k=s.get(`${w}.${O}`);if(w!==t.schema){let N=o.get(w)??new Set;N.add(k),o.set(w,N)}return k},arrow(w,O,k){return c(t,w,O)?(r.add(`type ${k}`),`(): ${k} =>`):"() =>"}};u.push(" columns: {");for(let w of t.columns)u.push(` ${cr(w.name)}: ${ia(t,w,n,r,a,g===w.name,p.has(w.name),h.get(w.name),y,S,i.get(`${l}.${w.name}`))},`);u.push(" },"),t.primaryKey.length>1&&u.push(` primaryKey: [${t.primaryKey.map(j).join(", ")}],`);let f=t.uniques.filter(w=>!(w.columns.length===1&&p.has(w.columns[0])&&w.name===`${t.name}_${w.columns[0]}_key`));f.length>0&&u.push(` unique: [${f.map(w=>`{ name: ${j(w.name)}, columns: [${w.columns.map(j).join(", ")}] }`).join(", ")}],`),t.checks.length>0&&u.push(` checks: [${t.checks.map(w=>`{ name: ${j(w.name)}, expr: ${j(w.expr)} }`).join(", ")}],`);let d=[],T=[];for(let w of t.indexes)(ca(w)?d:T).push(w);d.length>0&&u.push(` indexes: () => [${d.map(w=>ua(w)).join(", ")}],`);let E=t.foreignKeys.filter(w=>!m(w)&&h.get(w.columns[0])!==w);return E.length>0&&(r.add("foreignKey"),u.push(` foreignKeys: (c) => [${E.map(w=>ma(t,w,S)).join(", ")}],`)),t.policies.length>0&&!t.rls?a.push(`table ${l} has ${t.policies.length} polic${t.policies.length===1?"y":"ies"} with row-level security off: they do nothing, and the files leave them out \u2014 the take-over drops them; to have them hold, declare rls: true and the policies`):t.policies.length>0&&(r.add("policy"),u.push(` policies: () => [${t.policies.map(w=>pa(t,w)).join(", ")}],`)),t.rls||u.push(" rls: false,"),T.length>0&&(r.add("raw"),u.push(` raw: [${T.map(w=>`raw(${j(w.name)}, ${j(da(t,w))})`).join(", ")}],`)),`export const ${s.get(l)} = defineTable(${j(t.name)}, {
311
+ `)}return{files:r,notes:s}}function Lr(t,e){let n=r=>`${t.schema==="public"?t.name:`${t.schema}_${t.name}`}_${r}_fkey`,s=new Map;for(let r of t.foreignKeys)r.columns.length===1&&r.name===n(r.columns[0])&&r.match!=="full"&&!Jt(e,r)&&s.set(r.columns[0],r);return s}var Jt=(t,e)=>!Yt(e.refSchema)||!t.tables.some(n=>n.schema===e.refSchema&&n.name===e.refTable);function Na(t){let e=new Map(t.tables.map(u=>[D(u),u.foreignKeys.filter(g=>!Jt(t,g)).map(g=>`${g.refSchema}.${g.refTable}`)])),n=new Map,s=new Map,r=new Map,o=[],a=new Set,i=0,c=0,l=u=>{n.set(u,i),s.set(u,i),i++,o.push(u),a.add(u);for(let m of e.get(u)??[])n.has(m)?a.has(m)&&s.set(u,Math.min(s.get(u),n.get(m))):(l(m),s.set(u,Math.min(s.get(u),s.get(m))));if(s.get(u)!==n.get(u))return;let g;do g=o.pop(),a.delete(g),r.set(g,c);while(g!==u);c++};for(let u of e.keys())n.has(u)||l(u);return(u,g,m)=>r.get(D(u))===r.get(`${g}.${m}`)}function Aa(t){let e=i=>i.endsWith("_id")?i.slice(0,-3):i,n=new Map,s=[];for(let i of t.tables)for(let[c,l]of Lr(i,t))s.push({fk:`${D(i)}.${c}`,child:D(i),column:c,target:`${l.refSchema}.${l.refTable}`,childName:i.name});let r=new Map,o=(i,c)=>r.set(`${i}\0${c}`,(r.get(`${i}\0${c}`)??0)+1);for(let i of s)o(i.child,e(i.column)),i.target!==i.child&&o(i.target,i.childName);let a=(i,c)=>(r.get(`${i}\0${c}`)??0)>1;for(let i of s){let c={};a(i.child,e(i.column))&&(c.as=i.column),i.target!==i.child&&a(i.target,i.childName)&&(c.reverseAs=`${i.childName}_${e(i.column)}`),(c.as!==void 0||c.reverseAs!==void 0)&&n.set(i.fk,c)}return n}function Oa(t,e,n,s,r,o,a,i,c){let l=D(t),u=[],g=t.primaryKey.length===1?t.primaryKey[0]:void 0,m=new Set(t.uniques.filter(w=>w.columns.length===1&&w.name===`${t.name}_${w.columns[0]}_key`).map(w=>w.columns[0])),h=Lr(t,e),p=w=>Jt(e,w);for(let w of t.foreignKeys)p(w)&&a.push(`foreign key ${l}.${w.name} references ${w.refSchema}.${w.refTable}, outside the pulled schemas: left out, kept in the database as it is`);for(let w of t.foreignKeys)p(w)||!He(w.onDelete,w.onUpdate)||w.deferrable||a.push(`foreign key ${l}.${w.name} is checked at once, so the files say deferrable: false \u2014 remove it to let the next migration make the key deferrable: forgetting a user needs that where the user's rows cascade onto a row with more than one key with an action`);let E=new Set(t.indexes.map(w=>w.name)),$={name(w,O){let k=s.get(`${w}.${O}`);if(w!==t.schema){let N=o.get(w)??new Set;N.add(k),o.set(w,N)}return k},arrow(w,O,k){return c(t,w,O)?(r.add(`type ${k}`),`(): ${k} =>`):"() =>"}};u.push(" columns: {");for(let w of t.columns)u.push(` ${kr(w.name)}: ${ka(t,w,n,r,a,g===w.name,m.has(w.name),h.get(w.name),E,$,i.get(`${l}.${w.name}`))},`);u.push(" },"),t.primaryKey.length>1&&u.push(` primaryKey: [${t.primaryKey.map(j).join(", ")}],`);let f=t.uniques.filter(w=>!(w.columns.length===1&&m.has(w.columns[0])&&w.name===`${t.name}_${w.columns[0]}_key`));f.length>0&&u.push(` unique: [${f.map(w=>`{ name: ${j(w.name)}, columns: [${w.columns.map(j).join(", ")}] }`).join(", ")}],`),t.checks.length>0&&u.push(` checks: [${t.checks.map(w=>`{ name: ${j(w.name)}, expr: ${j(w.expr)} }`).join(", ")}],`);let d=[],T=[];for(let w of t.indexes)(xa(w)?d:T).push(w);d.length>0&&u.push(` indexes: () => [${d.map(w=>Ia(w)).join(", ")}],`);let y=t.foreignKeys.filter(w=>!p(w)&&h.get(w.columns[0])!==w);return y.length>0&&(r.add("foreignKey"),u.push(` foreignKeys: (c) => [${y.map(w=>va(t,w,$)).join(", ")}],`)),t.policies.length>0&&!t.rls?a.push(`table ${l} has ${t.policies.length} polic${t.policies.length===1?"y":"ies"} with row-level security off: they do nothing, and the files leave them out \u2014 the take-over drops them; to have them hold, declare rls: true and the policies`):t.policies.length>0&&(r.add("policy"),u.push(` policies: () => [${t.policies.map(w=>_a(t,w)).join(", ")}],`)),t.rls||u.push(" rls: false,"),T.length>0&&(r.add("raw"),u.push(` raw: [${T.map(w=>`raw(${j(w.name)}, ${j(Ca(t,w))})`).join(", ")}],`)),`export const ${s.get(l)} = defineTable(${j(t.name)}, {
308
312
  ${u.join(`
309
313
  `)}
310
- });`}function ia(t,e,n,s,r,o,a,i,c,l,u){let g=`${D(t)}.${e.name}`,p,h=e.type,m=!1;h.endsWith("[]")&&(na.has(h.slice(0,-2))||n.has(h.slice(0,-2)))&&(h=h.slice(0,-2),m=!0);let y=n.get(h),S=/^numeric\((\d+),(\d+)\)$/.exec(h);if(ir[h]?p=ir[h]:y&&y.schema===t.schema?(p=`enumType(${j(y.name)}, [${y.values.map(j).join(", ")}])`,s.add("enumType")):S?p=`numeric({ precision: ${S[1]}, scale: ${S[2]} })`:(p=`sqlType(${j(e.type)})`,s.add("sqlType"),m=!1),s.add(p.slice(0,p.indexOf("("))),m&&(p+=".array()"),o&&(p+=".primaryKey()"),e.identity&&(p+=e.identity==="always"?".identity()":".identity({ always: false })"),e.nullable&&!o&&(p+=".nullable()"),a&&(p+=".unique()"),e.generated&&(p+=`.generated(${j(e.generated.expr)}${e.generated.stored?", { stored: true }":""})`),e.default!==void 0&&(p+=la(e,m)),i){let f=l.name(i.refSchema,i.refTable),d=[];u?.as!==void 0&&d.push(`as: ${j(u.as)}`),u?.reverseAs!==void 0&&d.push(`reverseAs: ${j(u.reverseAs)}`),i.onDelete!=="no action"&&d.push(`onDelete: ${j(i.onDelete)}`),i.onUpdate!=="no action"&&d.push(`onUpdate: ${j(i.onUpdate)}`),dr(t,e.name)||d.push("index: false"),je(i.onDelete,i.onUpdate)&&!i.deferrable&&d.push("deferrable: false"),p+=`.references(${l.arrow(i.refSchema,i.refTable,"AnyColumn")} ${f}.${cr(i.refColumns[0])}${d.length>0?`, { ${d.join(", ")} }`:""})`}return/^(owner|user_id|created_by|author_id|.*_user_id)$/.test(e.name)&&!i&&r.push(`column ${g} may hold a user's id: mark it ownedByUser() or userRef() so user.deleted reaches it`),p}function dr(t,e){let n=t.indexes.find(r=>r.name===`${t.name}_${e}_idx`);if(n===void 0||n.unique||n.where!==void 0||n.method!==void 0||n.include?.length||n.keys.length!==1)return!1;let s=n.keys[0];return"column"in s&&s.column===e&&!s.desc&&s.nulls===void 0}function la(t,e){let n=t.default;if(n==="gen_random_uuid()")return".defaultRandom()";if(n==="now()"&&t.type==="timestamp with time zone"||n==="CURRENT_DATE"&&t.type==="date")return".defaultNow()";if(n==="true"||n==="false")return`.default(${n})`;if(/^-?\d+(\.\d+)?$/.test(n)&&(t.type==="integer"||t.type==="bigint"))return`.default(${n})`;if(n==="'{}'::text[]"||/^'\{\}'::/.test(n))return e?".default([])":`.defaultSql(${j(n)})`;let s=ta(n);if(s!==void 0&&(/^'(?:[^']|'')*'::text$/.test(n)||t.type.startsWith("public.")&&!/::(?:text|character varying|character)\b/.test(n)))return`.default(${j(s)})`;if(s!==void 0&&t.type==="jsonb"&&/^'(?:[^']|'')*'::jsonb$/.test(n))try{let r=JSON.stringify(JSON.parse(s));if(r===s&&!/"__proto__"\s*:/.test(s))return`.default(${r})`}catch{}return`.defaultSql(${j(n)})`}function ca(t){if(t.method!==void 0||t.where!==void 0||!t.keys.every(n=>"column"in n))return!1;let e=t.keys[0];return t.keys.every(n=>n.desc===e.desc&&n.nulls===e.nulls)}function ua(t){let e=t.keys[0],n=[`name: ${j(t.name)}`,`columns: [${t.keys.map(s=>j(s.column)).join(", ")}]`];return t.unique&&n.push("unique: true"),e.desc&&n.push("sort: 'desc'"),e.nulls&&n.push(`nulls: ${j(e.nulls)}`),t.include?.length&&n.push(`include: [${t.include.map(j).join(", ")}]`),`{ ${n.join(", ")} }`}function da(t,e){let n=r=>`"${r.replace(/"/g,'""')}"`,s=e.keys.map(r=>`${"column"in r?n(r.column):r.expr}${r.desc?" DESC":""}${r.nulls?` NULLS ${r.nulls.toUpperCase()}`:""}`).join(", ");return`CREATE ${e.unique?"UNIQUE ":""}INDEX ${n(e.name)} ON ${n(t.schema)}.${n(t.name)}${e.method?` USING ${e.method}`:""} (${s})${e.include?.length?` INCLUDE (${e.include.map(n).join(", ")})`:""}${e.where?` WHERE ${e.where}`:""}`}function ma(t,e,n){let s=`foreignKey(${j(e.name)}).on(${e.columns.map(r=>`c.col(${j(r)})`).join(", ")}).references(${n.arrow(e.refSchema,e.refTable,"TableHandle")} ${n.name(e.refSchema,e.refTable)}, ${e.refColumns.map(j).join(", ")})`;return e.onDelete!=="no action"&&(s+=`.onDelete(${j(e.onDelete)})`),e.onUpdate!=="no action"&&(s+=`.onUpdate(${j(e.onUpdate)})`),e.match==="full"&&(s+=".match('full')"),e.columns.length===1&&!dr(t,e.columns[0])&&(s+=".index(false)"),je(e.onDelete,e.onUpdate)&&!e.deferrable&&(s+=".deferrable(false)"),s}function pa(t,e){let n=`policy(${j(e.name)}).for(${j(e.for)}).to(${e.to.map(j).join(", ")})`;e.restrictive&&(n+=".as('restrictive')"),e.using!==void 0&&(n+=`.using(${j(e.using)})`),e.withCheck!==void 0&&(n+=`.withCheck(${j(e.withCheck)})`);let s=r=>t.primaryKey[0]===r||t.uniques.some(o=>o.columns[0]===r)||t.indexes.some(o=>o.where===void 0&&"column"in(o.keys[0]??{})&&o.keys[0].column===r);return ys(t,e).some(r=>!s(r)&&!t.indexes.some(o=>o.name===`${t.name}_${r}_idx`))&&(n+=".withoutIndexes()"),n}function ze(t){if(t==null)return null;switch(typeof t){case"string":return t;case"number":case"bigint":return String(t);case"boolean":return t?"true":"false";case"symbol":case"function":throw new TypeError(`a ${typeof t} is not a database value`)}return t instanceof Date?fa(t):t instanceof Uint8Array?`\\x${Buffer.from(t).toString("hex")}`:Array.isArray(t)&&fr(t)?En(t):JSON.stringify(t)}function fr(t){return t.every(e=>e==null||typeof e!="object"&&typeof e!="function"&&typeof e!="symbol"||e instanceof Date||e instanceof Uint8Array||Array.isArray(e)&&fr(e))}function En(t){let e=n=>n==null?"NULL":Array.isArray(n)?En(n):`"${String(ze(n)).replace(/(["\\])/g,"\\$1")}"`;return`{${t.map(e).join(",")}}`}function fa(t){if(Number.isNaN(t.getTime()))throw new TypeError("an invalid Date is not a database value");return t.toISOString()}var ga={json:{to:114,from:[114,3802],serialize:t=>t,parse:t=>JSON.parse(t)},boolean:{to:16,from:[16],serialize:t=>t,parse:t=>t==="t"},date:{to:1184,from:[1082,1114,1184],serialize:t=>t,parse:t=>new Date(t)},bytea:{to:17,from:[17],serialize:t=>t,parse:t=>Buffer.from(t.slice(2),"hex")}};function ha(t){let e=t;return e.length>0&&Array.isArray(e[e.length-1])?e[e.length-1]:e}var gr=/^[A-Za-z0-9:_-]{1,80}$/;function hr(t,e){let n=new Array(e.length).fill(!1),s="",r=0,o=0;for(;o<t.length;){let a=t.charCodeAt(o);if(a===39||a===34){let i=o+1;for(;;){if(i>=t.length||t.charCodeAt(i)===92)return;if(t.charCodeAt(i)===a){if(t.charCodeAt(i+1)!==a)break;i+=2}else i++}o=i+1;continue}if(a===36){let i=o+1,c=0;for(;i<t.length&&t.charCodeAt(i)>=48&&t.charCodeAt(i)<=57&&i-o<=6;)c=c*10+(t.charCodeAt(i++)-48);if(i===o+1||c<1||c>e.length||n[c-1])return;n[c-1]=!0;let l=e[c-1];if(l!==null&&typeof l!="string"||l!==null&&l.includes("\0"))return;s+=t.slice(r,o)+(l===null?"NULL":de(l)),r=o=i;continue}if(a===59||a===92||a===45&&t.charCodeAt(o+1)===45||a===47&&t.charCodeAt(o+1)===42)return;o++}for(let a of n)if(!a)return;return s+t.slice(r)}function mr(t){return On(t)?Object.assign(new Error("current transaction is aborted, commands ignored until end of transaction block",{cause:t}),{errno:"25P02",code:"ERR_POSTGRES_SERVER_ERROR"}):t}var et=10,nt=2;function Er(t,e){let n={unsafe:(s,r)=>n.begin(o=>Promise.resolve(o.unsafe(s,r))),async begin(s,r){if(r?.tag!==void 0&&!gr.test(r.tag))throw new Error(`palgres: an opening's tag is letters, digits, ":", "_" and "-"`);let o=`${r?.tag===void 0?"":`/* ${r.tag} */ `}BEGIN${r===void 0?"":`; ${r.sql}`}`,a=await t.reserve(),i=!0,c=!1,l=!1,u=null,g,p=!1,h=0,m=d=>(u=(async()=>{for(let T=1;;T++){c=!0;try{let E=await a.unsafe(d===void 0?o:`${o}; ${d}`).simple();if((E.length>0&&Array.isArray(E[0])?E[0]:E).command!=="BEGIN")throw new Error("palgres: the round trip that opens the transaction did not begin one");return r?.opened?.(E[E.length-(d===void 0?1:2)]),l=!0,d===void 0?void 0:E[E.length-1]}catch(E){let w=Es(E);w&&(t.discard!==void 0?t.discard(a):Promise.resolve(a.close({timeout:0})).catch(()=>{}),i=!1,c=!1);let O=w?"unusable":ue(E);if(O===void 0||T>=(O==="never"?nt:et))throw g={error:E},E;w||(await Promise.resolve(a.close()).catch(()=>{}),a.release(),i=!1,c=!1);try{a=await t.reserve()}catch(k){throw g={error:k},k}i=!0}}})(),u.catch(()=>{}),u),y=()=>(u===null&&m(),u.then(()=>{},()=>{throw mr(g.error)})),S={unsafe(d,T,E){if(g!==void 0)return Promise.reject(mr(g.error));if(l)return a.unsafe(d,T);if(u===null&&E?.inline===!0){let w=hr(d,T??[]);if(w!==void 0)return m(w)}return y().then(()=>a.unsafe(d,T))},async savepoint(d){await y();let T=`palgres_sp_${++h}`;await a.unsafe(`SAVEPOINT ${T}`).simple();let E;try{E=await d(S)}catch(w){throw await Promise.resolve(a.unsafe(`ROLLBACK TO SAVEPOINT ${T}; RELEASE SAVEPOINT ${T}`).simple()).catch(()=>{}),w}return await a.unsafe(`RELEASE SAVEPOINT ${T}`).simple(),E},abandon(){p||(p=!0,Promise.resolve(a.close({timeout:0})).catch(()=>{}))}},f=async d=>{let T=await a.unsafe(d).simple();if(c=!1,d==="COMMIT"&&T.command==="ROLLBACK")throw new Error("palgres: COMMIT was answered with ROLLBACK \u2014 a statement of the transaction had failed")};try{let d;try{if(d=await s(S),await u?.catch(()=>{}),g!==void 0)throw g.error}catch(T){throw await u?.catch(()=>{}),c&&!p&&await f("ROLLBACK").catch(()=>{}),T}if(!c)return d;try{await f("COMMIT")}catch(T){throw c&&await f("ROLLBACK").catch(()=>{}),T}return d}finally{i&&(c&&!p&&await Promise.resolve(a.close()).catch(()=>{}),a.release())}}};if(e!==void 0){let s=Er(e);n.cancelBackend=Ut(s),n.cancelOpening=yr(s)}return n}var Ft=1e3;async function wr(t,e){let n;try{await Promise.race([Promise.resolve(t.close({timeout:e})),new Promise(s=>{n=setTimeout(s,e*1e3+Ft)})])}finally{clearTimeout(n)}}function Ea(t){let e=t(),n=0,s=!1,r=new WeakMap,o=new Map;return{get current(){return e},get renewals(){return n},unsafe:(a,i)=>e.unsafe(a,i),async reserve(){let a=e,i=await a.reserve();return r.set(i,a),i},discard(a){let i=r.get(a);if(i===e&&!s){e=t(),n++;let c=Promise.resolve(i.close()).catch(()=>{});o.set(i,c),c.then(()=>o.delete(i))}a.release()},async close(a){s=!0;let i=a?.timeout??0,c;try{await Promise.all([wr(e,i),Promise.race([Promise.all(o.values()),new Promise(l=>{c=setTimeout(l,i*1e3+Ft)})])])}finally{clearTimeout(c)}}}}function yr(t){return async e=>{if(!gr.test(e))throw new Error(`palgres: an opening's tag is letters, digits, ":", "_" and "-"`);let n=`/* ${e} */`;return(await t.unsafe(`SELECT pg_cancel_backend(pid) AS cancelled FROM pg_stat_activity
314
+ });`}function ka(t,e,n,s,r,o,a,i,c,l,u){let g=`${D(t)}.${e.name}`,m,h=e.type,p=!1;h.endsWith("[]")&&(Sa.has(h.slice(0,-2))||n.has(h.slice(0,-2)))&&(h=h.slice(0,-2),p=!0);let E=n.get(h),$=/^numeric\((\d+),(\d+)\)$/.exec(h);if(Ar[h]?m=Ar[h]:E&&E.schema===t.schema?(m=`enumType(${j(E.name)}, [${E.values.map(j).join(", ")}])`,s.add("enumType")):$?m=`numeric({ precision: ${$[1]}, scale: ${$[2]} })`:(m=`sqlType(${j(e.type)})`,s.add("sqlType"),p=!1),s.add(m.slice(0,m.indexOf("("))),p&&(m+=".array()"),o&&(m+=".primaryKey()"),e.identity&&(m+=e.identity==="always"?".identity()":".identity({ always: false })"),e.nullable&&!o&&(m+=".nullable()"),a&&(m+=".unique()"),e.generated&&(m+=`.generated(${j(e.generated.expr)}${e.generated.stored?", { stored: true }":""})`),e.default!==void 0&&(m+=La(e,p)),i){let f=l.name(i.refSchema,i.refTable),d=[];u?.as!==void 0&&d.push(`as: ${j(u.as)}`),u?.reverseAs!==void 0&&d.push(`reverseAs: ${j(u.reverseAs)}`),i.onDelete!=="no action"&&d.push(`onDelete: ${j(i.onDelete)}`),i.onUpdate!=="no action"&&d.push(`onUpdate: ${j(i.onUpdate)}`),xr(t,e.name)||d.push("index: false"),He(i.onDelete,i.onUpdate)&&!i.deferrable&&d.push("deferrable: false"),m+=`.references(${l.arrow(i.refSchema,i.refTable,"AnyColumn")} ${f}.${kr(i.refColumns[0])}${d.length>0?`, { ${d.join(", ")} }`:""})`}return/^(owner|user_id|created_by|author_id|.*_user_id)$/.test(e.name)&&!i&&r.push(`column ${g} may hold a user's id: mark it ownedByUser() or userRef() so user.deleted reaches it`),m}function xr(t,e){let n=t.indexes.find(r=>r.name===`${t.name}_${e}_idx`);if(n===void 0||n.unique||n.where!==void 0||n.method!==void 0||n.include?.length||n.keys.length!==1)return!1;let s=n.keys[0];return"column"in s&&s.column===e&&!s.desc&&s.nulls===void 0}function La(t,e){let n=t.default;if(n==="gen_random_uuid()")return".defaultRandom()";if(n==="now()"&&t.type==="timestamp with time zone"||n==="CURRENT_DATE"&&t.type==="date")return".defaultNow()";if(n==="true"||n==="false")return`.default(${n})`;if(/^-?\d+(\.\d+)?$/.test(n)&&(t.type==="integer"||t.type==="bigint"))return`.default(${n})`;if(n==="'{}'::text[]"||/^'\{\}'::/.test(n))return e?".default([])":`.defaultSql(${j(n)})`;let s=ba(n);if(s!==void 0&&(/^'(?:[^']|'')*'::text$/.test(n)||t.type.startsWith("public.")&&!/::(?:text|character varying|character)\b/.test(n)))return`.default(${j(s)})`;if(s!==void 0&&t.type==="jsonb"&&/^'(?:[^']|'')*'::jsonb$/.test(n))try{let r=JSON.stringify(JSON.parse(s));if(r===s&&!/"__proto__"\s*:/.test(s))return`.default(${r})`}catch{}return`.defaultSql(${j(n)})`}function xa(t){if(t.method!==void 0||t.where!==void 0||!t.keys.every(n=>"column"in n))return!1;let e=t.keys[0];return t.keys.every(n=>n.desc===e.desc&&n.nulls===e.nulls)}function Ia(t){let e=t.keys[0],n=[`name: ${j(t.name)}`,`columns: [${t.keys.map(s=>j(s.column)).join(", ")}]`];return t.unique&&n.push("unique: true"),e.desc&&n.push("sort: 'desc'"),e.nulls&&n.push(`nulls: ${j(e.nulls)}`),t.include?.length&&n.push(`include: [${t.include.map(j).join(", ")}]`),`{ ${n.join(", ")} }`}function Ca(t,e){let n=r=>`"${r.replace(/"/g,'""')}"`,s=e.keys.map(r=>`${"column"in r?n(r.column):r.expr}${r.desc?" DESC":""}${r.nulls?` NULLS ${r.nulls.toUpperCase()}`:""}`).join(", ");return`CREATE ${e.unique?"UNIQUE ":""}INDEX ${n(e.name)} ON ${n(t.schema)}.${n(t.name)}${e.method?` USING ${e.method}`:""} (${s})${e.include?.length?` INCLUDE (${e.include.map(n).join(", ")})`:""}${e.where?` WHERE ${e.where}`:""}`}function va(t,e,n){let s=`foreignKey(${j(e.name)}).on(${e.columns.map(r=>`c.col(${j(r)})`).join(", ")}).references(${n.arrow(e.refSchema,e.refTable,"TableHandle")} ${n.name(e.refSchema,e.refTable)}, ${e.refColumns.map(j).join(", ")})`;return e.onDelete!=="no action"&&(s+=`.onDelete(${j(e.onDelete)})`),e.onUpdate!=="no action"&&(s+=`.onUpdate(${j(e.onUpdate)})`),e.match==="full"&&(s+=".match('full')"),e.columns.length===1&&!xr(t,e.columns[0])&&(s+=".index(false)"),He(e.onDelete,e.onUpdate)&&!e.deferrable&&(s+=".deferrable(false)"),s}function _a(t,e){let n=`policy(${j(e.name)}).for(${j(e.for)}).to(${e.to.map(j).join(", ")})`;e.restrictive&&(n+=".as('restrictive')"),e.using!==void 0&&(n+=`.using(${j(e.using)})`),e.withCheck!==void 0&&(n+=`.withCheck(${j(e.withCheck)})`);let s=r=>t.primaryKey[0]===r||t.uniques.some(o=>o.columns[0]===r)||t.indexes.some(o=>o.where===void 0&&"column"in(o.keys[0]??{})&&o.keys[0].column===r);return Ps(t,e).some(r=>!s(r)&&!t.indexes.some(o=>o.name===`${t.name}_${r}_idx`))&&(n+=".withoutIndexes()"),n}function tn(t){if(t==null)return null;switch(typeof t){case"string":return t;case"number":case"bigint":return String(t);case"boolean":return t?"true":"false";case"symbol":case"function":throw new TypeError(`a ${typeof t} is not a database value`)}return t instanceof Date?Da(t):t instanceof Uint8Array?`\\x${Buffer.from(t).toString("hex")}`:Array.isArray(t)&&vr(t)?Rn(t):JSON.stringify(t)}function vr(t){return t.every(e=>e==null||typeof e!="object"&&typeof e!="function"&&typeof e!="symbol"||e instanceof Date||e instanceof Uint8Array||Array.isArray(e)&&vr(e))}function Rn(t){let e=n=>n==null?"NULL":Array.isArray(n)?Rn(n):`"${String(tn(n)).replace(/(["\\])/g,"\\$1")}"`;return`{${t.map(e).join(",")}}`}function Da(t){if(Number.isNaN(t.getTime()))throw new TypeError("an invalid Date is not a database value");return t.toISOString()}var Pa={json:{to:114,from:[114,3802],serialize:t=>t,parse:t=>JSON.parse(t)},boolean:{to:16,from:[16],serialize:t=>t,parse:t=>t==="t"},date:{to:1184,from:[1082,1114,1184],serialize:t=>t,parse:t=>new Date(t)},bytea:{to:17,from:[17],serialize:t=>t,parse:t=>Buffer.from(t.slice(2),"hex")}};function Ma(t){let e=t;return e.length>0&&Array.isArray(e[e.length-1])?e[e.length-1]:e}var _r=/^[A-Za-z0-9:_-]{1,80}$/;function Dr(t,e){let n=new Array(e.length).fill(!1),s="",r=0,o=0;for(;o<t.length;){let a=t.charCodeAt(o);if(a===39||a===34){let i=o+1;for(;;){if(i>=t.length||t.charCodeAt(i)===92)return;if(t.charCodeAt(i)===a){if(t.charCodeAt(i+1)!==a)break;i+=2}else i++}o=i+1;continue}if(a===36){let i=o+1,c=0;for(;i<t.length&&t.charCodeAt(i)>=48&&t.charCodeAt(i)<=57&&i-o<=6;)c=c*10+(t.charCodeAt(i++)-48);if(i===o+1||c<1||c>e.length||n[c-1])return;n[c-1]=!0;let l=e[c-1];if(l!==null&&typeof l!="string"||l!==null&&l.includes("\0"))return;s+=t.slice(r,o)+(l===null?"NULL":me(l)),r=o=i;continue}if(a===59||a===92||a===45&&t.charCodeAt(o+1)===45||a===47&&t.charCodeAt(o+1)===42)return;o++}for(let a of n)if(!a)return;return s+t.slice(r)}function Ir(t){return Dn(t)?Object.assign(new Error("current transaction is aborted, commands ignored until end of transaction block",{cause:t}),{errno:"25P02",code:"ERR_POSTGRES_SERVER_ERROR"}):t}var dt=10,mt=2;function Pr(t,e){let n={unsafe:(s,r)=>n.begin(o=>Promise.resolve(o.unsafe(s,r))),async begin(s,r){if(r?.tag!==void 0&&!_r.test(r.tag))throw new Error(`palgres: an opening's tag is letters, digits, ":", "_" and "-"`);let o=`${r?.tag===void 0?"":`/* ${r.tag} */ `}BEGIN${r===void 0?"":`; ${r.sql}`}`,a=await t.reserve(),i=!0,c=!1,l=!1,u=null,g,m=!1,h=0,p=d=>(u=(async()=>{for(let T=1;;T++){c=!0;try{let y=await a.unsafe(d===void 0?o:`${o}; ${d}`).simple();if((y.length>0&&Array.isArray(y[0])?y[0]:y).command!=="BEGIN")throw new Error("palgres: the round trip that opens the transaction did not begin one");return r?.opened?.(y[y.length-(d===void 0?1:2)]),l=!0,d===void 0?void 0:y[y.length-1]}catch(y){let w=_s(y);w&&(t.discard!==void 0?t.discard(a):Promise.resolve(a.close({timeout:0})).catch(()=>{}),i=!1,c=!1);let O=w?"unusable":ue(y);if(O===void 0||T>=(O==="never"?mt:dt))throw g={error:y},y;w||(await Promise.resolve(a.close()).catch(()=>{}),a.release(),i=!1,c=!1);try{a=await t.reserve()}catch(k){throw g={error:k},k}i=!0}}})(),u.catch(()=>{}),u),E=()=>(u===null&&p(),u.then(()=>{},()=>{throw Ir(g.error)})),$={unsafe(d,T,y){if(g!==void 0)return Promise.reject(Ir(g.error));if(l)return a.unsafe(d,T);if(u===null&&y?.inline===!0){let w=Dr(d,T??[]);if(w!==void 0)return p(w)}return E().then(()=>a.unsafe(d,T))},async savepoint(d){await E();let T=`palgres_sp_${++h}`;await a.unsafe(`SAVEPOINT ${T}`).simple();let y;try{y=await d($)}catch(w){throw await Promise.resolve(a.unsafe(`ROLLBACK TO SAVEPOINT ${T}; RELEASE SAVEPOINT ${T}`).simple()).catch(()=>{}),w}return await a.unsafe(`RELEASE SAVEPOINT ${T}`).simple(),y},abandon(){m||(m=!0,Promise.resolve(a.close({timeout:0})).catch(()=>{}))}},f=async d=>{let T=await a.unsafe(d).simple();if(c=!1,d==="COMMIT"&&T.command==="ROLLBACK")throw new Error("palgres: COMMIT was answered with ROLLBACK \u2014 a statement of the transaction had failed")};try{let d;try{if(d=await s($),await u?.catch(()=>{}),g!==void 0)throw g.error}catch(T){throw await u?.catch(()=>{}),c&&!m&&await f("ROLLBACK").catch(()=>{}),T}if(!c)return d;try{await f("COMMIT")}catch(T){throw c&&await f("ROLLBACK").catch(()=>{}),T}return d}finally{i&&(c&&!m&&await Promise.resolve(a.close()).catch(()=>{}),a.release())}}};if(e!==void 0){let s=Pr(e);n.cancelBackend=Qt(s),n.cancelOpening=qr(s)}return n}var zt=1e3;async function Mr(t,e){let n;try{await Promise.race([Promise.resolve(t.close({timeout:e})),new Promise(s=>{n=setTimeout(s,e*1e3+zt)})])}finally{clearTimeout(n)}}function qa(t){let e=t(),n=0,s=!1,r=new WeakMap,o=new Map;return{get current(){return e},get renewals(){return n},unsafe:(a,i)=>e.unsafe(a,i),async reserve(){let a=e,i=await a.reserve();return r.set(i,a),i},discard(a){let i=r.get(a);if(i===e&&!s){e=t(),n++;let c=Promise.resolve(i.close()).catch(()=>{});o.set(i,c),c.then(()=>o.delete(i))}a.release()},async close(a){s=!0;let i=a?.timeout??0,c;try{await Promise.all([Mr(e,i),Promise.race([Promise.all(o.values()),new Promise(l=>{c=setTimeout(l,i*1e3+zt)})])])}finally{clearTimeout(c)}}}}function qr(t){return async e=>{if(!_r.test(e))throw new Error(`palgres: an opening's tag is letters, digits, ":", "_" and "-"`);let n=`/* ${e} */`;return(await t.unsafe(`SELECT pg_cancel_backend(pid) AS cancelled FROM pg_stat_activity
311
315
  WHERE state = 'active' AND left(query, $1::integer) = $2
312
- AND usename = session_user AND datname = current_database() AND backend_type = 'client backend'`,[String(n.length),n])).length>0}}function Ut(t){return async(e,n,s)=>{await t.unsafe(`SELECT pg_cancel_backend(pid) FROM pg_stat_activity
316
+ AND usename = session_user AND datname = current_database() AND backend_type = 'client backend'`,[String(n.length),n])).length>0}}function Qt(t){return async(e,n,s)=>{await t.unsafe(`SELECT pg_cancel_backend(pid) FROM pg_stat_activity
313
317
  WHERE pid = $1::integer AND backend_start = $2::timestamptz AND xact_start = $3::timestamptz
314
- AND usename = session_user AND datname = current_database() AND backend_type = 'client backend'`,[String(e),n,s])}}var Ie=class extends Error{constructor(e){super(`palgres: the driver ${e}. The engine sends every parameter as the text Postgres reads, and the driver must send it as it is \u2014 build Bun.SQL with { prepare: false } (Bun 1.4.2 or later) through bunDriver(), postgres.js with { types: POSTGRES_JS_TYPES } through postgresJsDriver()`),this.name="DriverRefused"}};async function Bt(t){let n=(await t.unsafe("SELECT $1::jsonb AS j, $2::boolean AS b, $3::timestamptz = '2026-01-02 03:04:05.123456+00'::timestamptz AS t, array_length($4::int[], 1)::int AS a, $5::bytea = '\\x0102'::bytea AS y",['{"palgres":[1]}',"true","2026-01-02T03:04:05.123456Z","{1,2}","\\x0102"]))[0]??{},s=n.j;if(typeof s=="string"||!Array.isArray(s?.palgres))throw new Ie("re-encodes text bound for a jsonb parameter (JSON text became a JSON string)");if(n.b!==!0)throw new Ie("changes the text bound for a boolean ('true' was not read as true)");if(n.t!==!0)throw new Ie("changes the text bound for a timestamp (its microseconds did not arrive)");if(Number(n.a)!==2)throw new Ie("changes the text bound for an array (the literal {1,2} did not arrive)");if(n.y!==!0)throw new Ie("changes the text bound for a bytea");if((await t.begin(async o=>await o.unsafe("SELECT pg_catalog.current_setting('palgres.driver_opened', true) AS v"),{sql:"SELECT pg_catalog.set_config('palgres.driver_opened', 'yes', true)"}))[0]?.v!=="yes")throw new Ie("does not run the opening of a transaction (its role and its caller) before the work \u2014 every request would run as the login, no one's")}var pr=()=>new Promise(()=>{});function wa(t,e){let n=a=>Promise.resolve(a).then(i=>i),s=a=>async(i,c)=>{for(let l=1;;l++){let u=!1,g,p=S=>g!==void 0?Promise.reject(g.error):n(S()).catch(f=>{throw ue(f)==="lost"&&(g??={error:f}),f}),h=(S,f)=>S.then(d=>g===void 0?d:(f(g.error),pr()),d=>g===void 0?Promise.reject(d):(f(d),pr())),m=S=>({unsafe:(f,d)=>p(()=>S.unsafe(f,d??[])),savepoint:f=>new Promise((d,T)=>{if(g!==void 0)return T(g.error);S.savepoint(E=>h(f(m(E)),T)).then(d,T)})}),y=a.begin(S=>h((async()=>{if(c!==void 0){let f=ha(await p(()=>S.unsafe(c.sql).simple()));c.opened?.(f)}return u=!0,i(m(S))})(),()=>{}));y.catch(S=>{ue(S)==="lost"&&(g??={error:S})});try{return await y}catch(S){let f=ue(S);if(u||f===void 0||l>=(f==="lost"?et:nt))throw S}}},r=s(t),o=s(e);return{unsafe:(a,i)=>r(c=>Promise.resolve(c.unsafe(a,i))),begin:r,cancelBackend:Ut({unsafe:(a,i)=>o(c=>Promise.resolve(c.unsafe(a,i)))})}}var Tr=(t,e)=>({embed:t,serving:new Map,said:new Map,log:e}),jt=3e4,Kt=`SELECT set_config('hnsw.iterative_scan', 'relaxed_order', true), set_config('hnsw.ef_search', '200', true), set_config('hnsw.max_scan_tuples', '200000', true), g.gen, g.model, g.dimensions, g.metric, (SELECT n.nspname FROM pg_catalog.pg_extension e JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace WHERE e.extname = 'vector') AS types FROM (SELECT 1) one LEFT JOIN ${J}.generations g ON g.table_key = $1 AND g.status = 'active' ORDER BY g.gen DESC LIMIT 1`;function Ht(t){if(!(t===void 0||t.gen===null||t.gen===void 0||typeof t.types!="string"))return{gen:Number(t.gen),model:String(t.model),dimensions:Number(t.dimensions),metric:t.metric,types:t.types}}var ya=["hybrid","text","vector"],Wt=(t,e)=>Ne(new Ae({fields:[{field:t,message:e}]},`search: ${t} ${e}`));function $r(t,e,n){if(n===null||typeof n!="object")throw new TypeError(`search(${t}): its options are { limit, where, mode, minScore }`);if(typeof e!="string")throw new TypeError(`search(${t}): the query is the text searched for, not ${e===null?"null":typeof e}`);let s=e.trim().slice(0,jt);if(s==="")throw Wt("query","is empty \u2014 say what to search for");let r=n.mode??"hybrid";if(typeof r!="string"||!ya.includes(r))throw new TypeError(`search(${t}): mode is "hybrid", "text" or "vector", not ${typeof r=="string"?JSON.stringify(String(r).slice(0,40)):typeof r}`);let o=n.limit??20;if(typeof o!="number"||!Number.isFinite(o))throw Wt("limit","must be a number");if(n.minScore!==void 0&&(typeof n.minScore!="number"||!Number.isFinite(n.minScore)))throw Wt("minScore","must be a number");return{text:s,mode:r,limit:Math.min(Math.max(1,Math.trunc(o)),100),...n.minScore===void 0?{}:{minScore:n.minScore}}}function Vt(t,e){if(!Array.isArray(t)||t.length!==e)throw new Error(`the embedder answered ${Array.isArray(t)?`a vector of ${t.length} dimensions`:"no vector"} where ${e} were asked for`);for(let n of t)if(typeof n!="number"||!Number.isFinite(n))throw new Error("the embedder answered a vector that holds what is not a number");return`[${t.join(",")}]`}async function Sr(t,e,n){let s=await t({texts:[e],model:n.model,dimensions:n.dimensions,purpose:"query"});if(s===null||typeof s!="object"||!Array.isArray(s.vectors)||s.vectors.length!==1)throw new Error("the embedder answered no vector for the one text it was given");return Vt(s.vectors[0],n.dimensions)}var Rr=100,Ta="2 minutes",$a=8,Sa=256,Ra=25e4,br=1e3,ba=15e3,Na=3e4,Aa=5e3,le=J,tt=t=>(t instanceof Error?t.message:String(t)).slice(0,500);function Oa(t){let{sql:e,embed:n,log:s}=t,r={...Je,...t.roles},o=`SELECT set_config('role', ${de(r.service)}, true), set_config('search_path', 'pg_catalog, pg_temp', true), set_config('datestyle', 'ISO, YMD', true), set_config('lock_timeout', '5s', true), set_config('statement_timeout', '60s', true)`,a=N=>e.begin(A=>N(async(R,L=[])=>await A.unsafe(R,L.map(ze))),{sql:o}),i=(N,A)=>a(R=>R(N,A)),c=!0,l=N=>i(`WITH due AS (SELECT id FROM ${le}.queue WHERE next_attempt_at <= now() ORDER BY enqueued_at, id LIMIT ${N} FOR UPDATE SKIP LOCKED)
315
- UPDATE ${le}.queue q SET next_attempt_at = now() + interval '${Ta}' FROM due WHERE q.id = due.id
316
- RETURNING q.id::text AS id, q.table_key, q.gen, q.row_id, q.enqueued_at::text AS enqueued_at`).then(A=>A.map(R=>({id:String(R.id),table_key:String(R.table_key),gen:Number(R.gen),row_id:String(R.row_id),enqueued_at:String(R.enqueued_at)})));async function u(N,A){let[R]=await i(`SELECT g.model, g.dimensions, g.metric, g.from_columns, t.rel::text AS parent, a.attname AS pk, format_type(a.atttypid, a.atttypmod) AS pk_type,
318
+ AND usename = session_user AND datname = current_database() AND backend_type = 'client backend'`,[String(e),n,s])}}var Ce=class extends Error{constructor(e){super(`palgres: the driver ${e}. The engine sends every parameter as the text Postgres reads, and the driver must send it as it is \u2014 build Bun.SQL with { prepare: false } (Bun 1.4.2 or later) through bunDriver(), postgres.js with { types: POSTGRES_JS_TYPES } through postgresJsDriver()`),this.name="DriverRefused"}};async function Zt(t){let n=(await t.unsafe("SELECT $1::jsonb AS j, $2::boolean AS b, $3::timestamptz = '2026-01-02 03:04:05.123456+00'::timestamptz AS t, array_length($4::int[], 1)::int AS a, $5::bytea = '\\x0102'::bytea AS y",['{"palgres":[1]}',"true","2026-01-02T03:04:05.123456Z","{1,2}","\\x0102"]))[0]??{},s=n.j;if(typeof s=="string"||!Array.isArray(s?.palgres))throw new Ce("re-encodes text bound for a jsonb parameter (JSON text became a JSON string)");if(n.b!==!0)throw new Ce("changes the text bound for a boolean ('true' was not read as true)");if(n.t!==!0)throw new Ce("changes the text bound for a timestamp (its microseconds did not arrive)");if(Number(n.a)!==2)throw new Ce("changes the text bound for an array (the literal {1,2} did not arrive)");if(n.y!==!0)throw new Ce("changes the text bound for a bytea");if((await t.begin(async o=>await o.unsafe("SELECT pg_catalog.current_setting('palgres.driver_opened', true) AS v"),{sql:"SELECT pg_catalog.set_config('palgres.driver_opened', 'yes', true)"}))[0]?.v!=="yes")throw new Ce("does not run the opening of a transaction (its role and its caller) before the work \u2014 every request would run as the login, no one's")}var Cr=()=>new Promise(()=>{});function Fa(t,e){let n=a=>Promise.resolve(a).then(i=>i),s=a=>async(i,c)=>{for(let l=1;;l++){let u=!1,g,m=$=>g!==void 0?Promise.reject(g.error):n($()).catch(f=>{throw ue(f)==="lost"&&(g??={error:f}),f}),h=($,f)=>$.then(d=>g===void 0?d:(f(g.error),Cr()),d=>g===void 0?Promise.reject(d):(f(d),Cr())),p=$=>({unsafe:(f,d)=>m(()=>$.unsafe(f,d??[])),savepoint:f=>new Promise((d,T)=>{if(g!==void 0)return T(g.error);$.savepoint(y=>h(f(p(y)),T)).then(d,T)})}),E=a.begin($=>h((async()=>{if(c!==void 0){let f=Ma(await m(()=>$.unsafe(c.sql).simple()));c.opened?.(f)}return u=!0,i(p($))})(),()=>{}));E.catch($=>{ue($)==="lost"&&(g??={error:$})});try{return await E}catch($){let f=ue($);if(u||f===void 0||l>=(f==="lost"?dt:mt))throw $}}},r=s(t),o=s(e);return{unsafe:(a,i)=>r(c=>Promise.resolve(c.unsafe(a,i))),begin:r,cancelBackend:Qt({unsafe:(a,i)=>o(c=>Promise.resolve(c.unsafe(a,i)))})}}var Fr=(t,e)=>({embed:t,serving:new Map,said:new Map,log:e}),ns=3e4,ts=`SELECT set_config('hnsw.iterative_scan', 'relaxed_order', true), set_config('hnsw.ef_search', '200', true), set_config('hnsw.max_scan_tuples', '200000', true), g.gen, g.model, g.dimensions, g.metric, (SELECT n.nspname FROM pg_catalog.pg_extension e JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace WHERE e.extname = 'vector') AS types FROM (SELECT 1) one LEFT JOIN ${J}.generations g ON g.table_key = $1 AND g.status = 'active' ORDER BY g.gen DESC LIMIT 1`;function ss(t){if(!(t===void 0||t.gen===null||t.gen===void 0||typeof t.types!="string"))return{gen:Number(t.gen),model:String(t.model),dimensions:Number(t.dimensions),metric:t.metric,types:t.types}}var Ua=["hybrid","text","vector"],es=(t,e)=>Ae(new Oe({fields:[{field:t,message:e}]},`search: ${t} ${e}`));function Ur(t,e,n){if(n===null||typeof n!="object")throw new TypeError(`search(${t}): its options are { limit, where, mode, minScore }`);if(typeof e!="string")throw new TypeError(`search(${t}): the query is the text searched for, not ${e===null?"null":typeof e}`);let s=e.trim().slice(0,ns);if(s==="")throw es("query","is empty \u2014 say what to search for");let r=n.mode??"hybrid";if(typeof r!="string"||!Ua.includes(r))throw new TypeError(`search(${t}): mode is "hybrid", "text" or "vector", not ${typeof r=="string"?JSON.stringify(String(r).slice(0,40)):typeof r}`);let o=n.limit??20;if(typeof o!="number"||!Number.isFinite(o))throw es("limit","must be a number");if(n.minScore!==void 0&&(typeof n.minScore!="number"||!Number.isFinite(n.minScore)))throw es("minScore","must be a number");return{text:s,mode:r,limit:Math.min(Math.max(1,Math.trunc(o)),100),...n.minScore===void 0?{}:{minScore:n.minScore}}}function rs(t,e){if(!Array.isArray(t)||t.length!==e)throw new Error(`the embedder answered ${Array.isArray(t)?`a vector of ${t.length} dimensions`:"no vector"} where ${e} were asked for`);for(let n of t)if(typeof n!="number"||!Number.isFinite(n))throw new Error("the embedder answered a vector that holds what is not a number");return`[${t.join(",")}]`}async function Br(t,e,n){let s=await t({texts:[e],model:n.model,dimensions:n.dimensions,purpose:"query"});if(s===null||typeof s!="object"||!Array.isArray(s.vectors)||s.vectors.length!==1)throw new Error("the embedder answered no vector for the one text it was given");return rs(s.vectors[0],n.dimensions)}var Wr=100,Ba="2 minutes",Wa=8,ja=256,Ka=25e4,jr=1e3,Ha=15e3,Va=3e4,Ga=5e3,le=J,pt=t=>(t instanceof Error?t.message:String(t)).slice(0,500);function Xa(t){let{sql:e,embed:n,log:s}=t,r={...nn,...t.roles},o=`SELECT set_config('role', ${me(r.service)}, true), set_config('search_path', 'pg_catalog, pg_temp', true), set_config('datestyle', 'ISO, YMD', true), set_config('lock_timeout', '5s', true), set_config('statement_timeout', '60s', true)`,a=N=>e.begin(A=>N(async(b,L=[])=>await A.unsafe(b,L.map(tn))),{sql:o}),i=(N,A)=>a(b=>b(N,A)),c=!0,l=N=>i(`WITH due AS (SELECT id FROM ${le}.queue WHERE next_attempt_at <= now() ORDER BY enqueued_at, id LIMIT ${N} FOR UPDATE SKIP LOCKED)
319
+ UPDATE ${le}.queue q SET next_attempt_at = now() + interval '${Ba}' FROM due WHERE q.id = due.id
320
+ RETURNING q.id::text AS id, q.table_key, q.gen, q.row_id, q.enqueued_at::text AS enqueued_at`).then(A=>A.map(b=>({id:String(b.id),table_key:String(b.table_key),gen:Number(b.gen),row_id:String(b.row_id),enqueued_at:String(b.enqueued_at)})));async function u(N,A){let[b]=await i(`SELECT g.model, g.dimensions, g.metric, g.from_columns, t.rel::text AS parent, a.attname AS pk, format_type(a.atttypid, a.atttypmod) AS pk_type,
317
321
  (SELECT n.nspname FROM pg_extension e JOIN pg_namespace n ON n.oid = e.extnamespace WHERE e.extname = 'vector') AS types
318
322
  FROM ${le}.generations g
319
323
  CROSS JOIN LATERAL (SELECT to_regclass(format('%I.%I', split_part(g.table_key, '.', 1), substr(g.table_key, strpos(g.table_key, '.') + 1))) AS rel) t
320
324
  JOIN pg_index i ON i.indrelid = t.rel AND i.indisprimary AND i.indnkeyatts = 1
321
325
  JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = i.indkey[0]
322
- WHERE g.table_key = $1 AND g.gen = $2::integer AND g.status <> 'retired'`,[N,A]);if(R===void 0||typeof R.types!="string")return;let L=Number(R.dimensions),$=R.metric;return{model:String(R.model),dimensions:L,metric:$,from:R.from_columns.map(String),parent:String(R.parent),pk:b(String(R.pk)),pkType:String(R.pk_type),vectors:`${le}.${b(ve(N,A))}`,vectorType:`${b(R.types)}.${cn(L,$).type}`}}let g="unnest($1::bigint[], $2::timestamptz[]) AS c(id, at) WHERE q.id = c.id AND q.enqueued_at = c.at",p=N=>[N.map(A=>A.id),N.map(A=>A.enqueued_at)],h=N=>i(`DELETE FROM ${le}.queue q USING ${g}`,p(N)),m=async(N,A)=>{N.length!==0&&(s?.(`palgres: search of ${N[0].table_key}: ${N.length} row(s) not embedded, tried again later (${tt(A)})`),await i(`UPDATE ${le}.queue q SET attempts = q.attempts + 1, last_error = $3,
323
- next_attempt_at = CASE WHEN q.attempts + 1 >= ${$a} THEN 'infinity'::timestamptz ELSE now() + interval '1 minute' * power(4, least(q.attempts, 4)) END
324
- FROM ${g}`,[...p(N),tt(A)]))};async function y(N,A,R,L){let $=[],C=[],q=0;for(let x of A){let B=Math.ceil(x.text.length/4);C.length>0&&(C.length>=Sa||q+B>Ra)&&($.push(C),C=[],q=0),C.push(x),q+=B}C.length>0&&$.push(C);let U=(x,B)=>(L.failed+=x.length,m(x.map(F=>F.row),B)),v=async x=>{if(x.length===0)return;let B=Math.ceil(x.length/2);await I(x.slice(0,B)),B<x.length&&await I(x.slice(B))},I=async x=>{if(L.down)return U(x,new Error("the embedder is not answering"));let B,F;try{let W=await n({texts:x.map(V=>V.text),model:N.model,dimensions:N.dimensions,purpose:"document"});if(W===null||typeof W!="object"||!Array.isArray(W.vectors)||W.vectors.length!==x.length)throw new Error(`the embedder answered ${Array.isArray(W?.vectors)?W.vectors.length:"no"} vector(s) for ${x.length} text(s)`);B=W.vectors.map(V=>Vt(V,N.dimensions)),F=typeof W.model=="string"&&W.model!==""?W.model:N.model}catch(W){return x.length===1?U(x,W):L.answered?v(x):(await I([x[0]]),await I([x[x.length-1]]),L.answered?v(x.slice(1,-1)):(L.down=!0,U(x.slice(1,-1),W)))}L.answered=!0,await R(x,F,B)};for(let x of $)await I(x)}async function S(N,A){let R=await u(N[0].table_key,N[0].gen);if(R===void 0)return await h(N),0;let L=new Map((await i(`SELECT p.${R.pk}::text AS id, ${qn(R.from,"p")} AS text FROM ${R.parent} p WHERE p.${R.pk} = ANY($1::${R.pkType}[])`,[N.map(v=>v.row_id)])).map(v=>[String(v.id),String(v.text??"")])),$=N.filter(v=>!L.has(v.row_id));$.length>0&&await h($);let C=N.filter(v=>L.has(v.row_id)&&L.get(v.row_id).trim()==="");C.length>0&&await i(`WITH done AS (DELETE FROM ${le}.queue q USING ${g} RETURNING q.row_id) DELETE FROM ${R.vectors} v USING done d WHERE v.id = d.row_id::${R.pkType}`,p(C));let q=N.filter(v=>(L.get(v.row_id)??"").trim()!=="").map(v=>({row:v,text:L.get(v.row_id).slice(0,jt)})),U=0;return await y(R,q,async(v,I,x)=>{try{let[B]=await i(`WITH done AS (DELETE FROM ${le}.queue q USING ${g} RETURNING q.row_id),
325
- there AS (SELECT p.${R.pk}::text AS id FROM ${R.parent} p WHERE p.${R.pk} = ANY($3::${R.pkType}[]) FOR KEY SHARE),
326
+ WHERE g.table_key = $1 AND g.gen = $2::integer AND g.status <> 'retired'`,[N,A]);if(b===void 0||typeof b.types!="string")return;let L=Number(b.dimensions),S=b.metric;return{model:String(b.model),dimensions:L,metric:S,from:b.from_columns.map(String),parent:String(b.parent),pk:R(String(b.pk)),pkType:String(b.pk_type),vectors:`${le}.${R(ve(N,A))}`,vectorType:`${R(b.types)}.${En(L,S).type}`}}let g="unnest($1::bigint[], $2::timestamptz[]) AS c(id, at) WHERE q.id = c.id AND q.enqueued_at = c.at",m=N=>[N.map(A=>A.id),N.map(A=>A.enqueued_at)],h=N=>i(`DELETE FROM ${le}.queue q USING ${g}`,m(N)),p=async(N,A)=>{N.length!==0&&(s?.(`palgres: search of ${N[0].table_key}: ${N.length} row(s) not embedded, tried again later (${pt(A)})`),await i(`UPDATE ${le}.queue q SET attempts = q.attempts + 1, last_error = $3,
327
+ next_attempt_at = CASE WHEN q.attempts + 1 >= ${Wa} THEN 'infinity'::timestamptz ELSE now() + interval '1 minute' * power(4, least(q.attempts, 4)) END
328
+ FROM ${g}`,[...m(N),pt(A)]))};async function E(N,A,b,L){let S=[],v=[],q=0;for(let I of A){let B=Math.ceil(I.text.length/4);v.length>0&&(v.length>=ja||q+B>Ka)&&(S.push(v),v=[],q=0),v.push(I),q+=B}v.length>0&&S.push(v);let U=(I,B)=>(L.failed+=I.length,p(I.map(F=>F.row),B)),C=async I=>{if(I.length===0)return;let B=Math.ceil(I.length/2);await x(I.slice(0,B)),B<I.length&&await x(I.slice(B))},x=async I=>{if(L.down)return U(I,new Error("the embedder is not answering"));let B,F;try{let W=await n({texts:I.map(V=>V.text),model:N.model,dimensions:N.dimensions,purpose:"document"});if(W===null||typeof W!="object"||!Array.isArray(W.vectors)||W.vectors.length!==I.length)throw new Error(`the embedder answered ${Array.isArray(W?.vectors)?W.vectors.length:"no"} vector(s) for ${I.length} text(s)`);B=W.vectors.map(V=>rs(V,N.dimensions)),F=typeof W.model=="string"&&W.model!==""?W.model:N.model}catch(W){return I.length===1?U(I,W):L.answered?C(I):(await x([I[0]]),await x([I[I.length-1]]),L.answered?C(I.slice(1,-1)):(L.down=!0,U(I.slice(1,-1),W)))}L.answered=!0,await b(I,F,B)};for(let I of S)await x(I)}async function $(N,A){let b=await u(N[0].table_key,N[0].gen);if(b===void 0)return await h(N),0;let L=new Map((await i(`SELECT p.${b.pk}::text AS id, ${Jn(b.from,"p")} AS text FROM ${b.parent} p WHERE p.${b.pk} = ANY($1::${b.pkType}[])`,[N.map(C=>C.row_id)])).map(C=>[String(C.id),String(C.text??"")])),S=N.filter(C=>!L.has(C.row_id));S.length>0&&await h(S);let v=N.filter(C=>L.has(C.row_id)&&L.get(C.row_id).trim()==="");v.length>0&&await i(`WITH done AS (DELETE FROM ${le}.queue q USING ${g} RETURNING q.row_id) DELETE FROM ${b.vectors} v USING done d WHERE v.id = d.row_id::${b.pkType}`,m(v));let q=N.filter(C=>(L.get(C.row_id)??"").trim()!=="").map(C=>({row:C,text:L.get(C.row_id).slice(0,ns)})),U=0;return await E(b,q,async(C,x,I)=>{try{let[B]=await i(`WITH done AS (DELETE FROM ${le}.queue q USING ${g} RETURNING q.row_id),
329
+ there AS (SELECT p.${b.pk}::text AS id FROM ${b.parent} p WHERE p.${b.pk} = ANY($3::${b.pkType}[]) FOR KEY SHARE),
326
330
  written AS (
327
- INSERT INTO ${R.vectors} (id, embedding, model)
328
- SELECT s.id::${R.pkType}, s.embedding::${R.vectorType}, $5::text
331
+ INSERT INTO ${b.vectors} (id, embedding, model)
332
+ SELECT s.id::${b.pkType}, s.embedding::${b.vectorType}, $5::text
329
333
  FROM unnest($6::text[], $4::text[]) AS s(id, embedding) JOIN done d ON d.row_id = s.id JOIN there ON there.id = s.id
330
334
  ON CONFLICT (id) DO UPDATE SET embedding = EXCLUDED.embedding, model = EXCLUDED.model, embedded_at = now()
331
335
  RETURNING 1)
332
- SELECT count(*)::int AS n FROM written`,[...p(v.map(F=>F.row)),v.map(F=>F.row.row_id),x,I,v.map(F=>F.row.row_id)]);U+=Number(B?.n??0)}catch(B){A.failed+=v.length,await m(v.map(F=>F.row),B)}},A),U}async function f(N){let A=0,R=await i(`SELECT g.table_key, g.gen FROM ${le}.generations g WHERE g.status = 'filling' AND NOT EXISTS (SELECT 1 FROM ${le}.queue q WHERE q.table_key = g.table_key AND q.gen = g.gen) ORDER BY 1, 2`);for(let L of R){let $=String(L.table_key),C=Number(L.gen),q=await u($,C);if(q===void 0)continue;let[U]=await i(`WITH missing AS (
336
+ SELECT count(*)::int AS n FROM written`,[...m(C.map(F=>F.row)),C.map(F=>F.row.row_id),I,x,C.map(F=>F.row.row_id)]);U+=Number(B?.n??0)}catch(B){A.failed+=C.length,await p(C.map(F=>F.row),B)}},A),U}async function f(N){let A=0,b=await i(`SELECT g.table_key, g.gen FROM ${le}.generations g WHERE g.status = 'filling' AND NOT EXISTS (SELECT 1 FROM ${le}.queue q WHERE q.table_key = g.table_key AND q.gen = g.gen) ORDER BY 1, 2`);for(let L of b){let S=String(L.table_key),v=Number(L.gen),q=await u(S,v);if(q===void 0)continue;let[U]=await i(`WITH missing AS (
333
337
  INSERT INTO ${le}.queue (table_key, gen, row_id)
334
338
  SELECT $1::text, $2::integer, p.${q.pk}::text FROM ${q.parent} p
335
- WHERE btrim(${qn(q.from,"p")}) <> '' AND NOT EXISTS (SELECT 1 FROM ${q.vectors} v WHERE v.id = p.${q.pk})
339
+ WHERE btrim(${Jn(q.from,"p")}) <> '' AND NOT EXISTS (SELECT 1 FROM ${q.vectors} v WHERE v.id = p.${q.pk})
336
340
  ON CONFLICT ON CONSTRAINT queue_one_pending DO NOTHING RETURNING 1)
337
- SELECT count(*)::int AS n FROM missing`,[$,C]);if(Number(U?.n??0)>0){A+=Number(U.n);continue}let[v]=await i(`SELECT ${le}.promote($1) AS gen`,[$]);v?.gen!==null&&v?.gen!==void 0&&(N.push($),s?.(`palgres: search of ${$}: every row is embedded again \u2014 generation ${String(v.gen)} serves`))}return A}async function d(N={}){let A=N.timeoutMs===void 0?1/0:Date.now()+N.timeoutMs,R=[],L=0,$=()=>Date.now()<A&&(N.max===void 0||L<N.max)&&!(N.whileRunning===!0&&c);for(;;){for(;$();){let C=await l(N.max===void 0?Rr:Math.min(Rr,N.max-L));if(C.length===0)break;let q=new Map;for(let I of C){let x=`${I.table_key}\0${I.gen}`,B=q.get(x);B?B.push(I):q.set(x,[I])}let U={answered:!1,down:!1,failed:0},v=0;for(let I of q.values())try{v+=await S(I,U)}catch(x){U.failed+=I.length,await m(I,x).catch(()=>{})}if(L+=v,v===0&&U.failed>0)return{embedded:L,promoted:R}}if(!$()||await f(R)===0)break}return{embedded:L,promoted:R}}let T,E,w=!1,O,k=()=>{w=!0,E?.()};return{drain:N=>d(N),kick:k,start(){T===void 0&&(c=!1,O=jn.listen(k),T=(async()=>{await i(`UPDATE ${le}.queue SET attempts = 0, next_attempt_at = now(), last_error = NULL WHERE next_attempt_at = 'infinity'`).catch(A=>s?.(`palgres: the search worker could not read its queue (${tt(A)})`));let N=br;for(;!c;){w=!1;let A=!1;try{let R=await d({timeoutMs:Na,whileRunning:!0});A=R.embedded>0||R.promoted.length>0}catch(R){s?.(`palgres: the search worker could not embed (${tt(R)}); it looks again`)}N=A?br:Math.min(ba,N*2),!(c||w)&&(await new Promise(R=>{let L=setTimeout(R,N);L.unref?.(),E=()=>{clearTimeout(L),R()}}),E=void 0)}})())},async stop(){if(T===void 0)return;c=!0,O?.(),O=void 0,E?.();let N=T;T=void 0;let A;await Promise.race([N,new Promise(R=>A=setTimeout(R,Aa))]),clearTimeout(A)}}}var Gt=class{options;active=0;queued=0;tenants=new Map;pending=new Map;lastTenant;accepted=0;rejected={full:0,timeout:0,cancelled:0};limit;timeout;nestedLimit;nestedActive=0;nestedPending=new Set;constructor(e){if(this.options=e,this.limit=e.queueLimit??Math.min(512,Math.max(32,e.concurrency*8)),this.timeout=e.queueTimeoutMs??1e3,this.nestedLimit=e.nestedConcurrency??e.concurrency*2,!Number.isSafeInteger(e.concurrency)||e.concurrency<1||!Number.isSafeInteger(this.nestedLimit)||this.nestedLimit<1||!Number.isSafeInteger(this.limit)||this.limit<0||this.limit>1e4||!Number.isSafeInteger(this.timeout)||this.timeout<1||this.timeout>6e4)throw new Error("Invalid database pool or queue deployment settings")}get queueTimeoutMs(){return this.timeout}get snapshot(){return{active:this.active,queued:this.queued,nested:{active:this.nestedActive,queued:this.nestedPending.size},tenants:this.tenants.size,accepted:this.accepted,rejected:{...this.rejected}}}nestedLease(e){this.nestedActive++;let n=!1;return{queueMs:performance.now()-e,release:()=>{if(n)return;n=!0,this.nestedActive--;let s=this.nestedPending.values().next().value;s&&(this.nestedPending.delete(s),s.cleanup(),s.grant(this.nestedLease(s.entered)))}}}acquireNested(e){let n=performance.now();return this.nestedActive<this.nestedLimit?Promise.resolve(this.nestedLease(n)):new Promise((s,r)=>{let o={grant:s,reject:r,entered:n,cleanup(){}},a=(l,u)=>{this.nestedPending.delete(o)&&(o.cleanup(),this.rejection(l),r(u))},i=()=>a("cancelled",e?.reason??new Error("Database admission cancelled")),c=setTimeout(()=>a("timeout",new Me({retryAfter:1},"Database queue deadline exceeded")),this.timeout);o.cleanup=()=>{clearTimeout(c),e?.removeEventListener("abort",i)},this.nestedPending.add(o),e?.addEventListener("abort",i,{once:!0}),e?.aborted&&i()})}rejection(e){this.rejected[e]++;try{this.options.onReject?.({reason:e,active:this.active,queued:this.queued})}catch{}}take(e,n){this.active++,this.accepted++,this.lastTenant=e,this.tenants.set(e,(this.tenants.get(e)??0)+1);let s=!1;return{queueMs:performance.now()-n,release:()=>{if(s)return;s=!0,this.active--;let r=(this.tenants.get(e)??1)-1;r?this.tenants.set(e,r):this.tenants.delete(e),this.drain()}}}drain(){for(;this.active<this.options.concurrency&&this.queued;){let e=this.pending.keys().next().value;if(this.pending.size>1&&e===this.lastTenant){let r=this.pending.get(e);this.pending.delete(e),this.pending.set(e,r),e=this.pending.keys().next().value}let n=this.pending.get(e),s=n.values().next().value;n.delete(s),this.pending.delete(e),n.size&&this.pending.set(e,n),this.queued--,s.cleanup(),s.grant(this.take(e,s.entered))}}async acquire(e,n,s={}){if(n?.aborted)throw this.rejection("cancelled"),n.reason??new Error("Database admission cancelled");if(s.nested)return this.acquireNested(n);let r=this.options.tenantClaim?e[this.options.tenantClaim]:e.sub,o=typeof r=="string"&&r.length?r:"__anonymous__",a=performance.now();if(this.active<this.options.concurrency&&!this.queued)return this.take(o,a);if(!s.returning&&this.queued>=this.limit)throw this.rejection("full"),new Me({retryAfter:1},"Database queue is full");return new Promise((i,c)=>{let l=this.pending.get(o)??new Set;this.pending.has(o)||this.pending.set(o,l);let u={grant:i,reject:c,entered:a,cleanup(){}},g=(m,y)=>{l.delete(u)&&(l.size||this.pending.delete(o),this.queued--,u.cleanup(),this.rejection(m),c(y),this.drain())},p=()=>g("cancelled",n?.reason??new Error("Database admission cancelled")),h=setTimeout(()=>g("timeout",new Me({retryAfter:1},"Database queue deadline exceeded")),this.timeout);if(u.cleanup=()=>{clearTimeout(h),n?.removeEventListener("abort",p)},s.returning){u.returning=!0;let m=[...l];l.clear();for(let y of m)y.returning&&l.add(y);l.add(u);for(let y of m)y.returning||l.add(y)}else l.add(u);this.queued++,n?.addEventListener("abort",p,{once:!0}),n?.aborted?p():this.drain()})}},Nr=new WeakMap;function Ar(t,e={concurrency:10}){let n=Nr.get(t);if(!n)return n=new Gt(e),Nr.set(t,n),n;for(let s of["concurrency","queueLimit","queueTimeoutMs","tenantClaim"])if(e[s]!==n.options[s])throw new Error("Database admission cannot be reconfigured while its pool is shared");return n}function ka(t){return t.endsWith("_id")?t.slice(0,-3):t}function Or(t){return t.direction==="forward"?`the foreign key "${t.table}.${t.column}"`:`the reverse of "${t.table}.${t.column}"`}function kr(t){return t.direction==="reverse"?'references(() => \u2026, { reverseAs: "\u2026" })':t.def.selfRefColumn!==void 0?'selfReferences("\u2026", { as: "\u2026" })':'references(() => \u2026, { as: "\u2026" })'}function wn(t){let e=new Map,n=new Map;for(let r of t)for(let o of Object.values(r.tables)){let a=he(r.name,o.name);e.set(a,[]),n.set(a,new Map)}let s=(r,o,a,i)=>{let c=n.get(r);if(c===void 0)return;let l=c.get(o);if(l!==void 0){let u=kr(l),g=kr(a),p=u===g?`rename one of them: ${u}`:`rename one of them \u2014 "${l.table}.${l.column}": ${u}; "${a.table}.${a.column}": ${g}`;throw new De([`table "${r}": ${Or(l)} and ${Or(a)} both resolve to the relation name "${o}" \u2014 ${p}`])}c.set(o,a),e.get(r)?.push(i)};for(let r of t)for(let o of Object.values(r.tables)){let a=he(r.name,o.name);for(let[i,c]of Object.entries(o.columns)){let l=c._def;if(l.references===void 0)continue;let u=l.references.table,g=l.refAs??ka(i);if(s(a,g,{table:o.name,column:i,direction:"forward",def:l},{name:g,to:u,kind:"one",via:i}),!e.has(u)||u===a)continue;let p=l.reverseAs??o.name;s(u,p,{table:o.name,column:i,direction:"reverse",def:l},{name:p,to:a,kind:"many",via:i})}}return e}function La(t){let e=t.columns??{},n=[],s=[];for(let[a,i]of Object.entries(e)){let c=i&&typeof i=="object"&&"_def"in i?i._def:i;c?.primaryKey&&n.push(a),c?.unique&&s.push([a])}let r=t.primaryKey??n;r.length&&s.unshift([...r]);for(let a of t.unique??[])s.push([...a.columns]);let o=new Set;return s.filter(a=>{if(!a.length||new Set(a).size!==a.length||a.some(c=>!Object.hasOwn(e,c)))throw new Error("Unique lookup requires a nonempty declared key of distinct, known columns");let i=JSON.stringify([...a].sort());return o.has(i)?!1:(o.add(i),!0)})}function st(t){let e=Object.fromEntries(Object.entries(t.columns).filter(([,n])=>n?._def?.ignored!==!0));return La({columns:e,primaryKey:t.primaryKey,unique:t.unique})}function Lr(t,e,n){if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`findUnique(${t}): where must contain one declared unique key`);let s=Object.keys(n);if(!e.some(r=>r.length===s.length&&r.every(o=>Object.hasOwn(n,o))))throw new Error(`findUnique(${t}): supply exactly one declared unique key (${e.map(r=>r.join(" + ")).join("; ")||"none declared"}); use findMany for other filters`);for(let[r,o]of Object.entries(n))if(o==null||typeof o=="object"&&!(o instanceof Date)||typeof o=="function"||typeof o=="symbol")throw new Error(`findUnique(${t}): ${r} requires a non-null scalar equality value`)}var _=t=>`"${t.replace(/"/g,'""')}"`;function Cr(t){return t.type==="sql"&&typeof t.sqlType=="string"?`sql:${t.sqlType}`:t.type}var rt=class{version;tables=new Map;ignoredTables=new Set;schemas;deferrals;constructor(e,n){this.version=n.version,this.schemas=e;let s=wn(e);for(let r of e)for(let o of Object.values(r.tables)){let a=he(r.name,o.name);if(o.ignored){this.ignoredTables.add(a);continue}this.tables.set(a,xa(r.name,o,a,n,s.get(a)??[]))}}table(e,n){let s=this.tables.get(e);if(s)return s;throw this.ignoredTables.has(e)?new Error(`${n}(${e}): the table is .ignored() in this version \u2014 the version has promised not to name it, so the next one can drop it`):new Error(`${n}(${e}): no such table in this version's schema (a table outside public is "schema.table")`)}deferral(e){return this.deferrals??=Ia(ws([...this.schemas])),this.deferrals.get(`${e.schema}.${e.name}`)??null}};function Ia(t){let e=(o,a)=>`${o}.${a}`,n=new Map,s=new Map;for(let o of t.tables)for(let a of o.foreignKeys){let i=e(a.refSchema,a.refTable);a.onDelete==="cascade"&&n.set(i,[...n.get(i)??[],e(o.schema,o.name)]),a.deferrable&&s.set(i,[...s.get(i)??[],e(o.schema,a.name)])}let r=new Map;for(let o of t.tables){let a=new Set([e(o.schema,o.name)]);for(let l of a)for(let u of n.get(l)??[])a.add(u);let i=[...new Set([...a].flatMap(l=>s.get(l)??[]))].sort();if(i.length===0)continue;let c=`ARRAY[${i.map(M).join(", ")}]::text[]`;r.set(e(o.schema,o.name),{defer:`SELECT palgres.defer_keys(${c}, true)`,check:`SELECT palgres.defer_keys(${c}, false)`})}return r}function xa(t,e,n,s,r){let o=new Map,a=new Set,i=[],c=new Map,l=new Set;for(let[g,p]of Object.entries(e.columns)){let h=p._def;if(h.ignored){a.add(g);continue}if(o.set(g,h),h.primaryKey&&i.push(g),typeof h.codec=="string"&&h.codec in Ge){let m=Ge[h.codec];c.set(g,{fromDb:m.fromDb,toDb:m.toDb})}else h.transform!==void 0&&c.set(g,h.transform);(h.identity==="always"||h.generated!==void 0)&&l.add(g)}let u=e.primaryKey??i;return{key:n,schema:t,name:e.name,sql:t==="public"?_(e.name):`${_(s.schema(t))}.${_(e.name)}`,columns:o,ignored:a,primaryKey:u,singleKey:u.length===1?u[0]:null,uniqueKeys:st(e),transforms:c,databaseOnly:l,relations:r,projections:new Map,...e.search!==void 0?{search:{key:`${t}.${e.name}`,from:[...e.search.from]}}:{}}}function Ir(t){return`CASE WHEN isfinite(${t}) AND extract(year FROM ${t} AT TIME ZONE 'UTC') BETWEEN 1 AND 9999 THEN to_char(${t} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') ELSE ${t}::text END`}function xr(t){return`CASE WHEN isfinite(${t}) AND extract(year FROM ${t}) BETWEEN 1 AND 9999 THEN to_char(${t}, 'YYYY-MM-DD') ELSE ${t}::text END`}function vr(t,e){return`CASE WHEN ${t} IS NULL THEN NULL ELSE ARRAY(SELECT ${e("u.e")} FROM unnest(${t}) WITH ORDINALITY AS u(e, i) ORDER BY u.i) END`}function Ue(t,e){if(t!==null&&t.startsWith("sql:")){let n=t.slice(4);return kn.has(n)||Ln.has(n)?null:`CASE WHEN ${e} IS NULL THEN NULL ELSE format('%s', ${e}) END`}switch(t){case"timestamp":return Ir(e);case"date":return xr(e);case"bigint[]":case"numeric[]":case"uuid[]":case"enum[]":return`${e}::text[]`;case"date[]":return vr(e,xr);case"timestamp[]":return vr(e,Ir)}return null}function _r(t){return t==="jsonb"||t==="sql:json"}import{createCipheriv as va,createDecipheriv as Ca,createHash as Dr,randomBytes as _a}from"node:crypto";var Ee=(t,e="page")=>new Ae({fields:[{field:e,message:t}]},t);function Pr(t){return Dr("sha256").update("palbase:cursor:v1\0").update(t).digest()}function Xt(t){let e=n=>typeof n=="bigint"?{$bigint:n.toString()}:n instanceof Date?{$date:n.toISOString()}:Array.isArray(n)?n.map(e):n&&typeof n=="object"?Object.fromEntries(Object.keys(n).sort().map(s=>[s,e(n[s])])):n;return Dr("sha256").update(JSON.stringify(e(t))).digest("base64url")}function Mr(t,e){let{iat:n,exp:s,nbf:r,jti:o,...a}=e;return Xt({role:t,authorization:a})}function qr(t,e,n){let s=_a(12),r=va("aes-256-gcm",t,s);r.setAAD(Buffer.from(e));let o=Buffer.concat([r.update(JSON.stringify(n),"utf8"),r.final()]),a=`p1.${Buffer.concat([s,r.getAuthTag(),o]).toString("base64url")}`;if(a.length>16384)throw Ee("page cursor values are too large; choose shorter ordering columns");return a}function Fr(t,e,n,s){try{if(typeof n!="string"||n.length>16384||!/^p1\.[\w-]+$/.test(n))throw new Error;let r=Buffer.from(n.slice(3),"base64url");if(r.length<30||r.toString("base64url")!==n.slice(3))throw new Error;let o=Ca("aes-256-gcm",t,r.subarray(0,12));o.setAAD(Buffer.from(e)),o.setAuthTag(r.subarray(12,28));let a=JSON.parse(Buffer.concat([o.update(r.subarray(28)),o.final()]).toString("utf8"));if(!Array.isArray(a)||a.length!==s||a.some(i=>i!==null&&typeof i!="string"))throw new Error;return a}catch{throw Ee("Invalid cursor for this query or identity; restart from the first page","cursor")}}var Da=new Set(["uuid","text","integer","bigint","boolean","timestamp","numeric","enum"]);function Ur(t,e,n){let s=n;if("limit"in s||"offset"in s)throw Ee("page uses first/after or last/before, not limit/offset");let r=n.last!==void 0||n.before!==void 0;if(r&&(n.first!==void 0||n.after!==void 0))throw Ee("Use first/after or last/before in one page request");let o=(r?n.last:n.first)??50;if(!Number.isInteger(o)||o<1||o>1e3)throw Ee("page size must be an integer between 1 and 1000");if(e.length===0)throw new Error("page requires a declared primary key for a unique, stable ordering");Y(n.orderBy,"orderBy","the order");let a=n.orderBy===void 0?[]:Array.isArray(n.orderBy)?n.orderBy:[n.orderBy];if(a.length>16)throw Ee("page supports at most 16 ordering columns");let i=new Set,c=[],l=u=>{Y(u,"orderBy","the order");let g=t[u?.column];if(!Object.hasOwn(t,u?.column)||!g)throw Ee(`page order column ${u?.column} is not declared`);if(!Da.has(g.type??""))throw Ee(`page cannot order ${u.column}: ${g.type??"unknown"} is not a supported scalar column`);if(i.has(u.column))throw Ee(`page order column ${u.column} is repeated`);if(u.direction!==void 0&&u.direction!=="asc"&&u.direction!=="desc")throw Ee("page direction must be asc or desc");if(u.nulls!==void 0&&u.nulls!=="first"&&u.nulls!=="last")throw Ee("page nulls must be first or last");let p=u.direction??"asc";i.add(u.column),c.push({column:u.column,direction:p,nulls:u.nulls??(p==="asc"?"last":"first"),nullable:g.nullable!==!1})};for(let u of a)l(u);for(let u of e)i.has(u)||l({column:u,direction:c.at(-1)?.direction??"asc"});return{order:c,size:o,backward:r,token:r?n.before:n.after}}function Yt(t,e,n,s,r,o=!1){let a=e.map(l=>s(l));if(t.every(l=>!l.nullable&&l.direction===t[0].direction)&&e.every(l=>l!==null)){let l=t[0].direction==="asc"!==n;return`(${t.map(u=>r(u.column)).join(", ")}) ${l?">":"<"}${o?"=":""} (${a.join(", ")})`}let i=[],c=[];for(let l=0;l<t.length;l++){let u=t[l],g=r(u.column),p=a[l],h=u.nulls==="last"!==n,m=u.direction==="asc"!==n?">":"<",y=e[l]===null?h?"false":`${g} IS NOT NULL`:`(${g} ${m} ${p}${h?` OR ${g} IS NULL`:""})`;i.push(`(${[...c,y].join(" AND ")})`),c.push(`${g} IS NOT DISTINCT FROM ${p}`)}return o&&i.push(`(${c.join(" AND ")})`),`(${i.join(" OR ")})`}import{AsyncResource as mo}from"node:async_hooks";var Pa=5e3,ot=()=>new oe(503,"database_deadline_exceeded","Database transaction exceeded its deadline"),Qe=class{deadline;controller=new AbortController;active=new Set;cancelBackend;cancellation=Promise.resolve();cancelledAt;timer;unlink;rejection;get signal(){return this.controller.signal}constructor(e,n){this.deadline=e===void 0?void 0:performance.now()+e,this.rejection=new Promise((r,o)=>{this.signal.addEventListener("abort",()=>{o(this.signal.reason),this.active.size&&this.cancelBackend&&this.cancel()},{once:!0})}),this.rejection.catch(()=>{});let s=()=>this.controller.abort(n?.reason??new DOMException("Database transaction cancelled","AbortError"));n?.addEventListener("abort",s,{once:!0}),this.unlink=()=>n?.removeEventListener("abort",s),n?.aborted&&s(),e!==void 0&&(this.timer=setTimeout(()=>this.controller.abort(ot()),e))}check(){this.deadline!==void 0&&performance.now()>=this.deadline&&!this.signal.aborted&&this.controller.abort(ot()),this.signal.throwIfAborted()}checkDeadline(){if(!(this.deadline===void 0||performance.now()<this.deadline))throw this.signal.aborted||this.controller.abort(ot()),ot()}remainingMs(){return this.check(),this.deadline===void 0?void 0:Math.max(1,Math.ceil(this.deadline-performance.now()))}race(e){return Promise.race([e,this.rejection])}bindBackend(e){this.cancelBackend=e}async drainCancellation(){let e=(async()=>(await this.cancellation,await Promise.allSettled([...this.active]),!0))();if(this.cancelledAt===void 0)return e;let n,s=new Promise(r=>{n=setTimeout(()=>r(!1),Math.max(0,this.cancelledAt+Pa-performance.now()))});try{return await Promise.race([e,s])}finally{clearTimeout(n)}}async watch(e){this.active.add(e);try{return this.signal.aborted&&this.cancelBackend&&this.cancel(),await e}finally{this.active.delete(e)}}cancel(){this.cancelledAt??=performance.now(),this.cancellation=this.cancelBackend().catch(()=>{})}dispose(){this.timer!==void 0&&clearTimeout(this.timer),this.unlink()}};import{createHash as Ma}from"node:crypto";var at=class{start=performance.now();options;ended;failure;state;constructor(e){this.options=e;for(let n of["maxQueries","maxRows","maxBytes"]){let s=e[n];if(s!==void 0&&(!Number.isSafeInteger(s)||s<0))throw new Error(`database ${n} must be a nonnegative safe integer`)}this.state={endpoint:e.endpoint,requestId:e.requestId,outcome:"active",elapsedMs:0,queries:0,rows:0,bytes:0,queueMs:0,poolMs:0,setupMs:0,sqlMs:0,commitMs:0,rollbackMs:0,connectionMs:0,commits:0,commitFailures:0,rollbackRequests:0,retries:0,statements:[]}}check(){if(this.failure)throw this.failure}time(e,n){this.state[e]=(this.state[e]??0)+performance.now()-n}retry(){this.state.retries++}committed(){this.state.commits++}commitFailed(){this.state.commitFailures++}failed(){this.state.outcome="failed"}rolledBack(){this.state.rollbackRequests++}refuse(e){throw this.failure??=new oe(500,"database_budget_exceeded",`Database ${e} budget exceeded${this.options.endpoint?` in ${this.options.endpoint}`:""}`),this.failure}emit(e,n){try{let s=e?.(n);s&&Promise.resolve(s).catch(()=>{})}catch{}}async query(e,n){this.check(),this.options.maxQueries!==void 0&&this.state.queries>=this.options.maxQueries&&this.refuse("query count");let r={ordinal:++this.state.queries,fingerprint:Ma("sha256").update(e).digest("hex").slice(0,24),...this.options.includeSql?{sql:e.slice(0,4096)}:{},durationMs:0,rows:0,bytes:0};this.options.captureSource&&(r.source=new Error().stack?.split(`
341
+ SELECT count(*)::int AS n FROM missing`,[S,v]);if(Number(U?.n??0)>0){A+=Number(U.n);continue}let[C]=await i(`SELECT ${le}.promote($1) AS gen`,[S]);C?.gen!==null&&C?.gen!==void 0&&(N.push(S),s?.(`palgres: search of ${S}: every row is embedded again \u2014 generation ${String(C.gen)} serves`))}return A}async function d(N={}){let A=N.timeoutMs===void 0?1/0:Date.now()+N.timeoutMs,b=[],L=0,S=()=>Date.now()<A&&(N.max===void 0||L<N.max)&&!(N.whileRunning===!0&&c);for(;;){for(;S();){let v=await l(N.max===void 0?Wr:Math.min(Wr,N.max-L));if(v.length===0)break;let q=new Map;for(let x of v){let I=`${x.table_key}\0${x.gen}`,B=q.get(I);B?B.push(x):q.set(I,[x])}let U={answered:!1,down:!1,failed:0},C=0;for(let x of q.values())try{C+=await $(x,U)}catch(I){U.failed+=x.length,await p(x,I).catch(()=>{})}if(L+=C,C===0&&U.failed>0)return{embedded:L,promoted:b}}if(!S()||await f(b)===0)break}return{embedded:L,promoted:b}}let T,y,w=!1,O,k=()=>{w=!0,y?.()};return{drain:N=>d(N),kick:k,start(){T===void 0&&(c=!1,O=nt.listen(k),T=(async()=>{await i(`UPDATE ${le}.queue SET attempts = 0, next_attempt_at = now(), last_error = NULL WHERE next_attempt_at = 'infinity'`).catch(A=>s?.(`palgres: the search worker could not read its queue (${pt(A)})`));let N=jr;for(;!c;){w=!1;let A=!1;try{let b=await d({timeoutMs:Va,whileRunning:!0});A=b.embedded>0||b.promoted.length>0}catch(b){s?.(`palgres: the search worker could not embed (${pt(b)}); it looks again`)}N=A?jr:Math.min(Ha,N*2),!(c||w)&&(await new Promise(b=>{let L=setTimeout(b,N);L.unref?.(),y=()=>{clearTimeout(L),b()}}),y=void 0)}})())},async stop(){if(T===void 0)return;c=!0,O?.(),O=void 0,y?.();let N=T;T=void 0;let A;await Promise.race([N,new Promise(b=>A=setTimeout(b,Ga))]),clearTimeout(A)}}}var os=class{options;active=0;queued=0;tenants=new Map;pending=new Map;lastTenant;accepted=0;rejected={full:0,timeout:0,cancelled:0};limit;timeout;nestedLimit;nestedActive=0;nestedPending=new Set;constructor(e){if(this.options=e,this.limit=e.queueLimit??Math.min(512,Math.max(32,e.concurrency*8)),this.timeout=e.queueTimeoutMs??1e3,this.nestedLimit=e.nestedConcurrency??e.concurrency*2,!Number.isSafeInteger(e.concurrency)||e.concurrency<1||!Number.isSafeInteger(this.nestedLimit)||this.nestedLimit<1||!Number.isSafeInteger(this.limit)||this.limit<0||this.limit>1e4||!Number.isSafeInteger(this.timeout)||this.timeout<1||this.timeout>6e4)throw new Error("Invalid database pool or queue deployment settings")}get queueTimeoutMs(){return this.timeout}get snapshot(){return{active:this.active,queued:this.queued,nested:{active:this.nestedActive,queued:this.nestedPending.size},tenants:this.tenants.size,accepted:this.accepted,rejected:{...this.rejected}}}nestedLease(e){this.nestedActive++;let n=!1;return{queueMs:performance.now()-e,release:()=>{if(n)return;n=!0,this.nestedActive--;let s=this.nestedPending.values().next().value;s&&(this.nestedPending.delete(s),s.cleanup(),s.grant(this.nestedLease(s.entered)))}}}acquireNested(e){let n=performance.now();return this.nestedActive<this.nestedLimit?Promise.resolve(this.nestedLease(n)):new Promise((s,r)=>{let o={grant:s,reject:r,entered:n,cleanup(){}},a=(l,u)=>{this.nestedPending.delete(o)&&(o.cleanup(),this.rejection(l),r(u))},i=()=>a("cancelled",e?.reason??new Error("Database admission cancelled")),c=setTimeout(()=>a("timeout",new Fe({retryAfter:1},"Database queue deadline exceeded")),this.timeout);o.cleanup=()=>{clearTimeout(c),e?.removeEventListener("abort",i)},this.nestedPending.add(o),e?.addEventListener("abort",i,{once:!0}),e?.aborted&&i()})}rejection(e){this.rejected[e]++;try{this.options.onReject?.({reason:e,active:this.active,queued:this.queued})}catch{}}take(e,n){this.active++,this.accepted++,this.lastTenant=e,this.tenants.set(e,(this.tenants.get(e)??0)+1);let s=!1;return{queueMs:performance.now()-n,release:()=>{if(s)return;s=!0,this.active--;let r=(this.tenants.get(e)??1)-1;r?this.tenants.set(e,r):this.tenants.delete(e),this.drain()}}}drain(){for(;this.active<this.options.concurrency&&this.queued;){let e=this.pending.keys().next().value;if(this.pending.size>1&&e===this.lastTenant){let r=this.pending.get(e);this.pending.delete(e),this.pending.set(e,r),e=this.pending.keys().next().value}let n=this.pending.get(e),s=n.values().next().value;n.delete(s),this.pending.delete(e),n.size&&this.pending.set(e,n),this.queued--,s.cleanup(),s.grant(this.take(e,s.entered))}}async acquire(e,n,s={}){if(n?.aborted)throw this.rejection("cancelled"),n.reason??new Error("Database admission cancelled");if(s.nested)return this.acquireNested(n);let r=this.options.tenantClaim?e[this.options.tenantClaim]:e.sub,o=typeof r=="string"&&r.length?r:"__anonymous__",a=performance.now();if(this.active<this.options.concurrency&&!this.queued)return this.take(o,a);if(!s.returning&&this.queued>=this.limit)throw this.rejection("full"),new Fe({retryAfter:1},"Database queue is full");return new Promise((i,c)=>{let l=this.pending.get(o)??new Set;this.pending.has(o)||this.pending.set(o,l);let u={grant:i,reject:c,entered:a,cleanup(){}},g=(p,E)=>{l.delete(u)&&(l.size||this.pending.delete(o),this.queued--,u.cleanup(),this.rejection(p),c(E),this.drain())},m=()=>g("cancelled",n?.reason??new Error("Database admission cancelled")),h=setTimeout(()=>g("timeout",new Fe({retryAfter:1},"Database queue deadline exceeded")),this.timeout);if(u.cleanup=()=>{clearTimeout(h),n?.removeEventListener("abort",m)},s.returning){u.returning=!0;let p=[...l];l.clear();for(let E of p)E.returning&&l.add(E);l.add(u);for(let E of p)E.returning||l.add(E)}else l.add(u);this.queued++,n?.addEventListener("abort",m,{once:!0}),n?.aborted?m():this.drain()})}},Kr=new WeakMap;function Hr(t,e={concurrency:10}){let n=Kr.get(t);if(!n)return n=new os(e),Kr.set(t,n),n;for(let s of["concurrency","queueLimit","queueTimeoutMs","tenantClaim"])if(e[s]!==n.options[s])throw new Error("Database admission cannot be reconfigured while its pool is shared");return n}function Ya(t){return t.endsWith("_id")?t.slice(0,-3):t}function Vr(t){return t.direction==="forward"?`the foreign key "${t.table}.${t.column}"`:`the reverse of "${t.table}.${t.column}"`}function Gr(t){return t.direction==="reverse"?'references(() => \u2026, { reverseAs: "\u2026" })':t.def.selfRefColumn!==void 0?'selfReferences("\u2026", { as: "\u2026" })':'references(() => \u2026, { as: "\u2026" })'}function Nn(t){let e=new Map,n=new Map;for(let r of t)for(let o of Object.values(r.tables)){let a=ye(r.name,o.name);e.set(a,[]),n.set(a,new Map)}let s=(r,o,a,i)=>{let c=n.get(r);if(c===void 0)return;let l=c.get(o);if(l!==void 0){let u=Gr(l),g=Gr(a),m=u===g?`rename one of them: ${u}`:`rename one of them \u2014 "${l.table}.${l.column}": ${u}; "${a.table}.${a.column}": ${g}`;throw new Me([`table "${r}": ${Vr(l)} and ${Vr(a)} both resolve to the relation name "${o}" \u2014 ${m}`])}c.set(o,a),e.get(r)?.push(i)};for(let r of t)for(let o of Object.values(r.tables)){let a=ye(r.name,o.name);for(let[i,c]of Object.entries(o.columns)){let l=c._def;if(l.references===void 0)continue;let u=l.references.table,g=l.refAs??Ya(i);if(s(a,g,{table:o.name,column:i,direction:"forward",def:l},{name:g,to:u,kind:"one",via:i}),!e.has(u)||u===a)continue;let m=l.reverseAs??o.name;s(u,m,{table:o.name,column:i,direction:"reverse",def:l},{name:m,to:a,kind:"many",via:i})}}return e}function Ja(t){let e=t.columns??{},n=[],s=[];for(let[a,i]of Object.entries(e)){let c=i&&typeof i=="object"&&"_def"in i?i._def:i;c?.primaryKey&&n.push(a),c?.unique&&s.push([a])}let r=t.primaryKey??n;r.length&&s.unshift([...r]);for(let a of t.unique??[])s.push([...a.columns]);let o=new Set;return s.filter(a=>{if(!a.length||new Set(a).size!==a.length||a.some(c=>!Object.hasOwn(e,c)))throw new Error("Unique lookup requires a nonempty declared key of distinct, known columns");let i=JSON.stringify([...a].sort());return o.has(i)?!1:(o.add(i),!0)})}function ft(t){let e=Object.fromEntries(Object.entries(t.columns).filter(([,n])=>n?._def?.ignored!==!0));return Ja({columns:e,primaryKey:t.primaryKey,unique:t.unique})}function Xr(t,e,n){if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`findUnique(${t}): where must contain one declared unique key`);let s=Object.keys(n);if(!e.some(r=>r.length===s.length&&r.every(o=>Object.hasOwn(n,o))))throw new Error(`findUnique(${t}): supply exactly one declared unique key (${e.map(r=>r.join(" + ")).join("; ")||"none declared"}); use findMany for other filters`);for(let[r,o]of Object.entries(n))if(o==null||typeof o=="object"&&!(o instanceof Date)||typeof o=="function"||typeof o=="symbol")throw new Error(`findUnique(${t}): ${r} requires a non-null scalar equality value`)}var _=t=>`"${t.replace(/"/g,'""')}"`;function Qr(t){return t.type==="sql"&&typeof t.sqlType=="string"?`sql:${t.sqlType}`:t.type}var gt=class{version;tables=new Map;ignoredTables=new Set;schemas;deferrals;fields;constructor(e,n,s=null){this.version=n.version,this.schemas=e,this.fields=s;let r=Nn(e);for(let o of e)for(let a of Object.values(o.tables)){let i=ye(o.name,a.name);if(a.ignored){this.ignoredTables.add(i);continue}this.tables.set(i,Qa(o.name,a,i,n,r.get(i)??[],s))}}encryptedColumns(){return[...this.tables.values()].flatMap(e=>[...e.encrypted].map(([n,s])=>({table:e,column:n,encrypted:s})))}table(e,n){let s=this.tables.get(e);if(s)return s;throw this.ignoredTables.has(e)?new Error(`${n}(${e}): the table is .ignored() in this version \u2014 the version has promised not to name it, so the next one can drop it`):new Error(`${n}(${e}): no such table in this version's schema (a table outside public is "schema.table")`)}deferral(e){return this.deferrals??=za(Ds([...this.schemas])),this.deferrals.get(`${e.schema}.${e.name}`)??null}};function za(t){let e=(o,a)=>`${o}.${a}`,n=new Map,s=new Map;for(let o of t.tables)for(let a of o.foreignKeys){let i=e(a.refSchema,a.refTable);a.onDelete==="cascade"&&n.set(i,[...n.get(i)??[],e(o.schema,o.name)]),a.deferrable&&s.set(i,[...s.get(i)??[],e(o.schema,a.name)])}let r=new Map;for(let o of t.tables){let a=new Set([e(o.schema,o.name)]);for(let l of a)for(let u of n.get(l)??[])a.add(u);let i=[...new Set([...a].flatMap(l=>s.get(l)??[]))].sort();if(i.length===0)continue;let c=`ARRAY[${i.map(M).join(", ")}]::text[]`;r.set(e(o.schema,o.name),{defer:`SELECT palgres.defer_keys(${c}, true)`,check:`SELECT palgres.defer_keys(${c}, false)`})}return r}function Qa(t,e,n,s,r,o){let a=new Map,i=new Set,c=[],l=new Map,u=new Set,g=new Map;for(let[h,p]of Object.entries(e.columns)){let E=p._def;if(E.ignored){i.add(h);continue}a.set(h,E),E.primaryKey&&c.push(h);let $=Qe(t,e.name,h);if(E.encrypted!==void 0){if(o===null)throw new Error(`${n}.${h} is .encrypted(): the engine needs the project's fields to seal and open it \u2014 createDatabase({ fields }) (palbase/backend gives it)`);g.set(h,{address:$,lookup:E.encrypted.lookup?ks(h):null}),l.set(h,{fromDb:f=>Za(o,$,f)});continue}if(o!==null&&E.type==="text"&&o.sealing.get($)?.direction==="open"){l.set(h,{fromDb:f=>typeof f=="string"&&o.sealing.get($)!==void 0&&o.cipher.isEncrypted(f)?o.cipher.decrypt($,f):f,toDb:f=>(o.sealing.get($)!==void 0&&Vn($,f),f)});continue}if(typeof E.codec=="string"&&E.codec in Ye){let f=Ye[E.codec];l.set(h,{fromDb:f.fromDb,toDb:f.toDb})}else E.transform!==void 0&&l.set(h,E.transform);(E.identity==="always"||E.generated!==void 0)&&u.add(h)}let m=e.primaryKey??c;return{key:n,schema:t,name:e.name,sql:t==="public"?_(e.name):`${_(s.schema(t))}.${_(e.name)}`,columns:a,ignored:i,primaryKey:m,singleKey:m.length===1?m[0]:null,uniqueKeys:ft(e),transforms:l,databaseOnly:u,relations:r,projections:new Map,...e.search!==void 0?{search:{key:`${t}.${e.name}`,from:[...e.search.from]}}:{},encrypted:g,fields:o}}function Za(t,e,n){if(typeof n!="string")return n;if(t.sealing.get(e)===void 0)return t.cipher.decrypt(e,n);if(!t.cipher.isEncrypted(n))return n;try{return t.cipher.decrypt(e,n)}catch{return n}}function Yr(t){return`CASE WHEN isfinite(${t}) AND extract(year FROM ${t} AT TIME ZONE 'UTC') BETWEEN 1 AND 9999 THEN to_char(${t} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"') ELSE ${t}::text END`}function Jr(t){return`CASE WHEN isfinite(${t}) AND extract(year FROM ${t}) BETWEEN 1 AND 9999 THEN to_char(${t}, 'YYYY-MM-DD') ELSE ${t}::text END`}function zr(t,e){return`CASE WHEN ${t} IS NULL THEN NULL ELSE ARRAY(SELECT ${e("u.e")} FROM unnest(${t}) WITH ORDINALITY AS u(e, i) ORDER BY u.i) END`}function We(t,e){if(t!==null&&t.startsWith("sql:")){let n=t.slice(4);return Pn.has(n)||Mn.has(n)?null:`CASE WHEN ${e} IS NULL THEN NULL ELSE format('%s', ${e}) END`}switch(t){case"timestamp":return Yr(e);case"date":return Jr(e);case"bigint[]":case"numeric[]":case"uuid[]":case"enum[]":return`${e}::text[]`;case"date[]":return zr(e,Jr);case"timestamp[]":return zr(e,Yr)}return null}function Zr(t){return t==="jsonb"||t==="sql:json"}import{createCipheriv as ei,createDecipheriv as ni,createHash as eo,randomBytes as ti}from"node:crypto";var we=(t,e="page")=>new Oe({fields:[{field:e,message:t}]},t);function no(t){return eo("sha256").update("palbase:cursor:v1\0").update(t).digest()}function as(t){let e=n=>typeof n=="bigint"?{$bigint:n.toString()}:n instanceof Date?{$date:n.toISOString()}:Array.isArray(n)?n.map(e):n&&typeof n=="object"?Object.fromEntries(Object.keys(n).sort().map(s=>[s,e(n[s])])):n;return eo("sha256").update(JSON.stringify(e(t))).digest("base64url")}function to(t,e){let{iat:n,exp:s,nbf:r,jti:o,...a}=e;return as({role:t,authorization:a})}function so(t,e,n){let s=ti(12),r=ei("aes-256-gcm",t,s);r.setAAD(Buffer.from(e));let o=Buffer.concat([r.update(JSON.stringify(n),"utf8"),r.final()]),a=`p1.${Buffer.concat([s,r.getAuthTag(),o]).toString("base64url")}`;if(a.length>16384)throw we("page cursor values are too large; choose shorter ordering columns");return a}function ro(t,e,n,s){try{if(typeof n!="string"||n.length>16384||!/^p1\.[\w-]+$/.test(n))throw new Error;let r=Buffer.from(n.slice(3),"base64url");if(r.length<30||r.toString("base64url")!==n.slice(3))throw new Error;let o=ni("aes-256-gcm",t,r.subarray(0,12));o.setAAD(Buffer.from(e)),o.setAuthTag(r.subarray(12,28));let a=JSON.parse(Buffer.concat([o.update(r.subarray(28)),o.final()]).toString("utf8"));if(!Array.isArray(a)||a.length!==s||a.some(i=>i!==null&&typeof i!="string"))throw new Error;return a}catch{throw we("Invalid cursor for this query or identity; restart from the first page","cursor")}}var si=new Set(["uuid","text","integer","bigint","boolean","timestamp","numeric","enum"]);function oo(t,e,n){let s=n;if("limit"in s||"offset"in s)throw we("page uses first/after or last/before, not limit/offset");let r=n.last!==void 0||n.before!==void 0;if(r&&(n.first!==void 0||n.after!==void 0))throw we("Use first/after or last/before in one page request");let o=(r?n.last:n.first)??50;if(!Number.isInteger(o)||o<1||o>1e3)throw we("page size must be an integer between 1 and 1000");if(e.length===0)throw new Error("page requires a declared primary key for a unique, stable ordering");Y(n.orderBy,"orderBy","the order");let a=n.orderBy===void 0?[]:Array.isArray(n.orderBy)?n.orderBy:[n.orderBy];if(a.length>16)throw we("page supports at most 16 ordering columns");let i=new Set,c=[],l=u=>{Y(u,"orderBy","the order");let g=t[u?.column];if(!Object.hasOwn(t,u?.column)||!g)throw we(`page order column ${u?.column} is not declared`);if(!si.has(g.type??""))throw we(`page cannot order ${u.column}: ${g.type??"unknown"} is not a supported scalar column`);if(i.has(u.column))throw we(`page order column ${u.column} is repeated`);if(u.direction!==void 0&&u.direction!=="asc"&&u.direction!=="desc")throw we("page direction must be asc or desc");if(u.nulls!==void 0&&u.nulls!=="first"&&u.nulls!=="last")throw we("page nulls must be first or last");let m=u.direction??"asc";i.add(u.column),c.push({column:u.column,direction:m,nulls:u.nulls??(m==="asc"?"last":"first"),nullable:g.nullable!==!1})};for(let u of a)l(u);for(let u of e)i.has(u)||l({column:u,direction:c.at(-1)?.direction??"asc"});return{order:c,size:o,backward:r,token:r?n.before:n.after}}function is(t,e,n,s,r,o=!1){let a=e.map(l=>s(l));if(t.every(l=>!l.nullable&&l.direction===t[0].direction)&&e.every(l=>l!==null)){let l=t[0].direction==="asc"!==n;return`(${t.map(u=>r(u.column)).join(", ")}) ${l?">":"<"}${o?"=":""} (${a.join(", ")})`}let i=[],c=[];for(let l=0;l<t.length;l++){let u=t[l],g=r(u.column),m=a[l],h=u.nulls==="last"!==n,p=u.direction==="asc"!==n?">":"<",E=e[l]===null?h?"false":`${g} IS NOT NULL`:`(${g} ${p} ${m}${h?` OR ${g} IS NULL`:""})`;i.push(`(${[...c,E].join(" AND ")})`),c.push(`${g} IS NOT DISTINCT FROM ${m}`)}return o&&i.push(`(${c.join(" AND ")})`),`(${i.join(" OR ")})`}import{AsyncResource as Co}from"node:async_hooks";var ri=5e3,ht=()=>new oe(503,"database_deadline_exceeded","Database transaction exceeded its deadline"),sn=class{deadline;controller=new AbortController;active=new Set;cancelBackend;cancellation=Promise.resolve();cancelledAt;timer;unlink;rejection;get signal(){return this.controller.signal}constructor(e,n){this.deadline=e===void 0?void 0:performance.now()+e,this.rejection=new Promise((r,o)=>{this.signal.addEventListener("abort",()=>{o(this.signal.reason),this.active.size&&this.cancelBackend&&this.cancel()},{once:!0})}),this.rejection.catch(()=>{});let s=()=>this.controller.abort(n?.reason??new DOMException("Database transaction cancelled","AbortError"));n?.addEventListener("abort",s,{once:!0}),this.unlink=()=>n?.removeEventListener("abort",s),n?.aborted&&s(),e!==void 0&&(this.timer=setTimeout(()=>this.controller.abort(ht()),e))}check(){this.deadline!==void 0&&performance.now()>=this.deadline&&!this.signal.aborted&&this.controller.abort(ht()),this.signal.throwIfAborted()}checkDeadline(){if(!(this.deadline===void 0||performance.now()<this.deadline))throw this.signal.aborted||this.controller.abort(ht()),ht()}remainingMs(){return this.check(),this.deadline===void 0?void 0:Math.max(1,Math.ceil(this.deadline-performance.now()))}race(e){return Promise.race([e,this.rejection])}bindBackend(e){this.cancelBackend=e}async drainCancellation(){let e=(async()=>(await this.cancellation,await Promise.allSettled([...this.active]),!0))();if(this.cancelledAt===void 0)return e;let n,s=new Promise(r=>{n=setTimeout(()=>r(!1),Math.max(0,this.cancelledAt+ri-performance.now()))});try{return await Promise.race([e,s])}finally{clearTimeout(n)}}async watch(e){this.active.add(e);try{return this.signal.aborted&&this.cancelBackend&&this.cancel(),await e}finally{this.active.delete(e)}}cancel(){this.cancelledAt??=performance.now(),this.cancellation=this.cancelBackend().catch(()=>{})}dispose(){this.timer!==void 0&&clearTimeout(this.timer),this.unlink()}};import{createHash as oi}from"node:crypto";var Et=class{start=performance.now();options;ended;failure;state;constructor(e){this.options=e;for(let n of["maxQueries","maxRows","maxBytes"]){let s=e[n];if(s!==void 0&&(!Number.isSafeInteger(s)||s<0))throw new Error(`database ${n} must be a nonnegative safe integer`)}this.state={endpoint:e.endpoint,requestId:e.requestId,outcome:"active",elapsedMs:0,queries:0,rows:0,bytes:0,queueMs:0,poolMs:0,setupMs:0,sqlMs:0,commitMs:0,rollbackMs:0,connectionMs:0,commits:0,commitFailures:0,rollbackRequests:0,retries:0,statements:[]}}check(){if(this.failure)throw this.failure}time(e,n){this.state[e]=(this.state[e]??0)+performance.now()-n}retry(){this.state.retries++}committed(){this.state.commits++}commitFailed(){this.state.commitFailures++}failed(){this.state.outcome="failed"}rolledBack(){this.state.rollbackRequests++}refuse(e){throw this.failure??=new oe(500,"database_budget_exceeded",`Database ${e} budget exceeded${this.options.endpoint?` in ${this.options.endpoint}`:""}`),this.failure}emit(e,n){try{let s=e?.(n);s&&Promise.resolve(s).catch(()=>{})}catch{}}async query(e,n){this.check(),this.options.maxQueries!==void 0&&this.state.queries>=this.options.maxQueries&&this.refuse("query count");let r={ordinal:++this.state.queries,fingerprint:oi("sha256").update(e).digest("hex").slice(0,24),...this.options.includeSql?{sql:e.slice(0,4096)}:{},durationMs:0,rows:0,bytes:0};this.options.captureSource&&(r.source=new Error().stack?.split(`
338
342
  `).slice(1,9).join(`
339
- `).slice(0,2500));let o=performance.now(),a=!1;try{let i=await n();return r.durationMs=performance.now()-o,a=!0,Array.isArray(i)&&(r.rows=i.length,r.bytes=Buffer.byteLength(JSON.stringify(i,(c,l)=>typeof l=="bigint"?l.toString():l))),this.state.rows+=r.rows,this.state.bytes+=r.bytes,this.options.maxRows!==void 0&&this.state.rows>this.options.maxRows&&this.refuse("returned rows"),this.options.maxBytes!==void 0&&this.state.bytes>this.options.maxBytes&&this.refuse("result bytes"),i}catch(i){let c=i;throw r.errorCode=String(c?.errno??c?.code??"query_failed").slice(0,80),i}finally{a||(r.durationMs=performance.now()-o),this.state.sqlMs+=r.durationMs;let i=Object.freeze(r);this.state.statements.length<200&&this.state.statements.push(i),this.emit(this.options.onQuery,i)}}get snapshot(){return Object.freeze({...this.state,elapsedMs:(this.ended??performance.now())-this.start,statements:Object.freeze([...this.state.statements].sort((e,n)=>e.ordinal-n.ordinal))})}complete(e){this.ended===void 0&&(this.ended=performance.now(),this.state.outcome=e,this.emit(this.options.onComplete,this.snapshot))}};var Kr=new WeakMap,Hr=new WeakSet;function ee(t){let e=n=>`$${t.push(n)}`;return Kr.set(e,t),e}var Qt=t=>Hr.has(t);var Vr=t=>`'${t.replace(/'/g,"''")}'`;function Se(t,e){let n=t.columns.get(e);return n?Cr(n):null}function se(t,e,n,s){if(!t.columns.has(e))throw t.ignored.has(e)?new Error(`${n}(${t.key}): ${s} "${e}" is .ignored() in this version \u2014 the version has promised not to name it, so the next one can drop it`):new Error(`${n}(${t.key}): ${s} "${e}" is not a column of the table`)}function we(t,e,n){if(n==null)return n;let s=t.transforms.get(e)?.toDb,r=s===void 0?n:s(n),o=Se(t,e);return o===null||r===null||r===void 0?r:o.endsWith("[]")&&Array.isArray(r)?En(r):_r(o)?JSON.stringify(r):r}function Gr(t,e,n){let s=n.find(r=>t.databaseOnly.has(r));if(s!==void 0)throw new Error(`${e}(${t.key}): "${s}" is written by the database (an ALWAYS .identity()) \u2014 leave it out of the write; Postgres refuses any value for it`)}function nn(t,e,n){for(let s of n)se(t,s,e,"column");Gr(t,e,n)}function Xr(t,e,n,s){return xn(e,t.key,[n],s),bs(e,t.key,[n],s),we(t,n,s[n])}function Zt(t,e,n){let s=`${n?`${_(n)}.`:""}${_(e)}`;return Ue(Se(t,e),s)??s}function Yr(t,e,n){let s=Zt(t,e,n);return Ue(Se(t,e),"x")!==null?`${s} AS ${_(e)}`:s}function Z(t,e){let n=e??"",s=t.projections.get(n);return s===void 0&&(s=[...t.columns.keys()].map(r=>Yr(t,r,e)).join(", "),t.projections.set(n,s)),s}function es(t,e,n){if(Y(e,"select","which columns a call reads"),e!==void 0&&e.length===0)throw new Error(`${n}(${t.key}): select got an empty list \u2014 that is not "all of them" but "none counted". Leave the key out for every column; name at least one otherwise.`);return e===void 0?Z(t,"t"):e.map(s=>(se(t,s,n,"select column"),Yr(t,s,"t"))).join(", ")}function Jr(t,e,n,s="t"){if(e==null)return"";Y(e,"orderBy","the order");let r=Array.isArray(e)?e:[e];return r.length===0?"":` ORDER BY ${r.map(a=>{Y(a,"orderBy","the order"),se(t,a.column,n,"orderBy column");let i=a.direction==="desc"?"DESC":"ASC",c=a.nulls==="first"?" NULLS FIRST":a.nulls==="last"?" NULLS LAST":"";return`${_(s)}.${_(a.column)} ${i}${c}`}).join(", ")}`}function zt(t,e="findMany"){if(t===void 0)return"";if(!Number.isInteger(t)||t<0)throw new Error(`${e}: limit must be a non-negative integer (got ${String(t)})`);return` LIMIT ${t}`}function qa(t,e,n="findMany"){if(t===void 0)return"";if(!Number.isInteger(t)||t<0)throw new Error(`${n}: offset must be a non-negative integer (got ${String(t)})`);if(e===void 0)throw new Error(`${n}: offset is given only with limit \u2014 an offset without one is the shifted tail of an unbounded result, not a page`);return` OFFSET ${t}`}var Ze={gt:">",gte:">=",lt:"<",lte:"<=",neq:"<>"},Fa=[["days","days","int"],["hours","hours","int"],["minutes","mins","int"],["seconds","secs","double precision"]];function en(t,e){let n=t?.minus;if(n===void 0)return"now()";let s=As(n);if("refused"in s)throw new TypeError(`palgres: ago() ${s.refused}`);return`(now() - make_interval(${Fa.filter(([o])=>s.span[o]!==void 0).map(([o,a,i])=>`${a} => ${e(s.span[o])}::${i}`).join(", ")}))`}var Br=Object.freeze({update:"FOR UPDATE",share:"FOR SHARE",noKeyUpdate:"FOR NO KEY UPDATE"});function ns(t,e,n,s){if(typeof s=="string"&&Object.hasOwn(Br,s))return Br[s];let r=typeof s=="string"?JSON.stringify(s.slice(0,40)):typeof s;throw new TypeError(`${t}(${e}): unknown ${n} ${r} \u2014 "update" (FOR UPDATE), "share" (FOR SHARE) or "noKeyUpdate" (FOR NO KEY UPDATE).`)}var Wr=t=>vn(t);function jr(t,e,n,s){if(!t.columns.has(e.$col))throw new Error(`${n}(${t.key}): col("${e.$col}") is not a column of the table`);return`${_(s)}.${_(e.$col)}`}function zr(t,e,n,s){let o=(n.kind==="many"?t.table(n.to,s):e).columns.get(n.via)?.references?.column??(n.kind==="many"?e.singleKey:t.table(n.to,s).singleKey);return n.kind==="many"?[o,n.via]:[n.via,o]}function Be(t,e,n){return Ne(new Ae({fields:[{field:e,message:n}]},`${t}: ${e} ${n}`))}function Ua(t,e){if(Y(t,e,"a filter"),!(typeof t!="object"||t===null))for(let[n,s]of Object.entries(t))n==="OR"||n==="AND"||n==="NOT"||n==="has"?Y(s,`${e}.${n}`,`a filter's ${n}`):s!==null&&typeof s=="object"&&!Array.isArray(s)&&Y(s,`${e}.${n}`,"an operator")}function it(t,e,n,s,r,o,a,i){let c=[];if(Ua(n,i),Ns(r,e.key,n),ln(n)){let{text:l,values:u}=n.$sql,g=Kr.get(s);if(g===void 0)throw new Error("palgres: an sqlFragment was compiled outside binder()");if(Hr.add(g),l.length!==u.length+1)throw new Error(`${r}(${e.key}): the sqlFragment's parts are broken (${l.length} texts, ${u.length} values) \u2014 only the template tag makes one`);let p=l[0]??"";for(let h=0;h<u.length;h++)p+=`${s(u[h])}${l[h+1]??""}`;if(p.trim()==="")throw Be(r,i,"is an empty sqlFragment \u2014 no condition. Write the condition in it, or leave it out.");return[`(${p})`]}for(let[l,u]of Object.entries(n)){if(l==="OR"||l==="AND"){let m=u;if(m.length===0){if(l==="AND")throw Be(r,`${i}.AND`,"is an empty list \u2014 no condition at all. Leave it out, or name a condition in it.");c.push("false");continue}let y=m.map((S,f)=>{let d=it(t,e,S,s,r,o,a,`${i}.${l}[${f}]`);if(d.length===0)throw Be(r,`${i}.${l}[${f}]`,"holds no condition \u2014 a branch that matches every row. Name a condition in it, or leave it out.");return`(${d.join(" AND ")})`});c.push(`(${y.join(l==="OR"?" OR ":" AND ")})`);continue}if(l==="NOT"){if(Array.isArray(u))throw Be(r,`${i}.NOT`,"is a list \u2014 NOT takes one filter object. For several conditions, NOT: { AND: [...] } or NOT: { OR: [...] }.");let m=it(t,e,u,s,r,o,a,`${i}.NOT`);if(m.length===0)throw Be(r,`${i}.NOT`,"holds no condition \u2014 NOT of nothing is not a filter. Name the condition to exclude.");c.push(`NOT (${m.join(" AND ")})`);continue}if(l==="has"){let m=Object.entries(u);if(m.length===0)throw Be(r,`${i}.has`,"names no relation \u2014 no condition. Name one: has: { <relation>: { \u2026 } }.");for(let[y,S]of m){let f=e.relations.find(N=>N.name===y);if(f===void 0){let N=e.relations.map(A=>A.name).sort();throw new Error(`${r}(${e.key}): there is no relation has.${y}`+(N.length>0?` (known: ${N.join(", ")}). Relations come from foreign keys; to rename one, references(..., { as, reverseAs }).`:". The table declares no foreign key, and relations come from them: references(() => <table>.<column>)."))}let[d,T]=zr(t,e,f,r);if(d===null||T===null)throw new Error(`${r}(${e.key}): has.${y} cannot be built \u2014 "${d===null?e.key:f.to}" has no single-column primary key to correlate on; write the condition as an sqlFragment`);let E=t.table(f.to,r),w=`r${a+1}`,O=lt(t,E,S??{},s,r,w,a+1,`${i}.has.${y}`),k=`${w}.${_(T)} = ${_(o)}.${_(d)}`;c.push(`EXISTS (SELECT 1 FROM ${E.sql} ${w} WHERE ${k}${O===""?"":` AND ${O}`})`)}continue}se(e,l,r,"where column");let g=`${_(o)}.${_(l)}`,p=Se(e,l)?.endsWith("[]")===!0,h=m=>s(we(e,l,m));if(xe(u)){c.push(`${g} = ${jr(e,u,r,o)}`);continue}if(Tt(u)){c.push(`${g} = ${en(Wr(u),s)}`);continue}if(u!==null&&typeof u=="object"&&!Array.isArray(u))for(let[m,y]of Object.entries(u)){if(p&&(m==="contains"||m==="overlaps")){if(!Array.isArray(y))throw new Error(`${r}(${e.key}): where.${l}.${m} must be an array \u2014 ${l} is an array column`);c.push(`${g} ${m==="contains"?"@>":"&&"} ${h(y)}`);continue}if(!p&&(m==="contains"||m==="icontains"||m==="startsWith"||m==="endsWith")){if(typeof y!="string")throw new Error(`${r}(${e.key}): where.${l}.${m} must be a string`);let f=y.replace(/([\\%_])/g,"\\$1"),d=m==="startsWith"?`${f}%`:m==="endsWith"?`%${f}`:`%${f}%`;c.push(`${g} ${m==="icontains"?"ILIKE":"LIKE"} ${s(d)}`);continue}if(m==="isNull"){if(typeof y!="boolean")throw new Error(`${r}(${e.key}): where.${l}.isNull must be a boolean`);c.push(`${g} IS ${y?"NULL":"NOT NULL"}`);continue}if(m==="in"){if(!Array.isArray(y))throw new Error(`${r}(${e.key}): where.${l}.in must be an array`);if(y.some(xe))throw new Error(`${r}(${e.key}): where.${l}.in takes values, not col() \u2014 compare with a column bare ({ ${l}: col("\u2026") }) or with gt/gte/lt/lte/neq`);if(y.length===0){c.push("false");continue}c.push(`${g} IN (${y.map(f=>h(f)).join(", ")})`);continue}if(Tt(y)){if(!(m in Ze))throw new Error(`${r}(${e.key}): where.${l}.${m} cannot take now() \u2014 for equality write it bare: { ${l}: now() }`);c.push(`${g} ${Ze[m]} ${en(Wr(y),s)}`);continue}if(In(y))throw new Error(`${r}(${e.key}): where.${l}.${m} got a WRITE expression (increment/decrement), not a comparison value. For the server's time use now(); for a numeric threshold, the value.`);if(xe(y)){if(!(m in Ze))throw new Error(`${r}(${e.key}): where.${l}.${m} cannot take col() \u2014 for equality write it bare: { ${l}: col("\u2026") }`);c.push(`${g} ${Ze[m]} ${jr(e,y,r,o)}`);continue}let S=Rs(y);if(S!==null){let f=S==="col"?"col()":S==="sql"?"sqlFragment":"now()";throw new Error(`${r}(${e.key}): where.${l}.${m} got an imitation of ${f} \u2014 this object was not made by ${f} in this process. A filter from a request body cannot carry a handle; build the condition in your code.`)}if(m in Ze){if(y===null&&m==="neq"){c.push(`${g} IS NOT NULL`);continue}c.push(`${g} ${Ze[m]} ${h(y)}`);continue}throw new Error(`${r}(${e.key}): where.${l} has an unknown operator "${m}" (gt/gte/lt/lte/neq/in)`)}else u===null?c.push(`${g} IS NULL`):c.push(`${g} = ${h(u)}`)}return c}function lt(t,e,n,s,r,o="t",a=0,i="where"){return it(t,e,n,s,r,o,a,i).join(" AND ")}function Re(t,e,n,s,r){let o=it(t,e,n,s,r,"t",0,"where");return{sql:o.length===0?"":` AND ${o.join(" AND ")}`,conditions:o.length}}function tn(t,e){if(!(t.conditions>0))throw Be(e,"where",`holds no condition, so ${e} would reach EVERY row of the table. Name a condition.`)}function Tn(t,e,n){if(n!=="ignore"&&n!=="update")throw new TypeError(`palgres: a conflict's action is "ignore" or "update", not ${typeof n=="string"?JSON.stringify(String(n).slice(0,40)):typeof n}`);if(e.length===0){if(n==="ignore")return"ON CONFLICT DO NOTHING";throw new Error("palgres: ON CONFLICT DO UPDATE needs the columns a collision is matched on")}let s=`ON CONFLICT (${e.map(_).join(", ")})`;if(n==="ignore")return`${s} DO NOTHING`;let r=new Set(e),o=t.filter(a=>!r.has(a)).map(a=>`${_(a)} = EXCLUDED.${_(a)}`);return o.length?`${s} DO UPDATE SET ${o.join(", ")}`:`${s} DO UPDATE SET ${_(e[0])} = EXCLUDED.${_(e[0])}`}function ts(t,e,n,s,r){return Gr(t,r,e),e.map(o=>{let a=vn(n[o]);if(a!==null&&a.fn==="now")return`${_(o)} = ${en(a,s)}`;if(a!==null){let i=t.transforms.get(o)?.toDb,c=i===void 0?a.by:i(a.by);return`${_(o)} = ${_(o)} ${a.fn==="inc"?"+":"-"} ${s(c)}`}return`${_(o)} = ${s(Xr(t,r,o,n))}`}).join(", ")}function $n(t,e,n,s,r){return e.map(o=>{let a=vn(n[o]);if(a!==null&&a.fn==="now")return en(a,s);if(a!==null){let i=a.fn==="inc"?"increment":"decrement";throw new Error(`${r}(${t.key}): "${o}" got ${i}() \u2014 the row does not exist yet, so there is no current value. Write the starting value; to change it once the row exists, updateMany({ where, set: { ${o}: ${i}(n) } }).`)}return s(Xr(t,r,o,n))}).join(", ")}var Ba=new Set(["integer","bigint","numeric"]);function Qr(t){return t!==null&&Ba.has(t)}function Zr(t,e,n,s){let r=`t.${_(n)}`,o=Se(t,n);if(e==="sum"||e==="avg")return`${e}(${r})::text AS ${_(s)}`;let a=o!==null&&!o.endsWith("[]")?Ue(o,`${e}(${r})`):null;return a!==null?`${a} AS ${_(s)}`:o==="bigint"||o==="numeric"?`${e}(${r})::text AS ${_(s)}`:`${e}(${r}) AS ${_(s)}`}function Wa(t,e,n,s=[]){return`json_build_object(${[...e.map(o=>{let a=Se(t,o),i=`${n}.${_(o)}`,c=a==="numeric"||a==="bigint"?`${i}::text`:Ue(a,i)??i;return`${Vr(o)}, ${c}`}),...s].join(", ")})`}function ct(t,e,n,s,r,o="t",a=0,i={value:0}){if(Y(n,"with","which relations a call reads"),a>=3&&Object.values(n).some(Boolean))throw new Error(`${r}(${e.key}): with supports at most three relation levels`);let c=[],l=[],u=[];for(let[g,p]of Object.entries(n)){if(p===!1||p===void 0)continue;Y(p,`with.${g}`,"which relations a call reads");let h=e.relations.find(v=>v.name===g);if(h===void 0){let v=e.relations.map(I=>I.name).sort();throw new Error(`${r}(${e.key}): there is no relation with.${g}`+(v.length>0?` (known: ${v.join(", ")})`:". The table declares no foreign key, and relations come from them")+". A relation is declared with references(() => <table>.<column>).")}let[m,y]=zr(t,e,h,r);if(m===null||y===null)throw new Error(`${r}(${e.key}): with.${g} needs a single-column primary key at one end of the relation`);let S=t.table(h.to,r),f=typeof p=="object"&&p!==null?p:{},d=++i.value,T=`w${d}`;if(Y(f.select,`with.${g}.select`,"which columns a call reads"),Y(f.orderBy,`with.${g}.orderBy`,"the order"),f.select!==void 0&&(!Array.isArray(f.select)||f.select.length===0))throw new Error(`${r}(${e.key}): with.${g}.select must be a non-empty array of columns`);let E=Array.isArray(f.select)?f.select:[...S.columns.keys()];for(let v of E)se(S,v,r,`with.${g}.select column`);let w=f.with;if(w!==void 0&&(w===null||typeof w!="object"||Array.isArray(w)))throw new Error(`${r}(${e.key}): with.${g}.with must be a relation object`);let O=w===void 0?{joins:[],jsonPairs:[]}:ct(t,S,w,s,r,T,a+1,i),k=O.joins.length?` ${O.joins.join(" ")}`:"",N=Wa(S,E,T,O.jsonPairs),A=f.where!==void 0&&f.where!==null?lt(t,S,f.where,s,r,T,d,`with.${g}.where`):"",R=`${T}.${_(y)} = ${_(o)}.${_(m)}`,L=A===""?R:`${R} AND ${A}`,$=f.limit;zt($,r);let C=h.kind==="many"?$:Math.min(1,$??1),q=Jr(S,f.orderBy,r,T)+zt(C,r),U=`wj${d}`;h.kind==="many"?l.push(`LEFT JOIN LATERAL (SELECT coalesce(json_agg(x.o), '[]'::json) AS d FROM (SELECT ${N} AS o FROM ${S.sql} ${T}${k} WHERE ${L}${q}) x) ${_(U)} ON true`):l.push(`LEFT JOIN LATERAL (SELECT ${N} AS d FROM ${S.sql} ${T}${k} WHERE ${L}${q}) ${_(U)} ON true`),c.push(`${_(U)}."d" AS ${_(g)}`),u.push(`${Vr(g)}, ${_(U)}."d"`)}return{select:c,joins:l,jsonPairs:u}}function ss(t,e,n,s){let r=[],o=ee(r),a=Re(t,e,n,o,"findMany").sql,i=Jr(e,s.orderBy,"findMany"),c=zt(s.limit),l=qa(s.offset,s.limit),u=es(e,s.select,"findMany"),g=s.with!==void 0&&Object.keys(s.with).length>0?ct(t,e,s.with,o,"findMany"):{select:[],joins:[]},p=g.select.length>0?`${u}, ${g.select.join(", ")}`:u,h=g.joins.length>0?` ${g.joins.join(" ")}`:"",m=s.lock===void 0?"":` ${ns("findUnique",e.key,"lock",s.lock)} OF t`;return{sql:`SELECT ${p} FROM ${e.sql} t${h} WHERE true${a}${i}${c}${l}${m}`,params:r}}var Jt=50;function rs(t,e,n,s){if(e.search===void 0||e.singleKey===null)throw new Error(`search(${e.key}): the table declares no search`);if(n.text===void 0&&n.vector===void 0)throw new Error(`search(${e.key}): neither the query's words nor its vector to search by`);let r=[],o=ee(r),a=_(e.singleKey),i=Re(t,e,s.where??{},o,"search").sql,c=Math.max(s.limit*3,30),l=[];if(n.vector!==void 0){let g=`v."embedding" ${n.vector.operator} ${o(n.vector.literal)}::${n.vector.type}`;l.push(`sem AS (SELECT s."id", row_number() OVER (ORDER BY s."d", s."id") AS r FROM (SELECT t.${a} AS "id", ${g} AS "d" FROM ${n.vector.table} v JOIN ${e.sql} t ON t.${a} = v."id" WHERE true${i} ORDER BY ${g} LIMIT ${c}) s)`)}if(n.text!==void 0){let g=Fn(e.search.from,"t"),p=`websearch_to_tsquery('simple', ${o(n.text)})`;l.push(`kw AS (SELECT s."id", row_number() OVER (ORDER BY s."k" DESC, s."id") AS r FROM (SELECT t.${a} AS "id", ts_rank_cd(${g}, ${p}) AS "k" FROM ${e.sql} t WHERE ${g} @@ ${p}${i} ORDER BY "k" DESC LIMIT ${c}) s)`)}l.push(l.length===2?`fused AS (SELECT coalesce(sem."id", kw."id") AS "id", (coalesce(1.0 / (${Jt} + sem.r), 0) + coalesce(1.0 / (${Jt} + kw.r), 0))::float8 AS "score" FROM sem FULL OUTER JOIN kw ON sem."id" = kw."id")`:`fused AS (SELECT x."id", (1.0 / (${Jt} + x.r))::float8 AS "score" FROM ${n.vector!==void 0?"sem":"kw"} x)`);let u=s.minScore===void 0?"":` AND f."score" >= ${o(s.minScore)}`;return{sql:`WITH ${l.join(", ")} SELECT ${Z(e,"t")}, f."score" AS "_score" FROM fused f JOIN ${e.sql} t ON t.${a} = f."id" WHERE true${u} ORDER BY f."score" DESC, t.${a} LIMIT ${ja(s.limit)}`,params:r}}function ja(t){if(!Number.isInteger(t)||t<1)throw new Error(`search: limit must be a positive integer (got ${String(t)})`);return t}function eo(t){return t instanceof Date?t.toISOString():Array.isArray(t)?t.map(eo):t}function os(t){if(t===null||typeof t!="object")return t;let e={};for(let[n,s]of Object.entries(t))e[n]=eo(s);return e}function Ka(t,e){for(let[n,s]of e.transforms){if(s.fromDb===void 0)continue;let r=t[n];r!=null&&(t[n]=s.fromDb(r))}return t}function yn(t,e,n,s){let r=n.map(o=>Ka(os(o),e));if(s)for(let o of e.relations){let a=s[o.name];if(!a)continue;let i=typeof a=="object"?a.with:void 0,c=t.table(o.to,"with");for(let l of r){let u=l[o.name];Array.isArray(u)?l[o.name]=yn(t,c,u,i):u&&typeof u=="object"&&(l[o.name]=yn(t,c,[u],i)[0])}}return Xe(r)}var Ha={inline:!0},as={inline:!0,read:!0},Va=t=>ae(t)===ne.uniqueViolation||Ke.is(t);function no(t,e){if(e===null)return!1;let n=Object.keys(t);if(n.length!==1||n[0]!==e)return!1;let s=t[e];return s!==null&&(typeof s!="object"||Array.isArray(s))}var Ga=6e4;function Sn(t,e){let{cat:n}=e,s=(p,h)=>n.table(p,h),r=(p,h)=>{let m=n.table(p,h);return m.search!==void 0&&e.searchable?.(),m},o=async(p,h=[],m=!1)=>await(await t()).unsafe(p,h,Qt(h)?void 0:m?as:Ha),a=(p,h=[])=>o(p,h,!0),i=async(p,h=[])=>await(await t()).unsafe(p,h),c=async(p,h)=>{let m=n.deferral(p);if(m===null)return h();await o(m.defer);let y=await h();return await o(m.check),y},l=(p,h,m)=>yn(n,p,h,m),u=(p,h)=>yn(n,p,[h])[0],g={diagnostics(){return e.trace?.snapshot??null},async query(p,h=[]){return Xe((await i(p,h)).map(m=>os(m)))},async insert(p,h){let m=r(p,"insert"),y=Object.keys(h);if(y.length===0)throw new Error(`insert into ${p}: no columns given`);nn(m,"insert",y);let S=[],f=$n(m,y,h,ee(S),"insert"),d=await o(`INSERT INTO ${m.sql} (${y.map(_).join(", ")}) VALUES (${f}) RETURNING ${Z(m)}`,S);if(!d[0])throw new Error(`insert into ${p} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return u(m,d[0])},insertMany:(async function(p,h,m){if(Is(m),h.length===0)return m?.returning===!1?0:[];let y=r(p,"insertMany"),S=Object.keys(h[0]);if(S.length===0)throw new Error(`insertMany into ${p}: no columns given`);for(let k=1;k<h.length;k++){let N=S.filter(R=>!(R in h[k])),A=Object.keys(h[k]).filter(R=>!S.includes(R));if(N.length>0||A.length>0)throw new Error(`insertMany(${p}): row ${k} does not have the first row's columns`+(N.length>0?` (missing: ${N.join(", ")})`:"")+(A.length>0?` (extra: ${A.join(", ")})`:"")+". One statement shares the column list: write null for a missing value, or insert differently shaped rows in calls of their own.")}nn(y,"insertMany",S),Y(m?.onConflict,"onConflict","which columns a conflict is on");for(let k of m?.onConflict??[])se(y,k,"insertMany","onConflict column");let f=[],d=ee(f),T=h.map(k=>`(${$n(y,S,k,d,"insertMany")})`),E=m?.onConflict??[],w=E.length>0||m?.action==="ignore"?` ${Tn(S,E,m?.action??"ignore")}`:"",O=await o(`INSERT INTO ${y.sql} (${S.map(_).join(", ")}) VALUES ${T.join(", ")}${w}${m?.returning===!1?"":` RETURNING ${Z(y)}`}`,f);if(m?.returning===!1){if(!Number.isSafeInteger(O.count)||O.count<0)throw new Error("insertMany returning:false requires a driver with an affected row count");return O.count}return l(y,O)}),async advisoryXactLock(p){await o("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))",[p])},async lockRows(p,h){let m=[...new Set(h)].sort();if(m.length===0)return;let y=s(p,"lockRows");if(y.singleKey===null)throw new Error(`lockRows(${p}): no single-column primary key \u2014 the lock order needs one`);let S=_(y.singleKey),f=[],d=ee(f),T=m.map(E=>d(we(y,y.singleKey,E))).join(", ");await o(`SELECT t.${S} FROM ${y.sql} t WHERE t.${S} IN (${T}) ORDER BY t.${S} FOR NO KEY UPDATE`,f)},async lockRowsWhere(p,h,m){let y=ns("lockRowsWhere",p,"mode",m?.mode===void 0?"update":m.mode),S=s(p,"lockRowsWhere");if(S.singleKey===null)throw new Error(`lockRowsWhere(${p}): no single-column primary key \u2014 the lock order needs one`);let f=[],d=Re(n,S,h,ee(f),"lockRowsWhere");tn(d,"lockRowsWhere");let T=_(S.singleKey);await o(`SELECT t.${T} FROM ${S.sql} t WHERE true${d.sql} ORDER BY t.${T} ${y}`,f)},async claim(p,h,m={}){let y=r(p,"claim");Y(h,"unique","which key a claim is on");let S=Object.keys(h);if(S.length===0)throw new Error(`claim(${p}): no unique field given. claim takes ownership of a key; with none there is nothing to own \u2014 use insert(${p}, \u2026).`);xn("claim",p,S,h);for(let w of S){let O=h[w];if(O===null||typeof O=="object"||typeof O=="function")throw new Error(`claim(${p}): the unique field "${w}" is ${O===null?"null":"an object"} \u2014 a key is one value (a string, number, bigint or boolean); NULL never equals a claimed row.`)}let f=Object.keys(m).filter(w=>Object.hasOwn(h,w));if(f.length>0)throw new Error(`claim(${p}): ${f.map(w=>`"${w}"`).join(", ")} is in both the unique fields and extra \u2014 say a key once, in the unique fields.`);let d={...h,...m},T=Object.keys(d);nn(y,"claim",T);let E=await t();try{return await E.savepoint(async w=>{let O=[],k=$n(y,T,d,ee(O),"claim"),N=await w.unsafe(`INSERT INTO ${y.sql} (${T.map(_).join(", ")}) VALUES (${k}) RETURNING ${Z(y)}`,O);if(!N[0])throw new Error(`claim(${p}): the INSERT returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return{inserted:!0,row:u(y,N[0])}})}catch(w){if(!Va(w))throw w;let O=[],k=ee(O),N=S.map(R=>`t.${_(R)} = ${k(we(y,R,h[R]))}`).join(" AND "),A=await o(`SELECT ${Z(y,"t")} FROM ${y.sql} t WHERE ${N} LIMIT 1`,O);if(!A[0]){let R=on(w);throw new Error(`claim(${p}): a unique violation${R?` (${R})`:""} was caught but no row has these ${S.join(", ")}. Either the violation is of ANOTHER unique constraint \u2014 claim() is the wrong tool for this call \u2014 or the row exists and an RLS policy hides it from this caller.`)}return{inserted:!1,row:u(y,A[0])}}},async put(p,h,m){let y=r(p,"put"),S=m.onConflict;if(S.length===0)throw new Error(`put into ${p}: onConflict needs at least one column`);let f=Object.keys(h);if(f.length===0)throw new Error(`put into ${p}: no columns given`);nn(y,"put",f),Y(S,"onConflict","which columns a conflict is on");for(let w of S)se(y,w,"put","onConflict column");let d=[],T=$n(y,f,h,ee(d),"put"),E=await o(`INSERT INTO ${y.sql} (${f.map(_).join(", ")}) VALUES (${T}) ${Tn(f,S,"update")} RETURNING ${Z(y)}`,d);if(!E[0])throw new Error(`put into ${p} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return u(y,E[0])},async update(p,h,m){let y=r(p,"update");if(!y.columns.has("id"))throw new Error(`update(${p}): the table has no "id" column \u2014 update a row by its key with updateMany({ where, set })`);let S=Object.keys(m);if(S.length===0)return g.findById(p,h);for(let w of S)se(y,w,"update","set column");let f=[],d=ee(f),T=ts(y,S,m,d,"update"),E=await o(`UPDATE ${y.sql} SET ${T} WHERE "id" = ${d(we(y,"id",h))} RETURNING ${Z(y)}`,f);return E[0]?u(y,E[0]):null},async delete(p,h){let m=s(p,"delete");if(!m.columns.has("id"))throw new Error(`delete(${p}): the table has no "id" column \u2014 delete by its key with deleteMany({ where })`);let y=[we(m,"id",h)];await c(m,()=>o(`DELETE FROM ${m.sql} WHERE "id" = $1`,y))},async updateMany(p,h,m,y){let S=r(p,"updateMany"),f=Object.keys(m);if(f.length===0)throw new Error(`updateMany(${p}): nothing to set. An update with no columns is not a no-op worth pretending happened \u2014 pass the columns to write.`);for(let U of f)se(S,U,"updateMany","set column");let d=[],T=ee(d),E=ts(S,f,m,T,"updateMany"),w=Re(n,S,h,T,"updateMany");tn(w,"updateMany");let O=w.sql,k=S.singleKey,N=y?.returning!==!1,A=k===null||no(h,k),R=N?`RETURNING ${Z(S,"t")}`:"RETURNING 1",L=A?`UPDATE ${S.sql} AS t SET ${E} WHERE true${O} ${R}`:`UPDATE ${S.sql} AS t SET ${E} FROM locked WHERE t.${_(k)} = locked."__pb_lock" ${R}`,$=A?"":`WITH locked AS (SELECT t.${_(k)} AS "__pb_lock" FROM ${S.sql} t WHERE true${O} ORDER BY t.${_(k)} FOR NO KEY UPDATE)`,C=N?`${$} ${L}`.trim():A?`WITH upd AS (${L}) SELECT count(*)::int AS n FROM upd`:`${$}, upd AS (${L}) SELECT count(*)::int AS n FROM upd`,q=await o(C,d);return N?l(S,q):Number(q[0]?.n??0)},async deleteMany(p,h){let m=s(p,"deleteMany"),y=[],S=Re(n,m,h,ee(y),"deleteMany");return tn(S,"deleteMany"),(await c(m,()=>o(`DELETE FROM ${m.sql} AS t WHERE true${S.sql} RETURNING 1`,y))).length},async aggregate(p,h={}){let m=s(p,"aggregate");for(let R of["sum","avg","min","max","groupBy"])Y(h[R],R,"which columns an aggregate reads");Y(h.count,"count","which counts an aggregate takes");let y=[],S=ee(y),f=[],d=[];for(let R of["sum","avg","min","max"])for(let L of h[R]??[]){if(se(m,L,"aggregate",`${R} column`),(R==="sum"||R==="avg")&&!Qr(Se(m,L)))throw new Error(`aggregate(${p}): ${R}("${L}") on a column that is not numeric \u2014 "${L}" is ${Se(m,L)}. Only integer, bigint and numeric sum; to count rows, count: true.`);let $=`${R}__${L}`;d.push({fn:R,col:L,alias:$}),f.push(Zr(m,R,L,$))}h.count===!0&&f.push('count(*) AS "_count"');let T=h.count!==null&&typeof h.count=="object"?Object.entries(h.count):[];if(h.count!==void 0&&typeof h.count!="boolean"&&(h.count===null||typeof h.count!="object"||Array.isArray(h.count)||T.length===0))throw new Error(`aggregate(${p}): count is true, or named filters \u2014 { <name>: <filter> }, at least one`);if(T.forEach(([R,L],$)=>{let C=lt(n,m,L,S,"aggregate","t",0,`count.${R}`);f.push(`count(*) FILTER (WHERE ${C===""?"true":C}) AS ${_(`count__${$}`)}`)}),f.length===0)throw new Error(`aggregate(${p}): no aggregate asked for \u2014 the result would be an empty object. Name sum/avg/min/max columns or count: true.`);let E=h.groupBy??[];for(let R of E)se(m,R,"aggregate","groupBy column");let w=E.map(R=>`${Zt(m,R,"t")} AS ${_(`g__${R}`)}`),O=Re(n,m,h.where??{},S,"aggregate").sql,k=E.length>0?` GROUP BY ${E.map(R=>`t.${_(R)}`).join(", ")}`:"",N=await a(`SELECT ${[...w,...f].join(", ")} FROM ${m.sql} t WHERE true${O}${k}`,y),A=R=>{let L={};for(let $ of E)L[$]=R[`g__${$}`];for(let $ of d){let C=L[$.fn]??={};C[$.col]=R[$.alias]??null}return h.count===!0&&(L.count=Number(R._count??0)),T.length>0&&(L.count=Object.fromEntries(T.map(([$],C)=>[$,Number(R[`count__${C}`]??0)]))),L};return E.length>0?N.map(A):A(N[0]??{})},async count(p,h={}){let m=s(p,"count"),y=[],S=Re(n,m,h,ee(y),"count").sql,f=await a(`SELECT count(*) AS n FROM ${m.sql} t WHERE true${S}`,y);return Number(f[0]?.n??0)},async findUnique(p,h,m={}){let y=s(p,"findUnique");Lr(p,y.uniqueKeys,h);let S={select:m.select===void 0?void 0:an(m.select,[...m.select]),with:m.with,limit:2},f;if(m.lock===void 0)f=await g.findMany(p,h,S);else{let d=ss(n,y,h,{...S,lock:m.lock});f=l(y,await o(d.sql,d.params),m.with)}if(f.length>1)throw new Error(`findUnique(${p}): the database's constraints disagree with the schema; more than one row matched`);return f[0]??null},async findById(p,h){let m=s(p,"findById");if(!m.columns.has("id"))throw new Error(`findById(${p}): the table has no "id" column \u2014 use findUnique({ where: <its key> })`);let y=await a(`SELECT ${Z(m)} FROM ${m.sql} WHERE "id" = $1`,[we(m,"id",h)]);return y[0]?u(m,y[0]):null},async findMany(p,h={},m={}){let y=s(p,"findMany"),S=ss(n,y,h,m),f=m.lock!==void 0;return l(y,await(f?o:a)(S.sql,S.params),m.with)},async search(p,h,m={}){let y=s(p,"search"),S=y.search;if(S===void 0)throw new Error(`search(${p}): the table declares no search \u2014 defineTable(${JSON.stringify(y.name)}, { \u2026, search: { from: [<its text columns>], model } })`);let f=$r(p,h,m),d=e.search,T=A=>l(y,A),E=async()=>{let A=rs(n,y,{text:f.text},{where:m.where,limit:f.limit,minScore:f.minScore});return T(await a(A.sql,A.params))};if(f.mode==="text")return E();let w=d.embed;if(w===void 0)throw new Error(`search(${p}): no embedder was given, and a search by meaning embeds its query \u2014 createDatabase({ embed }) (the backend's db.embed); mode: "text" searches by word alone`);let O=A=>(A===void 0?d.serving.delete(S.key):d.serving.set(S.key,A),A),k=d.serving.get(S.key)??O(Ht((await a(Kt,[S.key]))[0])),N;for(let A=1;;A++){if(k===void 0){if(f.mode==="vector")throw new Error(`search(${p}): the database holds no vectors for this table \u2014 its schema is migrated before the app serves`);return E()}if(N===void 0||N.of.model!==k.model||N.of.dimensions!==k.dimensions)try{N={of:k,literal:await Sr(w,f.text,k)}}catch(I){if(f.mode==="vector")throw I;let x=Date.now();return x-(d.said.get(S.key)??-1/0)>=Ga&&(d.said.set(S.key,x),d.log?.(`palgres: search(${p}) answered by word alone: its query could not be embedded (${I instanceof Error?I.message:String(I)})`)),E()}let R=cn(k.dimensions,k.metric),L=_(k.types),$=rs(n,y,{...f.mode==="hybrid"?{text:f.text}:{},vector:{table:`${_(J)}.${_(ve(S.key,k.gen))}`,literal:N.literal,type:`${L}.${R.type}`,operator:`OPERATOR(${L}.${R.operator})`}},{where:m.where,limit:f.limit,minScore:f.minScore}),C=await t(),[q,U]=await Promise.all([C.unsafe(Kt,[S.key],as),C.unsafe($.sql,$.params,Qt($.params)?void 0:as)]),v=O(Ht(q[0]));if(v!==void 0&&v.gen===k.gen)return T(U);if(A>=3)throw new Error(`search(${p}): the vectors that serve the table changed while it was searched, three times over`);k=v}},async page(p,h={},m={}){let y=s(p,"page");if(e.cursorKey===null)throw new Error("Database.page needs a cursor secret shared by every replica: createDatabase({ cursorSecret })");let S=e.cursorKey,f=Object.create(null);for(let[H,re]of y.columns)f[H]={type:re.type,nullable:re.nullable&&!y.primaryKey.includes(H)};let{order:d,size:T,backward:E,token:w}=Ur(f,y.primaryKey,m),O=[],k=ee(O),N=Re(n,y,h,k,"page").sql,A=es(y,m.select===void 0?void 0:an(m.select,[...m.select]),"page"),R=Xt({table:p,version:n.version,columns:f,order:d,where:N,params:O,select:m.select,with:m.with,identity:e.cursorScope()}),L=w===void 0?void 0:Fr(S,R,w,d.length),$=H=>`t.${_(H)}`,C=L?` AND ${Yt(d,L,E,k,$)}`:"",q=L?`EXISTS (SELECT 1 FROM ${y.sql} t WHERE true${N} AND ${Yt(d,L,!E,k,$,!0)})`:"false",U="__pb_page_",v=[...y.columns.keys(),...Object.keys(m.with??{})];for(;v.some(H=>H.startsWith(U));)U+="_";let I=`${U}ordinal`,x=`${U}opposite`,B=d.map((H,re)=>`${U}${re}`),F=d.map((H,re)=>`${Se(y,H.column)==="timestamp"?Ue("timestamp",$(H.column)):`${$(H.column)}::text`} AS ${_(B[re])}`),W=m.with&&Object.keys(m.with).length?ct(n,y,m.with,k,"page"):{select:[],joins:[]},V=d.map(H=>`${$(H.column)} ${H.direction==="asc"!==E?"ASC":"DESC"} NULLS ${H.nulls==="first"!==E?"FIRST":"LAST"}`).join(", "),X=`SELECT ${[A,...W.select,...F,`row_number() OVER (ORDER BY ${V}) AS ${_(I)}`].join(", ")} FROM ${y.sql} t ${W.joins.join(" ")} WHERE true${N}${C} ORDER BY ${V} LIMIT ${T+1}`,K=`SELECT p.*, b.${_(x)} FROM (SELECT ${q} AS ${_(x)}) b LEFT JOIN LATERAL (${X}) p ON true ORDER BY p.${_(I)}`,G=await a(K,O),te=G[0]?.[x]===!0,Q=G.filter(H=>H[I]!==null&&H[I]!==void 0),An=Q.length>T;Q=Q.slice(0,T),E&&Q.reverse();let ce=H=>H?qr(S,R,B.map(re=>H[re]===null?null:String(H[re]))):null,We={startCursor:ce(Q[0]),endCursor:ce(Q.at(-1)),hasNextPage:E?te:An,hasPreviousPage:E?An:te};for(let H of Q)for(let re of[...B,I,x])delete H[re];return{rows:l(y,Q,m.with),pageInfo:We}},async attempt(p){return(await t()).savepoint(m=>p(Sn(()=>Promise.resolve(m),e)))},async txPlan(p){return(await t()).savepoint(async m=>{let y=[];for(let S of p.ops){let f=S.op==="select"||S.op==="delete"?s(S.table,"transaction plan"):r(S.table,"transaction plan"),d=Ya(n,f,S,y),T=S.op==="delete"?n.deferral(f):null;d!==null&&T!==null&&await m.unsafe(T.defer,[]);let E=d===null?[]:l(f,await m.unsafe(d.sql,d.params));d!==null&&T!==null&&await m.unsafe(T.check,[]);let w={rows:E,rows_affected:E.length};y.push(w),Ja(S,w)}return{results:y}})}};return g}function Xa(t,e){let n;return t.op<0||t.op>=e.length?n=`transaction plan: a reference points at operation ${t.op}, but the plan has run ${e.length} (0\u2026${e.length-1}). A reference can only read an EARLIER operation's row.`:e[t.op].rows[0]?n=`transaction plan: operation ${t.op}'s row has no column "${t.field}" (its columns: ${Object.keys(e[t.op].rows[0]).join(", ")}).`:n=`transaction plan: operation ${t.op} returned NO ROW, so "${t.field}" cannot be read. A reference does not guarantee its row exists \u2014 declare the expectation first (\`.expectOne(err)\`).`,Object.assign(new Error(n),{error_code:"tx_ref_unresolved"})}function to(t,e){if(Ss(t))throw new Error(`${e}: got an imitation of a plan reference ({ $ref: \u2026 }) \u2014 this object was not made by the plan's builder. A reference is built in your code from an earlier operation's row (insert(...).expectOne(err).id); a filter from a request body cannot carry one.`)}function so(t,e){let n=e[t.$ref.op]?.rows[0];if(!n||!(t.$ref.field in n))throw Xa(t.$ref,e);return n[t.$ref.field]}function ut(t,e,n,s,r){if(to(e,`transaction plan (${n})`),yt(e))return s(we(t,n,so(e,r)));if($s(e)){let o=e.$expr;return o.fn==="now"?en(o,s):`${_(n)} ${o.fn==="inc"?"+":"-"} ${s(we(t,n,o.by))}`}return s(we(t,n,e))}function ls(t,e){if(to(t,"transaction plan filter"),yt(t)){let n=so(t,e);if(n==null)throw Object.assign(new Error(`transaction plan: a filter's reference to operation ${t.$ref.op}'s "${t.$ref.field}" is NULL. As a filter value NULL means IS NULL \u2014 every row with no value there, not the one the reference named. Write null in the filter when that is what you mean.`),{error_code:"tx_ref_null"});if(typeof n=="object"&&!Array.isArray(n)&&!Ts(n))throw Object.assign(new Error(`transaction plan: a filter's reference to operation ${t.$ref.op}'s "${t.$ref.field}" is an object. A filter compares a column with a value; an object there would be read as operators. Reference a scalar column.`),{error_code:"tx_ref_object"});return n}if(Array.isArray(t))return an(t,t.map(n=>ls(n,e)));if(t!==null&&typeof t=="object"&&!xe(t)&&!ln(t)&&!In(t)&&!(t instanceof Date)){let n=an(t,{});for(let[s,r]of Object.entries(t))n[s]=ls(r,e);return n}return t}function is(t,e,n,s,r,o){if(n===void 0||Object.keys(n).length===0&&!ln(n))return{sql:"",conditions:0,resolved:{}};let a=ls(n,r);return{...Re(t,e,a,s,o),resolved:a}}function Ya(t,e,n,s){let r=[],o=ee(r),a=`transaction plan ${n.op}`,i=n.op==="insertMany"?[...new Set((n.rows??[]).flatMap(l=>Object.keys(l)))]:Object.keys(n.values??n.set??{});nn(e,a,i);let c;switch(n.op){case"insert":{let l=n.values??{},u=Object.keys(l),g=u.map(p=>ut(e,l[p],p,o,s));c=u.length?`INSERT INTO ${e.sql} (${u.map(_).join(", ")}) VALUES (${g.join(", ")}) RETURNING ${Z(e)}`:`INSERT INTO ${e.sql} DEFAULT VALUES RETURNING ${Z(e)}`;break}case"upsert":{let l=n.values??{},u=Object.keys(l),g=n.onConflict??[];if(u.length===0||g.length===0)throw Object.assign(new Error(`put on ${n.table} needs columns and onConflict`),{error_code:"tx_bad_upsert"});Y(n.onConflict,"onConflict","which columns a conflict is on");for(let h of g)se(e,h,a,"onConflict column");let p=u.map(h=>ut(e,l[h],h,o,s));c=`INSERT INTO ${e.sql} (${u.map(_).join(", ")}) VALUES (${p.join(", ")}) ${Tn(u,g,"update")} RETURNING ${Z(e)}`;break}case"insertMany":{let l=n.rows??[];if(l.length===0)return null;let u=Object.keys(l[0]),g=l.map(m=>`(${u.map(y=>ut(e,m[y],y,o,s)).join(", ")})`),p=n.onConflict??[];Y(n.onConflict,"onConflict","which columns a conflict is on");for(let m of p)se(e,m,a,"onConflict column");if(n.action==="update"&&p.length===0)throw Object.assign(new Error(`insertMany on ${n.table}: an overwrite needs onConflict columns`),{error_code:"tx_bad_upsert"});let h=n.action!==void 0?` ${Tn(u,p,n.action)}`:"";c=`INSERT INTO ${e.sql} (${u.map(_).join(", ")}) VALUES ${g.join(", ")}${h} RETURNING ${Z(e)}`;break}case"update":{let l=n.set??{},u=Object.keys(l);if(u.length===0)throw new Error(`update ${n.table}: nothing to set`);let g=u.map(m=>`${_(m)} = ${ut(e,l[m],m,o,s)}`),p=is(t,e,n.where,o,s,a);tn(p,a);let h=e.singleKey;c=h===null||no(p.resolved,h)?`UPDATE ${e.sql} AS t SET ${g.join(", ")} WHERE true${p.sql} RETURNING ${Z(e,"t")}`:`WITH locked AS (SELECT t.${_(h)} AS "__pb_lock" FROM ${e.sql} t WHERE true${p.sql} ORDER BY t.${_(h)} FOR NO KEY UPDATE) UPDATE ${e.sql} AS t SET ${g.join(", ")} FROM locked WHERE t.${_(h)} = locked."__pb_lock" RETURNING ${Z(e,"t")}`;break}case"delete":{let l=is(t,e,n.where,o,s,a);tn(l,a),c=`DELETE FROM ${e.sql} AS t WHERE true${l.sql} RETURNING ${Z(e,"t")}`;break}case"select":{let l="";if(n.limit!==void 0){let g=Number(n.limit);if(!Number.isInteger(g)||g<0)throw new Error(`transaction plan (${n.table}): limit must be an integer, got "${String(n.limit)}"`);l=` LIMIT ${g}`}let u=n.lock==="update"?" FOR UPDATE":"";c=`SELECT ${Z(e,"t")} FROM ${e.sql} t WHERE true${is(t,e,n.where,o,s,a).sql}${l}${u}`;break}default:throw new Error(`unknown operation "${String(n.op)}" in a transaction plan`)}return{sql:c,params:r}}function Ja(t,e){let n=t.guard;if(!n)return;let s=e.rows.length;if(!(n.kind==="one"?s===1:n.kind==="none"?s===0:n.kind==="atLeast"?s>=n.n:s<=n.n))throw Object.assign(new Error(`transaction expectation failed: ${n.kind} (${s} row(s))`),{error_code:"tx_guard_failed",slot:n.slot})}import{AsyncLocalStorage as ao}from"node:async_hooks";import{randomUUID as za}from"node:crypto";var dt=new ao,ro=()=>({running:new Set}),Qa=t=>String(t?.message??t);function Za(t){return new Ve(`The transaction was rolled back, not committed: a statement in it failed (${Qa(t)}) and the code went on. One failed statement aborts the whole transaction \u2014 Postgres refuses every later one and answers COMMIT with ROLLBACK. Wrap a write you expect to fail in \`Database.$attempt(async (tx) => \u2026)\` \u2014 it takes a SAVEPOINT, so only that write rolls back \u2014 or use \`Database.public.<t>.put({ data, onConflict: [...] })\` when what you brace for is a duplicate row.`,t)}async function oo(t){for(;t.running.size;)await Promise.allSettled([...t.running])}function io(t,e){let n=e.bind;if(e.lockTimeout!==void 0&&(n+=`, set_config('lock_timeout', ${de(e.lockTimeout)}, true)`),e.statementTimeout!==void 0&&(n+=`, set_config('statement_timeout', ${de(e.statementTimeout)}, true)`),!/^select /i.test(n))throw new Error("palgres: the binding statement must be a SELECT list");n+=", pg_catalog.current_setting('transaction_isolation') AS palgres_isolation";let s=null,r=null,o=null,a=null,i=!1,c=null,l=ro(),u=!0,g,p=!1,h,m=async()=>!e.control||await e.control.drainCancellation()?!0:(h?.abandon?.(),!1),y=()=>{p=!0},S=()=>{if(i)throw new Error("Database transaction has settled; its handle cannot be used again");if(e.control?.check(),e.trace?.check(),dt.getStore()!==e.scope)throw new Error("Database.$atomic cannot use a handle from another transaction or identity; use its tx argument")},f,d,T=new Set,E=0,w=!1,O=()=>s!==null&&!i&&p&&l.running.size===0&&T.size===0,k=(R,L,$=S,C,q=new Set)=>{let U=()=>{if($(),d!==C||f?.getStore()!==C)throw new Error("Database connection belongs to another active savepoint; use its tx argument and await it before using the parent handle")};return{unsafe(v,I,x){try{U()}catch(W){return Promise.reject(W)}x?.read!==!0&&(u=!1);let B=(I??[]).map(ze),F=()=>{let W=R.unsafe(v,B,x),V=Promise.resolve(e.control?e.control.watch(W):W).catch(X=>{throw On(X)&&(L.refused??={error:X}),X});return L.running.add(V),E++,V.catch(()=>{}).finally(()=>{L.running.delete(V),y(),--E===0&&!i&&e.onIdle?.()}),V};return e.trace?e.trace.query(v,F):F()},async savepoint(v){U(),u=!1;let I=Symbol("savepoint"),x=new Set,B=ro();f??=new ao,d=I;let F=(async()=>{try{return await R.savepoint(async W=>{let V=!1,X=()=>{if($(),V)throw new Error("Database savepoint has settled; its handle cannot be used again")};try{let K=f.run(I,()=>v(k(W,B,X,I,x))),G=await(e.control?e.control.race(K):K);if(await oo(B),B.refused)throw B.refused.error;return G}finally{x.size&&await Promise.allSettled([...x]),V=!0}})}finally{d=C}})();T.add(F),q.add(F);try{return await F}finally{T.delete(F),q.delete(F)}}}},N=async()=>(S(),s||(s=new Promise((R,L)=>{let $=new Promise((C,q)=>{r=C,o=q});$.catch(()=>{}),a=(async()=>{let C=performance.now(),q;try{q=await(e.acquire?e.acquire(e.control?.signal):e.admission.acquire(e.claims,e.control?.signal))}finally{e.trace?.time("queueMs",C)}let U=performance.now(),v,I=e.control!==void 0&&t.cancelBackend!==void 0,x=[];if(e.isolation!==void 0||e.readOnly!==void 0){let K=e.isolation??"read committed";_n({isolation:K,readOnly:e.readOnly}),x.push(`SET TRANSACTION ISOLATION LEVEL ${K.toUpperCase()}${e.readOnly===void 0?"":e.readOnly?" READ ONLY":" READ WRITE"}`)}x.push(I?`WITH backend AS MATERIALIZED (SELECT pid, backend_start::text AS started, xact_start::text AS xact_started FROM pg_catalog.pg_stat_get_activity(pg_catalog.pg_backend_pid())) ${n}, backend.pid, backend.started, backend.xact_started FROM backend`:n);let B=I&&t.cancelOpening!==void 0?`palgres:${za()}`:void 0,F=!1,W=K=>{p=!0;let G=K[0];if(typeof G?.palgres_isolation=="string"&&(g=G.palgres_isolation),!I)return;if(!Number.isInteger(G?.pid)||typeof G?.started!="string"||typeof G?.xact_started!="string"){let Q=new Error("Database cancellation cannot identify its own backend");throw l.refused??={error:Q},Q}let te={pid:G.pid,started:G.started,xactStarted:G.xact_started};F=!0,e.control.bindBackend(()=>t.cancelBackend(te.pid,te.started,te.xactStarted))},V=async()=>{for(let K=0;K<400&&!p&&!F;K++){if(await t.cancelOpening(B))return;await new Promise(G=>setTimeout(G,5))}},X=K=>t.begin(async G=>{v=performance.now(),e.trace?.time("poolMs",U);let te=e.trace?performance.now():0;if(e.control?.check(),i)throw new Error("Database transaction closed while waiting for its connection");B!==void 0&&!F&&e.control.bindBackend(V),e.trace?.time("setupMs",te),K(),h=G,R(k(G,l)),await $},{sql:x.join("; "),opened:W,tag:B});try{if(e.control?.check(),i)throw new Error("Database transaction closed while waiting for admission");let K=!1;for(let G=1;;G++)try{return await X(()=>{K=!0})}catch(te){let Q=ue(te);if(K||i||Q===void 0||G>=(Q==="lost"?et:nt))throw te;e.control?.check()}}finally{v!==void 0&&e.trace?.time("connectionMs",v),q.release()}})().catch(C=>{throw L(C),C}),a.catch(()=>{})}),s.then(void 0,()=>{w=!0,i||e.onIdle?.()}),s)),A=R=>c??=(async()=>{if(i=!0,!s)return;await m(),T.size&&await Promise.allSettled([...T]);let L=e.trace?performance.now():0;o(R),await a?.catch(()=>{}),e.trace?.time("rollbackMs",L),e.trace?.rolledBack()})();return{ensure:N,get opened(){return s!==null},get busy(){return s!==null&&!i&&!w&&(!p||E>0)},get failed(){return w},get releasable(){return O()&&u&&l.refused===void 0&&(g==="read committed"||g==="read uncommitted")},async commit(){if(T.size&&await Promise.allSettled([...T]),!s){e.trace?.check(),i=!0;return}await oo(l);try{if(e.trace?.check(),e.control?.checkDeadline(),l.refused)throw Za(l.refused.error)}catch(L){throw await A(L),L}if(i=!0,!await m()){let L=Ne(new oe(503,"database_unavailable","The database is temporarily unavailable",{retrySafe:!1},1));throw await A(L),L}let R=e.trace?performance.now():0;if(r(),u&&g!==void 0&&g!=="serializable"){a.then(()=>e.trace?.committed(),()=>e.trace?.commitFailed());return}try{await a,e.trace?.committed()}catch(L){throw e.trace?.commitFailed(),L}finally{e.trace?.time("commitMs",R)}},rollback:A}}var ei="5s",ni="10s",ti=new Set(["22P02","22007","22008","22003","22001"]),lo="55s",po=1,si=1e3,bn=new Set,Rn,ri=new mo("palgres.release");function oi(t){bn.add(t),Rn===void 0&&(Rn=ri.runInAsyncScope(()=>setInterval(()=>{let e=performance.now();for(let n of bn){let s=!0;try{s=n(e)}catch{s=!0}s&&bn.delete(n)}bn.size===0&&(clearInterval(Rn),Rn=void 0)},po)),Rn.unref?.())}function ai(t,e){let n=[],s=u=>u!==null&&u.opened&&!u.failed,r=new Set,o,a=!1,i=()=>{for(let u of n)if(s(u.tx)&&u.tx.busy)return!0;for(let u of r)if(u.busy)return!0;return!1},c=mo.bind(u=>{if(o===void 0||i())return!0;let g=r.size,p=r.size===0;for(let m of n)s(m.tx)&&(g++,m.tx.releasable||(p=!1));if(g===0)return!0;let h=u-o;if(p){if(h<po)return!1;for(let m of n){let y=m.tx;s(y)&&(m.tx=null,m.lease?.leave(),m.lease=void 0,y.commit().catch(()=>{}))}return o=void 0,!0}return e===void 0||a?!0:h<si?!1:(a=!0,e(Math.round(h)),!0)}),l=()=>{i()||(o=performance.now(),oi(c))};return{onIdle:l,surface(u,g){let p={tx:null};n.push(p);let h=()=>{bn.delete(c);let m=p.tx;return p.tx=null,p.lease=void 0,m};return{ensure(){if(o!==void 0&&(o=performance.now()),p.tx===null){if(t())return Promise.reject(new Error("Database transaction has settled; its handle cannot be used again"));p.tx=u(l,m=>g(m).then(y=>(p.lease=y,y)))}return p.tx.ensure()},commit:()=>h()?.commit()??Promise.resolve(),rollback:m=>h()?.rollback(m)??Promise.resolve()}},atomic(u){return r.add(u),()=>{r.delete(u)&&l()}}}}function ii(t){let e=ae(t),n=t?.code,s=o=>e!==void 0&&o.has(e)||typeof n=="string"&&o.has(n),r;if(s(gs))r=!0;else if(s(hs))r=!1;else return;return _e(new oe(503,"database_unavailable","The database is temporarily unavailable",{retrySafe:r},1),t)}var sn=t=>String(t?.message??t);function _e(t,e){return t.cause=e,Ne(t)}function cs(t,e,n){if(typeof t=="object"&&t!==null&&co.has(t))return t;let s=li(t,e,n);return typeof s=="object"&&s!==null&&co.add(s),s}var co=new WeakSet,mt=(t,e,n)=>Object.assign(new Error(t,{cause:e}),{sqlstate:n});function li(t,e,n){if(Ve.is(t))return t;let s=ae(t);if(s===ne.inFailedTransaction||/current transaction is aborted/i.test(sn(t)))return mt(`This request cannot write any more: an earlier write in it failed, and a request runs in ONE Postgres transaction, so every statement after the failure is refused. Wrap a write you expect to fail in \`Database.$attempt(async (tx) => \u2026)\` \u2014 it takes a SAVEPOINT, so only that write rolls back \u2014 or use \`Database.public.<t>.put({ data, onConflict: [...] })\` when what you brace for is a duplicate row. (${sn(t)})`,t,ne.inFailedTransaction);if(Ke.is(t))return t;if(s===ne.uniqueViolation)return _e(new Ke(on(t)),t);if(s===ne.serializationFailure)return _e(new ht(s),t);if(s===ne.deadlockDetected)return _e(new Et(s),t);if(s===ne.queryCancelled)return _e(Object.assign(new oe(503,"database_query_cancelled","Database statement was cancelled"),{sqlstate:s}),t);let r=ii(t);if(r)return r;if(e==="service"&&s===ne.foreignKeyViolation)return mt(`Database.$asService() hit a foreign key with nothing to point at. It runs in its OWN transaction on its OWN connection, so a row this request wrote through \`Database.*\` is not visible to it until the request commits \u2014 and the request cannot commit until the handler returns. If the row it needs is one this request just created, do both writes on ONE surface. (${sn(t)})`,t,s);if(/lock timeout/i.test(sn(t))){let o;return e==="service"?o=mt(`Database.$asService() waited too long for a row lock. It runs in its OWN transaction, so a row this request already wrote through Database.* is locked against it until the request commits \u2014 a wait that cannot end. Do that row's work on one surface or the other. (${sn(t)})`,t,s??ne.lockNotAvailable):o=mt(`Database waited too long for a lock. Another transaction holds it: a concurrent one, or another of this request's own \u2014 Database.*, $asService() and $atomic each run in their OWN transaction, and a row one of them wrote stays locked against the others until it commits, a wait that cannot end while the handler runs. Do that row's work on one surface. (${sn(t)})`,t,s??ne.lockNotAvailable),_e(Object.assign(new oe(503,"database_busy","The database waited too long for a lock",{retrySafe:!1},1),{sqlstate:s??ne.lockNotAvailable}),o)}return s!==void 0&&ti.has(s)?_e(Object.assign(new oe(400,"invalid_value","A value is not one its column can take"),{sqlstate:s}),t):s===ne.insufficientPrivilege&&n!==null?_e(Object.assign(new oe(n==="anon"?401:403,"permission_denied","The database does not allow this caller to do this"),{sqlstate:s}),t):(s!==void 0&&typeof t=="object"&&t!==null&&!Object.hasOwn(t,"sqlstate")&&Object.defineProperty(t,"sqlstate",{value:s,enumerable:!0,configurable:!0}),t)}function ci(t,e,n){let s=r=>({unsafe(o,a,i){let c;try{c=r.unsafe(o,a,i)}catch(l){return Promise.reject(cs(l,e,n))}return Promise.resolve(c).then(Xe,l=>{throw cs(l,e,n)})},savepoint:o=>r.savepoint(a=>o(s(a))),...r.abandon?{abandon:r.abandon.bind(r)}:{}});return{unsafe:(r,o)=>t.unsafe(r,o),begin:(r,o)=>t.begin(a=>r(s(a)),o).catch(a=>{throw cs(a,e,n)}),...t.cancelBackend?{cancelBackend:t.cancelBackend.bind(t)}:{},...t.cancelOpening?{cancelOpening:t.cancelOpening.bind(t)}:{}}}var ui=2,uo={anon:"anon",authenticated:"authenticated",service:"service"};function di(t,e){let n=Object.hasOwn(uo,e.role)?uo[e.role]:void 0;if(n===void 0)throw new Error(`palgres: a request is anon, authenticated or service, not "${String(e.role)}"`);return t[n]}function fo(t,e,n,s={}){let{signal:r}=s,o=s.diagnostics===void 0?void 0:new at(s.diagnostics),a=r===void 0?void 0:new Qe(void 0,r),i=di(e.roles,n),c=e.roles.service,l=n.role==="anon"||n.role==="authenticated"?n.role:null,u=n.claims,g=!1,p=!1,h=()=>{p&&jn.committed()},m=I=>{let x;return{cat:e.cat,trace:o,cursorKey:e.cursorKey,cursorScope:()=>x??=Mr(I,u),search:e.search,searchable:()=>{p=!0}}},y=m(i),S=m(c),f=new Set,d=null,T=!1,E=0,w=new Set,O=I=>new Promise((x,B)=>{let F=K=>{w.delete(W),clearTimeout(X),I?.removeEventListener("abort",V),K===void 0?x():B(K)},W=()=>F(),V=()=>F(I?.reason??new Error("Database admission cancelled")),X=setTimeout(()=>F(new Me({retryAfter:1},"Database queue deadline exceeded")),e.admission.queueTimeoutMs);w.add(W),I?.addEventListener("abort",V,{once:!0}),I?.aborted&&V()}),k=async I=>{let x;for(;;){for(;f.size===0&&d!==null;)await d;let W=f.size>0;if(W){for(;E>=ui;)await O(I);E++}let V;try{let X=e.admission.acquire(u,I,{nested:W,returning:!W&&T}).then(K=>{if(W&&f.size===0)return K.release(),null;let G={nested:W,turn:K};return f.add(G),W||(T=!0),G});if(!W){let K=X.then(()=>{},()=>{});d=K,K.then(()=>{d===K&&(d=null)})}V=await X}catch(X){throw W&&N(),X}if(V!==null){x=V;break}N()}let B=!1,F=()=>{if(!B){if(B=!0,f.delete(x),x.nested){N();return}for(let W of f){[x.turn,W.turn]=[W.turn,x.turn],W.nested=!1,x.nested=!0,N();return}}};return{queueMs:x.turn.queueMs,leave:F,release:()=>{F(),x.turn.release()}}},N=()=>{E--;let I=w.values().next().value;I?.()},A=ai(()=>g,s.heldIdle),R=(I,x,B={})=>io(ci(t,x,x==="user"?l:null),{bind:hn(e.binding,I,u),claims:u,admission:e.admission,acquire:k,trace:o,...B}),L=(I,x)=>async(B,F={})=>{if(_n(F),g)throw new Error("Database request has settled; it cannot open another transaction");if(dt.getStore()!==void 0)throw new Error("Nested Database.$atomic is not supported; use tx.$attempt for a savepoint");let W=Cn(F.retry),V=F.signal&&r?AbortSignal.any([F.signal,r]):F.signal??r,X=F.timeoutMs!==void 0||V!==void 0?new Qe(F.timeoutMs,V):void 0;try{X?.check();for(let K=0;;K++){X?.check();let G=[F.statementTimeoutMs,X?.remainingMs()].filter(ce=>ce!==void 0),te=Symbol("atomic transaction"),Q=R(I,x,{scope:te,isolation:F.isolation,readOnly:F.readOnly,control:X,lockTimeout:`${F.lockTimeoutMs??5e3}ms`,statementTimeout:G.length===0?void 0:`${Math.min(...G)}ms`,onIdle:A.onIdle}),An=A.atomic(Q);try{let ce=Sn(()=>Q.ensure(),x==="user"?y:S),We=dt.run(te,()=>B(ce)),H=await(X?X.race(We):We);return await Q.commit(),h(),H}catch(ce){await Q.rollback(ce);let We=He(ce)||Ve.is(ce)&&He(ce.cause);if(K>=W||!We)throw ce;o?.retry();let H=new Promise(re=>setTimeout(re,Math.min(100,2**K)));await(X?X.race(H):H)}finally{An()}}}finally{X?.dispose()}},$=A.surface((I,x)=>R(i,"user",{lockTimeout:ni,statementTimeout:lo,control:a,onIdle:I,acquire:x}),k),C=null,q,U=null,v=()=>{if(U===null){if(g)throw new Error("Database request has settled; it cannot open another transaction");q=r===void 0?void 0:new Qe(void 0,r);let I=q,x=A.surface((B,F)=>R(c,"service",{lockTimeout:ei,statementTimeout:lo,control:I,onIdle:B,acquire:F}),k);C=x,U=Object.assign(Sn(()=>x.ensure(),S),{atomic:L(c,"service")})}return U};return{client:Object.assign(Sn(()=>$.ensure(),y),{asService:v,atomic:L(i,"user")}),async commit(){g=!0;try{try{o?.check()}catch(I){throw await $.rollback(I),await C?.rollback(I),I}try{await $.commit()}catch(I){throw await C?.rollback(I),I}await C?.commit(),h(),o?.complete("committed"),a?.dispose(),q?.dispose()}catch(I){throw o?.failed(),I}},async rollback(I){g=!0,await $.rollback(I),await C?.rollback(I),a?.dispose(),q?.dispose(),o?.complete("failed")}}}function mi(t){if(t.codec!==void 0&&t.codec in Ge)return Ge[t.codec].tsType;switch(t.type){case"uuid":case"text":case"timestamp":case"date":return"string";case"sql":return t.sqlType!==void 0&&kn.has(t.sqlType)?"number":t.sqlType!==void 0&&Ln.has(t.sqlType)?"Json":"string";case"integer[]":return"number[]";case"boolean[]":return"boolean[]";case"uuid[]":case"text[]":case"bigint[]":case"numeric[]":case"timestamp[]":case"date[]":return"string[]";case"integer":return"number";case"bigint":case"numeric":return"string";case"boolean":return"boolean";case"jsonb":return"Json";case"enum":{let e=t.enumValues??[];return e.length===0?"string":e.map(n=>JSON.stringify(n)).join(" | ")}case"enum[]":{let e=t.enumValues??[];return e.length===0?"string[]":`(${e.map(n=>JSON.stringify(n)).join(" | ")})[]`}default:{let e=t.type;throw new Error(`env-gen: the column type "${String(e)}" has no TypeScript type \u2014 add a case to baseTsType`)}}}function pi(t){if(t.type==="enum"){let e=[...t.enumValues??[]].sort();return e.length===0?"enum":`enum:${e.join("|")}`}return t.type}function go(t){let e=`Pg<${mi(t)}, ${JSON.stringify(pi(t))}>`;return t.nullable?`${e} | null`:e}function fi(t){return t.nullable===!0||t.defaultRandom===!0||t.defaultNow===!0||t.defaultValue!==void 0||t.defaultSql!==void 0||t.dbAssigned===!0||t.identity!==void 0}function gi(t){return t.identity==="always"||t.generated!==void 0}var Nn=t=>/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?t:JSON.stringify(t);function ho(t,e,n){let s=Object.entries(t.columns).filter(([,i])=>i._def.ignored!==!0),r=s.map(([i,c])=>`${n} ${Nn(i)}: ${go(c._def)};`),o=s.filter(([,i])=>!gi(i._def)).map(([i,c])=>`${n} ${Nn(i)}${fi(c._def)?"?":""}: ${go(c._def)};`),a=e.map(i=>`${Nn(i.name)}: { to: ${JSON.stringify(i.to)}; kind: ${JSON.stringify(i.kind)}; via: ${JSON.stringify(i.via)} }`).join("; ");return[`${n}${Nn(t.name)}: {`,`${n} row: {`,...r,`${n} };`,`${n} insert: {`,...o,`${n} };`,`${n} relations: {${a===""?"":` ${a} `}};`,`${n} uniqueKeys: ${JSON.stringify(st(t))};`,...t.search!==void 0?[`${n} searchable: true;`]:[],`${n}};`].join(`
340
- `)}function hi(t){for(let e of t)for(let n of Object.values(e.tables))for(let[s,r]of Object.entries(n.columns)){let o=r._def;if(!(o.transform===void 0||o.codec!==void 0))throw new De([`table "${he(e.name,n.name)}" column "${s}" declares .transform<T>(): its target type does not exist at runtime, so the generated types would say something the engine contradicts. Declare a named codec instead \u2014 .asNumber() for a JS number, .asDecimal() for the exact string.`])}}var us="// palbase:env:begin",ds="// palbase:env:end",Eo=`/**
343
+ `).slice(0,2500));let o=performance.now(),a=!1;try{let i=await n();return r.durationMs=performance.now()-o,a=!0,Array.isArray(i)&&(r.rows=i.length,r.bytes=Buffer.byteLength(JSON.stringify(i,(c,l)=>typeof l=="bigint"?l.toString():l))),this.state.rows+=r.rows,this.state.bytes+=r.bytes,this.options.maxRows!==void 0&&this.state.rows>this.options.maxRows&&this.refuse("returned rows"),this.options.maxBytes!==void 0&&this.state.bytes>this.options.maxBytes&&this.refuse("result bytes"),i}catch(i){let c=i;throw r.errorCode=String(c?.errno??c?.code??"query_failed").slice(0,80),i}finally{a||(r.durationMs=performance.now()-o),this.state.sqlMs+=r.durationMs;let i=Object.freeze(r);this.state.statements.length<200&&this.state.statements.push(i),this.emit(this.options.onQuery,i)}}get snapshot(){return Object.freeze({...this.state,elapsedMs:(this.ended??performance.now())-this.start,statements:Object.freeze([...this.state.statements].sort((e,n)=>e.ordinal-n.ordinal))})}complete(e){this.ended===void 0&&(this.ended=performance.now(),this.state.outcome=e,this.emit(this.options.onComplete,this.snapshot))}};var co=new WeakMap,uo=new WeakSet;function ee(t){let e=n=>`$${t.push(n)}`;return co.set(e,t),e}var us=t=>uo.has(t);var mo=t=>`'${t.replace(/'/g,"''")}'`;function Se(t,e){let n=t.columns.get(e);return n?Qr(n):null}function se(t,e,n,s){if(!t.columns.has(e))throw t.ignored.has(e)?new Error(`${n}(${t.key}): ${s} "${e}" is .ignored() in this version \u2014 the version has promised not to name it, so the next one can drop it`):new Error(`${n}(${t.key}): ${s} "${e}" is not a column of the table`)}function be(t,e,n){if(t.encrypted.has(e))throw new Error(`palgres: ${t.key}.${e} is .encrypted() \u2014 its value is not bound as it is (an engine path that reached it without sealing it)`);if(n==null)return n;let s=t.transforms.get(e)?.toDb,r=s===void 0?n:s(n),o=Se(t,e);return o===null||r===null||r===void 0?r:o.endsWith("[]")&&Array.isArray(r)?Rn(r):Zr(o)?JSON.stringify(r):r}function po(t,e){return e.flatMap(n=>{let s=t.encrypted.get(n)?.lookup;return s?[n,s]:[n]})}function De(t,e){return po(t,e).map(_).join(", ")}function ai(t,e,n){return e.map(s=>{let r=t.encrypted.get(s);if(r===void 0)return s;if(r.lookup===null)throw new Error(`${n}(${t.key}): onConflict names "${s}", which is .encrypted() without { lookup: true } \u2014 no key is kept on it`);return r.lookup})}function fo(t,e,n,s,r,o){if(fn(s)!==null)throw new Error(`${o}(${t.key}): "${e}" is .encrypted() \u2014 the database holds no value there to compute with; write the value`);if(s===null)return n.lookup?[r(null),r(null)]:[r(null)];if(typeof s!="string")throw new TypeError(`${o}(${t.key}): "${e}" is .encrypted(), a text column \u2014 got ${typeof s}`);let{cipher:a,sealing:i}=t.fields;i.get(n.address)?.direction==="seal"&&Vn(n.address,s);let c=r(a.encrypt(n.address,s)),l=i.get(n.address)?.direction==="seal"?`CASE WHEN EXISTS (SELECT 1 FROM ${de} WHERE address = ${r(n.address)} AND phase = 'mixed') THEN ${r(s)}::text ELSE ${c}::text END`:c;return n.lookup?[l,r(a.lookup(n.address,s))]:[l]}function go(t,e,n,s,r){let o=t.encrypted.get(e);return o===void 0?null:fo(t,e,o,n,s,r)}function ho(t,e,n,s,r){let o=t.encrypted.get(n);return o===void 0?[r(ds(t,e,n,s))]:(pn(e,t.key,[n],s),xt(e,t.key,[n],s),fo(t,n,o,s[n],r,e))}function wt(t,e,n,s){if(t.encrypted.has(e))throw new Error(`${n}(${t.key}): ${s} names "${e}", which is .encrypted() \u2014 the database holds its ciphertext, not its value, so nothing there orders, ranges, groups or matches it`)}function Eo(t,e,n){let s=n.find(r=>t.databaseOnly.has(r));if(s!==void 0)throw new Error(`${e}(${t.key}): "${s}" is written by the database (an ALWAYS .identity()) \u2014 leave it out of the write; Postgres refuses any value for it`)}function an(t,e,n){for(let s of n)se(t,s,e,"column");Eo(t,e,n)}function ds(t,e,n,s){return pn(e,t.key,[n],s),xt(e,t.key,[n],s),be(t,n,s[n])}function ms(t,e,n){let s=`${n?`${_(n)}.`:""}${_(e)}`;return We(Se(t,e),s)??s}function yo(t,e,n){let s=ms(t,e,n);return We(Se(t,e),"x")!==null?`${s} AS ${_(e)}`:s}function Z(t,e){let n=e??"",s=t.projections.get(n);return s===void 0&&(s=[...t.columns.keys()].map(r=>yo(t,r,e)).join(", "),t.projections.set(n,s)),s}function ps(t,e,n){if(Y(e,"select","which columns a call reads"),e!==void 0&&e.length===0)throw new Error(`${n}(${t.key}): select got an empty list \u2014 that is not "all of them" but "none counted". Leave the key out for every column; name at least one otherwise.`);return e===void 0?Z(t,"t"):e.map(s=>(se(t,s,n,"select column"),yo(t,s,"t"))).join(", ")}function wo(t,e,n,s="t"){if(e==null)return"";Y(e,"orderBy","the order");let r=Array.isArray(e)?e:[e];return r.length===0?"":` ORDER BY ${r.map(a=>{Y(a,"orderBy","the order"),se(t,a.column,n,"orderBy column"),wt(t,a.column,n,"orderBy");let i=a.direction==="desc"?"DESC":"ASC",c=a.nulls==="first"?" NULLS FIRST":a.nulls==="last"?" NULLS LAST":"";return`${_(s)}.${_(a.column)} ${i}${c}`}).join(", ")}`}function cs(t,e="findMany"){if(t===void 0)return"";if(!Number.isInteger(t)||t<0)throw new Error(`${e}: limit must be a non-negative integer (got ${String(t)})`);return` LIMIT ${t}`}function ii(t,e,n="findMany"){if(t===void 0)return"";if(!Number.isInteger(t)||t<0)throw new Error(`${n}: offset must be a non-negative integer (got ${String(t)})`);if(e===void 0)throw new Error(`${n}: offset is given only with limit \u2014 an offset without one is the shifted tail of an unbounded result, not a page`);return` OFFSET ${t}`}var rn={gt:">",gte:">=",lt:"<",lte:"<=",neq:"<>"},li=[["days","days","int"],["hours","hours","int"],["minutes","mins","int"],["seconds","secs","double precision"]];function on(t,e){let n=t?.minus;if(n===void 0)return"now()";let s=Ws(n);if("refused"in s)throw new TypeError(`palgres: ago() ${s.refused}`);return`(now() - make_interval(${li.filter(([o])=>s.span[o]!==void 0).map(([o,a,i])=>`${a} => ${e(s.span[o])}::${i}`).join(", ")}))`}var ao=Object.freeze({update:"FOR UPDATE",share:"FOR SHARE",noKeyUpdate:"FOR NO KEY UPDATE"});function fs(t,e,n,s){if(typeof s=="string"&&Object.hasOwn(ao,s))return ao[s];let r=typeof s=="string"?JSON.stringify(s.slice(0,40)):typeof s;throw new TypeError(`${t}(${e}): unknown ${n} ${r} \u2014 "update" (FOR UPDATE), "share" (FOR SHARE) or "noKeyUpdate" (FOR NO KEY UPDATE).`)}var io=t=>fn(t);function lo(t,e,n,s){if(!t.columns.has(e.$col))throw new Error(`${n}(${t.key}): col("${e.$col}") is not a column of the table`);return`${_(s)}.${_(e.$col)}`}function To(t,e,n,s){let o=(n.kind==="many"?t.table(n.to,s):e).columns.get(n.via)?.references?.column??(n.kind==="many"?e.singleKey:t.table(n.to,s).singleKey);return n.kind==="many"?[o,n.via]:[n.via,o]}function je(t,e,n){return Ae(new Oe({fields:[{field:e,message:n}]},`${t}: ${e} ${n}`))}function ci(t,e){if(Y(t,e,"a filter"),!(typeof t!="object"||t===null))for(let[n,s]of Object.entries(t))n==="OR"||n==="AND"||n==="NOT"||n==="has"?Y(s,`${e}.${n}`,`a filter's ${n}`):s!==null&&typeof s=="object"&&!Array.isArray(s)&&Y(s,`${e}.${n}`,"an operator")}function yt(t,e,n,s,r,o,a,i){let c=[];if(ci(n,i),Bs(r,e.key,n),ze(n)){let{text:l,values:u}=n.$sql,g=co.get(s);if(g===void 0)throw new Error("palgres: an sqlFragment was compiled outside binder()");if(uo.add(g),l.length!==u.length+1)throw new Error(`${r}(${e.key}): the sqlFragment's parts are broken (${l.length} texts, ${u.length} values) \u2014 only the template tag makes one`);let m=l[0]??"";for(let h=0;h<u.length;h++)m+=`${s(u[h])}${l[h+1]??""}`;if(m.trim()==="")throw je(r,i,"is an empty sqlFragment \u2014 no condition. Write the condition in it, or leave it out.");return[`(${m})`]}for(let[l,u]of Object.entries(n)){if(l==="OR"||l==="AND"){let E=u;if(E.length===0){if(l==="AND")throw je(r,`${i}.AND`,"is an empty list \u2014 no condition at all. Leave it out, or name a condition in it.");c.push("false");continue}let $=E.map((f,d)=>{let T=yt(t,e,f,s,r,o,a,`${i}.${l}[${d}]`);if(T.length===0)throw je(r,`${i}.${l}[${d}]`,"holds no condition \u2014 a branch that matches every row. Name a condition in it, or leave it out.");return`(${T.join(" AND ")})`});c.push(`(${$.join(l==="OR"?" OR ":" AND ")})`);continue}if(l==="NOT"){if(Array.isArray(u))throw je(r,`${i}.NOT`,"is a list \u2014 NOT takes one filter object. For several conditions, NOT: { AND: [...] } or NOT: { OR: [...] }.");let E=yt(t,e,u,s,r,o,a,`${i}.NOT`);if(E.length===0)throw je(r,`${i}.NOT`,"holds no condition \u2014 NOT of nothing is not a filter. Name the condition to exclude.");c.push(`NOT (${E.join(" AND ")})`);continue}if(l==="has"){let E=Object.entries(u);if(E.length===0)throw je(r,`${i}.has`,"names no relation \u2014 no condition. Name one: has: { <relation>: { \u2026 } }.");for(let[$,f]of E){let d=e.relations.find(A=>A.name===$);if(d===void 0){let A=e.relations.map(b=>b.name).sort();throw new Error(`${r}(${e.key}): there is no relation has.${$}`+(A.length>0?` (known: ${A.join(", ")}). Relations come from foreign keys; to rename one, references(..., { as, reverseAs }).`:". The table declares no foreign key, and relations come from them: references(() => <table>.<column>)."))}let[T,y]=To(t,e,d,r);if(T===null||y===null)throw new Error(`${r}(${e.key}): has.${$} cannot be built \u2014 "${T===null?e.key:d.to}" has no single-column primary key to correlate on; write the condition as an sqlFragment`);let w=t.table(d.to,r),O=`r${a+1}`,k=On(t,w,f??{},s,r,O,a+1,`${i}.has.${$}`),N=`${O}.${_(y)} = ${_(o)}.${_(T)}`;c.push(`EXISTS (SELECT 1 FROM ${w.sql} ${O} WHERE ${N}${k===""?"":` AND ${k}`})`)}continue}se(e,l,r,"where column");let g=e.encrypted.get(l);if(g!==void 0){c.push(ui(e,l,g,u,s,r,o,i));continue}let m=`${_(o)}.${_(l)}`,h=Se(e,l)?.endsWith("[]")===!0,p=E=>s(be(e,l,E));if(ke(u)){c.push(`${m} = ${lo(e,u,r,o)}`);continue}if(Un(u)){c.push(`${m} = ${on(io(u),s)}`);continue}if(u!==null&&typeof u=="object"&&!Array.isArray(u))for(let[E,$]of Object.entries(u)){if(h&&(E==="contains"||E==="overlaps")){if(!Array.isArray($))throw new Error(`${r}(${e.key}): where.${l}.${E} must be an array \u2014 ${l} is an array column`);c.push(`${m} ${E==="contains"?"@>":"&&"} ${p($)}`);continue}if(!h&&(E==="contains"||E==="icontains"||E==="startsWith"||E==="endsWith")){if(typeof $!="string")throw new Error(`${r}(${e.key}): where.${l}.${E} must be a string`);let d=$.replace(/([\\%_])/g,"\\$1"),T=E==="startsWith"?`${d}%`:E==="endsWith"?`%${d}`:`%${d}%`;c.push(`${m} ${E==="icontains"?"ILIKE":"LIKE"} ${s(T)}`);continue}if(E==="isNull"){if(typeof $!="boolean")throw new Error(`${r}(${e.key}): where.${l}.isNull must be a boolean`);c.push(`${m} IS ${$?"NULL":"NOT NULL"}`);continue}if(E==="in"){if(!Array.isArray($))throw new Error(`${r}(${e.key}): where.${l}.in must be an array`);if($.some(ke))throw new Error(`${r}(${e.key}): where.${l}.in takes values, not col() \u2014 compare with a column bare ({ ${l}: col("\u2026") }) or with gt/gte/lt/lte/neq`);if($.length===0){c.push("false");continue}c.push(`${m} IN (${$.map(d=>p(d)).join(", ")})`);continue}if(Un($)){if(!(E in rn))throw new Error(`${r}(${e.key}): where.${l}.${E} cannot take now() \u2014 for equality write it bare: { ${l}: now() }`);c.push(`${m} ${rn[E]} ${on(io($),s)}`);continue}if(Fn($))throw new Error(`${r}(${e.key}): where.${l}.${E} got a WRITE expression (increment/decrement), not a comparison value. For the server's time use now(); for a numeric threshold, the value.`);if(ke($)){if(!(E in rn))throw new Error(`${r}(${e.key}): where.${l}.${E} cannot take col() \u2014 for equality write it bare: { ${l}: col("\u2026") }`);c.push(`${m} ${rn[E]} ${lo(e,$,r,o)}`);continue}let f=Us($);if(f!==null){let d=f==="col"?"col()":f==="sql"?"sqlFragment":"now()";throw new Error(`${r}(${e.key}): where.${l}.${E} got an imitation of ${d} \u2014 this object was not made by ${d} in this process. A filter from a request body cannot carry a handle; build the condition in your code.`)}if(E in rn){if($===null&&E==="neq"){c.push(`${m} IS NOT NULL`);continue}c.push(`${m} ${rn[E]} ${p($)}`);continue}throw new Error(`${r}(${e.key}): where.${l} has an unknown operator "${E}" (gt/gte/lt/lte/neq/in)`)}else u===null?c.push(`${m} IS NULL`):c.push(`${m} = ${p(u)}`)}return c}function ui(t,e,n,s,r,o,a,i){let c=`${_(a)}.${_(e)}`;if(s===null)return`${c} IS NULL`;let l=E=>{throw new Error(`${o}(${t.key}): ${i}.${e} ${E} \u2014 "${e}" is .encrypted(): the database holds its ciphertext, so it is asked only isNull`+(n.lookup?", equality and in":" (equality needs .encrypted({ lookup: true }))"))};(ke(s)||Un(s)||ze(s))&&l("compares with an expression");let{cipher:u,sealing:g}=t.fields,m=g.get(n.address)!==void 0,h=E=>{if(n.lookup===null&&l("asks for equality"),E.some(y=>typeof y!="string")&&l("compares with a value that is not text"),E.length===0)return"false";let $=`${_(a)}.${_(n.lookup)}`,f=E.map(y=>r(u.lookup(n.address,y))),d=E.length===1?`${$} = ${f[0]}`:`${$} IN (${f.join(", ")})`;if(!m)return d;let T=E.map(y=>r(y));return`(${d} OR ${E.length===1?`${c} = ${T[0]}`:`${c} IN (${T.join(", ")})`})`};if(typeof s!="object"||Array.isArray(s))return h([s]);let p=[];for(let[E,$]of Object.entries(s))if(E==="isNull"){if(typeof $!="boolean")throw new Error(`${o}(${t.key}): where.${e}.isNull must be a boolean`);p.push(`${c} IS ${$?"NULL":"NOT NULL"}`)}else if(E==="in"){if(!Array.isArray($))throw new Error(`${o}(${t.key}): where.${e}.in must be an array`);p.push(h($))}else E==="neq"?p.push($===null?`${c} IS NOT NULL`:`(${c} IS NOT NULL AND NOT ${h([$])})`):l(`asks ${E}`);return p.length===0&&l("holds no condition"),p.length===1?p[0]:`(${p.join(" AND ")})`}function On(t,e,n,s,r,o="t",a=0,i="where"){return yt(t,e,n,s,r,o,a,i).join(" AND ")}function Re(t,e,n,s,r){let o=yt(t,e,n,s,r,"t",0,"where");return{sql:o.length===0?"":` AND ${o.join(" AND ")}`,conditions:o.length}}function ln(t,e){if(!(t.conditions>0))throw je(e,"where",`holds no condition, so ${e} would reach EVERY row of the table. Name a condition.`)}function kn(t,e,n,s,r){let o=po(t,e),a=ai(t,n,r);if(s!=="ignore"&&s!=="update")throw new TypeError(`palgres: a conflict's action is "ignore" or "update", not ${typeof s=="string"?JSON.stringify(String(s).slice(0,40)):typeof s}`);if(a.length===0){if(s==="ignore")return"ON CONFLICT DO NOTHING";throw new Error("palgres: ON CONFLICT DO UPDATE needs the columns a collision is matched on")}let i=`ON CONFLICT (${a.map(_).join(", ")})`;if(s==="ignore")return`${i} DO NOTHING`;let c=new Set(a),l=o.filter(u=>!c.has(u)).map(u=>`${_(u)} = EXCLUDED.${_(u)}`);return l.length?`${i} DO UPDATE SET ${l.join(", ")}`:`${i} DO UPDATE SET ${_(a[0])} = EXCLUDED.${_(a[0])}`}function gs(t,e,n,s,r){return Eo(t,r,e),e.map(o=>{let a=t.encrypted.get(o);if(a!==void 0){let[c,l]=ho(t,r,o,n,s);return`${_(o)} = ${c}${a.lookup?`, ${_(a.lookup)} = ${l}`:""}`}let i=fn(n[o]);if(i!==null&&i.fn==="now")return`${_(o)} = ${on(i,s)}`;if(i!==null){let c=t.transforms.get(o)?.toDb,l=c===void 0?i.by:c(i.by);return`${_(o)} = ${_(o)} ${i.fn==="inc"?"+":"-"} ${s(l)}`}return`${_(o)} = ${s(ds(t,r,o,n))}`}).join(", ")}function Ln(t,e,n,s,r){return e.map(o=>{if(t.encrypted.has(o))return ho(t,r,o,n,s).join(", ");let a=fn(n[o]);if(a!==null&&a.fn==="now")return on(a,s);if(a!==null){let i=a.fn==="inc"?"increment":"decrement";throw new Error(`${r}(${t.key}): "${o}" got ${i}() \u2014 the row does not exist yet, so there is no current value. Write the starting value; to change it once the row exists, updateMany({ where, set: { ${o}: ${i}(n) } }).`)}return s(ds(t,r,o,n))}).join(", ")}var di=new Set(["integer","bigint","numeric"]);function $o(t){return t!==null&&di.has(t)}function So(t,e,n,s){wt(t,n,"aggregate",e);let r=`t.${_(n)}`,o=Se(t,n);if(e==="sum"||e==="avg")return`${e}(${r})::text AS ${_(s)}`;let a=o!==null&&!o.endsWith("[]")?We(o,`${e}(${r})`):null;return a!==null?`${a} AS ${_(s)}`:o==="bigint"||o==="numeric"?`${e}(${r})::text AS ${_(s)}`:`${e}(${r}) AS ${_(s)}`}function mi(t,e,n,s=[]){return`json_build_object(${[...e.map(o=>{let a=Se(t,o),i=`${n}.${_(o)}`,c=a==="numeric"||a==="bigint"?`${i}::text`:We(a,i)??i;return`${mo(o)}, ${c}`}),...s].join(", ")})`}function Tt(t,e,n,s,r,o="t",a=0,i={value:0}){if(Y(n,"with","which relations a call reads"),a>=3&&Object.values(n).some(Boolean))throw new Error(`${r}(${e.key}): with supports at most three relation levels`);let c=[],l=[],u=[];for(let[g,m]of Object.entries(n)){if(m===!1||m===void 0)continue;Y(m,`with.${g}`,"which relations a call reads");let h=e.relations.find(C=>C.name===g);if(h===void 0){let C=e.relations.map(x=>x.name).sort();throw new Error(`${r}(${e.key}): there is no relation with.${g}`+(C.length>0?` (known: ${C.join(", ")})`:". The table declares no foreign key, and relations come from them")+". A relation is declared with references(() => <table>.<column>).")}let[p,E]=To(t,e,h,r);if(p===null||E===null)throw new Error(`${r}(${e.key}): with.${g} needs a single-column primary key at one end of the relation`);let $=t.table(h.to,r),f=typeof m=="object"&&m!==null?m:{},d=++i.value,T=`w${d}`;if(Y(f.select,`with.${g}.select`,"which columns a call reads"),Y(f.orderBy,`with.${g}.orderBy`,"the order"),f.select!==void 0&&(!Array.isArray(f.select)||f.select.length===0))throw new Error(`${r}(${e.key}): with.${g}.select must be a non-empty array of columns`);let y=Array.isArray(f.select)?f.select:[...$.columns.keys()];for(let C of y)se($,C,r,`with.${g}.select column`);let w=f.with;if(w!==void 0&&(w===null||typeof w!="object"||Array.isArray(w)))throw new Error(`${r}(${e.key}): with.${g}.with must be a relation object`);let O=w===void 0?{joins:[],jsonPairs:[]}:Tt(t,$,w,s,r,T,a+1,i),k=O.joins.length?` ${O.joins.join(" ")}`:"",N=mi($,y,T,O.jsonPairs),A=f.where!==void 0&&f.where!==null?On(t,$,f.where,s,r,T,d,`with.${g}.where`):"",b=`${T}.${_(E)} = ${_(o)}.${_(p)}`,L=A===""?b:`${b} AND ${A}`,S=f.limit;cs(S,r);let v=h.kind==="many"?S:Math.min(1,S??1),q=wo($,f.orderBy,r,T)+cs(v,r),U=`wj${d}`;h.kind==="many"?l.push(`LEFT JOIN LATERAL (SELECT coalesce(json_agg(x.o), '[]'::json) AS d FROM (SELECT ${N} AS o FROM ${$.sql} ${T}${k} WHERE ${L}${q}) x) ${_(U)} ON true`):l.push(`LEFT JOIN LATERAL (SELECT ${N} AS d FROM ${$.sql} ${T}${k} WHERE ${L}${q}) ${_(U)} ON true`),c.push(`${_(U)}."d" AS ${_(g)}`),u.push(`${mo(g)}, ${_(U)}."d"`)}return{select:c,joins:l,jsonPairs:u}}function hs(t,e,n,s){let r=[],o=ee(r),a=Re(t,e,n,o,"findMany").sql,i=wo(e,s.orderBy,"findMany"),c=cs(s.limit),l=ii(s.offset,s.limit),u=ps(e,s.select,"findMany"),g=s.with!==void 0&&Object.keys(s.with).length>0?Tt(t,e,s.with,o,"findMany"):{select:[],joins:[]},m=g.select.length>0?`${u}, ${g.select.join(", ")}`:u,h=g.joins.length>0?` ${g.joins.join(" ")}`:"",p=s.lock===void 0?"":` ${fs("findUnique",e.key,"lock",s.lock)} OF t`;return{sql:`SELECT ${m} FROM ${e.sql} t${h} WHERE true${a}${i}${c}${l}${p}`,params:r}}var ls=50;function Es(t,e,n,s){if(e.search===void 0||e.singleKey===null)throw new Error(`search(${e.key}): the table declares no search`);if(n.text===void 0&&n.vector===void 0)throw new Error(`search(${e.key}): neither the query's words nor its vector to search by`);let r=[],o=ee(r),a=_(e.singleKey),i=Re(t,e,s.where??{},o,"search").sql,c=Math.max(s.limit*3,30),l=[];if(n.vector!==void 0){let g=`v."embedding" ${n.vector.operator} ${o(n.vector.literal)}::${n.vector.type}`;l.push(`sem AS (SELECT s."id", row_number() OVER (ORDER BY s."d", s."id") AS r FROM (SELECT t.${a} AS "id", ${g} AS "d" FROM ${n.vector.table} v JOIN ${e.sql} t ON t.${a} = v."id" WHERE true${i} ORDER BY ${g} LIMIT ${c}) s)`)}if(n.text!==void 0){let g=zn(e.search.from,"t"),m=`websearch_to_tsquery('simple', ${o(n.text)})`;l.push(`kw AS (SELECT s."id", row_number() OVER (ORDER BY s."k" DESC, s."id") AS r FROM (SELECT t.${a} AS "id", ts_rank_cd(${g}, ${m}) AS "k" FROM ${e.sql} t WHERE ${g} @@ ${m}${i} ORDER BY "k" DESC LIMIT ${c}) s)`)}l.push(l.length===2?`fused AS (SELECT coalesce(sem."id", kw."id") AS "id", (coalesce(1.0 / (${ls} + sem.r), 0) + coalesce(1.0 / (${ls} + kw.r), 0))::float8 AS "score" FROM sem FULL OUTER JOIN kw ON sem."id" = kw."id")`:`fused AS (SELECT x."id", (1.0 / (${ls} + x.r))::float8 AS "score" FROM ${n.vector!==void 0?"sem":"kw"} x)`);let u=s.minScore===void 0?"":` AND f."score" >= ${o(s.minScore)}`;return{sql:`WITH ${l.join(", ")} SELECT ${Z(e,"t")}, f."score" AS "_score" FROM fused f JOIN ${e.sql} t ON t.${a} = f."id" WHERE true${u} ORDER BY f."score" DESC, t.${a} LIMIT ${pi(s.limit)}`,params:r}}function pi(t){if(!Number.isInteger(t)||t<1)throw new Error(`search: limit must be a positive integer (got ${String(t)})`);return t}function bo(t){return t instanceof Date?t.toISOString():Array.isArray(t)?t.map(bo):t}function ys(t){if(t===null||typeof t!="object")return t;let e={};for(let[n,s]of Object.entries(t))e[n]=bo(s);return e}function fi(t,e){for(let[n,s]of e.transforms){if(s.fromDb===void 0)continue;let r=t[n];r!=null&&(t[n]=s.fromDb(r))}return t}function An(t,e,n,s){let r=n.map(o=>fi(ys(o),e));if(s)for(let o of e.relations){let a=s[o.name];if(!a)continue;let i=typeof a=="object"?a.with:void 0,c=t.table(o.to,"with");for(let l of r){let u=l[o.name];Array.isArray(u)?l[o.name]=An(t,c,u,i):u&&typeof u=="object"&&(l[o.name]=An(t,c,[u],i)[0])}}return Je(r)}var gi={inline:!0},ws={inline:!0,read:!0},hi=t=>ae(t)===ne.uniqueViolation||Ve.is(t);function Ro(t,e){if(e===null)return!1;let n=Object.keys(t);if(n.length!==1||n[0]!==e)return!1;let s=t[e];return s!==null&&(typeof s!="object"||Array.isArray(s))}var Ei=6e4;function xn(t,e){let{cat:n}=e,s=(m,h)=>n.table(m,h),r=(m,h)=>{let p=n.table(m,h);return p.search!==void 0&&e.searchable?.(),p},o=async(m,h=[],p=!1)=>await(await t()).unsafe(m,h,us(h)?void 0:p?ws:gi),a=(m,h=[])=>o(m,h,!0),i=async(m,h=[])=>await(await t()).unsafe(m,h),c=async(m,h)=>{let p=n.deferral(m);if(p===null)return h();await o(p.defer);let E=await h();return await o(p.check),E},l=(m,h,p)=>An(n,m,h,p),u=(m,h)=>An(n,m,[h])[0],g={diagnostics(){return e.trace?.snapshot??null},async query(m,h=[]){return Je((await i(m,h)).map(p=>ys(p)))},async insert(m,h){let p=r(m,"insert"),E=Object.keys(h);if(E.length===0)throw new Error(`insert into ${m}: no columns given`);an(p,"insert",E);let $=[],f=Ln(p,E,h,ee($),"insert"),d=await o(`INSERT INTO ${p.sql} (${De(p,E)}) VALUES (${f}) RETURNING ${Z(p)}`,$);if(!d[0])throw new Error(`insert into ${m} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return u(p,d[0])},insertMany:(async function(m,h,p){if(Vs(p),h.length===0)return p?.returning===!1?0:[];let E=r(m,"insertMany"),$=Object.keys(h[0]);if($.length===0)throw new Error(`insertMany into ${m}: no columns given`);for(let k=1;k<h.length;k++){let N=$.filter(b=>!(b in h[k])),A=Object.keys(h[k]).filter(b=>!$.includes(b));if(N.length>0||A.length>0)throw new Error(`insertMany(${m}): row ${k} does not have the first row's columns`+(N.length>0?` (missing: ${N.join(", ")})`:"")+(A.length>0?` (extra: ${A.join(", ")})`:"")+". One statement shares the column list: write null for a missing value, or insert differently shaped rows in calls of their own.")}an(E,"insertMany",$),Y(p?.onConflict,"onConflict","which columns a conflict is on");for(let k of p?.onConflict??[])se(E,k,"insertMany","onConflict column");let f=[],d=ee(f),T=h.map(k=>`(${Ln(E,$,k,d,"insertMany")})`),y=p?.onConflict??[],w=y.length>0||p?.action==="ignore"?` ${kn(E,$,y,p?.action??"ignore","insertMany")}`:"",O=await o(`INSERT INTO ${E.sql} (${De(E,$)}) VALUES ${T.join(", ")}${w}${p?.returning===!1?"":` RETURNING ${Z(E)}`}`,f);if(p?.returning===!1){if(!Number.isSafeInteger(O.count)||O.count<0)throw new Error("insertMany returning:false requires a driver with an affected row count");return O.count}return l(E,O)}),async advisoryXactLock(m){await o("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))",[m])},async lockRows(m,h){let p=[...new Set(h)].sort();if(p.length===0)return;let E=s(m,"lockRows");if(E.singleKey===null)throw new Error(`lockRows(${m}): no single-column primary key \u2014 the lock order needs one`);let $=_(E.singleKey),f=[],d=ee(f),T=p.map(y=>d(be(E,E.singleKey,y))).join(", ");await o(`SELECT t.${$} FROM ${E.sql} t WHERE t.${$} IN (${T}) ORDER BY t.${$} FOR NO KEY UPDATE`,f)},async lockRowsWhere(m,h,p){let E=fs("lockRowsWhere",m,"mode",p?.mode===void 0?"update":p.mode),$=s(m,"lockRowsWhere");if($.singleKey===null)throw new Error(`lockRowsWhere(${m}): no single-column primary key \u2014 the lock order needs one`);let f=[],d=Re(n,$,h,ee(f),"lockRowsWhere");ln(d,"lockRowsWhere");let T=_($.singleKey);await o(`SELECT t.${T} FROM ${$.sql} t WHERE true${d.sql} ORDER BY t.${T} ${E}`,f)},async claim(m,h,p={}){let E=r(m,"claim");Y(h,"unique","which key a claim is on");let $=Object.keys(h);if($.length===0)throw new Error(`claim(${m}): no unique field given. claim takes ownership of a key; with none there is nothing to own \u2014 use insert(${m}, \u2026).`);pn("claim",m,$,h);for(let w of $){let O=h[w];if(O===null||typeof O=="object"||typeof O=="function")throw new Error(`claim(${m}): the unique field "${w}" is ${O===null?"null":"an object"} \u2014 a key is one value (a string, number, bigint or boolean); NULL never equals a claimed row.`)}let f=Object.keys(p).filter(w=>Object.hasOwn(h,w));if(f.length>0)throw new Error(`claim(${m}): ${f.map(w=>`"${w}"`).join(", ")} is in both the unique fields and extra \u2014 say a key once, in the unique fields.`);let d={...h,...p},T=Object.keys(d);an(E,"claim",T);let y=await t();try{return await y.savepoint(async w=>{let O=[],k=Ln(E,T,d,ee(O),"claim"),N=await w.unsafe(`INSERT INTO ${E.sql} (${De(E,T)}) VALUES (${k}) RETURNING ${Z(E)}`,O);if(!N[0])throw new Error(`claim(${m}): the INSERT returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return{inserted:!0,row:u(E,N[0])}})}catch(w){if(!hi(w))throw w;let O=[],k=ee(O),N=On(n,E,h,k,"claim"),A=await o(`SELECT ${Z(E,"t")} FROM ${E.sql} t WHERE ${N} LIMIT 1`,O);if(!A[0]){let b=dn(w);throw new Error(`claim(${m}): a unique violation${b?` (${b})`:""} was caught but no row has these ${$.join(", ")}. Either the violation is of ANOTHER unique constraint \u2014 claim() is the wrong tool for this call \u2014 or the row exists and an RLS policy hides it from this caller.`)}return{inserted:!1,row:u(E,A[0])}}},async put(m,h,p){let E=r(m,"put"),$=p.onConflict;if($.length===0)throw new Error(`put into ${m}: onConflict needs at least one column`);let f=Object.keys(h);if(f.length===0)throw new Error(`put into ${m}: no columns given`);an(E,"put",f),Y($,"onConflict","which columns a conflict is on");for(let w of $)se(E,w,"put","onConflict column");let d=[],T=Ln(E,f,h,ee(d),"put"),y=await o(`INSERT INTO ${E.sql} (${De(E,f)}) VALUES (${T}) ${kn(E,f,$,"update","put")} RETURNING ${Z(E)}`,d);if(!y[0])throw new Error(`put into ${m} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);return u(E,y[0])},async update(m,h,p){let E=r(m,"update");if(!E.columns.has("id"))throw new Error(`update(${m}): the table has no "id" column \u2014 update a row by its key with updateMany({ where, set })`);let $=Object.keys(p);if($.length===0)return g.findById(m,h);for(let w of $)se(E,w,"update","set column");let f=[],d=ee(f),T=gs(E,$,p,d,"update"),y=await o(`UPDATE ${E.sql} SET ${T} WHERE "id" = ${d(be(E,"id",h))} RETURNING ${Z(E)}`,f);return y[0]?u(E,y[0]):null},async delete(m,h){let p=s(m,"delete");if(!p.columns.has("id"))throw new Error(`delete(${m}): the table has no "id" column \u2014 delete by its key with deleteMany({ where })`);let E=[be(p,"id",h)];await c(p,()=>o(`DELETE FROM ${p.sql} WHERE "id" = $1`,E))},async updateMany(m,h,p,E){let $=r(m,"updateMany"),f=Object.keys(p);if(f.length===0)throw new Error(`updateMany(${m}): nothing to set. An update with no columns is not a no-op worth pretending happened \u2014 pass the columns to write.`);for(let U of f)se($,U,"updateMany","set column");let d=[],T=ee(d),y=gs($,f,p,T,"updateMany"),w=Re(n,$,h,T,"updateMany");ln(w,"updateMany");let O=w.sql,k=$.singleKey,N=E?.returning!==!1,A=k===null||Ro(h,k),b=N?`RETURNING ${Z($,"t")}`:"RETURNING 1",L=A?`UPDATE ${$.sql} AS t SET ${y} WHERE true${O} ${b}`:`UPDATE ${$.sql} AS t SET ${y} FROM locked WHERE t.${_(k)} = locked."__pb_lock" ${b}`,S=A?"":`WITH locked AS (SELECT t.${_(k)} AS "__pb_lock" FROM ${$.sql} t WHERE true${O} ORDER BY t.${_(k)} FOR NO KEY UPDATE)`,v=N?`${S} ${L}`.trim():A?`WITH upd AS (${L}) SELECT count(*)::int AS n FROM upd`:`${S}, upd AS (${L}) SELECT count(*)::int AS n FROM upd`,q=await o(v,d);return N?l($,q):Number(q[0]?.n??0)},async deleteMany(m,h){let p=s(m,"deleteMany"),E=[],$=Re(n,p,h,ee(E),"deleteMany");return ln($,"deleteMany"),(await c(p,()=>o(`DELETE FROM ${p.sql} AS t WHERE true${$.sql} RETURNING 1`,E))).length},async aggregate(m,h={}){let p=s(m,"aggregate");for(let b of["sum","avg","min","max","groupBy"])Y(h[b],b,"which columns an aggregate reads");Y(h.count,"count","which counts an aggregate takes");let E=[],$=ee(E),f=[],d=[];for(let b of["sum","avg","min","max"])for(let L of h[b]??[]){if(se(p,L,"aggregate",`${b} column`),(b==="sum"||b==="avg")&&!$o(Se(p,L)))throw new Error(`aggregate(${m}): ${b}("${L}") on a column that is not numeric \u2014 "${L}" is ${Se(p,L)}. Only integer, bigint and numeric sum; to count rows, count: true.`);let S=`${b}__${L}`;d.push({fn:b,col:L,alias:S}),f.push(So(p,b,L,S))}h.count===!0&&f.push('count(*) AS "_count"');let T=h.count!==null&&typeof h.count=="object"?Object.entries(h.count):[];if(h.count!==void 0&&typeof h.count!="boolean"&&(h.count===null||typeof h.count!="object"||Array.isArray(h.count)||T.length===0))throw new Error(`aggregate(${m}): count is true, or named filters \u2014 { <name>: <filter> }, at least one`);if(T.forEach(([b,L],S)=>{let v=On(n,p,L,$,"aggregate","t",0,`count.${b}`);f.push(`count(*) FILTER (WHERE ${v===""?"true":v}) AS ${_(`count__${S}`)}`)}),f.length===0)throw new Error(`aggregate(${m}): no aggregate asked for \u2014 the result would be an empty object. Name sum/avg/min/max columns or count: true.`);let y=h.groupBy??[];for(let b of y)se(p,b,"aggregate","groupBy column"),wt(p,b,"aggregate","groupBy");let w=y.map(b=>`${ms(p,b,"t")} AS ${_(`g__${b}`)}`),O=Re(n,p,h.where??{},$,"aggregate").sql,k=y.length>0?` GROUP BY ${y.map(b=>`t.${_(b)}`).join(", ")}`:"",N=await a(`SELECT ${[...w,...f].join(", ")} FROM ${p.sql} t WHERE true${O}${k}`,E),A=b=>{let L={};for(let S of y)L[S]=b[`g__${S}`];for(let S of d){let v=L[S.fn]??={};v[S.col]=b[S.alias]??null}return h.count===!0&&(L.count=Number(b._count??0)),T.length>0&&(L.count=Object.fromEntries(T.map(([S],v)=>[S,Number(b[`count__${v}`]??0)]))),L};return y.length>0?N.map(A):A(N[0]??{})},async count(m,h={}){let p=s(m,"count"),E=[],$=Re(n,p,h,ee(E),"count").sql,f=await a(`SELECT count(*) AS n FROM ${p.sql} t WHERE true${$}`,E);return Number(f[0]?.n??0)},async findUnique(m,h,p={}){let E=s(m,"findUnique");Xr(m,E.uniqueKeys,h);let $={select:p.select===void 0?void 0:mn(p.select,[...p.select]),with:p.with,limit:2},f;if(p.lock===void 0)f=await g.findMany(m,h,$);else{let d=hs(n,E,h,{...$,lock:p.lock});f=l(E,await o(d.sql,d.params),p.with)}if(f.length>1)throw new Error(`findUnique(${m}): the database's constraints disagree with the schema; more than one row matched`);return f[0]??null},async findById(m,h){let p=s(m,"findById");if(!p.columns.has("id"))throw new Error(`findById(${m}): the table has no "id" column \u2014 use findUnique({ where: <its key> })`);let E=await a(`SELECT ${Z(p)} FROM ${p.sql} WHERE "id" = $1`,[be(p,"id",h)]);return E[0]?u(p,E[0]):null},async findMany(m,h={},p={}){let E=s(m,"findMany"),$=hs(n,E,h,p),f=p.lock!==void 0;return l(E,await(f?o:a)($.sql,$.params),p.with)},async search(m,h,p={}){let E=s(m,"search"),$=E.search;if($===void 0)throw new Error(`search(${m}): the table declares no search \u2014 defineTable(${JSON.stringify(E.name)}, { \u2026, search: { from: [<its text columns>], model } })`);let f=Ur(m,h,p),d=e.search,T=A=>l(E,A),y=async()=>{let A=Es(n,E,{text:f.text},{where:p.where,limit:f.limit,minScore:f.minScore});return T(await a(A.sql,A.params))};if(f.mode==="text")return y();let w=d.embed;if(w===void 0)throw new Error(`search(${m}): no embedder was given, and a search by meaning embeds its query \u2014 createDatabase({ embed }) (the backend's db.embed); mode: "text" searches by word alone`);let O=A=>(A===void 0?d.serving.delete($.key):d.serving.set($.key,A),A),k=d.serving.get($.key)??O(ss((await a(ts,[$.key]))[0])),N;for(let A=1;;A++){if(k===void 0){if(f.mode==="vector")throw new Error(`search(${m}): the database holds no vectors for this table \u2014 its schema is migrated before the app serves`);return y()}if(N===void 0||N.of.model!==k.model||N.of.dimensions!==k.dimensions)try{N={of:k,literal:await Br(w,f.text,k)}}catch(x){if(f.mode==="vector")throw x;let I=Date.now();return I-(d.said.get($.key)??-1/0)>=Ei&&(d.said.set($.key,I),d.log?.(`palgres: search(${m}) answered by word alone: its query could not be embedded (${x instanceof Error?x.message:String(x)})`)),y()}let b=En(k.dimensions,k.metric),L=_(k.types),S=Es(n,E,{...f.mode==="hybrid"?{text:f.text}:{},vector:{table:`${_(J)}.${_(ve($.key,k.gen))}`,literal:N.literal,type:`${L}.${b.type}`,operator:`OPERATOR(${L}.${b.operator})`}},{where:p.where,limit:f.limit,minScore:f.minScore}),v=await t(),[q,U]=await Promise.all([v.unsafe(ts,[$.key],ws),v.unsafe(S.sql,S.params,us(S.params)?void 0:ws)]),C=O(ss(q[0]));if(C!==void 0&&C.gen===k.gen)return T(U);if(A>=3)throw new Error(`search(${m}): the vectors that serve the table changed while it was searched, three times over`);k=C}},async page(m,h={},p={}){let E=s(m,"page");if(e.cursorKey===null)throw new Error("Database.page needs a cursor secret shared by every replica: createDatabase({ cursorSecret })");let $=e.cursorKey,f=Object.create(null);for(let[H,re]of E.columns)f[H]={type:re.type,nullable:re.nullable&&!E.primaryKey.includes(H)};let{order:d,size:T,backward:y,token:w}=oo(f,E.primaryKey,p),O=[],k=ee(O),N=Re(n,E,h,k,"page").sql,A=ps(E,p.select===void 0?void 0:mn(p.select,[...p.select]),"page"),b=as({table:m,version:n.version,columns:f,order:d,where:N,params:O,select:p.select,with:p.with,identity:e.cursorScope()}),L=w===void 0?void 0:ro($,b,w,d.length),S=H=>`t.${_(H)}`,v=L?` AND ${is(d,L,y,k,S)}`:"",q=L?`EXISTS (SELECT 1 FROM ${E.sql} t WHERE true${N} AND ${is(d,L,!y,k,S,!0)})`:"false",U="__pb_page_",C=[...E.columns.keys(),...Object.keys(p.with??{})];for(;C.some(H=>H.startsWith(U));)U+="_";let x=`${U}ordinal`,I=`${U}opposite`,B=d.map((H,re)=>`${U}${re}`),F=d.map((H,re)=>`${Se(E,H.column)==="timestamp"?We("timestamp",S(H.column)):`${S(H.column)}::text`} AS ${_(B[re])}`),W=p.with&&Object.keys(p.with).length?Tt(n,E,p.with,k,"page"):{select:[],joins:[]},V=d.map(H=>`${S(H.column)} ${H.direction==="asc"!==y?"ASC":"DESC"} NULLS ${H.nulls==="first"!==y?"FIRST":"LAST"}`).join(", "),X=`SELECT ${[A,...W.select,...F,`row_number() OVER (ORDER BY ${V}) AS ${_(x)}`].join(", ")} FROM ${E.sql} t ${W.joins.join(" ")} WHERE true${N}${v} ORDER BY ${V} LIMIT ${T+1}`,K=`SELECT p.*, b.${_(I)} FROM (SELECT ${q} AS ${_(I)}) b LEFT JOIN LATERAL (${X}) p ON true ORDER BY p.${_(x)}`,G=await a(K,O),te=G[0]?.[I]===!0,Q=G.filter(H=>H[x]!==null&&H[x]!==void 0),_n=Q.length>T;Q=Q.slice(0,T),y&&Q.reverse();let ce=H=>H?so($,b,B.map(re=>H[re]===null?null:String(H[re]))):null,Ke={startCursor:ce(Q[0]),endCursor:ce(Q.at(-1)),hasNextPage:y?te:_n,hasPreviousPage:y?_n:te};for(let H of Q)for(let re of[...B,x,I])delete H[re];return{rows:l(E,Q,p.with),pageInfo:Ke}},async attempt(m){return(await t()).savepoint(p=>m(xn(()=>Promise.resolve(p),e)))},async txPlan(m){return(await t()).savepoint(async p=>{let E=[];for(let $ of m.ops){let f=$.op==="select"||$.op==="delete"?s($.table,"transaction plan"):r($.table,"transaction plan"),d=Ti(n,f,$,E),T=$.op==="delete"?n.deferral(f):null;d!==null&&T!==null&&await p.unsafe(T.defer,[]);let y=d===null?[]:l(f,await p.unsafe(d.sql,d.params));d!==null&&T!==null&&await p.unsafe(T.check,[]);let w={rows:y,rows_affected:y.length};E.push(w),$i($,w)}return{results:E}})}};return g}function yi(t,e){let n;return t.op<0||t.op>=e.length?n=`transaction plan: a reference points at operation ${t.op}, but the plan has run ${e.length} (0\u2026${e.length-1}). A reference can only read an EARLIER operation's row.`:e[t.op].rows[0]?n=`transaction plan: operation ${t.op}'s row has no column "${t.field}" (its columns: ${Object.keys(e[t.op].rows[0]).join(", ")}).`:n=`transaction plan: operation ${t.op} returned NO ROW, so "${t.field}" cannot be read. A reference does not guarantee its row exists \u2014 declare the expectation first (\`.expectOne(err)\`).`,Object.assign(new Error(n),{error_code:"tx_ref_unresolved"})}function Ss(t,e){if(Fs(t))throw new Error(`${e}: got an imitation of a plan reference ({ $ref: \u2026 }) \u2014 this object was not made by the plan's builder. A reference is built in your code from an earlier operation's row (insert(...).expectOne(err).id); a filter from a request body cannot carry one.`)}function bs(t,e){let n=e[t.$ref.op]?.rows[0];if(!n||!(t.$ref.field in n))throw yi(t.$ref,e);return n[t.$ref.field]}function $t(t,e,n,s,r,o){return Ss(e,`transaction plan (${n})`),go(t,n,qn(e)?bs(e,r):e,s,o)??[wi(t,e,n,s,r)]}function wi(t,e,n,s,r){if(Ss(e,`transaction plan (${n})`),qn(e))return s(be(t,n,bs(e,r)));if(qs(e)){let o=e.$expr;return o.fn==="now"?on(o,s):`${_(n)} ${o.fn==="inc"?"+":"-"} ${s(be(t,n,o.by))}`}return s(be(t,n,e))}function $s(t,e){if(Ss(t,"transaction plan filter"),qn(t)){let n=bs(t,e);if(n==null)throw Object.assign(new Error(`transaction plan: a filter's reference to operation ${t.$ref.op}'s "${t.$ref.field}" is NULL. As a filter value NULL means IS NULL \u2014 every row with no value there, not the one the reference named. Write null in the filter when that is what you mean.`),{error_code:"tx_ref_null"});if(typeof n=="object"&&!Array.isArray(n)&&!Ms(n))throw Object.assign(new Error(`transaction plan: a filter's reference to operation ${t.$ref.op}'s "${t.$ref.field}" is an object. A filter compares a column with a value; an object there would be read as operators. Reference a scalar column.`),{error_code:"tx_ref_object"});return n}if(Array.isArray(t))return mn(t,t.map(n=>$s(n,e)));if(t!==null&&typeof t=="object"&&!ke(t)&&!ze(t)&&!Fn(t)&&!(t instanceof Date)){let n=mn(t,{});for(let[s,r]of Object.entries(t))n[s]=$s(r,e);return n}return t}function Ts(t,e,n,s,r,o){if(n===void 0||Object.keys(n).length===0&&!ze(n))return{sql:"",conditions:0,resolved:{}};let a=$s(n,r);return{...Re(t,e,a,s,o),resolved:a}}function Ti(t,e,n,s){let r=[],o=ee(r),a=`transaction plan ${n.op}`,i=n.op==="insertMany"?[...new Set((n.rows??[]).flatMap(l=>Object.keys(l)))]:Object.keys(n.values??n.set??{});an(e,a,i);let c;switch(n.op){case"insert":{let l=n.values??{},u=Object.keys(l),g=u.flatMap(m=>$t(e,l[m],m,o,s,a));c=u.length?`INSERT INTO ${e.sql} (${De(e,u)}) VALUES (${g.join(", ")}) RETURNING ${Z(e)}`:`INSERT INTO ${e.sql} DEFAULT VALUES RETURNING ${Z(e)}`;break}case"upsert":{let l=n.values??{},u=Object.keys(l),g=n.onConflict??[];if(u.length===0||g.length===0)throw Object.assign(new Error(`put on ${n.table} needs columns and onConflict`),{error_code:"tx_bad_upsert"});Y(n.onConflict,"onConflict","which columns a conflict is on");for(let h of g)se(e,h,a,"onConflict column");let m=u.flatMap(h=>$t(e,l[h],h,o,s,a));c=`INSERT INTO ${e.sql} (${De(e,u)}) VALUES (${m.join(", ")}) ${kn(e,u,g,"update",a)} RETURNING ${Z(e)}`;break}case"insertMany":{let l=n.rows??[];if(l.length===0)return null;let u=Object.keys(l[0]),g=l.map(p=>`(${u.flatMap(E=>$t(e,p[E],E,o,s,a)).join(", ")})`),m=n.onConflict??[];Y(n.onConflict,"onConflict","which columns a conflict is on");for(let p of m)se(e,p,a,"onConflict column");if(n.action==="update"&&m.length===0)throw Object.assign(new Error(`insertMany on ${n.table}: an overwrite needs onConflict columns`),{error_code:"tx_bad_upsert"});let h=n.action!==void 0?` ${kn(e,u,m,n.action,a)}`:"";c=`INSERT INTO ${e.sql} (${De(e,u)}) VALUES ${g.join(", ")}${h} RETURNING ${Z(e)}`;break}case"update":{let l=n.set??{},u=Object.keys(l);if(u.length===0)throw new Error(`update ${n.table}: nothing to set`);let g=u.map(p=>{let[E,$]=$t(e,l[p],p,o,s,a),f=e.encrypted.get(p)?.lookup;return`${_(p)} = ${E}${f?`, ${_(f)} = ${$}`:""}`}),m=Ts(t,e,n.where,o,s,a);ln(m,a);let h=e.singleKey;c=h===null||Ro(m.resolved,h)?`UPDATE ${e.sql} AS t SET ${g.join(", ")} WHERE true${m.sql} RETURNING ${Z(e,"t")}`:`WITH locked AS (SELECT t.${_(h)} AS "__pb_lock" FROM ${e.sql} t WHERE true${m.sql} ORDER BY t.${_(h)} FOR NO KEY UPDATE) UPDATE ${e.sql} AS t SET ${g.join(", ")} FROM locked WHERE t.${_(h)} = locked."__pb_lock" RETURNING ${Z(e,"t")}`;break}case"delete":{let l=Ts(t,e,n.where,o,s,a);ln(l,a),c=`DELETE FROM ${e.sql} AS t WHERE true${l.sql} RETURNING ${Z(e,"t")}`;break}case"select":{let l="";if(n.limit!==void 0){let g=Number(n.limit);if(!Number.isInteger(g)||g<0)throw new Error(`transaction plan (${n.table}): limit must be an integer, got "${String(n.limit)}"`);l=` LIMIT ${g}`}let u=n.lock==="update"?" FOR UPDATE":"";c=`SELECT ${Z(e,"t")} FROM ${e.sql} t WHERE true${Ts(t,e,n.where,o,s,a).sql}${l}${u}`;break}default:throw new Error(`unknown operation "${String(n.op)}" in a transaction plan`)}return{sql:c,params:r}}function $i(t,e){let n=t.guard;if(!n)return;let s=e.rows.length;if(!(n.kind==="one"?s===1:n.kind==="none"?s===0:n.kind==="atLeast"?s>=n.n:s<=n.n))throw Object.assign(new Error(`transaction expectation failed: ${n.kind} (${s} row(s))`),{error_code:"tx_guard_failed",slot:n.slot})}import{AsyncLocalStorage as Oo}from"node:async_hooks";import{randomUUID as Si}from"node:crypto";var St=new Oo,No=()=>({running:new Set}),bi=t=>String(t?.message??t);function Ri(t){return new Xe(`The transaction was rolled back, not committed: a statement in it failed (${bi(t)}) and the code went on. One failed statement aborts the whole transaction \u2014 Postgres refuses every later one and answers COMMIT with ROLLBACK. Wrap a write you expect to fail in \`Database.$attempt(async (tx) => \u2026)\` \u2014 it takes a SAVEPOINT, so only that write rolls back \u2014 or use \`Database.public.<t>.put({ data, onConflict: [...] })\` when what you brace for is a duplicate row.`,t)}async function Ao(t){for(;t.running.size;)await Promise.allSettled([...t.running])}function ko(t,e){let n=e.bind;if(e.lockTimeout!==void 0&&(n+=`, set_config('lock_timeout', ${me(e.lockTimeout)}, true)`),e.statementTimeout!==void 0&&(n+=`, set_config('statement_timeout', ${me(e.statementTimeout)}, true)`),!/^select /i.test(n))throw new Error("palgres: the binding statement must be a SELECT list");n+=", pg_catalog.current_setting('transaction_isolation') AS palgres_isolation";let s=null,r=null,o=null,a=null,i=!1,c=null,l=No(),u=!0,g,m=!1,h,p=async()=>!e.control||await e.control.drainCancellation()?!0:(h?.abandon?.(),!1),E=()=>{m=!0},$=()=>{if(i)throw new Error("Database transaction has settled; its handle cannot be used again");if(e.control?.check(),e.trace?.check(),St.getStore()!==e.scope)throw new Error("Database.$atomic cannot use a handle from another transaction or identity; use its tx argument")},f,d,T=new Set,y=0,w=!1,O=()=>s!==null&&!i&&m&&l.running.size===0&&T.size===0,k=(b,L,S=$,v,q=new Set)=>{let U=()=>{if(S(),d!==v||f?.getStore()!==v)throw new Error("Database connection belongs to another active savepoint; use its tx argument and await it before using the parent handle")};return{unsafe(C,x,I){try{U()}catch(W){return Promise.reject(W)}I?.read!==!0&&(u=!1);let B=(x??[]).map(tn),F=()=>{let W=b.unsafe(C,B,I),V=Promise.resolve(e.control?e.control.watch(W):W).catch(X=>{throw Dn(X)&&(L.refused??={error:X}),X});return L.running.add(V),y++,V.catch(()=>{}).finally(()=>{L.running.delete(V),E(),--y===0&&!i&&e.onIdle?.()}),V};return e.trace?e.trace.query(C,F):F()},async savepoint(C){U(),u=!1;let x=Symbol("savepoint"),I=new Set,B=No();f??=new Oo,d=x;let F=(async()=>{try{return await b.savepoint(async W=>{let V=!1,X=()=>{if(S(),V)throw new Error("Database savepoint has settled; its handle cannot be used again")};try{let K=f.run(x,()=>C(k(W,B,X,x,I))),G=await(e.control?e.control.race(K):K);if(await Ao(B),B.refused)throw B.refused.error;return G}finally{I.size&&await Promise.allSettled([...I]),V=!0}})}finally{d=v}})();T.add(F),q.add(F);try{return await F}finally{T.delete(F),q.delete(F)}}}},N=async()=>($(),s||(s=new Promise((b,L)=>{let S=new Promise((v,q)=>{r=v,o=q});S.catch(()=>{}),a=(async()=>{let v=performance.now(),q;try{q=await(e.acquire?e.acquire(e.control?.signal):e.admission.acquire(e.claims,e.control?.signal))}finally{e.trace?.time("queueMs",v)}let U=performance.now(),C,x=e.control!==void 0&&t.cancelBackend!==void 0,I=[];if(e.isolation!==void 0||e.readOnly!==void 0){let K=e.isolation??"read committed";Wn({isolation:K,readOnly:e.readOnly}),I.push(`SET TRANSACTION ISOLATION LEVEL ${K.toUpperCase()}${e.readOnly===void 0?"":e.readOnly?" READ ONLY":" READ WRITE"}`)}I.push(x?`WITH backend AS MATERIALIZED (SELECT pid, backend_start::text AS started, xact_start::text AS xact_started FROM pg_catalog.pg_stat_get_activity(pg_catalog.pg_backend_pid())) ${n}, backend.pid, backend.started, backend.xact_started FROM backend`:n);let B=x&&t.cancelOpening!==void 0?`palgres:${Si()}`:void 0,F=!1,W=K=>{m=!0;let G=K[0];if(typeof G?.palgres_isolation=="string"&&(g=G.palgres_isolation),!x)return;if(!Number.isInteger(G?.pid)||typeof G?.started!="string"||typeof G?.xact_started!="string"){let Q=new Error("Database cancellation cannot identify its own backend");throw l.refused??={error:Q},Q}let te={pid:G.pid,started:G.started,xactStarted:G.xact_started};F=!0,e.control.bindBackend(()=>t.cancelBackend(te.pid,te.started,te.xactStarted))},V=async()=>{for(let K=0;K<400&&!m&&!F;K++){if(await t.cancelOpening(B))return;await new Promise(G=>setTimeout(G,5))}},X=K=>t.begin(async G=>{C=performance.now(),e.trace?.time("poolMs",U);let te=e.trace?performance.now():0;if(e.control?.check(),i)throw new Error("Database transaction closed while waiting for its connection");B!==void 0&&!F&&e.control.bindBackend(V),e.trace?.time("setupMs",te),K(),h=G,b(k(G,l)),await S},{sql:I.join("; "),opened:W,tag:B});try{if(e.control?.check(),i)throw new Error("Database transaction closed while waiting for admission");let K=!1;for(let G=1;;G++)try{return await X(()=>{K=!0})}catch(te){let Q=ue(te);if(K||i||Q===void 0||G>=(Q==="lost"?dt:mt))throw te;e.control?.check()}}finally{C!==void 0&&e.trace?.time("connectionMs",C),q.release()}})().catch(v=>{throw L(v),v}),a.catch(()=>{})}),s.then(void 0,()=>{w=!0,i||e.onIdle?.()}),s)),A=b=>c??=(async()=>{if(i=!0,!s)return;await p(),T.size&&await Promise.allSettled([...T]);let L=e.trace?performance.now():0;o(b),await a?.catch(()=>{}),e.trace?.time("rollbackMs",L),e.trace?.rolledBack()})();return{ensure:N,get opened(){return s!==null},get busy(){return s!==null&&!i&&!w&&(!m||y>0)},get failed(){return w},get releasable(){return O()&&u&&l.refused===void 0&&(g==="read committed"||g==="read uncommitted")},async commit(){if(T.size&&await Promise.allSettled([...T]),!s){e.trace?.check(),i=!0;return}await Ao(l);try{if(e.trace?.check(),e.control?.checkDeadline(),l.refused)throw Ri(l.refused.error)}catch(L){throw await A(L),L}if(i=!0,!await p()){let L=Ae(new oe(503,"database_unavailable","The database is temporarily unavailable",{retrySafe:!1},1));throw await A(L),L}let b=e.trace?performance.now():0;if(r(),u&&g!==void 0&&g!=="serializable"){a.then(()=>e.trace?.committed(),()=>e.trace?.commitFailed());return}try{await a,e.trace?.committed()}catch(L){throw e.trace?.commitFailed(),L}finally{e.trace?.time("commitMs",b)}},rollback:A}}var Ni="5s",Ai="10s",Oi=new Set(["22P02","22007","22008","22003","22001"]),Lo="55s",vo=1,ki=1e3,Cn=new Set,In,Li=new Co("palgres.release");function xi(t){Cn.add(t),In===void 0&&(In=Li.runInAsyncScope(()=>setInterval(()=>{let e=performance.now();for(let n of Cn){let s=!0;try{s=n(e)}catch{s=!0}s&&Cn.delete(n)}Cn.size===0&&(clearInterval(In),In=void 0)},vo)),In.unref?.())}function Ii(t,e){let n=[],s=u=>u!==null&&u.opened&&!u.failed,r=new Set,o,a=!1,i=()=>{for(let u of n)if(s(u.tx)&&u.tx.busy)return!0;for(let u of r)if(u.busy)return!0;return!1},c=Co.bind(u=>{if(o===void 0||i())return!0;let g=r.size,m=r.size===0;for(let p of n)s(p.tx)&&(g++,p.tx.releasable||(m=!1));if(g===0)return!0;let h=u-o;if(m){if(h<vo)return!1;for(let p of n){let E=p.tx;s(E)&&(p.tx=null,p.lease?.leave(),p.lease=void 0,E.commit().catch(()=>{}))}return o=void 0,!0}return e===void 0||a?!0:h<ki?!1:(a=!0,e(Math.round(h)),!0)}),l=()=>{i()||(o=performance.now(),xi(c))};return{onIdle:l,surface(u,g){let m={tx:null};n.push(m);let h=()=>{Cn.delete(c);let p=m.tx;return m.tx=null,m.lease=void 0,p};return{ensure(){if(o!==void 0&&(o=performance.now()),m.tx===null){if(t())return Promise.reject(new Error("Database transaction has settled; its handle cannot be used again"));m.tx=u(l,p=>g(p).then(E=>(m.lease=E,E)))}return m.tx.ensure()},commit:()=>h()?.commit()??Promise.resolve(),rollback:p=>h()?.rollback(p)??Promise.resolve()}},atomic(u){return r.add(u),()=>{r.delete(u)&&l()}}}}function Ci(t){let e=ae(t),n=t?.code,s=o=>e!==void 0&&o.has(e)||typeof n=="string"&&o.has(n),r;if(s(Cs))r=!0;else if(s(vs))r=!1;else return;return Pe(new oe(503,"database_unavailable","The database is temporarily unavailable",{retrySafe:r},1),t)}var cn=t=>String(t?.message??t);function Pe(t,e){return t.cause=e,Ae(t)}function Rs(t,e,n){if(typeof t=="object"&&t!==null&&xo.has(t))return t;let s=vi(t,e,n);return typeof s=="object"&&s!==null&&xo.add(s),s}var xo=new WeakSet,bt=(t,e,n)=>Object.assign(new Error(t,{cause:e}),{sqlstate:n});function vi(t,e,n){if(Xe.is(t))return t;let s=ae(t);if(s===ne.inFailedTransaction||/current transaction is aborted/i.test(cn(t)))return bt(`This request cannot write any more: an earlier write in it failed, and a request runs in ONE Postgres transaction, so every statement after the failure is refused. Wrap a write you expect to fail in \`Database.$attempt(async (tx) => \u2026)\` \u2014 it takes a SAVEPOINT, so only that write rolls back \u2014 or use \`Database.public.<t>.put({ data, onConflict: [...] })\` when what you brace for is a duplicate row. (${cn(t)})`,t,ne.inFailedTransaction);if(Ve.is(t))return t;if(s===ne.uniqueViolation)return Pe(new Ve(dn(t)),t);if(s===ne.serializationFailure)return Pe(new Ot(s),t);if(s===ne.deadlockDetected)return Pe(new kt(s),t);if(s===ne.queryCancelled)return Pe(Object.assign(new oe(503,"database_query_cancelled","Database statement was cancelled"),{sqlstate:s}),t);let r=Ci(t);if(r)return r;if(e==="service"&&s===ne.foreignKeyViolation)return bt(`Database.$asService() hit a foreign key with nothing to point at. It runs in its OWN transaction on its OWN connection, so a row this request wrote through \`Database.*\` is not visible to it until the request commits \u2014 and the request cannot commit until the handler returns. If the row it needs is one this request just created, do both writes on ONE surface. (${cn(t)})`,t,s);if(/lock timeout/i.test(cn(t))){let o;return e==="service"?o=bt(`Database.$asService() waited too long for a row lock. It runs in its OWN transaction, so a row this request already wrote through Database.* is locked against it until the request commits \u2014 a wait that cannot end. Do that row's work on one surface or the other. (${cn(t)})`,t,s??ne.lockNotAvailable):o=bt(`Database waited too long for a lock. Another transaction holds it: a concurrent one, or another of this request's own \u2014 Database.*, $asService() and $atomic each run in their OWN transaction, and a row one of them wrote stays locked against the others until it commits, a wait that cannot end while the handler runs. Do that row's work on one surface. (${cn(t)})`,t,s??ne.lockNotAvailable),Pe(Object.assign(new oe(503,"database_busy","The database waited too long for a lock",{retrySafe:!1},1),{sqlstate:s??ne.lockNotAvailable}),o)}return s!==void 0&&Oi.has(s)?Pe(Object.assign(new oe(400,"invalid_value","A value is not one its column can take"),{sqlstate:s}),t):s===ne.insufficientPrivilege&&n!==null?Pe(Object.assign(new oe(n==="anon"?401:403,"permission_denied","The database does not allow this caller to do this"),{sqlstate:s}),t):(s!==void 0&&typeof t=="object"&&t!==null&&!Object.hasOwn(t,"sqlstate")&&Object.defineProperty(t,"sqlstate",{value:s,enumerable:!0,configurable:!0}),t)}function _i(t,e,n){let s=r=>({unsafe(o,a,i){let c;try{c=r.unsafe(o,a,i)}catch(l){return Promise.reject(Rs(l,e,n))}return Promise.resolve(c).then(Je,l=>{throw Rs(l,e,n)})},savepoint:o=>r.savepoint(a=>o(s(a))),...r.abandon?{abandon:r.abandon.bind(r)}:{}});return{unsafe:(r,o)=>t.unsafe(r,o),begin:(r,o)=>t.begin(a=>r(s(a)),o).catch(a=>{throw Rs(a,e,n)}),...t.cancelBackend?{cancelBackend:t.cancelBackend.bind(t)}:{},...t.cancelOpening?{cancelOpening:t.cancelOpening.bind(t)}:{}}}var Di=2,Io={anon:"anon",authenticated:"authenticated",service:"service"};function Pi(t,e){let n=Object.hasOwn(Io,e.role)?Io[e.role]:void 0;if(n===void 0)throw new Error(`palgres: a request is anon, authenticated or service, not "${String(e.role)}"`);return t[n]}function Ns(t,e,n,s={}){let{signal:r}=s,o=s.diagnostics===void 0?void 0:new Et(s.diagnostics),a=r===void 0?void 0:new sn(void 0,r),i=Pi(e.roles,n),c=e.roles.service,l=n.role==="anon"||n.role==="authenticated"?n.role:null,u=n.claims,g=!1,m=!1,h=()=>{m&&nt.committed()},p=x=>{let I;return{cat:e.cat,trace:o,cursorKey:e.cursorKey,cursorScope:()=>I??=to(x,u),search:e.search,searchable:()=>{m=!0}}},E=p(i),$=p(c),f=new Set,d=null,T=!1,y=0,w=new Set,O=x=>new Promise((I,B)=>{let F=K=>{w.delete(W),clearTimeout(X),x?.removeEventListener("abort",V),K===void 0?I():B(K)},W=()=>F(),V=()=>F(x?.reason??new Error("Database admission cancelled")),X=setTimeout(()=>F(new Fe({retryAfter:1},"Database queue deadline exceeded")),e.admission.queueTimeoutMs);w.add(W),x?.addEventListener("abort",V,{once:!0}),x?.aborted&&V()}),k=async x=>{let I;for(;;){for(;f.size===0&&d!==null;)await d;let W=f.size>0;if(W){for(;y>=Di;)await O(x);y++}let V;try{let X=e.admission.acquire(u,x,{nested:W,returning:!W&&T}).then(K=>{if(W&&f.size===0)return K.release(),null;let G={nested:W,turn:K};return f.add(G),W||(T=!0),G});if(!W){let K=X.then(()=>{},()=>{});d=K,K.then(()=>{d===K&&(d=null)})}V=await X}catch(X){throw W&&N(),X}if(V!==null){I=V;break}N()}let B=!1,F=()=>{if(!B){if(B=!0,f.delete(I),I.nested){N();return}for(let W of f){[I.turn,W.turn]=[W.turn,I.turn],W.nested=!1,I.nested=!0,N();return}}};return{queueMs:I.turn.queueMs,leave:F,release:()=>{F(),I.turn.release()}}},N=()=>{y--;let x=w.values().next().value;x?.()},A=Ii(()=>g,s.heldIdle),b=(x,I,B={})=>ko(_i(t,I,I==="user"?l:null),{bind:bn(e.binding,x,u),claims:u,admission:e.admission,acquire:k,trace:o,...B}),L=(x,I)=>async(B,F={})=>{if(Wn(F),g)throw new Error("Database request has settled; it cannot open another transaction");if(St.getStore()!==void 0)throw new Error("Nested Database.$atomic is not supported; use tx.$attempt for a savepoint");let W=Bn(F.retry),V=F.signal&&r?AbortSignal.any([F.signal,r]):F.signal??r,X=F.timeoutMs!==void 0||V!==void 0?new sn(F.timeoutMs,V):void 0;try{X?.check();for(let K=0;;K++){X?.check();let G=[F.statementTimeoutMs,X?.remainingMs()].filter(ce=>ce!==void 0),te=Symbol("atomic transaction"),Q=b(x,I,{scope:te,isolation:F.isolation,readOnly:F.readOnly,control:X,lockTimeout:`${F.lockTimeoutMs??5e3}ms`,statementTimeout:G.length===0?void 0:`${Math.min(...G)}ms`,onIdle:A.onIdle}),_n=A.atomic(Q);try{let ce=xn(()=>Q.ensure(),I==="user"?E:$),Ke=St.run(te,()=>B(ce)),H=await(X?X.race(Ke):Ke);return await Q.commit(),h(),H}catch(ce){await Q.rollback(ce);let Ke=Ge(ce)||Xe.is(ce)&&Ge(ce.cause);if(K>=W||!Ke)throw ce;o?.retry();let H=new Promise(re=>setTimeout(re,Math.min(100,2**K)));await(X?X.race(H):H)}finally{_n()}}}finally{X?.dispose()}},S=A.surface((x,I)=>b(i,"user",{lockTimeout:Ai,statementTimeout:Lo,control:a,onIdle:x,acquire:I}),k),v=null,q,U=null,C=()=>{if(U===null){if(g)throw new Error("Database request has settled; it cannot open another transaction");q=r===void 0?void 0:new sn(void 0,r);let x=q,I=A.surface((B,F)=>b(c,"service",{lockTimeout:Ni,statementTimeout:Lo,control:x,onIdle:B,acquire:F}),k);v=I,U=Object.assign(xn(()=>I.ensure(),$),{atomic:L(c,"service")})}return U};return{client:Object.assign(xn(()=>S.ensure(),E),{asService:C,atomic:L(i,"user")}),async commit(){g=!0;try{try{o?.check()}catch(x){throw await S.rollback(x),await v?.rollback(x),x}try{await S.commit()}catch(x){throw await v?.rollback(x),x}await v?.commit(),h(),o?.complete("committed"),a?.dispose(),q?.dispose()}catch(x){throw o?.failed(),x}},async rollback(x){g=!0,await S.rollback(x),await v?.rollback(x),a?.dispose(),q?.dispose(),o?.complete("failed")}}}function Mi(t){if(t.codec!==void 0&&t.codec in Ye)return Ye[t.codec].tsType;switch(t.type){case"uuid":case"text":case"timestamp":case"date":return"string";case"sql":return t.sqlType!==void 0&&Pn.has(t.sqlType)?"number":t.sqlType!==void 0&&Mn.has(t.sqlType)?"Json":"string";case"integer[]":return"number[]";case"boolean[]":return"boolean[]";case"uuid[]":case"text[]":case"bigint[]":case"numeric[]":case"timestamp[]":case"date[]":return"string[]";case"integer":return"number";case"bigint":case"numeric":return"string";case"boolean":return"boolean";case"jsonb":return"Json";case"enum":{let e=t.enumValues??[];return e.length===0?"string":e.map(n=>JSON.stringify(n)).join(" | ")}case"enum[]":{let e=t.enumValues??[];return e.length===0?"string[]":`(${e.map(n=>JSON.stringify(n)).join(" | ")})[]`}default:{let e=t.type;throw new Error(`env-gen: the column type "${String(e)}" has no TypeScript type \u2014 add a case to baseTsType`)}}}function qi(t){if(t.encrypted!==void 0)return t.encrypted.lookup?"encrypted:lookup":"encrypted";if(t.type==="enum"){let e=[...t.enumValues??[]].sort();return e.length===0?"enum":`enum:${e.join("|")}`}return t.type}function _o(t){let e=`Pg<${Mi(t)}, ${JSON.stringify(qi(t))}>`;return t.nullable?`${e} | null`:e}function Fi(t){return t.nullable===!0||t.defaultRandom===!0||t.defaultNow===!0||t.defaultValue!==void 0||t.defaultSql!==void 0||t.dbAssigned===!0||t.identity!==void 0}function Ui(t){return t.identity==="always"||t.generated!==void 0}var vn=t=>/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?t:JSON.stringify(t);function Do(t,e,n){let s=Object.entries(t.columns).filter(([,i])=>i._def.ignored!==!0),r=s.map(([i,c])=>`${n} ${vn(i)}: ${_o(c._def)};`),o=s.filter(([,i])=>!Ui(i._def)).map(([i,c])=>`${n} ${vn(i)}${Fi(c._def)?"?":""}: ${_o(c._def)};`),a=e.map(i=>`${vn(i.name)}: { to: ${JSON.stringify(i.to)}; kind: ${JSON.stringify(i.kind)}; via: ${JSON.stringify(i.via)} }`).join("; ");return[`${n}${vn(t.name)}: {`,`${n} row: {`,...r,`${n} };`,`${n} insert: {`,...o,`${n} };`,`${n} relations: {${a===""?"":` ${a} `}};`,`${n} uniqueKeys: ${JSON.stringify(ft(t))};`,...t.search!==void 0?[`${n} searchable: true;`]:[],`${n}};`].join(`
344
+ `)}function Bi(t){for(let e of t)for(let n of Object.values(e.tables))for(let[s,r]of Object.entries(n.columns)){let o=r._def;if(!(o.transform===void 0||o.codec!==void 0))throw new Me([`table "${ye(e.name,n.name)}" column "${s}" declares .transform<T>(): its target type does not exist at runtime, so the generated types would say something the engine contradicts. Declare a named codec instead \u2014 .asNumber() for a JS number, .asDecimal() for the exact string.`])}}var As="// palbase:env:begin",Os="// palbase:env:end",Po=`/**
341
345
  * A column's Postgres type, carried in its TypeScript type.
342
346
  *
343
347
  * __pg is optional, so a row still reads as a plain string or number and is
@@ -354,10 +358,10 @@ type Pg<T, N extends string> = T & { readonly __pg?: N };
354
358
  * undefined included: JSON.stringify drops undefined fields, and code that
355
359
  * writes { a: undefined } is everywhere \u2014 refusing it would be wrong.
356
360
  */
357
- type Json = string | number | boolean | null | undefined | Json[] | { [k: string]: Json };`;function wo(t,e){hi(t);let n=wn(t),s=u=>Object.values(u.tables).filter(g=>g.ignored!==!0),r=t.find(u=>u.name==="public"),o=t.filter(u=>u.name!=="public"),a=(r?s(r):[]).map(u=>ho(u,n.get(u.name)??[]," ")),i=a.length>0?`
361
+ type Json = string | number | boolean | null | undefined | Json[] | { [k: string]: Json };`;function Mo(t,e){Bi(t);let n=Nn(t),s=u=>Object.values(u.tables).filter(g=>g.ignored!==!0),r=t.find(u=>u.name==="public"),o=t.filter(u=>u.name!=="public"),a=(r?s(r):[]).map(u=>Do(u,n.get(u.name)??[]," ")),i=a.length>0?`
358
362
  ${a.join(`
359
363
  `)}
360
- `:"",c=o.map(u=>{let g=s(u).map(p=>ho(p,n.get(he(u.name,p.name))??[]," "));return` ${Nn(u.name)}: {
364
+ `:"",c=o.map(u=>{let g=s(u).map(m=>Do(m,n.get(ye(u.name,m.name))??[]," "));return` ${vn(u.name)}: {
361
365
  ${g.join(`
362
366
  `)}
363
367
  };`}),l=c.length>0?`
@@ -366,24 +370,24 @@ ${c.join(`
366
370
  `:"";return`declare module ${JSON.stringify(e)} {
367
371
  interface Tables {${i}}
368
372
  interface Schemas {${l}}
369
- }`}function Ei(t,e={}){let n=e.module??"palbase/backend/env",s=wo(t,n);return`// AUTO-GENERATED by Palgres' makeEnvDts from the app's schema files \u2014 DO NOT EDIT.
373
+ }`}function Wi(t,e={}){let n=e.module??"palbase/backend/env",s=Mo(t,n);return`// AUTO-GENERATED by Palgres' makeEnvDts from the app's schema files \u2014 DO NOT EDIT.
370
374
  // Nothing writes it again on its own: run makeEnvDts again when a schema changes.
371
375
  // Augments the ${n} \`Tables\` interface so \`Database.public.*\`
372
376
  // is typed with no import and no generic. Schemas other than \`public\` land
373
377
  // under \`Schemas\` and are reached by name the same way:
374
378
  // \`Database.<schema>.<table>\`.
375
379
 
376
- ${Eo}
380
+ ${Po}
377
381
 
378
- ${us}
382
+ ${As}
379
383
  ${s}
380
- ${ds}
384
+ ${Os}
381
385
 
382
386
  export {};
383
- `}function wi(t,e={}){let n=e.module??"palbase/backend/env";return`${us}
387
+ `}function ji(t,e={}){let n=e.module??"palbase/backend/env";return`${As}
384
388
  // The app's tables, from its schema files: rows, inserts, unique keys and relations (with, has). Written by
385
389
  // palbase db:types \u2014 run it again when a schema changes.
386
- ${Eo}
390
+ ${Po}
387
391
 
388
- ${wo(t,n)}
389
- ${ds}`}function yi(t,e){let n=e.tenant,s=e.key??"id",r=(u,g)=>{if(g==null||typeof g!="string"&&typeof g!="number"&&typeof g!="bigint"&&typeof g!="boolean")throw new TypeError(`defineRepository: the ${u} is a string, number, bigint or boolean, not ${g===null?"null":typeof g}`);return g},o=u=>({[n]:r("tenant",u)}),a=(u,g)=>({[n]:r("tenant",u),[s]:r(s,g)}),i=(u,g)=>({...u,[n]:r("tenant",g)}),c=u=>{let g=[n,s].filter(p=>Object.hasOwn(u,p));if(g.length>0)throw new Ae({fields:g.map(p=>({field:p,message:"cannot be changed through this update"}))},`defineRepository: the patch carries ${g.join(" and ")}, which an update does not change`);return u};class l{async list(g){return t.findMany({where:o(g)})}async find(g,p){return(await t.findMany({where:a(g,p),limit:1}))[0]??null}async insert(g,p){return t.insert(i(p,g))}async update(g,p,h){let m=await this.updateScoped(g,p,h);if(m===null)throw new gt(`no row ${s}=${String(p)} where ${String(n)}=${String(g)}`);return m}async updateScoped(g,p,h){return(await t.updateMany({where:a(g,p),set:c(h)}))[0]??null}async delete(g,p){await t.deleteMany({where:a(g,p)})}}return l}function Ti(t){return wt({$col:t},"col")}function $i(t,...e){return wt({$sql:{text:[...t],values:e}},"sql")}async function Si(t,e={}){let n=Cn(e.retry),s=0;for(;;)try{return await t()}catch(r){if(s>=n||!He(r))throw r;s+=1}}function Ri(t,e){return{search:(n,s)=>e.search(t,n,s),insert:n=>e.insert(t,n),aggregate:(n=>e.aggregate(t,n)),insertMany:((n,s)=>e.insertMany(t,n,s)),put:n=>e.put(t,n.data,{onConflict:n.onConflict}),update:n=>e.update(t,Os(t,n.where),n.set),delete:n=>e.delete(t,n),findUnique:(n=>e.findUnique(t,n.where,{select:n.select,lock:n.lock})),findById:n=>e.findById(t,n),page:(n=>{let{where:s,...r}=n??{};return e.page(t,s,r)}),findMany:(n=>{let{where:s,...r}=n??{};return e.findMany(t,s,r)}),updateMany:(n=>e.updateMany(t,n.where,n.set,n.returning===void 0?void 0:{returning:n.returning})),deleteMany:n=>e.deleteMany(t,n.where),count:n=>e.count(t,n?.where)}}function bi(t,e){let n={},s=r=>Object.fromEntries(Object.values(t.tables).map(o=>[o.name,r.table(he(t.name,o.name))]));for(let[r,o]of Object.entries(t.tables))n[r]=Ri(he(t.name,o.name),e);return{tables:n,diagnostics:()=>e.diagnostics(),transaction(r){let o=new ks;return Ls(e,{tables:s(o)},o,r)}}}async function nu(t){await Bt(t.sql);let e={cat:new rt(t.schemas,t.binding),binding:t.binding,roles:{...Je,...t.roles},admission:Ar(t.sql,t.admission),cursorKey:t.cursorSecret?Pr(t.cursorSecret):null,search:Tr(t.embed,t.log)};return{binding:t.binding,request(n,s){let r=fo(t.sql,e,n,s);return{database:xs(r.client),client:r.client,commit:()=>r.commit(),rollback:o=>r.rollback(o)}}}}export{Ft as BUN_CLOSE_GRACE_MS,Ae as BadRequest,So as Conflict,Je as DEFAULT_ROLES,Et as DeadlockDetected,Ie as DriverRefused,To as ENGINE_RAISED,ds as ENV_BLOCK_END,us as ENV_BLOCK_START,yo as HTTP_ERROR_BRAND,oe as HttpError,pn as MigrationOpen,$e as MigrationRefused,Dt as Migrator,gt as NotFound,ga as POSTGRES_JS_TYPES,gn as RowsHeld,J as SEARCH_SCHEMA,ne as SQLSTATE,De as SchemaError,ht as SerializationFailure,Me as TooManyRequests,Ve as TransactionAborted,Ao as TxPlanError,No as TxRefError,Ke as UniqueViolation,Zn as VersionNotMigrated,fn as VersionStillConnected,xt as adoptionBaseline,ko as ago,Qn as applicationName,Jo as bind,hn as bindStatement,ar as binding,wn as buildRelations,Er as bunDriver,Ut as cancelBackendThrough,yr as cancelOpeningThrough,be as canonicalType,wr as closeBunPool,Ti as col,ue as connectionFailure,on as constraintOf,nu as createDatabase,Oa as createSearchWorker,Vo as cutOff,Io as decrement,yi as defineRepository,Pe as digest,Po as drift,pt as emptySchema,ze as encodeParam,En as encodePgArray,wi as envBlock,zo as forgetUser,Lo as increment,hr as inlineParams,Yn as introspect,xe as isColRef,bo as isData,rr as isDirect,$o as isEngineRaised,He as isRetryable,Ei as makeEnvDts,bi as makeTypedDB,Ro as markData,Ne as markEngineRaised,ge as normalize,Oo as now,Lt as plan,wa as postgresJsDriver,sa as pullSchema,Ea as renewingBunPool,Pt as searchPath,$i as sqlFragment,ae as sqlstateOf,ft as validate,ve as vectorTable,Bt as verifyDriver,Te as versionSchema,Si as withRetry};
392
+ ${Mo(t,n)}
393
+ ${Os}`}function Ki(t,e){let n=e.tenant,s=e.key??"id",r=(u,g)=>{if(g==null||typeof g!="string"&&typeof g!="number"&&typeof g!="bigint"&&typeof g!="boolean")throw new TypeError(`defineRepository: the ${u} is a string, number, bigint or boolean, not ${g===null?"null":typeof g}`);return g},o=u=>({[n]:r("tenant",u)}),a=(u,g)=>({[n]:r("tenant",u),[s]:r(s,g)}),i=(u,g)=>({...u,[n]:r("tenant",g)}),c=u=>{let g=[n,s].filter(m=>Object.hasOwn(u,m));if(g.length>0)throw new Oe({fields:g.map(m=>({field:m,message:"cannot be changed through this update"}))},`defineRepository: the patch carries ${g.join(" and ")}, which an update does not change`);return u};class l{async list(g){return t.findMany({where:o(g)})}async find(g,m){return(await t.findMany({where:a(g,m),limit:1}))[0]??null}async insert(g,m){return t.insert(i(m,g))}async update(g,m,h){let p=await this.updateScoped(g,m,h);if(p===null)throw new At(`no row ${s}=${String(m)} where ${String(n)}=${String(g)}`);return p}async updateScoped(g,m,h){return(await t.updateMany({where:a(g,m),set:c(h)}))[0]??null}async delete(g,m){await t.deleteMany({where:a(g,m)})}}return l}function Hi(t){return Lt({$col:t},"col")}function Vi(t,...e){return Lt({$sql:{text:[...t],values:e}},"sql")}async function Gi(t,e={}){let n=Bn(e.retry),s=0;for(;;)try{return await t()}catch(r){if(s>=n||!Ge(r))throw r;s+=1}}function Xi(t,e){return{search:(n,s)=>e.search(t,n,s),insert:n=>e.insert(t,n),aggregate:(n=>e.aggregate(t,n)),insertMany:((n,s)=>e.insertMany(t,n,s)),put:n=>e.put(t,n.data,{onConflict:n.onConflict}),update:n=>e.update(t,js(t,n.where),n.set),delete:n=>e.delete(t,n),findUnique:(n=>e.findUnique(t,n.where,{select:n.select,lock:n.lock})),findById:n=>e.findById(t,n),page:(n=>{let{where:s,...r}=n??{};return e.page(t,s,r)}),findMany:(n=>{let{where:s,...r}=n??{};return e.findMany(t,s,r)}),updateMany:(n=>e.updateMany(t,n.where,n.set,n.returning===void 0?void 0:{returning:n.returning})),deleteMany:n=>e.deleteMany(t,n.where),count:n=>e.count(t,n?.where)}}function Yi(t,e){let n={},s=r=>Object.fromEntries(Object.values(t.tables).map(o=>[o.name,r.table(ye(t.name,o.name))]));for(let[r,o]of Object.entries(t.tables))n[r]=Xi(ye(t.name,o.name),e);return{tables:n,diagnostics:()=>e.diagnostics(),transaction(r){let o=new Ks;return Hs(e,{tables:s(o)},o,r)}}}async function vu(t){await Zt(t.sql);let e=new gn;await e.read(o=>t.sql.unsafe(o));let n=t.schemas.some(o=>Object.values(o.tables).some(a=>!a.ignored&&Object.values(a.columns).some(i=>i._def.encrypted!==void 0&&!i._def.ignored))),s=null;if(n||e.size>0){if(t.fields===void 0)throw new Error(`palgres: ${n?"the schema has an .encrypted() column":"a migration is taking a column's encryption on or off"}: the engine needs the project's fields to seal and open it \u2014 createDatabase({ fields })`);s=await jn(t.fields),setInterval(()=>{e.read(a=>t.sql.unsafe(a)).catch(a=>t.log?.(`palgres: which columns are going over could not be read (${a instanceof Error?a.message:String(a)}); kept as last read`))},Kn).unref?.()}let r={cat:new gt(t.schemas,t.binding,s!==null?{cipher:s,sealing:e}:null),binding:t.binding,roles:{...nn,...t.roles},admission:Hr(t.sql,t.admission),cursorKey:t.cursorSecret?no(t.cursorSecret):null,search:Fr(t.embed,t.log)};return{binding:t.binding,request(o,a){let i=Ns(t.sql,r,o,a);return{database:Gs(i.client),client:i.client,commit:()=>i.commit(),rollback:c=>i.rollback(c)}},async reseal(o={}){let a=r.cat.fields;if(a===null||!t.binding.direct)return[];let i=[];for(let{table:c,column:l,encrypted:u}of r.cat.encryptedColumns()){if(a.sealing.get(u.address)!==void 0)continue;let g={table:c.sql,column:l,lookup:u.lookup,address:u.address,direction:"seal"},m=null,h=0;do{let p=Ns(t.sql,r,{role:"service",claims:{}});try{let E=await Hn(($,f)=>p.client.query($,f),g,a.cipher,m,o.batchSize??500);await p.commit(),h+=E.done,m=E.last}catch(E){throw await p.rollback(E),E}}while(m!==null);i.push({address:u.address,resealed:h})}return i}}}export{zt as BUN_CLOSE_GRACE_MS,Oe as BadRequest,Bo as Conflict,nn as DEFAULT_ROLES,kt as DeadlockDetected,Ce as DriverRefused,Fo as ENGINE_RAISED,Os as ENV_BLOCK_END,As as ENV_BLOCK_START,qo as HTTP_ERROR_BRAND,oe as HttpError,$n as MigrationOpen,he as MigrationRefused,Gt as Migrator,At as NotFound,Pa as POSTGRES_JS_TYPES,en as RowsHeld,de as SEALING,Kn as SEALING_REFRESH_MS,J as SEARCH_SCHEMA,It as SETTLE_MS,ne as SQLSTATE,Me as SchemaError,gn as Sealing,Ot as SerializationFailure,Fe as TooManyRequests,Xe as TransactionAborted,Ho as TxPlanError,Ko as TxRefError,Ve as UniqueViolation,ut as VersionNotMigrated,Sn as VersionStillConnected,jt as adoptionBaseline,Go as ago,ct as applicationName,Ea as bind,bn as bindStatement,Nr as binding,Nn as buildRelations,Pr as bunDriver,Qt as cancelBackendThrough,qr as cancelOpeningThrough,Ne as canonicalType,Mr as closeBunPool,Hi as col,ue as connectionFailure,dn as constraintOf,vu as createDatabase,Xa as createSearchWorker,pa as cutOff,Yo as decrement,Ki as defineRepository,qe as digest,sa as drift,Rt as emptySchema,tn as encodeParam,Rn as encodePgArray,ji as envBlock,Qe as fieldAddress,ya as forgetUser,Xo as increment,Dr as inlineParams,at as introspect,ke as isColRef,jo as isData,br as isDirect,Uo as isEngineRaised,Ge as isRetryable,Wi as makeEnvDts,Yi as makeTypedDB,Wo as markData,Ae as markEngineRaised,Ee as normalize,Vo as now,Bt as plan,Fa as postgresJsDriver,Ra as pullSchema,qa as renewingBunPool,Xt as searchPath,Vi as sqlFragment,ae as sqlstateOf,Nt as validate,ve as vectorTable,Zt as verifyDriver,$e as versionSchema,Gi as withRetry};