@supabase/lite 0.5.0 → 0.6.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/LIMITATIONS.md CHANGED
@@ -36,6 +36,10 @@ Anchors below point to the corresponding STATUS.md section. If a limitation here
36
36
 
37
37
  Most SQLite-only limitations above do not apply. `rpc()`, ranges, regex, quantified comparisons, full-text search, and native `DEFAULT auth.uid()` all work on the Postgres path. See per-section status tables in [STATUS.md](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md).
38
38
 
39
+ - Custom domain types (data representations): read/`RETURNING` output formats via the domain's `CAST(… AS json)`, and mutating JSON values **into** a domain column (epoch→`timestamptz`, base64→`bytea`, decimal-string→`numeric`) is converted on the Postgres path. Remaining gap: domain formatting through cross-relation embeds. See [Translated Field Types](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#translated-field-types).
40
+ - Postgres sessions run in **UTC** by default (so `timestamptz` rendering is deterministic regardless of the server's host timezone). Override via the `postgresOptions.connection.TimeZone` connection option. See [Translated Field Types](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#translated-field-types).
41
+ - Embedding **through views** resolves for views whose FK column is a plain projection of a base-table column — including **materialized views** and **multi-level recursive view-of-view** chains (the column mapping is composed across each hop to the underlying base table). Views whose FK column is not a plain projection (CTE, GROUP BY, subselect-in-FROM, or any JOIN view) are still not traced. View-FK resolution matches relations by **bare name**: if two exposed schemas expose a relation with the same name, an embed through a view may resolve against the wrong one — keep colliding names out of co-exposed schemas, or embed via an explicit FK/constraint-name hint.
42
+
39
43
  ## Anti-patterns
40
44
 
41
45
  Common ways code goes wrong against supalite. The fix for each is the corresponding bullet above.
package/STATUS.md CHANGED
@@ -156,6 +156,8 @@ CREATE TABLE orders
156
156
 
157
157
  Unsupported PostgreSQL data types currently include `oid`, `xid`, `xid8`, `cid`, `money`, `citext`, `cidr`, `macaddr`, `macaddr8`, `bit`, `bit varying`, `varbit`, geometric types (`point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle`), `xml`, text-search types (`tsvector`, `tsquery`), range and multirange types, `reg*` catalog reference types, internal types (`tid`, `pg_lsn`, `internal`), pseudo-types, and handler types.
158
158
 
159
+ **Custom domains & data representations.** On the Postgres path (PGlite/PostgreSQL), a column typed as a domain that defines `CAST(<domain> AS json)` (the PostgREST "data representations" feature) renders through that cast on reads and `RETURNING` — e.g. a `unixtz` domain over `timestamptz` returns epoch seconds, a `monetary` domain over `numeric` returns a fixed-precision string. On the SQLite path the known representation types (`color`, `unixtz`, `isodate`, `monetary`, `bytea_b64`) are handled by built-in field shims. Mutating JSON values **into** a domain column (epoch→`timestamptz`, base64→`bytea`, decimal-string→`numeric`) is converted on the Postgres path via `buildDomainInputValue`. Not yet handled: domain formatting through cross-relation embeds. Postgres connections run with `TimeZone=UTC` by default so `timestamptz` rendering is deterministic regardless of the server's host timezone; override via the `postgresOptions.connection.TimeZone` connection option.
160
+
159
161
  ### Column Defaults
160
162
 
161
163
  Column `DEFAULT` expressions in Postgres DDL are evaluated by the SQLite translator at CREATE TABLE time. Only constant expressions and a small allow-list of functions are honored.
@@ -428,6 +430,8 @@ Supported natively on the Postgres / PGlite path.
428
430
  | `throwOnError()` | ✅ | ✅ | JS error mode |
429
431
  | `maxAffected()` | ✅ | ✅ | Check `changes()` after execution |
430
432
 
433
+ **CORS / `OPTIONS` preflight:** Handled across `/rest/v1`, `/auth/v1`, and `/storage/v1` (not a supabase-js method, so excluded from the counts below). Each surface matches its upstream service: on `/rest`, `OPTIONS` follows PostgREST semantics — `200` with CORS headers for a known table, `404` (PGRST205) for an unknown one — and never requires auth (preflight succeeds even when anonymous access is disabled); `/auth` mirrors GoTrue's `204` preflight (reflected method, credentials, wildcard origin); `/storage` answers preflight with `204`. Origin is `*` (matches the Supabase CLI), and `Content-Range`, `Content-Location`, and `Preference-Applied` are exposed via `Access-Control-Expose-Headers`.
434
+
431
435
  ### Control & Specialized
432
436
 
433
437
  | Method | SQLite | Postgres | Notes |
@@ -840,8 +844,8 @@ PostgREST spec status (`cd app && bun run test:spec:status`):
840
844
 
841
845
  | Backend | Total | Passing | Pass % | Skipped | Skip % | Failed |
842
846
  |---------|------:|--------:|-------:|--------:|-------:|-------:|
843
- | Postgres | 2,460 | **1,923** | 78.2% | 537 | 21.8% | 0 |
844
- | PGlite | 2,460 | **1,933** | 78.6% | 527 | 21.4% | 0 |
847
+ | Postgres | 2,460 | **2,339** | 95.1% | 121 | 4.9% | 0 |
848
+ | PGlite | 2,460 | **2,347** | 95.4% | 113 | 4.6% | 0 |
845
849
  | SQLite | 1,702 | **1,677** | 98.5% | 25 | 1.5% | 0 |
846
850
  | SQLite-Postgres | 1,702 | **1,677** | 98.5% | 25 | 1.5% | 0 |
847
851
 
@@ -129,6 +129,8 @@ interface RpcAST extends BaseAST {
129
129
  type: "rpc";
130
130
  function: string;
131
131
  args?: object | unknown[];
132
+ /** Embed joins, when `select=` embeds related tables on a `SETOF <table>` result. */
133
+ join?: JoinMap;
132
134
  where?: Where;
133
135
  order?: OrderEntry[];
134
136
  limit?: number;
@@ -282,6 +284,13 @@ interface ColumnInfo {
282
284
  } | null;
283
285
  is_identity: boolean;
284
286
  pg_type?: string;
287
+ /**
288
+ * Schema of the column's data type (information_schema `udt_schema`). For a
289
+ * composite/enum/domain typed column this is the schema the *type* lives in,
290
+ * which can differ from the table's `schema` — used to resolve the type
291
+ * against `custom_types` without cross-schema false matches. Postgres only.
292
+ */
293
+ udt_schema?: string;
285
294
  is_generated?: boolean;
286
295
  }
287
296
  interface IndexInfo {
@@ -352,6 +361,46 @@ interface CustomTypesInfo {
352
361
  type: string;
353
362
  }[];
354
363
  }
364
+ interface FunctionInfo {
365
+ schema: string;
366
+ name: string;
367
+ /** Input parameter names, in declaration order. Empty for unnamed-param functions. */
368
+ arg_names: string[];
369
+ /** Input parameter type names (format_type), aligned with proargtypes order. */
370
+ arg_types: string[];
371
+ /** Count of trailing input params that have a DEFAULT (pronargdefaults). */
372
+ arg_defaults: number;
373
+ /** True when the function has a VARIADIC parameter. */
374
+ has_variadic: boolean;
375
+ /** provolatile: 'i' immutable, 's' stable, 'v' volatile. */
376
+ volatility: string;
377
+ /** Formatted return type (e.g. "integer", "SETOF" is conveyed via return_is_setof). */
378
+ return_type: string;
379
+ /** proretset — function returns a set (SETOF / TABLE). */
380
+ return_is_setof: boolean;
381
+ /**
382
+ * prorows — planner row-count estimate. A SETOF function declared `ROWS 1`
383
+ * has prorows === 1, which PostgREST reads as a to-one computed relationship.
384
+ * SETOF without ROWS defaults to 1000; non-set functions to 0.
385
+ */
386
+ return_rows?: number;
387
+ /**
388
+ * pg_type.typtype of the return type: 'b' base, 'c' composite, 'd' domain,
389
+ * 'e' enum, 'p' pseudo (record/void), 'r' range, 'm' multirange. 'c'/'p'
390
+ * indicate a row/record (object) result rather than a scalar.
391
+ */
392
+ return_typtype: string;
393
+ /**
394
+ * When the return type is a domain ('d'), the formatted name of its underlying
395
+ * base type (pg_type.typbasetype via format_type) — e.g. a `"text/plain"`
396
+ * domain over `text` carries `return_base_type: "text"`. Empty/undefined for
397
+ * non-domain returns. Used to decode a media-type-domain RPC result as raw
398
+ * text vs raw bytea. See server/data/response/media-domain.ts.
399
+ */
400
+ return_base_type?: string;
401
+ /** True when the function has OUT/INOUT/TABLE output columns (object-shaped result). */
402
+ has_out_args: boolean;
403
+ }
355
404
  type IntrospectOptions = {
356
405
  exclude_tables?: string[];
357
406
  name?: string;
@@ -369,10 +418,39 @@ interface IntrospectResult {
369
418
  comments: CommentInfo[];
370
419
  custom_types: CustomTypesInfo[];
371
420
  triggers: TriggerInfo[];
421
+ /** Stored functions/procedures. Populated on the Postgres dialects only. */
422
+ functions?: FunctionInfo[];
423
+ /**
424
+ * Individual table partitions and their partitioned parent. Populated on the
425
+ * Postgres dialects only. Partitions are hidden from `tables`/`foreign_keys`
426
+ * (like PostgREST), so this carries the partition→parent mapping used to emit
427
+ * the "Perhaps you meant '<parent>'" hint when a partition is requested.
428
+ */
429
+ partitions?: {
430
+ name: string;
431
+ schema: string;
432
+ parent: string;
433
+ }[];
372
434
  database_name: string;
373
435
  version: string;
374
436
  ddl_dialect?: "postgres" | "sqlite";
375
437
  schema_separator?: string;
438
+ /**
439
+ * The API's configured default schema (PostgREST `db-schemas` head). Used to
440
+ * resolve schema-sensitive catalog lookups (e.g. computed relationships/
441
+ * columns) for requests that omit `Accept-/Content-Profile`, where the
442
+ * deparser's `currentSchema` is undefined but the DB still reads this schema.
443
+ */
444
+ default_schema?: string;
445
+ /**
446
+ * Valid time-zone names from `pg_timezone_names`. Populated on the Postgres
447
+ * dialects only and cached with the rest of the introspection. Mirrors
448
+ * PostgREST's cached `TimezoneNames`: a `Prefer: timezone=` value with
449
+ * `handling=strict` is rejected (PGRST122) unless it is a member. Absent on
450
+ * sqlite (no such catalog), where the preference stays lenient. Stored as an
451
+ * array (not a Set) so it survives the JSON schema-cache round-trip.
452
+ */
453
+ timezones?: readonly string[];
376
454
  }
377
455
  interface TableDiff {
378
456
  type: "added" | "removed" | "modified";
@@ -504,6 +582,21 @@ type TransactionOptions = {
504
582
  };
505
583
  type ConnectionContextOptions = {
506
584
  forceRollback?: boolean;
585
+ /**
586
+ * Present for RPC (`/rpc/*`) requests on the postgres backend only. Forces the
587
+ * call into one explicit transaction so request.* GUC injection, GET read-only
588
+ * mode, and the function's transaction-local response.* GUCs (read back by the
589
+ * handler) are atomic. Without it, the common anon path runs with no
590
+ * transaction and `set_config(...,true)` would be lost before the read-back.
591
+ * Ignored by the base/sqlite pass-through `withContext` (RPC is rejected on
592
+ * sqlite at server/data.ts, so sqlite never constructs this).
593
+ */
594
+ rpc?: {
595
+ method: string;
596
+ path: string;
597
+ readOnly: boolean;
598
+ requestHeaders?: Record<string, string>;
599
+ };
507
600
  };
508
601
  declare class RelationNotFoundError extends Error {
509
602
  readonly schema: string | undefined;
@@ -558,6 +651,29 @@ declare abstract class Connection<Driver = unknown, DB = any, Config extends ICo
558
651
  * Default: pass-through.
559
652
  */
560
653
  withContext<T>(_vars: VarsContext | undefined, fn: (db: Kysely<any>) => Promise<T>, _opts?: ConnectionContextOptions): Promise<T>;
654
+ /**
655
+ * Whether this connection serves RPC (stored functions). SQLite-backed
656
+ * connections have none; the data route uses this to gate `/rpc/*`.
657
+ */
658
+ get supportsRpc(): boolean;
659
+ /**
660
+ * OPTIONS write-capability for a view, resolved from the catalog. Returns
661
+ * `null` when the dialect cannot introspect view updatability via SQL (e.g.
662
+ * SQLite, where the caller derives it from `INSTEAD OF` triggers instead).
663
+ * Overridden on the Postgres path.
664
+ */
665
+ viewOptionsMetadata(_viewName: string, _viewSchema: string): Promise<ViewOptionsMetadata | null>;
666
+ }
667
+ /** Catalog metadata for a view used to build an OPTIONS `Allow` header. */
668
+ interface ViewOptionsMetadata {
669
+ canInsert: boolean;
670
+ canUpdate: boolean;
671
+ canDelete: boolean;
672
+ /** Base relations the view reads from, for scoping the PK check. */
673
+ baseTables: Array<{
674
+ schema: string;
675
+ name: string;
676
+ }>;
561
677
  }
562
678
 
563
- export { type QbUpdate as $, type AnyAST as A, type BaseAST as B, Connection as C, DataLossError as D, type EmbedDef as E, type FiltersResult as F, type InsertAST as G, type HeadersResult as H, type IConnectionConfig as I, type IntrospectOptions as J, type JoinDef as K, type JoinMap as L, type Meta as M, MigrationError as N, type OrderEntry as O, type PlanResult as P, type PlanStep as Q, PlanStepType as R, type PreferToken as S, type TransactionOptions as T, type PrimaryKeyInfo as U, type VarsContext as V, type Where as W, type Qb as X, type QbDelete as Y, type QbInsert as Z, type QbSelect as _, type IntrospectResult as a, type QueryAST as a0, type QueryParamsResult as a1, RelationNotFoundError as a2, type RouteResult as a3, type RpcAST as a4, type RpcResult as a5, type SchemaDiffResult as a6, type SelectEntry as a7, type SelectResult as a8, type TableDiff as a9, type TableInfo as aa, type TextSearchValue as ab, type TransformsResult as ac, type TranslatorConfig as ad, type TriggerInfo as ae, type UniqueConstraintInfo as af, type UpdateAST as ag, type UpsertAST as ah, type UpsertResult as ai, type ViewInfo as aj, type WhereValue as ak, isRef as al, type CacheDriver as b, type CacheSetOptions as c, type AST as d, type ASTType as e, type AggregateFunction as f, type BodyResult as g, type CheckConstraintInfo as h, type ColumnDef as i, type ColumnDiff as j, type ColumnInfo as k, type ColumnRef as l, type CommentInfo as m, type ConnectionContextOptions as n, type ConnectionMigrator as o, type CustomTypesInfo as p, type DataLossWarning as q, type DeleteAST as r, type Dialect as s, type DiffResult as t, type EmbedTransform as u, type ExplainOptions as v, type ForeignKeyDiff as w, type ForeignKeyInfo as x, type IndexDiff as y, type IndexInfo as z };
679
+ export { type QbSelect as $, type AnyAST as A, type BaseAST as B, Connection as C, DataLossError as D, type EmbedDef as E, type FiltersResult as F, type IndexInfo as G, type HeadersResult as H, type IConnectionConfig as I, type InsertAST as J, type IntrospectOptions as K, type JoinDef as L, type JoinMap as M, type Meta as N, MigrationError as O, type OrderEntry as P, type PlanResult as Q, type PlanStep as R, PlanStepType as S, type TransactionOptions as T, type PreferToken as U, type VarsContext as V, type Where as W, type PrimaryKeyInfo as X, type Qb as Y, type QbDelete as Z, type QbInsert as _, type IntrospectResult as a, type QbUpdate as a0, type QueryAST as a1, type QueryParamsResult as a2, RelationNotFoundError as a3, type RouteResult as a4, type RpcAST as a5, type RpcResult as a6, type SchemaDiffResult as a7, type SelectEntry as a8, type SelectResult as a9, type TableDiff as aa, type TableInfo as ab, type TextSearchValue as ac, type TransformsResult as ad, type TranslatorConfig as ae, type TriggerInfo as af, type UniqueConstraintInfo as ag, type UpdateAST as ah, type UpsertAST as ai, type UpsertResult as aj, type ViewInfo as ak, type ViewOptionsMetadata as al, type WhereValue as am, isRef as an, type CacheDriver as b, type CacheSetOptions as c, type AST as d, type ASTType as e, type AggregateFunction as f, type BodyResult as g, type CheckConstraintInfo as h, type ColumnDef as i, type ColumnDiff as j, type ColumnInfo as k, type ColumnRef as l, type CommentInfo as m, type ConnectionContextOptions as n, type ConnectionMigrator as o, type CustomTypesInfo as p, type DataLossWarning as q, type DeleteAST as r, type Dialect as s, type DiffResult as t, type EmbedTransform as u, type ExplainOptions as v, type ForeignKeyDiff as w, type ForeignKeyInfo as x, type FunctionInfo as y, type IndexDiff as z };
@@ -1,4 +1,4 @@
1
- import { I as IConnectionConfig, C as Connection } from '../Connection-DF_xKWko.js';
1
+ import { I as IConnectionConfig, C as Connection } from '../Connection-DJbw6dM8.js';
2
2
  import 'kysely';
3
3
 
4
4
  declare function createConnection<E extends IConnectionConfig = IConnectionConfig>(_config?: E): Promise<Connection>;
@@ -1,4 +1,4 @@
1
- import { IConnectionConfig, Connection, IntrospectResult, VarsContext, ConnectionContextOptions, AnyAST, TransactionOptions } from '@supabase/lite';
1
+ import { IConnectionConfig, Connection, IntrospectResult, VarsContext, ConnectionContextOptions, AnyAST, TransactionOptions, ViewOptionsMetadata } from '@supabase/lite';
2
2
  import { Kysely } from 'kysely';
3
3
 
4
4
  interface IBasePostgresConnectionConfig extends IConnectionConfig {
@@ -20,9 +20,22 @@ declare abstract class BasePostgresConnection<Driver = unknown, DB = any> extend
20
20
  private ensureRlsContext;
21
21
  private postgresTransactionActive;
22
22
  private applyJwtSessionContext;
23
+ /**
24
+ * Inject PostgREST's `request.*` context GUCs and reset `response.*` for an RPC
25
+ * request. A function may read the HTTP context via `current_setting('request.headers')`
26
+ * etc.; that call (used without the `missing_ok` arg in the fixtures) errors 42704
27
+ * if the GUC is unset, so request.method/path/headers are always set. response.status
28
+ * and response.headers are reset to empty first so a value set by an earlier step in
29
+ * the harness's shared outer transaction can't leak into this request (in production
30
+ * each RPC gets its own tx, so the leak is harness-only — but the reset is correct
31
+ * either way). All transaction-local (`is_local = true`).
32
+ */
33
+ private applyRpcRequestGucs;
23
34
  withContext<T>(vars: VarsContext | undefined, fn: (db: Kysely<any>) => Promise<T>, opts?: ConnectionContextOptions): Promise<T>;
24
35
  onPostgrestAST(ast: AnyAST): Promise<AnyAST>;
25
36
  transaction(statements: string[], opts?: TransactionOptions): Promise<void>;
37
+ get supportsRpc(): boolean;
38
+ viewOptionsMetadata(viewName: string, viewSchema: string): Promise<ViewOptionsMetadata>;
26
39
  }
27
40
 
28
41
  export { BasePostgresConnection as B, type IBasePostgresConnectionConfig as I };
@@ -1,9 +1,18 @@
1
1
  import postgres from 'postgres';
2
- import { I as IBasePostgresConnectionConfig, B as BasePostgresConnection } from './BasePostgresConnection-NlNmZWv1.js';
2
+ import { I as IBasePostgresConnectionConfig, B as BasePostgresConnection } from './BasePostgresConnection-xaPv2E6u.js';
3
3
  import '@supabase/lite';
4
4
  import 'kysely';
5
5
 
6
6
  interface IPostgresConnectionConfig extends IBasePostgresConnectionConfig {
7
+ /**
8
+ * Extra options forwarded to the underlying `postgres` (postgres.js) driver,
9
+ * merged over lite's defaults. `connection` and `types` are deep-merged (your
10
+ * keys win, lite's other defaults are kept); every other key is shallow-spread.
11
+ *
12
+ * Example — run the session in a non-UTC timezone instead of the UTC default:
13
+ * `{ connection: { TimeZone: "America/New_York" } }`.
14
+ */
15
+ postgresOptions?: postgres.Options<Record<string, postgres.PostgresType>>;
7
16
  }
8
17
  declare class PostgresConnection extends BasePostgresConnection<postgres.Sql, any> {
9
18
  driver: postgres.Sql<any>;
@@ -1,4 +1,4 @@
1
- import F from'postgres';import {PostgresJSDialect}from'kysely-postgres-js';import {Kysely,sql}from'kysely';import {Connection,invariant,RelationNotFoundError}from'@supabase/lite';try {
1
+ import me from'postgres';import {PostgresJSDialect}from'kysely-postgres-js';import {Kysely,sql}from'kysely';import {Connection,invariant,RelationNotFoundError}from'@supabase/lite';try {
2
2
  /**
3
3
  * Adding this to avoid warnings from node:sqlite being experimental
4
4
  */
@@ -8,13 +8,13 @@ import F from'postgres';import {PostgresJSDialect}from'kysely-postgres-js';impor
8
8
  return emitWarning(warning, ...args);
9
9
  };
10
10
  } catch {}
11
- var $=["anon","authenticated","service_role"];function v(c){return c==="service_role"?"NOLOGIN BYPASSRLS":"NOLOGIN"}function D(c){return c.size===0?"":`DO $$ BEGIN${[...c].map(s=>`
11
+ var Y=["anon","authenticated","service_role"];function V(a){return a==="service_role"?"NOLOGIN BYPASSRLS":"NOLOGIN"}function Q(a){return a.size===0?"":`DO $$ BEGIN${[...a].map(s=>`
12
12
  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${s}') THEN
13
- CREATE ROLE ${s} ${v(s)};
13
+ CREATE ROLE ${s} ${V(s)};
14
14
  END IF;`).join("")}
15
15
  END $$;
16
- `}var g=D(new Set($));var m="anon, authenticated, service_role",U=new Set(["anon","authenticated","service_role"]);function A(c){return `"${c.replace(/"/g,'""')}"`}var p=class extends Error{constructor(s){super("Force rollback");this.result=s;}},E=class extends Connection{dialect="postgres";harnessHoldingOuterTx=false;constructor(n){super({...n,baseSchema:`
17
- ${n.baseSchema??""}
16
+ `}var k=Q(new Set(Y));function T(a){let e=a.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("`")&&e.endsWith("`")||e.startsWith("[")&&e.endsWith("]")?e.slice(1,-1):e}function Z(a){let e=[],s="",i=0,n=null;for(let o=0;o<a.length;o++){let c=a[o];if(n){s+=c,c===n&&(n=null);continue}if(c==='"'||c==="`"||c==="'"){n=c,s+=c;continue}if(c==="("?i++:c===")"&&i>0&&i--,c===","&&i===0){e.push(s.trim()),s="";continue}s+=c;}return s.trim()&&e.push(s.trim()),e}function X(a){let e=a.match(/^(.*?)\s+as\s+(.+)$/i),s=e?e[1].trim():a.trim(),i=e?e[2].trim():void 0;if(!i){let c=a.match(/^(.+?)\s+((?:"[^"]+"|`[^`]+`|\[[^\]]+\]|\w+))$/);c&&!/[()]/.test(c[1])&&(s=c[1].trim(),i=c[2].trim());}let n=s.split(".").map(T);if(n.length>2)return null;let o=n.at(-1);return !o||!/^[A-Za-z_][\w$]*$/.test(o)?null:{baseColumn:o,viewColumn:i?T(i):o}}function x(a){return !!(a&&/[A-Za-z0-9_$]/.test(a))}function ee(a){let e=/\bselect\b/i.exec(a);if(!e)return null;let s=0,i=null;for(let n=e.index+e[0].length;n<a.length;n++){let o=a[n];if(i){o===i&&(i=null);continue}if(o==='"'||o==="`"||o==="'"){i=o;continue}if(o==="("){s++;continue}if(o===")"&&s>0){s--;continue}if(s===0&&a.slice(n,n+4).toLowerCase()==="from"&&!x(a[n-1])&&!x(a[n+4]))return {selectList:a.slice(e.index+e[0].length,n).trim(),fromRest:a.slice(n+4).trim()}}return null}function te(a){let e=0,s=[];for(;e<a.length;){for(;/\s/.test(a[e]??"");)e++;let i=a[e],n="";if(i==='"'||i==="`"){let r=a.indexOf(i,e+1);if(r===-1)return null;n=a.slice(e,r+1),e=r+1;}else if(i==="["){let r=a.indexOf("]",e+1);if(r===-1)return null;n=a.slice(e,r+1),e=r+1;}else {let r=/^[A-Za-z_][\w$]*/.exec(a.slice(e));if(!r)return null;n=r[0],e+=n.length;}s.push(n);let o=a.slice(e),c=/^\s*\./.exec(o);if(!c)break;e+=c[0].length;}return s.length===0?null:{raw:s.join("."),rest:a.slice(e).trim()}}function v(a,e,s){let i=a.get(e)??[];i.includes(s)||i.push(s),a.set(e,i);}function ne(a,e){if(!a)return null;let s=ee(a);if(!s)return null;let i=te(s.fromRest);if(!i)return null;let{raw:n,rest:o}=i;if(/\b(join|union|intersect|except)\b/i.test(o))return null;let c=n.split(".").map(T).at(-1);if(!c)return null;let r=new Map,l=e.get(c)??new Set;for(let p of Z(s.selectList)){let m=p.trim();if(m==="*"||m.endsWith(".*")){for(let d of l)v(r,d,d);continue}let g=X(p);g&&v(r,g.baseColumn,g.viewColumn);}return r.size===0?null:{baseTable:c,columns:r}}function se(a,e){let s=new Map;for(let[i,n]of e){let o=[];for(let c of n){let r=a.get(c);if(r)for(let l of r)o.includes(l)||o.push(l);}o.length>0&&s.set(i,o);}return s}function ae(a){let e=new Map,s=new Map;for(let r of a.columns??[]){let l=s.get(r.table)??new Set;l.add(r.name),s.set(r.table,l);}let i=(r,l)=>{let p=e.get(r)??[];p.some(m=>m.name===l.name&&m.schema===l.schema)||p.push(l),e.set(r,p);};for(let r of a.tables??[]){if(r.type!=="table")continue;let l=s.get(r.name);l&&i(r.name,{name:r.name,schema:r.schema,columnByBaseColumn:new Map([...l].map(p=>[p,[p]]))});}let n=new Map;for(let r of a.views??[]){let l=ne(r.sql,s);if(!l)continue;let p=s.get(r.name);if(!p)continue;let m=new Map;for(let[d,_]of l.columns){let f=_.filter(h=>p.has(h));f.length>0&&m.set(d,f);}if(m.size===0)continue;let g={name:r.name,schema:r.schema,columnByBaseColumn:m,fromRelation:l.baseTable};n.set(r.name,g);}let o=16;function c(r,l,p){if(l>o)return null;let m=r.fromRelation;if(e.has(m))return {physicalBase:m,columnByBaseColumn:r.columnByBaseColumn};let g=n.get(m);if(!g||p.has(m))return null;p.add(m);let d=c(g,l+1,p);if(p.delete(m),!d)return null;let _=se(r.columnByBaseColumn,d.columnByBaseColumn);return _.size===0?null:{physicalBase:d.physicalBase,columnByBaseColumn:_}}for(let r of n.values()){let l=c(r,0,new Set([r.name]));l&&i(l.physicalBase,{name:r.name,schema:r.schema,columnByBaseColumn:l.columnByBaseColumn});}return e}function B(a){return `${a.foreign_key_group??""}:${a.table}.${a.column}->${a.ref_table}.${a.ref_column}`}function oe(a){let e=new Map;for(let s of a){let i=`${s.schema}.${s.table}.${s.foreign_key_name}.${s.ref_schema??""}.${s.ref_table}`,n=e.get(i);n?n.push(s):e.set(i,[s]);}return [...e.values()]}function ie(a){let e=[[]];for(let s of a){let i=[];for(let n of e)for(let o of s)i.push([...n,o]);e=i;}return e}function re(a,e,s,i){let n=i.map(c=>c.childColumn).join(","),o=i.map(c=>c.parentColumn).join(",");return `${s}:${a.name}(${n})->${e.name}(${o})`}function $(a){if(!a.foreign_keys?.length||!a.views?.length)return a;let e=ae(a),s=new Set(a.foreign_keys.map(B)),i=[];for(let n of oe(a.foreign_keys)){let o=n[0],c=e.get(o.table)??[],r=e.get(o.ref_table)??[];for(let l of c)for(let p of r){if(l.schema!==p.schema)continue;let m=[];for(let g of n){let d=l.columnByBaseColumn.get(g.column)??[],_=p.columnByBaseColumn.get(g.ref_column)??[],f=d.flatMap(h=>_.map(y=>({fk:g,childColumn:h,parentColumn:y})));if(f.length===0){m.length=0;break}m.push(f);}for(let g of ie(m)){let _=l.name===o.table&&p.name===o.ref_table&&g.every(f=>f.childColumn===f.fk.column&&f.parentColumn===f.fk.ref_column)?void 0:re(l,p,o.foreign_key_name,g);for(let f of g){let h={...f.fk,table:l.name,column:f.childColumn,schema:l.schema,ref_table:p.name,ref_column:f.parentColumn,ref_schema:p.schema,foreign_key_group:_},y=B(h);s.has(y)||(s.add(y),i.push(h));}}}}return i.length?{...a,foreign_keys:[...a.foreign_keys,...i]}:a}var A="anon, authenticated, service_role",ue=new Set(["anon","authenticated","service_role"]);function F(a){return `"${a.replace(/"/g,'""')}"`}var S=class extends Error{constructor(s){super("Force rollback");this.result=s;}},O=class extends Connection{dialect="postgres";harnessHoldingOuterTx=false;constructor(e){super({...e,baseSchema:`
17
+ ${e.baseSchema??""}
18
18
 
19
19
  CREATE SCHEMA IF NOT EXISTS auth;
20
20
 
@@ -40,7 +40,7 @@ END $$;
40
40
  '{}'
41
41
  )::jsonb;
42
42
  $$ LANGUAGE SQL STABLE;
43
- `});}async introspect(n){invariant(typeof n=="object"||n===void 0,"options must be an object");let s=n?.useCache??false,t=await this.readCachedIntrospection({useCache:s});if(t)return t;try{let i=(await sql`
43
+ `});}async introspect(e){invariant(typeof e=="object"||e===void 0,"options must be an object");let s=e?.useCache??false,i=await this.readCachedIntrospection({useCache:s});if(i)return i;try{let n=await sql`
44
44
  SELECT
45
45
  tbls.table_name AS "name",
46
46
  tbls.table_schema AS "schema",
@@ -52,8 +52,47 @@ END $$;
52
52
  WHERE
53
53
  tbls.table_schema NOT IN ('information_schema', 'pg_catalog')
54
54
  AND tbls.table_type IN ('BASE TABLE', 'FOREIGN TABLE')
55
+ -- Individual partitions are hidden from the relation cache (like PostgREST):
56
+ -- direct access -> PGRST205, embedding -> PGRST200. The partitioned parent
57
+ -- (relkind 'p', relispartition = false) stays exposed.
58
+ AND NOT EXISTS (
59
+ SELECT 1
60
+ FROM pg_catalog.pg_class pc
61
+ JOIN pg_catalog.pg_namespace pn ON pn.oid = pc.relnamespace
62
+ WHERE pc.relname = tbls.table_name
63
+ AND pn.nspname = tbls.table_schema
64
+ AND pc.relispartition
65
+ )
55
66
  ORDER BY tbls.table_schema, tbls.table_name
56
- `.execute(this.kysely)).rows.map(e=>({name:e.name,schema:e.schema,type:"table",rows:Number(e.rows),sql:"",engine:"",collation:""})),l=(await sql`
67
+ `.execute(this.kysely),o=await sql`
68
+ SELECT
69
+ mv.schemaname AS "schema",
70
+ mv.matviewname AS "name",
71
+ mv.definition AS "sql"
72
+ FROM pg_catalog.pg_matviews mv
73
+ WHERE mv.schemaname NOT IN ('information_schema', 'pg_catalog')
74
+ ORDER BY mv.schemaname, mv.matviewname
75
+ `.execute(this.kysely),c=await sql`
76
+ SELECT
77
+ n.nspname AS "schema",
78
+ c.relname AS "table",
79
+ a.attname AS "name",
80
+ a.attnum AS "ordinal_position",
81
+ format_type(a.atttypid, a.atttypmod) AS "type",
82
+ NOT a.attnotnull AS "nullable",
83
+ pg_get_expr(d.adbin, d.adrelid) AS "default_value"
84
+ FROM pg_catalog.pg_class c
85
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
86
+ JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
87
+ LEFT JOIN pg_catalog.pg_attrdef d
88
+ ON d.adrelid = c.oid AND d.adnum = a.attnum
89
+ WHERE
90
+ c.relkind = 'm'
91
+ AND n.nspname NOT IN ('information_schema', 'pg_catalog')
92
+ AND a.attnum > 0
93
+ AND NOT a.attisdropped
94
+ ORDER BY n.nspname, c.relname, a.attnum
95
+ `.execute(this.kysely),r=n.rows.map(t=>({name:t.name,schema:t.schema,type:"table",rows:Number(t.rows),sql:"",engine:"",collation:""}));for(let t of o.rows)r.push({name:t.name,schema:t.schema,type:"table",rows:0,sql:"",engine:"",collation:""});let p=(await sql`
57
96
  SELECT
58
97
  cols.table_name AS "table",
59
98
  cols.table_schema AS "schema",
@@ -95,6 +134,7 @@ END $$;
95
134
  END AS "is_identity",
96
135
  COALESCE(cols.collation_name, '') AS "collation",
97
136
  cols.udt_name AS "udt_name",
137
+ cols.udt_schema AS "udt_schema",
98
138
  CASE WHEN pt.typtype = 'd' THEN pt.typname ELSE cols.udt_name END AS "domain_type",
99
139
  CASE WHEN cols.is_generated = 'NEVER' THEN false ELSE true END AS "is_generated"
100
140
  FROM information_schema.columns cols
@@ -106,7 +146,7 @@ END $$;
106
146
  LEFT JOIN pg_catalog.pg_type pt ON pt.oid = attr.atttypid
107
147
  WHERE cols.table_schema NOT IN ('information_schema', 'pg_catalog')
108
148
  ORDER BY cols.table_schema, cols.table_name, cols.ordinal_position
109
- `.execute(this.kysely)).rows.map(e=>({table:e.table,schema:e.schema,name:e.name,type:e.type,nullable:e.nullable,default_value:e.default_value,is_primary_key:!1,ordinal_position:Number(e.ordinal_position),character_maximum_length:e.character_maximum_length??null,precision:e.precision??null,is_identity:e.is_identity,collation:e.collation,pg_type:e.domain_type??e.udt_name??void 0,is_generated:e.is_generated??!1})),r=(await sql`
149
+ `.execute(this.kysely)).rows.map(t=>({table:t.table,schema:t.schema,name:t.name,type:t.type,nullable:t.nullable,default_value:t.default_value,is_primary_key:!1,ordinal_position:Number(t.ordinal_position),character_maximum_length:t.character_maximum_length??null,precision:t.precision??null,is_identity:t.is_identity,collation:t.collation,pg_type:t.domain_type??t.udt_name??void 0,udt_schema:t.udt_schema??void 0,is_generated:t.is_generated??!1}));for(let t of c.rows)p.push({table:t.table,schema:t.schema,name:t.name,type:t.type??"",nullable:t.nullable??!0,default_value:t.default_value??null,is_primary_key:!1,ordinal_position:Number(t.ordinal_position),character_maximum_length:null,precision:null,is_identity:!1,collation:"",pg_type:void 0,udt_schema:void 0,is_generated:!1});let g=(await sql`
110
150
  SELECT
111
151
  ns.nspname AS "schema",
112
152
  cl.relname AS "table",
@@ -130,8 +170,13 @@ END $$;
130
170
  AND ns.nspname NOT IN (
131
171
  'information_schema'
132
172
  , 'pg_catalog')
173
+ -- Skip FK rows on/to individual partitions (partition-level copies of an
174
+ -- inherited FK). Keeps the partitioned parent's FK; prevents a partition
175
+ -- surfacing as a spurious embed candidate.
176
+ AND NOT cl.relispartition
177
+ AND NOT ref_cl.relispartition
133
178
  ORDER BY ns.nspname, cl.relname, con.conname, cols.ord
134
- `.execute(this.kysely)).rows.map(e=>({table:e.table,column:e.column,schema:e.schema,ref_table:e.ref_table,ref_column:e.ref_column,foreign_key_name:e.foreign_key_name,fk_def:e.fk_def,on_update:"",on_delete:""})),_=(await sql`
179
+ `.execute(this.kysely)).rows.map(t=>({table:t.table,column:t.column,schema:t.schema,ref_table:t.ref_table,ref_column:t.ref_column,foreign_key_name:t.foreign_key_name,fk_def:t.fk_def,on_update:"",on_delete:""})),_=(await sql`
135
180
  SELECT
136
181
  ns.nspname AS "schema",
137
182
  cl.relname AS "table",
@@ -148,7 +193,7 @@ END $$;
148
193
  'information_schema'
149
194
  , 'pg_catalog')
150
195
  GROUP BY ns.nspname, cl.relname, con.oid
151
- `.execute(this.kysely)).rows.map(e=>({table:e.table,columns:e.columns,schema:e.schema,field_count:e.columns.length})),h=new Set(_.flatMap(e=>e.columns.map(x=>`${e.schema}.${e.table}.${x}`)));for(let e of l)e.is_primary_key=h.has(`${e.schema}.${e.table}.${e.name}`);let R=(await sql`
196
+ `.execute(this.kysely)).rows.map(t=>({table:t.table,columns:t.columns,schema:t.schema,field_count:t.columns.length})),f=new Set(_.flatMap(t=>t.columns.map(N=>`${t.schema}.${t.table}.${N}`)));for(let t of p)t.is_primary_key=f.has(`${t.schema}.${t.table}.${t.name}`);let y=(await sql`
152
197
  SELECT
153
198
  tnsp.nspname AS "schema",
154
199
  cl.relname AS "table",
@@ -169,7 +214,7 @@ END $$;
169
214
  'information_schema'
170
215
  , 'pg_catalog')
171
216
  GROUP BY tnsp.nspname, cl.relname, ic.relname, idx.indisunique
172
- `.execute(this.kysely)).rows.map(e=>({table:e.table,name:e.name,unique:e.unique,columns:e.columns,schema:e.schema})),O=(await sql`
217
+ `.execute(this.kysely)).rows.map(t=>({table:t.table,name:t.name,unique:t.unique,columns:t.columns,schema:t.schema})),C=(await sql`
173
218
  SELECT
174
219
  views.schemaname AS "schema",
175
220
  views.viewname AS "name",
@@ -177,7 +222,7 @@ END $$;
177
222
  FROM pg_views views
178
223
  WHERE views.schemaname NOT IN ('information_schema', 'pg_catalog')
179
224
  ORDER BY views.schemaname, views.viewname
180
- `.execute(this.kysely)).rows.map(e=>({name:e.name,schema:e.schema,sql:e.sql??""})),T=(await sql`
225
+ `.execute(this.kysely)).rows.map(t=>({name:t.name,schema:t.schema,sql:t.sql??""}));for(let t of o.rows)C.push({name:t.name,schema:t.schema,sql:t.sql??""});let D=(await sql`
181
226
  SELECT
182
227
  n.nspname AS "schema",
183
228
  cl.relname AS "table",
@@ -189,7 +234,7 @@ END $$;
189
234
  c.contype = 'c'
190
235
  AND n.nspname NOT IN ('information_schema', 'pg_catalog')
191
236
  ORDER BY n.nspname, cl.relname
192
- `.execute(this.kysely)).rows.map(e=>({schema:e.schema,table:e.table,expression:e.expression??""})),L=(await sql`
237
+ `.execute(this.kysely)).rows.map(t=>({schema:t.schema,table:t.table,expression:t.expression??""})),H=(await sql`
193
238
  SELECT
194
239
  n.nspname AS "schema",
195
240
  cl.relname AS "table",
@@ -204,7 +249,7 @@ END $$;
204
249
  c.contype = 'u'
205
250
  AND n.nspname NOT IN ('information_schema', 'pg_catalog')
206
251
  GROUP BY n.nspname, cl.relname, c.conname, c.oid
207
- `.execute(this.kysely)).rows.map(e=>({schema:e.schema,table:e.table,name:e.name,columns:e.columns})),w=(await sql`
252
+ `.execute(this.kysely)).rows.map(t=>({schema:t.schema,table:t.table,name:t.name,columns:t.columns})),J=(await sql`
208
253
  SELECT
209
254
  n.nspname AS "schema",
210
255
  cl.relname AS "table",
@@ -219,7 +264,7 @@ END $$;
219
264
  n.nspname NOT IN ('information_schema', 'pg_catalog')
220
265
  AND cl.relkind IN ('r', 'v', 'm', 'f', 'p')
221
266
  AND d.description IS NOT NULL
222
- `.execute(this.kysely)).rows.map(e=>({schema:e.schema,table:e.table,column:e.column??void 0,text:e.text})),b=await sql`
267
+ `.execute(this.kysely)).rows.map(t=>({schema:t.schema,table:t.table,column:t.column??void 0,text:t.text})),M=await sql`
223
268
  SELECT
224
269
  n.nspname AS "schema",
225
270
  t.typname AS "type",
@@ -230,7 +275,7 @@ END $$;
230
275
  JOIN pg_namespace n ON n.oid = t.typnamespace
231
276
  WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
232
277
  GROUP BY n.nspname, t.typname
233
- `.execute(this.kysely),I=await sql`
278
+ `.execute(this.kysely),U=await sql`
234
279
  SELECT
235
280
  n.nspname AS "schema",
236
281
  t.typname AS "type",
@@ -252,10 +297,51 @@ END $$;
252
297
  AND NOT a.attisdropped
253
298
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
254
299
  GROUP BY n.nspname, t.typname
255
- `.execute(this.kysely),C=[...b.rows.map(e=>({schema:e.schema,type:e.type,kind:"enum",values:e.values})),...I.rows.map(e=>({schema:e.schema,type:e.type,kind:"composite",fields:e.fields}))],k=(await sql`SELECT current_database() AS "name"`.execute(this.kysely)).rows[0]?.name??"postgres",f={tables:i,columns:l,indexes:R,foreign_keys:r,primary_keys:_,views:O,triggers:[],check_constraints:T,unique_constraints:L,comments:w,custom_types:C,database_name:k,version:""};return await this.writeCachedIntrospection(f,{useDriver:s}),f}catch(o){return console.error("Introspection failed:",o),{tables:[],columns:[],indexes:[],foreign_keys:[],primary_keys:[],views:[],triggers:[],check_constraints:[],unique_constraints:[],comments:[],custom_types:[],database_name:"postgres",version:""}}}rlsState="unknown";async ensureRlsContext(){if(this.rlsState!=="unknown")return this.rlsState==="active";let n=await sql`
300
+ `.execute(this.kysely),P=[...M.rows.map(t=>({schema:t.schema,type:t.type,kind:"enum",values:t.values})),...U.rows.map(t=>({schema:t.schema,type:t.type,kind:"composite",fields:t.fields}))],W=(await sql`
301
+ SELECT
302
+ n.nspname AS "schema",
303
+ p.proname AS "name",
304
+ p.proargnames AS "arg_names_raw",
305
+ p.proargmodes::text[] AS "arg_modes_raw",
306
+ p.pronargdefaults AS "arg_defaults",
307
+ p.provariadic <> 0 AS "has_variadic",
308
+ p.provolatile AS "volatility",
309
+ p.proretset AS "return_is_setof",
310
+ p.prorows AS "return_rows",
311
+ format_type(p.prorettype, NULL) AS "return_type",
312
+ rt.typtype AS "return_typtype",
313
+ CASE WHEN rt.typtype = 'd' AND rt.typbasetype <> 0
314
+ THEN format_type(rt.typbasetype, NULL) END AS "return_base_type",
315
+ (SELECT array_agg(format_type(t, NULL) ORDER BY ord)
316
+ FROM unnest(p.proargtypes) WITH ORDINALITY AS at(t, ord)) AS "arg_types_raw"
317
+ FROM pg_proc p
318
+ JOIN pg_namespace n ON n.oid = p.pronamespace
319
+ LEFT JOIN pg_type rt ON rt.oid = p.prorettype
320
+ WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
321
+ AND p.prokind = 'f'
322
+ ORDER BY n.nspname, p.proname
323
+ `.execute(this.kysely)).rows.map(t=>{let N=t.arg_names_raw??[],E=t.arg_modes_raw??null,q=E&&E.length===N.length?N.filter((R,w)=>E[w]==="i"||E[w]==="b"||E[w]==="v"):N,z=!!E?.some(R=>R==="o"||R==="b"||R==="t");return {schema:t.schema,name:t.name,arg_names:q,arg_types:t.arg_types_raw??[],arg_defaults:Number(t.arg_defaults??0),has_variadic:t.has_variadic===!0,volatility:t.volatility??"v",return_type:t.return_type??"",return_is_setof:t.return_is_setof===!0,return_rows:Number(t.return_rows??0),return_typtype:t.return_typtype??"",return_base_type:t.return_base_type??void 0,has_out_args:z}}),G=(await sql`
324
+ SELECT
325
+ c.relname AS "name",
326
+ n.nspname AS "schema",
327
+ p.relname AS "parent"
328
+ FROM pg_catalog.pg_inherits i
329
+ JOIN pg_catalog.pg_class c ON c.oid = i.inhrelid AND c.relispartition
330
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
331
+ JOIN pg_catalog.pg_class p ON p.oid = i.inhparent
332
+ WHERE n.nspname NOT IN ('information_schema', 'pg_catalog')
333
+ `.execute(this.kysely)).rows.map(t=>({name:t.name,schema:t.schema,parent:t.parent})),j=(await sql`SELECT name FROM pg_catalog.pg_timezone_names`.execute(this.kysely)).rows.map(t=>t.name),K=(await sql`SELECT current_database() AS "name"`.execute(this.kysely)).rows[0]?.name??"postgres",I=$({tables:r,columns:p,indexes:y,foreign_keys:g,primary_keys:_,views:C,triggers:[],functions:W,check_constraints:D,unique_constraints:H,comments:J,custom_types:P,partitions:G,database_name:K,version:"",default_schema:this.config?.translation?.schemas?.defaultSchema??"public",timezones:j});return await this.writeCachedIntrospection(I,{useDriver:s}),I}catch(n){return console.error("Introspection failed:",n),{tables:[],columns:[],indexes:[],foreign_keys:[],primary_keys:[],views:[],triggers:[],check_constraints:[],unique_constraints:[],comments:[],custom_types:[],database_name:"postgres",version:""}}}rlsState="unknown";async ensureRlsContext(){if(this.rlsState!=="unknown")return this.rlsState==="active";let e=await sql`
256
334
  SELECT count(*) ::text as count FROM pg_class WHERE relrowsecurity = true
257
- `.execute(this.kysely);if(!(Number(n.rows[0]?.count??0)>0))return this.rlsState="inactive",false;this.rlsState="active",await sql.raw(g).execute(this.kysely);let t=await sql`
335
+ `.execute(this.kysely);if(!(Number(e.rows[0]?.count??0)>0))return this.rlsState="inactive",false;this.rlsState="active",await sql.raw(k).execute(this.kysely);let i=await sql`
258
336
  SELECT DISTINCT n.nspname FROM pg_class c
259
337
  JOIN pg_namespace n ON n.oid = c.relnamespace
260
338
  WHERE c.relrowsecurity = true
261
- `.execute(this.kysely);for(let{nspname:o}of t.rows){let i=A(o);await sql.raw(`GRANT USAGE ON SCHEMA ${i} TO ${m}`).execute(this.kysely),await sql.raw(`GRANT ALL ON ALL TABLES IN SCHEMA ${i} TO ${m}`).execute(this.kysely),await sql.raw(`GRANT ALL ON ALL SEQUENCES IN SCHEMA ${i} TO ${m}`).execute(this.kysely),await sql.raw(`ALTER DEFAULT PRIVILEGES IN SCHEMA ${i} GRANT ALL ON TABLES TO ${m}`).execute(this.kysely),await sql.raw(`ALTER DEFAULT PRIVILEGES IN SCHEMA ${i} GRANT ALL ON SEQUENCES TO ${m}`).execute(this.kysely);}return true}async postgresTransactionActive(n){try{return await sql`SAVEPOINT __supalite_outer_tx_check`.execute(n),await sql`RELEASE SAVEPOINT __supalite_outer_tx_check`.execute(n),!0}catch{return false}}async applyJwtSessionContext(n,s,t){let o=s.auth,i=o?.role||"anon",d=String(o?.uid??""),l=o?.jwt;await sql`SELECT set_config('role', ${i}, true)`.execute(n),await sql`SELECT set_config('request.jwt.claim.sub', ${d}, true)`.execute(n),await sql`SELECT set_config('request.jwt.claim.role', ${i}, true)`.execute(n),t&&await sql.raw(`SET LOCAL ROLE ${A(i)}`).execute(n),l&&typeof l=="object"&&await sql`SELECT set_config('request.jwt.claims', ${JSON.stringify(l)}, true)`.execute(n);}async withContext(n,s,t){let o=t?.forceRollback===true;if(!o&&!n)return s(this.kysely);let i=n?await this.ensureRlsContext():false,l=n?.auth?.role||"anon",u=typeof l=="string"&&/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(l)&&!U.has(l);if(!o&&!i&&!u)return s(this.kysely);if(!o&&u)return this.harnessHoldingOuterTx?(invariant(await this.postgresTransactionActive(this.kysely),"harnessHoldingOuterTx is set but the connection has no open PostgreSQL transaction; wrap REST requests in BEGIN/ROLLBACK in the spec harness"),await this.applyJwtSessionContext(this.kysely,n,true),s(this.kysely)):this.kysely.transaction().execute(async r=>(await this.applyJwtSessionContext(r,n,true),s(r)));if(!o&&i&&!u)return this.kysely.transaction().execute(async r=>(await this.applyJwtSessionContext(r,n,true),s(r)));try{return await this.kysely.transaction().execute(async r=>{n&&(i||u)&&await this.applyJwtSessionContext(r,n,u);let S=await s(r);if(o)throw new p(S);return S})}catch(r){if(r instanceof p)return r.result;throw r}}async onPostgrestAST(n){if(!n.from)return n;let s=n.schema??"public",t=n.from,o=await this.introspect({useCache:true});if(!o.tables.some(i=>i.name===t&&i.schema===s)&&!o.views.some(i=>i.name===t&&i.schema===s))throw new RelationNotFoundError(s,t);return n}async transaction(n,s){await this.exec("BEGIN");try{for(let t of n)await this.exec(t);await this.exec("COMMIT");}catch(t){throw await this.exec("ROLLBACK"),t}finally{s?.intent==="migration"&&await this.clearSchemaCache();}}};var N=class extends E{driver;dialect="postgres";constructor(n){super(n),this.driver=F(n.url??"",{types:{bigint:{to:20,from:[20],serialize:t=>t.toString(),parse:t=>{let o=Number(t);return Number.isSafeInteger(o)?o:BigInt(t)}},json:{to:114,from:[114],serialize:t=>JSON.stringify(t),parse:t=>JSON.parse(t)},jsonb:{to:3802,from:[3802],serialize:t=>JSON.stringify(t),parse:t=>JSON.parse(t)},numeric:{to:1700,from:[1700],serialize:t=>String(t),parse:t=>{let o=Number(t);return Number.isFinite(o)&&String(o)===t?o:t}},date:{to:1082,from:[1082],serialize:t=>t,parse:t=>t},time:{to:1083,from:[1083],serialize:t=>t,parse:t=>t},timestamp:{to:1114,from:[1114],serialize:t=>t,parse:t=>t},timestamptz:{to:1184,from:[1184],serialize:t=>t,parse:t=>t},timetz:{to:1266,from:[1266],serialize:t=>t,parse:t=>t}}});let s=new PostgresJSDialect({postgres:this.driver});this.kysely=new Kysely({dialect:s});}async close(){await this.driver.end();}};function ae(c){return new N(c)}export{N as PostgresConnection,ae as createPostgresConnection};
339
+ `.execute(this.kysely);for(let{nspname:n}of i.rows){let o=F(n);await sql.raw(`GRANT USAGE ON SCHEMA ${o} TO ${A}`).execute(this.kysely),await sql.raw(`GRANT ALL ON ALL TABLES IN SCHEMA ${o} TO ${A}`).execute(this.kysely),await sql.raw(`GRANT ALL ON ALL SEQUENCES IN SCHEMA ${o} TO ${A}`).execute(this.kysely),await sql.raw(`ALTER DEFAULT PRIVILEGES IN SCHEMA ${o} GRANT ALL ON TABLES TO ${A}`).execute(this.kysely),await sql.raw(`ALTER DEFAULT PRIVILEGES IN SCHEMA ${o} GRANT ALL ON SEQUENCES TO ${A}`).execute(this.kysely);}return true}async postgresTransactionActive(e){try{return await sql`SAVEPOINT __supalite_outer_tx_check`.execute(e),await sql`RELEASE SAVEPOINT __supalite_outer_tx_check`.execute(e),!0}catch{return false}}async applyJwtSessionContext(e,s,i){let n=s.auth,o=n?.role||"anon",c=String(n?.uid??""),r=n?.jwt;await sql`SELECT set_config('role', ${o}, true)`.execute(e),await sql`SELECT set_config('request.jwt.claim.sub', ${c}, true)`.execute(e),await sql`SELECT set_config('request.jwt.claim.role', ${o}, true)`.execute(e),i&&await sql.raw(`SET LOCAL ROLE ${F(o)}`).execute(e),r&&typeof r=="object"&&await sql`SELECT set_config('request.jwt.claims', ${JSON.stringify(r)}, true)`.execute(e);}async applyRpcRequestGucs(e,s){await sql`SELECT set_config('response.status', '', true)`.execute(e),await sql`SELECT set_config('response.headers', '', true)`.execute(e),await sql`SELECT set_config('request.method', ${s.method}, true)`.execute(e),await sql`SELECT set_config('request.path', ${s.path}, true)`.execute(e),await sql`SELECT set_config('request.headers', ${JSON.stringify(s.requestHeaders??{})}, true)`.execute(e);}async withContext(e,s,i){let n=i?.forceRollback===true;if(!n&&!e)return s(this.kysely);let o=e?await this.ensureRlsContext():false,r=e?.auth?.role||"anon",l=typeof r=="string"&&/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(r)&&!ue.has(r),p=i?.rpc;if(p){let m=async g=>{e&&(o||l)&&await this.applyJwtSessionContext(g,e,l),await this.applyRpcRequestGucs(g,p),p.readOnly&&await sql`SET LOCAL transaction_read_only = on`.execute(g);};if(this.harnessHoldingOuterTx)return invariant(await this.postgresTransactionActive(this.kysely),"harnessHoldingOuterTx is set but the connection has no open PostgreSQL transaction; wrap REST requests in BEGIN/ROLLBACK in the spec harness"),await m(this.kysely),s(this.kysely);try{return await this.kysely.transaction().execute(async g=>{await m(g);let d=await s(g);if(n)throw new S(d);return d})}catch(g){if(g instanceof S)return g.result;throw g}}if(!n&&!o&&!l)return s(this.kysely);if(!n&&l)return this.harnessHoldingOuterTx?(invariant(await this.postgresTransactionActive(this.kysely),"harnessHoldingOuterTx is set but the connection has no open PostgreSQL transaction; wrap REST requests in BEGIN/ROLLBACK in the spec harness"),await this.applyJwtSessionContext(this.kysely,e,true),s(this.kysely)):this.kysely.transaction().execute(async m=>(await this.applyJwtSessionContext(m,e,true),s(m)));if(!n&&o&&!l)return this.kysely.transaction().execute(async m=>(await this.applyJwtSessionContext(m,e,true),s(m)));try{return await this.kysely.transaction().execute(async m=>{e&&(o||l)&&await this.applyJwtSessionContext(m,e,l);let g=await s(m);if(n)throw new S(g);return g})}catch(m){if(m instanceof S)return m.result;throw m}}async onPostgrestAST(e){if(!e.from)return e;let s=e.schema??"public",i=e.from,n=await this.introspect({useCache:true});if(!n.tables.some(o=>o.name===i&&o.schema===s)&&!n.views.some(o=>o.name===i&&o.schema===s))throw new RelationNotFoundError(s,i);return e}async transaction(e,s){await this.exec("BEGIN");try{for(let i of e)await this.exec(i);await this.exec("COMMIT");}catch(i){throw await this.exec("ROLLBACK"),i}finally{s?.intent==="migration"&&await this.clearSchemaCache();}}get supportsRpc(){return true}async viewOptionsMetadata(e,s){let{rows:i}=await sql`
340
+ select is_insertable_into, is_updatable,
341
+ is_trigger_insertable_into, is_trigger_updatable, is_trigger_deletable
342
+ from information_schema.views
343
+ where table_schema = ${s} and table_name = ${e}
344
+ `.execute(this.kysely),n=i[0],o=r=>r==="YES",{rows:c}=await sql`
345
+ select table_schema, table_name from information_schema.view_table_usage
346
+ where view_schema = ${s} and view_name = ${e}
347
+ `.execute(this.kysely);return {canInsert:o(n?.is_insertable_into)||o(n?.is_trigger_insertable_into),canUpdate:o(n?.is_updatable)||o(n?.is_trigger_updatable),canDelete:o(n?.is_updatable)||o(n?.is_trigger_deletable),baseTables:c.map(r=>({schema:r.table_schema,name:r.table_name}))}}};var L=class extends O{driver;dialect="postgres";constructor(e){super(e);let{postgresOptions:s}=e;this.driver=me(e.url??"",{...s,connection:{TimeZone:"UTC",...s?.connection},types:{bigint:{to:20,from:[20],serialize:n=>n.toString(),parse:n=>{let o=Number(n);return Number.isSafeInteger(o)?o:BigInt(n)}},json:{to:114,from:[114],serialize:n=>JSON.stringify(n),parse:n=>JSON.parse(n)},jsonb:{to:3802,from:[3802],serialize:n=>JSON.stringify(n),parse:n=>JSON.parse(n)},numeric:{to:1700,from:[1700],serialize:n=>String(n),parse:n=>{let o=Number(n);return Number.isFinite(o)&&String(o)===n?o:n}},date:{to:1082,from:[1082],serialize:n=>n,parse:n=>n},time:{to:1083,from:[1083],serialize:n=>n,parse:n=>n},timestamp:{to:1114,from:[1114],serialize:n=>n,parse:n=>n},timestamptz:{to:1184,from:[1184],serialize:n=>n,parse:n=>n},timetz:{to:1266,from:[1266],serialize:n=>n,parse:n=>n},...s?.types}});let i=new PostgresJSDialect({postgres:this.driver});this.kysely=new Kysely({dialect:i});}async close(){await this.driver.end();}};function ve(a){return new L(a)}export{L as PostgresConnection,ve as createPostgresConnection};
@@ -1,6 +1,6 @@
1
1
  import { PGliteOptions, PGlite } from '@electric-sql/pglite';
2
2
  export { PGlite } from '@electric-sql/pglite';
3
- import { I as IBasePostgresConnectionConfig, B as BasePostgresConnection } from '../BasePostgresConnection-NlNmZWv1.js';
3
+ import { I as IBasePostgresConnectionConfig, B as BasePostgresConnection } from '../BasePostgresConnection-xaPv2E6u.js';
4
4
  import { ConnectionMigrator, SchemaDiffResult, PlanResult, PlanStep } from '@supabase/lite';
5
5
  import 'kysely';
6
6