@murumets-ee/db 0.9.0 → 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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{drizzle as e}from"drizzle-orm/postgres-js";import t from"postgres";import{existsSync as n}from"node:fs";import{readdir as r}from"node:fs/promises";import{join as i}from"node:path";import{and as a,count as o,eq as s,getTableColumns as c,getTableName as l,gt as u,gte as ee,ilike as d,inArray as f,isNotNull as p,isNull as m,lt as te,lte as ne,ne as re,not as h,notInArray as g,or as _,sql as v}from"drizzle-orm";import{bigint as ie,boolean as y,doublePrecision as b,index as x,integer as S,jsonb as C,pgTable as w,primaryKey as ae,real as oe,text as se,timestamp as ce,unique as le,uuid as T,varchar as E}from"drizzle-orm/pg-core";function ue(n){return e(t(n.url,{max:n.poolMax||10,idle_timeout:20,max_lifetime:1800}))}function D(n){let r=t(n.readOnlyUrl||n.url,{max:n.poolMax||10,idle_timeout:20,max_lifetime:1800,connection:{application_name:`toolkit_readonly`},onnotice:()=>{}});return r.unsafe(`SET default_transaction_read_only = on`).catch(()=>{}),e(r)}async function O(e){await e.execute(v`
1
+ import{drizzle as e}from"drizzle-orm/postgres-js";import t from"postgres";import{AsyncLocalStorage as n}from"node:async_hooks";import{readdir as r}from"node:fs/promises";import{join as i}from"node:path";import{and as a,count as o,eq as s,getTableColumns as c,getTableName as l,gt as u,gte as ee,ilike as d,inArray as f,isNotNull as p,isNull as m,lt as te,lte as ne,ne as re,not as ie,notInArray as ae,or as oe,sql as h}from"drizzle-orm";import{bigint as se,boolean as ce,doublePrecision as g,index as le,integer as _,jsonb as v,pgTable as y,primaryKey as ue,real as de,text as b,timestamp as x,unique as S,uuid as C,varchar as w}from"drizzle-orm/pg-core";const T=new n;function fe(){return T.getStore()}function pe(e){let t={count:0};return T.run(t,()=>e(t))}const E=new class{logQuery(e,t){let n=T.getStore();n&&n.count++}};function D(){return process.env.LUMI_DB_QUERY_COUNTER===`1`}function O(){return D()?{logger:E}:void 0}function k(n){let r=t(n.url,{max:n.poolMax||10,idle_timeout:20,max_lifetime:1800}),i=O();return i?e(r,i):e(r)}function A(n){let r=t(n.readOnlyUrl||n.url,{max:n.poolMax||10,idle_timeout:20,max_lifetime:1800,connection:{application_name:`toolkit_readonly`,default_transaction_read_only:!0},onnotice:()=>{}}),i=O();return i?e(r,i):e(r)}async function j(e){try{return(await r(e)).filter(e=>e.endsWith(`.ts`))}catch(e){if(e.code===`ENOENT`)return[];throw e}}async function M(e){await e.execute(h`
2
2
  CREATE TABLE IF NOT EXISTS _toolkit_migrations (
3
3
  id SERIAL PRIMARY KEY,
4
4
  namespace VARCHAR(50) NOT NULL,
@@ -6,15 +6,15 @@ import{drizzle as e}from"drizzle-orm/postgres-js";import t from"postgres";import
6
6
  applied_at TIMESTAMP NOT NULL DEFAULT NOW(),
7
7
  UNIQUE(namespace, name)
8
8
  )
9
- `)}async function k(e){let t=i(e,`migrations`);if(!n(t))return[];let a=[],o=i(t,`.toolkit`);if(n(o)){let e=await r(o);for(let t of e)t.endsWith(`.ts`)&&a.push({path:i(o,t),namespace:`toolkit`,name:t})}let s=await r(t);for(let e of s)e!==`.toolkit`&&e.endsWith(`.ts`)&&a.push({path:i(t,e),namespace:`project`,name:e});let c=a.filter(e=>e.namespace===`toolkit`).sort((e,t)=>e.name.localeCompare(t.name)),l=a.filter(e=>e.namespace===`project`).sort((e,t)=>e.name.localeCompare(t.name));return[...c,...l]}async function A(e,t){await O(e);let n=await k(t),r=await e.execute(v`
9
+ `)}async function N(e){let t=i(e,`migrations`),n=i(t,`.toolkit`),[r,a]=await Promise.all([j(n),j(t)]),o=r.map(e=>({path:i(n,e),namespace:`toolkit`,name:e})).sort((e,t)=>e.name.localeCompare(t.name)),s=a.filter(e=>e!==`.toolkit`).map(e=>({path:i(t,e),namespace:`project`,name:e})).sort((e,t)=>e.name.localeCompare(t.name));return[...o,...s]}async function P(e,t){await M(e);let n=await N(t),r=await e.execute(h`
10
10
  SELECT namespace, name FROM _toolkit_migrations
11
11
  ORDER BY applied_at ASC
12
- `),i=new Set(r.map(e=>`${e.namespace}:${e.name}`)),a=[],o=[];for(let e of n)i.has(`${e.namespace}:${e.name}`)?a.push(e):o.push(e);return{applied:a,pending:o}}async function j(e,t,n){await O(e);let{pending:r}=await A(e,t);if(r.length===0){console.log(`No pending migrations`);return}console.log(`Running ${r.length} pending migration${r.length===1?``:`s`}...`);for(let t of r){console.log(` Applying ${t.namespace}/${t.name}...`);let r=await n(t.path);if(typeof r.up!=`function`)throw Error(`Migration ${t.namespace}/${t.name} has no \`up\` export. Every migration file must export an async \`up({ db })\` function.`);try{await e.transaction(async e=>{await r.up({db:e}),await e.execute(v`
12
+ `),i=new Set(r.map(e=>`${e.namespace}:${e.name}`)),a=[],o=[];for(let e of n)i.has(`${e.namespace}:${e.name}`)?a.push(e):o.push(e);return{applied:a,pending:o}}async function F(e,t,n){await M(e);let{pending:r}=await P(e,t);if(r.length===0){console.log(`No pending migrations`);return}console.log(`Running ${r.length} pending migration${r.length===1?``:`s`}...`);for(let t of r){console.log(` Applying ${t.namespace}/${t.name}...`);let r=await n(t.path);if(typeof r.up!=`function`)throw Error(`Migration ${t.namespace}/${t.name} has no \`up\` export. Every migration file must export an async \`up({ db })\` function.`);try{await e.transaction(async e=>{await r.up({db:e}),await e.execute(h`
13
13
  INSERT INTO _toolkit_migrations (namespace, name)
14
14
  VALUES (${t.namespace}, ${t.name})
15
- `)}),console.log(` ✓ Applied ${t.namespace}/${t.name}`)}catch(e){throw console.error(` ✗ Failed to apply ${t.namespace}/${t.name}:`,e),e}}console.log(`Successfully applied ${r.length} migration${r.length===1?``:`s`}`)}async function M(e,t,n,r=1){await O(e);let{applied:i}=await A(e,t);if(i.length===0){console.log(`No applied migrations to roll back`);return}let a=i.slice(-r).reverse(),o=await Promise.all(a.map(async e=>({meta:e,mod:await n(e.path)})));for(let{meta:e,mod:t}of o)if(typeof t.down!=`function`)throw Error(`Migration ${e.namespace}/${e.name} has no \`down\` export — cannot roll back. Add an async \`down({ db })\` function to the migration file.`);for(let{meta:t,mod:n}of o){console.log(` Rolling back ${t.namespace}/${t.name}...`);try{await e.transaction(async e=>{await n.down({db:e}),await e.execute(v`
15
+ `)}),console.log(` ✓ Applied ${t.namespace}/${t.name}`)}catch(e){throw console.error(` ✗ Failed to apply ${t.namespace}/${t.name}:`,e),e}}console.log(`Successfully applied ${r.length} migration${r.length===1?``:`s`}`)}async function I(e,t,n,r=1){await M(e);let{applied:i}=await P(e,t);if(i.length===0){console.log(`No applied migrations to roll back`);return}let a=i.slice(-r).reverse(),o=await Promise.all(a.map(async e=>({meta:e,mod:await n(e.path)})));for(let{meta:e,mod:t}of o)if(typeof t.down!=`function`)throw Error(`Migration ${e.namespace}/${e.name} has no \`down\` export — cannot roll back. Add an async \`down({ db })\` function to the migration file.`);for(let{meta:t,mod:n}of o){console.log(` Rolling back ${t.namespace}/${t.name}...`);try{await e.transaction(async e=>{await n.down({db:e}),await e.execute(h`
16
16
  DELETE FROM _toolkit_migrations
17
17
  WHERE namespace = ${t.namespace} AND name = ${t.name}
18
- `)}),console.log(` ✓ Rolled back ${t.namespace}/${t.name}`)}catch(e){throw console.error(` ✗ Failed to roll back ${t.namespace}/${t.name}:`,e),e}}console.log(`Successfully rolled back ${o.length} migration${o.length===1?``:`s`}`)}var N=class{schemas=new Map;register(e,t){this.schemas.set(e,t)}get(e){return this.schemas.get(e)}all(){let e={};for(let[t,n]of this.schemas.entries())e[t]=n;return e}has(e){return this.schemas.has(e)}};const P=new N;function F(){return new N}function I(e,t){let n=e;return Object.defineProperty(n,`__kind`,{value:t.kind,enumerable:!1}),Object.defineProperty(n,`__notNull`,{value:t.notNull,enumerable:!1}),Object.defineProperty(n,`__hasDefault`,{value:t.hasDefault,enumerable:!1}),Object.defineProperty(n,`__type`,{value:void 0,enumerable:!1}),t.pgName&&Object.defineProperty(n,`__pgName`,{value:t.pgName,enumerable:!1}),t.primaryKey&&Object.defineProperty(n,`__primaryKey`,{value:!0,enumerable:!1}),n}const L={uuid(e){let t=e?.notNull??!1,n=e?.defaultRandom??!1,r=e?.primaryKey??!1;return I(n=>{let i=T(n);return r&&(i=i.primaryKey()),e?.defaultRandom&&(i=i.defaultRandom()),t&&!r&&(i=i.notNull()),i},{kind:`uuid`,notNull:t||r,hasDefault:n||r,pgName:e?.pgName,primaryKey:r||void 0})},varchar(e){if(!Number.isInteger(e.length)||e.length<1||e.length>1073741823)throw Error(`column.varchar: length must be an integer between 1 and 1073741823, got ${e.length}`);let t=e.notNull??!1;return I(n=>{let r=E(n,{length:e.length});return t&&(r=r.notNull()),e.default!==void 0&&(r=r.default(e.default)),r},{kind:`varchar`,notNull:t,hasDefault:e.default!==void 0,pgName:e.pgName})},text(e){let t=e?.notNull??!1;return I(n=>{let r=se(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`text`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},integer(e){let t=e?.notNull??!1;return I(n=>{let r=S(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`integer`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},bigint(e){let t=e?.mode??`number`,n=e?.notNull??!1;return I(r=>{let i=ie(r,{mode:t});return n&&(i=i.notNull()),e?.default!==void 0&&(i=i.default(e.default)),i},{kind:`bigint`,notNull:n,hasDefault:e?.default!==void 0,pgName:e?.pgName})},double(e){let t=e?.notNull??!1;return I(n=>{let r=b(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`double`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},boolean(e){let t=e?.notNull??!1;return I(n=>{let r=y(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`boolean`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},timestamp(e){let t=e?.notNull??!1,n=e?.defaultNow??!1,r=e?.withTimezone??!0;return I(n=>{let i=ce(n,{withTimezone:r});return t&&(i=i.notNull()),e?.defaultNow&&(i=i.defaultNow()),i},{kind:`timestamp`,notNull:t,hasDefault:n,pgName:e?.pgName})},jsonb(e){let t=e?.notNull??!1;return I(n=>{let r=C(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`jsonb`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},uuidArray(e){let t=e?.notNull??!1;return I(e=>{let n=T(e).array();return t&&(n=n.notNull()),n},{kind:`uuidArray`,notNull:t,hasDefault:!1,pgName:e?.pgName})}},R=/^[a-zA-Z_][a-zA-Z0-9_-]*$|^\d+$/,z=new Set([`$and`,`$or`,`$not`]),B=new Set([`eq`,`ne`,`in`,`notIn`,`gt`,`gte`,`lt`,`lte`,`isNull`,`isNotNull`,`ilike`,`startsWith`]);var V=class extends Error{constructor(e){super(`WhereBuilder: ${e}`),this.name=`WhereBuilderError`}};function H(e){return e.replace(/[\\%_]/g,`\\$&`)}function U(e,t,n){if(!n.includes(`.`)){let t=e[n];if(!t)throw new V(`unknown column "${n}"`);return t}let[r,...i]=n.split(`.`);if(!r||i.length===0)throw new V(`malformed dotted key "${n}"`);let a=t[r];if(!a)throw new V(`unknown column "${r}" in dotted key "${n}"`);if(a!==`jsonb`)throw new V(`dotted-path access is only supported on jsonb columns, but "${r}" is ${a}`);for(let e of i)if(!R.test(e))throw new V(`invalid jsonb path segment "${e}" — must match [a-zA-Z_][a-zA-Z0-9_-]* or be a non-negative integer`);let o=e[r];if(!o)throw new V(`unknown column "${r}"`);let s=v`${o}`;for(let e=0;e<i.length;e++){let t=i[e],n=e===i.length-1;if(/^\d+$/.test(t)){if(t.length>10)throw new V(`jsonb path index "${t}" is too large`);let e=v.raw(t);s=n?v`${s}->>${e}`:v`${s}->${e}`}else s=n?v`${s}->>${t}`:v`${s}->${t}`}return s}function de(e,t){if(t===null)return m(e);if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`||typeof t==`bigint`||t instanceof Date)return s(e,t);if(Array.isArray(t))throw new V(`arrays must be wrapped in an operator (e.g. { in: [...] }) — bare arrays are not allowed`);if(typeof t!=`object`)throw new V(`unsupported value type: ${typeof t}`);let n=t,r=Object.keys(n);if(r.length===0)throw new V(`empty operator object`);let i=[];for(let t of r){if(!B.has(t))throw new V(`unknown operator "${t}"`);let r=n[t];switch(t){case`eq`:i.push(s(e,r));break;case`ne`:i.push(re(e,r));break;case`in`:if(!Array.isArray(r))throw new V(`"in" operator requires an array`);r.length===0?i.push(v`false`):i.push(f(e,r));break;case`notIn`:if(!Array.isArray(r))throw new V(`"notIn" operator requires an array`);r.length===0?i.push(v`true`):i.push(g(e,r));break;case`gt`:i.push(u(e,r));break;case`gte`:i.push(ee(e,r));break;case`lt`:i.push(te(e,r));break;case`lte`:i.push(ne(e,r));break;case`isNull`:if(r!==!0)throw new V('"isNull" operator must be `true`');i.push(m(e));break;case`isNotNull`:if(r!==!0)throw new V('"isNotNull" operator must be `true`');i.push(p(e));break;case`ilike`:if(typeof r!=`string`)throw new V(`"ilike" operator requires a string`);i.push(d(e,`%${H(r)}%`));break;case`startsWith`:if(typeof r!=`string`)throw new V(`"startsWith" operator requires a string`);i.push(d(e,`${H(r)}%`));break}}if(i.length!==0)return i.length===1?i[0]:a(...i)}function W(e,t,n,r=0){if(!n)return;if(typeof n!=`object`||Array.isArray(n))throw new V(`where clause must be a plain object`);if(r>16)throw new V(`where clause exceeds maximum nesting depth of 16 — real queries should not need this much nesting; if yours does, reconsider whether it should be expressed differently`);let i=[];for(let o of Object.keys(n)){let s=n[o];if(o===`$and`){if(!Array.isArray(s))throw new V(`$and must be an array`);if(s.length===0)throw new V(`$and must contain at least one clause`);let n=s.map(n=>W(e,t,n,r+1)).filter(e=>e!==void 0);n.length>0&&i.push(a(...n));continue}if(o===`$or`){if(!Array.isArray(s))throw new V(`$or must be an array`);if(s.length===0)throw new V(`$or must contain at least one clause`);let n=s.map(n=>W(e,t,n,r+1)).filter(e=>e!==void 0);n.length>0&&i.push(_(...n));continue}if(o===`$not`){if(!G(s))throw new V(`$not must contain a non-empty clause`);let n=W(e,t,s,r+1);n&&i.push(h(n));continue}if(z.has(o))continue;let c=de(U(e,t,o),s);c&&i.push(c)}if(i.length!==0)return i.length===1?i[0]:a(...i)}function G(e){return typeof e!=`object`||!e||Array.isArray(e)?!1:Object.keys(e).length>0}const K=w(`pg_class`,{relname:E(`relname`,{length:63}).notNull(),reltuples:oe(`reltuples`).notNull()}),fe=100,q=1e3,J=1e3;var Y=class extends Error{constructor(e){super(`TableClient: ${e}`),this.name=`TableClientError`}},X=class e{constructor(e,t,n,r=[]){this.table=e,this.columnKinds=t,this.db=n,this.primaryKeyColumns=r}get _selectTable(){return this.table}async findOne(e){if(!G(e))throw new Y(`findOne requires a non-empty where clause`);let t=this.buildWhereOrThrow(e);return(await this.db.select().from(this._selectTable).where(t).limit(1))[0]??null}async findMany(e={}){let t=this.validateLimit(e.limit);if(e.offset!==void 0&&(!Number.isInteger(e.offset)||e.offset<0))throw new Y(`offset must be a non-negative integer, got ${e.offset}`);let n=e.orderBy&&e.orderBy.length>0?e.orderBy.map(e=>{let t=this.table[e.column];if(!t)throw new Y(`unknown orderBy column "${e.column}"`);return e.dir===`desc`?v`${t} DESC`:v`${t} ASC`}):void 0,r=e.where?this.buildWhereOrThrow(e.where):void 0,i=this.db.select().from(this._selectTable).$dynamic();return r&&(i=i.where(r)),n&&(i=i.orderBy(...n)),i=i.limit(t),e.offset!==void 0&&(i=i.offset(e.offset)),await i}async count(e){let t=e?this.buildWhereOrThrow(e):void 0,n=this.db.select({value:o()}).from(this._selectTable).$dynamic();t&&(n=n.where(t));let r=await n;return Number(r[0]?.value??0)}async exists(e){if(!G(e))throw new Y(`exists requires a non-empty where clause`);let t=this.buildWhereOrThrow(e);return(await this.db.select({one:v`1`}).from(this._selectTable).where(t).limit(1)).length>0}async distinct(e,t){let n=this.table[e];if(!n)throw new Y(`distinct: unknown column "${e}"`);let r=[];if(t?.includeNull||r.push(p(n)),t?.where){let e=this.buildWhereOrThrow(t.where);r.push(e)}let i=this.db.selectDistinct({value:n}).from(this._selectTable).$dynamic();if(r.length===1?i=i.where(r[0]):r.length>1&&(i=i.where(a(...r))),t?.orderBy){let e=t.orderBy===`desc`?v`${n} DESC`:v`${n} ASC`;i=i.orderBy(e)}return(await i).map(e=>e.value)}async insert(e){return(await this.db.insert(this.table).values(e).returning())[0]}async upsert(e,t){let n=Array.isArray(t.target)?t.target:[t.target];if(n.length===0)throw new Y(`upsert requires at least one target column`);let r=c(this.table),i=n.map(e=>{let t=r[e];if(!t)throw new Y(`upsert target references unknown column "${e}"`);return t}),a=t.set??e,o=t.setWhere&&G(t.setWhere)?this.buildWhereOrThrow(t.setWhere):void 0,s=await this.db.insert(this.table).values(e).onConflictDoUpdate({target:i,set:a,...o?{setWhere:o}:{}}).returning();if(s.length>0)return s[0];let l={};for(let t of n)l[t]=e[t];let u=await this.findOne(l);if(!u)throw new Y(`upsert with setWhere: conflict row not found after blocked update — this should not happen`);return u}async insertMany(e){if(!Array.isArray(e))throw new Y(`insertMany requires an array of rows`);if(e.length===0)return[];if(e.length>1e3)throw new Y(`insertMany batch too large: ${e.length} > ${J}`);return await this.db.insert(this.table).values(e).returning()}async update(e,t){if(!G(e))throw new Y(`update requires a non-empty where clause`);let n=this.buildWhereOrThrow(e),r=await this.db.update(this.table).set(t).where(n).returning();if(r.length>1)throw new Y(`update matched ${r.length} rows but is expected to match at most one — use updateMany for bulk updates. WARNING: the update has already been applied; wrap in a transaction if you need rollback.`);return r[0]??null}async updateMany(e,t){if(!G(e))throw new Y(`updateMany requires a non-empty where clause`);let n=this.buildWhereOrThrow(e);return await this.db.update(this.table).set(t).where(n).returning()}async delete(e){if(!G(e))throw new Y(`delete requires a non-empty where clause`);let t=this.buildWhereOrThrow(e),n=await this.db.delete(this.table).where(t).returning();if(n.length>1)throw new Y(`delete matched ${n.length} rows but is expected to match at most one — use deleteMany for bulk deletes. WARNING: the delete has already been applied; wrap in a transaction if you need rollback.`);return n[0]??null}async deleteMany(e){if(!G(e))throw new Y(`deleteMany requires a non-empty where clause`);let t=this.buildWhereOrThrow(e);return await this.db.delete(this.table).where(t).returning()}async transaction(t){return await this.db.transaction(async n=>await t(new e(this.table,this.columnKinds,n,this.primaryKeyColumns)))}async claim(e){if(this.primaryKeyColumns.length===0)throw new Y(`claim() requires the table to have a primary key — declare primaryKey in defineTable() or use column.uuid({ primaryKey: true })`);if(this.primaryKeyColumns.length>1)throw new Y(`claim() does not support composite primary keys — use a single-column primary key or call transaction() with FOR UPDATE directly`);if(!G(e.where))throw new Y(`claim requires a non-empty where clause`);if(!Number.isInteger(e.limit)||e.limit<1)throw new Y(`claim limit must be a positive integer, got ${e.limit}`);if(e.limit>1e3)throw new Y(`claim limit ${e.limit} exceeds MAX_LIMIT ${q}`);let t=Object.keys(e.set??{}),n=Object.keys(e.setSql??{});if(t.length===0&&n.length===0)throw new Y(`claim requires at least one field in set or setSql`);for(let e of t)if(!this.table[e])throw new Y(`claim set: unknown column "${e}"`);for(let e of n)if(!this.table[e])throw new Y(`claim setSql: unknown column "${e}"`);let r=this.buildWhereOrThrow(e.where),i=e.orderBy&&e.orderBy.length>0?e.orderBy.map(e=>{let t=this.table[e.column];if(!t)throw new Y(`claim: unknown orderBy column "${e.column}"`);return e.dir===`desc`?v`${t} DESC`:v`${t} ASC`}):void 0,a=this.primaryKeyColumns[0],o=this.table[a];return await this.db.transaction(async t=>{let n=t.select({_pk:o}).from(this._selectTable).where(r).limit(e.limit).for(`update`,{skipLocked:!0}).$dynamic();i&&(n=n.orderBy(...i));let a=await n;if(a.length===0)return[];let s=a.map(e=>e._pk),c={...e.set??{}};if(e.setSql)for(let[t,n]of Object.entries(e.setSql))c[t]=n;return await t.update(this.table).set(c).where(f(o,s)).returning()})}async aggregate(e){let t=Object.entries(e.select);if(t.length===0)throw new Y(`aggregate requires at least one select field`);let n=c(this.table),r={};if(e.groupBy)for(let t of e.groupBy){let e=n[t];if(!e)throw new Y(`aggregate groupBy: unknown column "${t}"`);r[t]=e}for(let[e,i]of t)r[e]=this.buildAggregateExpr(i,n);let i=this.db.select(r).from(this._selectTable).$dynamic();if(e.where){let t=this.buildWhereOrThrow(e.where);i=i.where(t)}if(e.groupBy&&e.groupBy.length>0){let t=e.groupBy.map(e=>{let t=n[e];if(!t)throw new Y(`aggregate groupBy: unknown column "${e}"`);return t});i=i.groupBy(...t)}if(e.orderBy&&e.orderBy.length>0){let t=e.orderBy.map(e=>{let t=this.table[e.column];if(!t)throw new Y(`aggregate orderBy: unknown column "${e.column}"`);return e.dir===`desc`?v`${t} DESC`:v`${t} ASC`});i=i.orderBy(...t)}if(e.limit!==void 0){let t=this.validateLimit(e.limit);i=i.limit(t)}return await i}async countEstimate(){let e=l(this.table),[t]=await this.db.select({estimate:v`greatest(${K.reltuples}::bigint, 0)`}).from(K).where(s(K.relname,e)).limit(1);return t?Number(t.estimate):0}buildAggregateExpr(e,t){if(`column`in e&&e.column){let n=t[e.column];if(!n)throw new Y(`aggregate: unknown column "${String(e.column)}"`);switch(e.fn){case`count`:return v`count(${n})::int`;case`sum`:return v`sum(${n})`;case`avg`:return v`avg(${n})`;case`min`:return v`min(${n})`;case`max`:return v`max(${n})`;default:throw new Y(`aggregate: unknown function "${e.fn}"`)}}if(e.fn===`count`)return v`count(*)::int`;throw new Y(`aggregate: ${e.fn} requires a column`)}buildWhereOrThrow(e){try{let t=W(this.table,this.columnKinds,e);if(!t)throw new Y(`where clause produced no SQL predicate`);return t}catch(e){throw e instanceof V?new Y(e.message.replace(/^WhereBuilder: /,``)):e}}validateLimit(e){if(e===void 0)return 100;if(!Number.isInteger(e)||e<1)throw new Y(`limit must be a positive integer, got ${e}`);if(e>1e3)throw new Y(`limit ${e} exceeds MAX_LIMIT ${q} — paginate or use claim() for batch processing`);return e}},Z=class{byName=new Map;register(e,t,n){let r=this.byName.get(e);if(r){if(r.table===t||r.source&&n&&r.source===n)return;throw Error(`tableRegistry: a different table is already registered under name "${e}". Did you call defineTable twice? First registered from ${r.source??`<unknown>`}, now from ${n??`<unknown>`}.`)}this.byName.set(e,{name:e,table:t,source:n})}get(e){return this.byName.get(e)?.table}has(e){return this.byName.has(e)}allTables(){let e={};for(let t of this.byName.values())e[t.name]=t.table;return e}clear(){if(process.env.NODE_ENV===`production`)throw Error(`tableRegistry.clear() is not allowed when NODE_ENV=production — this is a test-only utility. If you reached this from production code, you have a bug.`);this.byName.clear()}};const Q=new Z;function pe(){return new Z}const me=/^[a-z][a-z0-9_]*$/;function $(e,t,n){if(e.length>63)throw Error(`defineTable: ${t} "${e}" is ${e.length} characters — Postgres truncates identifiers at 63 chars silently, which can cause name collisions${n?`. ${n}`:``}`)}function he(e){if(!me.test(e.name))throw Error(`defineTable: invalid table name "${e.name}" — must match /^[a-z][a-z0-9_]*$/`);$(e.name,`table name`);let t={},n={};for(let[r,i]of Object.entries(e.columns)){if(typeof i!=`function`)throw Error(`defineTable: column "${r}" is not a column factory — did you call e.g. column.uuid() with parens?`);$(r,`column name in table "${e.name}"`);let a=i.__pgName;a&&$(a,`pgName for column "${r}" in table "${e.name}"`),t[r]=i(a??r),n[r]=i.__kind}let r=new Set(Object.keys(t));if(e.primaryKey!==void 0){let t=Array.isArray(e.primaryKey)?e.primaryKey:[e.primaryKey];for(let e of t)if(!r.has(String(e)))throw Error(`defineTable: primaryKey references unknown column "${String(e)}"`)}if(e.unique)for(let t of e.unique){for(let e of t.on)if(!r.has(String(e)))throw Error(`defineTable: unique constraint references unknown column "${String(e)}"`);$(t.name??`uq_${e.name}_${t.on.map(String).join(`_`)}`,t.name?`unique constraint name`:`auto-generated unique constraint name`,t.name?void 0:"Supply a shorter explicit `name` to the unique definition.")}if(e.indexes)for(let t of e.indexes){for(let e of t.on)if(!r.has(String(e)))throw Error(`defineTable: index references unknown column "${String(e)}"`);$(t.name??`idx_${e.name}_${t.on.map(String).join(`_`)}`,t.name?`index name`:`auto-generated index name`,t.name?void 0:"Supply a shorter explicit `name` to the index definition.")}let i=e.primaryKey!==void 0||e.unique&&e.unique.length>0||e.indexes&&e.indexes.length>0;function a(e,t,n){let r=e[t];if(!r)throw Error(`defineTable: ${n} references unknown column "${t}"`);return r}let o=i?w(e.name,t,t=>{let n=t,r=[];if(e.primaryKey!==void 0){let t=Array.isArray(e.primaryKey)?e.primaryKey:[e.primaryKey],i=a(n,String(t[0]),`primaryKey`),o=t.slice(1).map(e=>a(n,String(e),`primaryKey`));r.push(ae({columns:[i,...o]}))}if(e.unique)for(let t of e.unique){let e=a(n,String(t.on[0]),`unique constraint`),i=t.on.slice(1).map(e=>a(n,String(e),`unique constraint`));r.push(le().on(e,...i))}if(e.indexes)for(let t of e.indexes){let i=a(n,String(t.on[0]),`index`),o=t.on.slice(1).map(e=>a(n,String(e),`index`));r.push(x(t.name??`idx_${e.name}_${t.on.map(String).join(`_`)}`).on(i,...o))}return r}):w(e.name,t),s=ge();Q.register(e.name,o,s);let c=Object.freeze({...n}),l;if(e.primaryKey!==void 0)l=Array.isArray(e.primaryKey)?e.primaryKey.map(String):[String(e.primaryKey)];else{l=[];for(let[t,n]of Object.entries(e.columns))n.__primaryKey&&l.push(t)}let u=Object.freeze([...l]);return{table:o,schema:e,columnKinds:c,primaryKeyColumns:u,makeClient:e=>new X(o,c,e,u)}}function ge(){let e=Error().stack;if(!e)return;let t=e.split(`
19
- `).slice(1);for(let e of t){if(e.includes(`/table/define.`)||e.includes(`/table/registry.`))continue;let t=e.match(/\(([^)]+)\)/)??e.match(/at (.+)$/);if(t)return t[1].trim()}}export{fe as DEFAULT_LIMIT,J as MAX_BATCH,q as MAX_LIMIT,X as TableClient,Y as TableClientError,V as WhereBuilderError,L as column,ue as createDbClient,D as createReadOnlyClient,F as createSchemaRegistry,pe as createTableRegistry,he as defineTable,k as discoverMigrations,A as getMigrationStatus,G as isNonEmptyWhere,M as rollbackMigrations,j as runMigrations,P as schemaRegistry,Q as tableRegistry};
18
+ `)}),console.log(` ✓ Rolled back ${t.namespace}/${t.name}`)}catch(e){throw console.error(` ✗ Failed to roll back ${t.namespace}/${t.name}:`,e),e}}console.log(`Successfully rolled back ${o.length} migration${o.length===1?``:`s`}`)}const L=new class{schemas=new Map;register(e,t){this.schemas.set(e,t)}get(e){return this.schemas.get(e)}all(){let e={};for(let[t,n]of this.schemas.entries())e[t]=n;return e}has(e){return this.schemas.has(e)}},R=/^[a-zA-Z_][a-zA-Z0-9_-]*$|^\d+$/,z=new Set([`$and`,`$or`,`$not`]),B=new Set([`eq`,`ne`,`in`,`notIn`,`gt`,`gte`,`lt`,`lte`,`isNull`,`isNotNull`,`ilike`,`startsWith`]);var V=class extends Error{constructor(e){super(`WhereBuilder: ${e}`),this.name=`WhereBuilderError`}};function H(e){return e.replace(/[\\%_]/g,`\\$&`)}function me(e,t,n){let r=c(e);if(!n.includes(`.`)){let e=r[n];if(!e)throw new V(`unknown column "${n}"`);return e}let[i,...a]=n.split(`.`);if(!i||a.length===0)throw new V(`malformed dotted key "${n}"`);let o=t[i];if(!o)throw new V(`unknown column "${i}" in dotted key "${n}"`);if(o!==`jsonb`)throw new V(`dotted-path access is only supported on jsonb columns, but "${i}" is ${o}`);for(let e of a)if(!R.test(e))throw new V(`invalid jsonb path segment "${e}" — must match [a-zA-Z_][a-zA-Z0-9_-]* or be a non-negative integer`);let s=r[i];if(!s)throw new V(`unknown column "${i}"`);let l=h`${s}`;for(let e=0;e<a.length;e++){let t=a[e],n=e===a.length-1;if(/^\d+$/.test(t)){if(t.length>10)throw new V(`jsonb path index "${t}" is too large`);let e=h.raw(t);l=n?h`${l}->>${e}`:h`${l}->${e}`}else l=n?h`${l}->>${t}`:h`${l}->${t}`}return l}function he(e,t){if(t===null)return m(e);if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`||typeof t==`bigint`||t instanceof Date)return s(e,t);if(Array.isArray(t))throw new V(`arrays must be wrapped in an operator (e.g. { in: [...] }) — bare arrays are not allowed`);if(typeof t!=`object`)throw new V(`unsupported value type: ${typeof t}`);let n=t,r=Object.keys(n);if(r.length===0)throw new V(`empty operator object`);let i=[];for(let t of r){if(!B.has(t))throw new V(`unknown operator "${t}"`);let r=n[t];switch(t){case`eq`:i.push(s(e,r));break;case`ne`:i.push(re(e,r));break;case`in`:if(!Array.isArray(r))throw new V(`"in" operator requires an array`);r.length===0?i.push(h`false`):i.push(f(e,r));break;case`notIn`:if(!Array.isArray(r))throw new V(`"notIn" operator requires an array`);r.length===0?i.push(h`true`):i.push(ae(e,r));break;case`gt`:i.push(u(e,r));break;case`gte`:i.push(ee(e,r));break;case`lt`:i.push(te(e,r));break;case`lte`:i.push(ne(e,r));break;case`isNull`:if(r!==!0)throw new V('"isNull" operator must be `true`');i.push(m(e));break;case`isNotNull`:if(r!==!0)throw new V('"isNotNull" operator must be `true`');i.push(p(e));break;case`ilike`:if(typeof r!=`string`)throw new V(`"ilike" operator requires a string`);i.push(d(e,`%${H(r)}%`));break;case`startsWith`:if(typeof r!=`string`)throw new V(`"startsWith" operator requires a string`);i.push(d(e,`${H(r)}%`));break}}if(i.length!==0)return i.length===1?i[0]:a(...i)}function U(e,t,n,r=0){if(!n)return;if(typeof n!=`object`||Array.isArray(n))throw new V(`where clause must be a plain object`);if(r>16)throw new V(`where clause exceeds maximum nesting depth of 16 — real queries should not need this much nesting; if yours does, reconsider whether it should be expressed differently`);let i=[];for(let o of Object.keys(n)){let s=n[o];if(o===`$and`){if(!Array.isArray(s))throw new V(`$and must be an array`);if(s.length===0)throw new V(`$and must contain at least one clause`);let n=s.map(n=>U(e,t,n,r+1)).filter(e=>e!==void 0);n.length>0&&i.push(a(...n));continue}if(o===`$or`){if(!Array.isArray(s))throw new V(`$or must be an array`);if(s.length===0)throw new V(`$or must contain at least one clause`);let n=s.map(n=>U(e,t,n,r+1)).filter(e=>e!==void 0);n.length>0&&i.push(oe(...n));continue}if(o===`$not`){if(!W(s))throw new V(`$not must contain a non-empty clause`);let n=U(e,t,s,r+1);n&&i.push(ie(n));continue}if(z.has(o))continue;let c=he(me(e,t,o),s);c&&i.push(c)}if(i.length!==0)return i.length===1?i[0]:a(...i)}function W(e){return typeof e!=`object`||!e||Array.isArray(e)?!1:Object.keys(e).length>0}const G=/^[a-zA-Z_][a-zA-Z0-9_]*$/,K=y(`pg_class`,{relname:w(`relname`,{length:63}).notNull(),reltuples:de(`reltuples`).notNull()}),ge=100,q=1e3,J=1e3;var Y=class extends Error{constructor(e){super(`TableClient: ${e}`),this.name=`TableClientError`}},X=class e{constructor(e,t,n,r=[]){this.table=e,this.columnKinds=t,this.db=n,this.primaryKeyColumns=r}get _selectTable(){return this.table}getColumnOrThrow(e,t){let n=c(this.table)[e];if(!n)throw new Y(`${t}: unknown column "${e}"`);return n}buildOrderBy(e,t){return e.map(e=>{let n=this.getColumnOrThrow(e.column,`${t}: orderBy`);return e.dir===`desc`?h`${n} DESC`:h`${n} ASC`})}requireNonEmptyWhere(e,t){if(!W(e))throw new Y(`${t} requires a non-empty where clause`)}validateColumnKeys(e,t){if(e.length===0)return;let n=c(this.table);for(let r of e)if(!Object.hasOwn(n,r))throw new Y(`${t}: unknown column "${r}"`)}async findOne(e){this.requireNonEmptyWhere(e,`findOne`);let t=this.buildWhereOrThrow(e);return(await this.db.select().from(this._selectTable).where(t).limit(1))[0]??null}async findMany(e={}){let t=this.validateLimit(e.limit);if(e.offset!==void 0&&(!Number.isInteger(e.offset)||e.offset<0))throw new Y(`offset must be a non-negative integer, got ${e.offset}`);let n=e.orderBy&&e.orderBy.length>0?this.buildOrderBy(e.orderBy,`findMany`):void 0,r=e.where?this.buildWhereOrThrow(e.where):void 0,i=this.db.select().from(this._selectTable).$dynamic();return r&&(i=i.where(r)),n&&(i=i.orderBy(...n)),i=i.limit(t),e.offset!==void 0&&(i=i.offset(e.offset)),await i}async count(e){let t=e?this.buildWhereOrThrow(e):void 0,n=this.db.select({value:o()}).from(this._selectTable).$dynamic();t&&(n=n.where(t));let r=await n;return Number(r[0]?.value??0)}async exists(e){this.requireNonEmptyWhere(e,`exists`);let t=this.buildWhereOrThrow(e);return(await this.db.select({one:h`1`}).from(this._selectTable).where(t).limit(1)).length>0}async distinct(e,t){let n=this.getColumnOrThrow(e,`distinct`),r=[];t?.includeNull||r.push(p(n)),t?.where&&r.push(this.buildWhereOrThrow(t.where));let i=this.db.selectDistinct({value:n}).from(this._selectTable).$dynamic();if(r.length===1?i=i.where(r[0]):r.length>1&&(i=i.where(a(...r))),t?.orderBy){let e=t.orderBy===`desc`?h`${n} DESC`:h`${n} ASC`;i=i.orderBy(e)}return(await i).map(e=>e.value)}async insert(e){return(await this.db.insert(this.table).values(e).returning())[0]}async upsert(e,t){let n=Array.isArray(t.target)?t.target:[t.target];if(n.length===0)throw new Y(`upsert requires at least one target column`);let r=n.map(e=>this.getColumnOrThrow(e,`upsert target`)),i=t.set??e;t.set&&this.validateColumnKeys(Object.keys(t.set),`upsert set`);let a=t.setWhere&&W(t.setWhere)?this.buildWhereOrThrow(t.setWhere):void 0,o=await this.db.insert(this.table).values(e).onConflictDoUpdate({target:r,set:i,...a?{setWhere:a}:{}}).returning();if(o.length>0)return o[0];let s={};for(let t of n)s[t]=e[t];let c=await this.findOne(s);if(!c)throw new Y(`upsert with setWhere: conflicting row was deleted concurrently — retry the operation`);return c}async tryClaim(e,t){let n=Array.isArray(t.target)?t.target:[t.target];if(n.length===0)throw new Y(`tryClaim requires at least one target column`);let r=n.map(e=>this.getColumnOrThrow(e,`tryClaim target`)),i=t.set??e;if(t.set&&this.validateColumnKeys(Object.keys(t.set),`tryClaim set`),!W(t.replaceWhen))throw new Y(`tryClaim requires a non-empty replaceWhen clause`);let a=this.buildWhereOrThrow(t.replaceWhen),o=await this.db.insert(this.table).values(e).onConflictDoUpdate({target:r,set:i,setWhere:a}).returning();if(o.length>0)return{acquired:!0,row:o[0]};let s={};for(let t of n)s[t]=e[t];let c=await this.findOne(s);if(!c)throw new Y(`tryClaim: conflicting row was deleted concurrently — retry the operation`);return{acquired:!1,row:c}}async insertMany(e){if(!Array.isArray(e))throw new Y(`insertMany requires an array of rows`);if(e.length===0)return[];if(e.length>1e3)throw new Y(`insertMany batch too large: ${e.length} > ${J}`);return await this.db.insert(this.table).values(e).returning()}async update(e,t){this.requireNonEmptyWhere(e,`update`),this.validateColumnKeys(Object.keys(t),`update`);let n=this.buildWhereOrThrow(e),r=await this.db.update(this.table).set(t).where(n).returning();if(r.length>1)throw new Y(`update matched ${r.length} rows but is expected to match at most one — use updateMany for bulk updates. WARNING: the update has already been applied; wrap in a transaction if you need rollback.`);return r[0]??null}async updateMany(e,t){this.requireNonEmptyWhere(e,`updateMany`),this.validateColumnKeys(Object.keys(t),`updateMany`);let n=this.buildWhereOrThrow(e);return await this.db.update(this.table).set(t).where(n).returning()}async delete(e){this.requireNonEmptyWhere(e,`delete`);let t=this.buildWhereOrThrow(e),n=await this.db.delete(this.table).where(t).returning();if(n.length>1)throw new Y(`delete matched ${n.length} rows but is expected to match at most one — use deleteMany for bulk deletes. WARNING: the delete has already been applied; wrap in a transaction if you need rollback.`);return n[0]??null}async deleteMany(e){this.requireNonEmptyWhere(e,`deleteMany`);let t=this.buildWhereOrThrow(e);return await this.db.delete(this.table).where(t).returning()}async transaction(t){return await this.db.transaction(async n=>await t(new e(this.table,this.columnKinds,n,this.primaryKeyColumns)))}async claim(e){if(this.primaryKeyColumns.length===0)throw new Y(`claim() requires the table to have a primary key — declare primaryKey in defineTable() or use column.uuid({ primaryKey: true })`);if(this.primaryKeyColumns.length>1)throw new Y(`claim() does not support composite primary keys — use a single-column primary key or call transaction() with FOR UPDATE directly`);if(this.requireNonEmptyWhere(e.where,`claim`),!Number.isInteger(e.limit)||e.limit<1)throw new Y(`claim limit must be a positive integer, got ${e.limit}`);if(e.limit>1e3)throw new Y(`claim limit ${e.limit} exceeds MAX_LIMIT ${q}`);let t=Object.keys(e.set??{}),n=Object.keys(e.setSql??{});if(t.length===0&&n.length===0)throw new Y(`claim requires at least one field in set or setSql`);this.validateColumnKeys(t,`claim set`),this.validateColumnKeys(n,`claim setSql`);let r=this.buildWhereOrThrow(e.where),i=e.orderBy&&e.orderBy.length>0?this.buildOrderBy(e.orderBy,`claim`):void 0,a=this.primaryKeyColumns[0],o=this.getColumnOrThrow(a,`claim primary key`);return await this.db.transaction(async t=>{let n=t.select({_pk:o}).from(this._selectTable).where(r).limit(e.limit).for(`update`,{skipLocked:!0}).$dynamic();i&&(n=n.orderBy(...i));let a=await n;if(a.length===0)return[];let s=a.map(e=>e._pk),c={...e.set??{}};if(e.setSql)for(let[t,n]of Object.entries(e.setSql))c[t]=n;return await t.update(this.table).set(c).where(f(o,s)).returning()})}async aggregate(e){let t=Object.entries(e.select);if(t.length===0)throw new Y(`aggregate requires at least one select field`);for(let[e]of t)if(!G.test(e))throw new Y(`aggregate: invalid output alias "${e}" — must match ${G.source}`);let n={};if(e.groupBy)for(let t of e.groupBy)n[t]=this.getColumnOrThrow(t,`aggregate groupBy`);for(let[e,r]of t)n[e]=this.buildAggregateExpr(r);let r=this.db.select(n).from(this._selectTable).$dynamic();if(e.where&&(r=r.where(this.buildWhereOrThrow(e.where))),e.groupBy&&e.groupBy.length>0){let t=e.groupBy.map(e=>this.getColumnOrThrow(e,`aggregate groupBy`));r=r.groupBy(...t)}return e.orderBy&&e.orderBy.length>0&&(r=r.orderBy(...this.buildOrderBy(e.orderBy,`aggregate`))),e.limit!==void 0&&(r=r.limit(this.validateLimit(e.limit))),await r}async countEstimate(){let e=l(this.table),[t]=await this.db.select({estimate:h`greatest(${K.reltuples}::bigint, 0)`}).from(K).where(s(K.relname,e)).limit(1);return t?Number(t.estimate):0}buildAggregateExpr(e){if(`column`in e&&e.column){let t=this.getColumnOrThrow(e.column,`aggregate`);switch(e.fn){case`count`:return h`count(${t})::int`;case`sum`:return h`sum(${t})`;case`avg`:return h`avg(${t})`;case`min`:return h`min(${t})`;case`max`:return h`max(${t})`;default:throw new Y(`aggregate: unknown function "${e.fn}"`)}}if(e.fn===`count`)return h`count(*)::int`;throw new Y(`aggregate: ${e.fn} requires a column`)}buildWhereOrThrow(e){try{let t=U(this.table,this.columnKinds,e);if(!t)throw new Y(`where clause produced no SQL predicate`);return t}catch(e){throw e instanceof V?new Y(e.message.replace(/^WhereBuilder: /,``)):e}}validateLimit(e){if(e===void 0)return 100;if(!Number.isInteger(e)||e<1)throw new Y(`limit must be a positive integer, got ${e}`);if(e>1e3)throw new Y(`limit ${e} exceeds MAX_LIMIT ${q} — paginate or use claim() for batch processing`);return e}};function Z(e,t){let n=e;return Object.defineProperty(n,`__kind`,{value:t.kind,enumerable:!1}),Object.defineProperty(n,`__notNull`,{value:t.notNull,enumerable:!1}),Object.defineProperty(n,`__hasDefault`,{value:t.hasDefault,enumerable:!1}),Object.defineProperty(n,`__type`,{value:void 0,enumerable:!1}),t.pgName&&Object.defineProperty(n,`__pgName`,{value:t.pgName,enumerable:!1}),t.primaryKey&&Object.defineProperty(n,`__primaryKey`,{value:!0,enumerable:!1}),n}const _e={uuid(e){let t=e?.notNull??!1,n=e?.defaultRandom??!1,r=e?.primaryKey??!1;return Z(n=>{let i=C(n);return r&&(i=i.primaryKey()),e?.defaultRandom&&(i=i.defaultRandom()),t&&!r&&(i=i.notNull()),i},{kind:`uuid`,notNull:t||r,hasDefault:n||r,pgName:e?.pgName,primaryKey:r||void 0})},varchar(e){if(!Number.isInteger(e.length)||e.length<1||e.length>1073741823)throw Error(`column.varchar: length must be an integer between 1 and 1073741823, got ${e.length}`);let t=e.notNull??!1;return Z(n=>{let r=w(n,{length:e.length});return t&&(r=r.notNull()),e.default!==void 0&&(r=r.default(e.default)),r},{kind:`varchar`,notNull:t,hasDefault:e.default!==void 0,pgName:e.pgName})},text(e){let t=e?.notNull??!1;return Z(n=>{let r=b(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`text`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},integer(e){let t=e?.notNull??!1;return Z(n=>{let r=_(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`integer`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},bigint(e){let t=e?.mode??`number`,n=e?.notNull??!1;return Z(r=>{let i=se(r,{mode:t});return n&&(i=i.notNull()),e?.default!==void 0&&(i=i.default(e.default)),i},{kind:`bigint`,notNull:n,hasDefault:e?.default!==void 0,pgName:e?.pgName})},double(e){let t=e?.notNull??!1;return Z(n=>{let r=g(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`double`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},boolean(e){let t=e?.notNull??!1;return Z(n=>{let r=ce(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`boolean`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},timestamp(e){let t=e?.notNull??!1,n=e?.defaultNow??!1,r=e?.withTimezone??!0;return Z(n=>{let i=x(n,{withTimezone:r});return t&&(i=i.notNull()),e?.defaultNow&&(i=i.defaultNow()),i},{kind:`timestamp`,notNull:t,hasDefault:n,pgName:e?.pgName})},jsonb(e){let t=e?.notNull??!1;return Z(n=>{let r=v(n);return t&&(r=r.notNull()),e?.default!==void 0&&(r=r.default(e.default)),r},{kind:`jsonb`,notNull:t,hasDefault:e?.default!==void 0,pgName:e?.pgName})},uuidArray(e){let t=e?.notNull??!1;return Z(e=>{let n=C(e).array();return t?n.notNull():n},{kind:`uuidArray`,notNull:t,hasDefault:!1,pgName:e?.pgName})}},Q=new class{byName=new Map;register(e,t,n){let r=this.byName.get(e);if(r){if(r.table===t||r.source&&n&&r.source===n)return;throw Error(`tableRegistry: a different table is already registered under name "${e}". Did you call defineTable twice? First registered from ${r.source??`<unknown>`}, now from ${n??`<unknown>`}.`)}this.byName.set(e,{name:e,table:t,source:n})}get(e){return this.byName.get(e)?.table}has(e){return this.byName.has(e)}allTables(){let e={};for(let t of this.byName.values())e[t.name]=t.table;return e}clear(){if(process.env.NODE_ENV===`production`)throw Error(`tableRegistry.clear() is not allowed when NODE_ENV=production — this is a test-only utility. If you reached this from production code, you have a bug.`);this.byName.clear()}},ve=/^[a-z][a-z0-9_]*$/;function $(e,t,n){if(e.length>63)throw Error(`defineTable: ${t} "${e}" is ${e.length} characters — Postgres truncates identifiers at 63 chars silently, which can cause name collisions${n?`. ${n}`:``}`)}function ye(e){if(!ve.test(e.name))throw Error(`defineTable: invalid table name "${e.name}" — must match /^[a-z][a-z0-9_]*$/`);$(e.name,`table name`);let t={},n={};for(let[r,i]of Object.entries(e.columns)){if(typeof i!=`function`)throw Error(`defineTable: column "${r}" is not a column factory — did you call e.g. column.uuid() with parens?`);$(r,`column name in table "${e.name}"`);let a=i.__pgName;a&&$(a,`pgName for column "${r}" in table "${e.name}"`),t[r]=i(a??r),n[r]=i.__kind}let r=new Set(Object.keys(t));if(e.primaryKey!==void 0){let t=Array.isArray(e.primaryKey)?e.primaryKey:[e.primaryKey];for(let e of t)if(!r.has(String(e)))throw Error(`defineTable: primaryKey references unknown column "${String(e)}"`)}if(e.unique)for(let t of e.unique){for(let e of t.on)if(!r.has(String(e)))throw Error(`defineTable: unique constraint references unknown column "${String(e)}"`);$(t.name??`uq_${e.name}_${t.on.map(String).join(`_`)}`,t.name?`unique constraint name`:`auto-generated unique constraint name`,t.name?void 0:"Supply a shorter explicit `name` to the unique definition.")}if(e.indexes)for(let t of e.indexes){for(let e of t.on)if(!r.has(String(e)))throw Error(`defineTable: index references unknown column "${String(e)}"`);$(t.name??`idx_${e.name}_${t.on.map(String).join(`_`)}`,t.name?`index name`:`auto-generated index name`,t.name?void 0:"Supply a shorter explicit `name` to the index definition.")}let i=e.primaryKey!==void 0||e.unique&&e.unique.length>0||e.indexes&&e.indexes.length>0;function a(e,t,n){let r=e[t];if(!r)throw Error(`defineTable: ${n} references unknown column "${t}"`);return r}let o=i?y(e.name,t,t=>{let n=t,r=[];if(e.primaryKey!==void 0){let t=Array.isArray(e.primaryKey)?e.primaryKey:[e.primaryKey],i=a(n,String(t[0]),`primaryKey`),o=t.slice(1).map(e=>a(n,String(e),`primaryKey`));r.push(ue({columns:[i,...o]}))}if(e.unique)for(let t of e.unique){let e=a(n,String(t.on[0]),`unique constraint`),i=t.on.slice(1).map(e=>a(n,String(e),`unique constraint`));r.push(S().on(e,...i))}if(e.indexes)for(let t of e.indexes){let i=a(n,String(t.on[0]),`index`),o=t.on.slice(1).map(e=>a(n,String(e),`index`));r.push(le(t.name??`idx_${e.name}_${t.on.map(String).join(`_`)}`).on(i,...o))}return r}):y(e.name,t),s=be();Q.register(e.name,o,s);let c=Object.freeze({...n}),l;if(e.primaryKey!==void 0)l=Array.isArray(e.primaryKey)?e.primaryKey.map(String):[String(e.primaryKey)];else{l=[];for(let[t,n]of Object.entries(e.columns))n.__primaryKey&&l.push(t)}let u=Object.freeze([...l]);return{table:o,schema:e,columnKinds:c,primaryKeyColumns:u,makeClient:e=>new X(o,c,e,u)}}function be(){let e=Error().stack;if(!e)return;let t=e.split(`
19
+ `).slice(1);for(let e of t){if(e.includes(`/table/define.`)||e.includes(`/table/registry.`))continue;let t=e.match(/\(([^)]+)\)/)??e.match(/at (.+)$/);if(t)return t[1].trim()}}export{ge as DEFAULT_LIMIT,J as MAX_BATCH,q as MAX_LIMIT,X as TableClient,Y as TableClientError,V as WhereBuilderError,_e as column,k as createDbClient,A as createReadOnlyClient,ye as defineTable,P as getMigrationStatus,fe as getQueryStats,W as isNonEmptyWhere,D as isQueryCounterEnabled,E as queryCountingLogger,I as rollbackMigrations,F as runMigrations,pe as runWithQueryStats,L as schemaRegistry,Q as tableRegistry};
20
20
  //# sourceMappingURL=index.mjs.map