@supabase/lite 0.5.0 → 0.5.1-next.1
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 +4 -0
- package/STATUS.md +6 -2
- package/dist/{Connection-DF_xKWko.d.ts → Connection-DJbw6dM8.d.ts} +117 -1
- package/dist/db/fallback.d.ts +1 -1
- package/dist/db/postgres/{BasePostgresConnection-NlNmZWv1.d.ts → BasePostgresConnection-xaPv2E6u.d.ts} +14 -1
- package/dist/db/postgres/PostgresConnection.d.ts +10 -1
- package/dist/db/postgres/PostgresConnection.js +105 -19
- package/dist/db/postgres/pglite/PgliteConnection.d.ts +1 -1
- package/dist/db/postgres/pglite/PgliteConnection.js +109 -23
- package/dist/index.d.ts +25 -2
- package/dist/index.js +45 -42
- package/dist/static/.vite/manifest.json +2 -2
- package/dist/static/assets/{main-DexXgo9R.css → main-BITGMylP.css} +4 -0
- package/dist/vite/index.d.ts +23 -0
- package/package.json +1 -1
- /package/dist/static/assets/{main-BsWx0q9l.js → main-DO_xnvTw.js} +0 -0
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 | **
|
|
844
|
-
| PGlite | 2,460 | **
|
|
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
|
|
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 };
|
package/dist/db/fallback.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IConnectionConfig, C as Connection } from '../Connection-
|
|
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-
|
|
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
|
|
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
|
|
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} ${
|
|
13
|
+
CREATE ROLE ${s} ${V(s)};
|
|
14
14
|
END IF;`).join("")}
|
|
15
15
|
END $$;
|
|
16
|
-
`}var g=
|
|
17
|
-
${
|
|
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(
|
|
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)
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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),
|
|
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),
|
|
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(
|
|
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:
|
|
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-
|
|
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
|
|