@palbase/backend 25.0.0 → 25.0.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/dist/bin/palbase-backend.cjs +2 -0
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +2 -2
- package/dist/{chunk-43A3KGWL.js → chunk-34I4GB7D.js} +4 -2
- package/dist/{chunk-43A3KGWL.js.map → chunk-34I4GB7D.js.map} +1 -1
- package/dist/{chunk-ZQRWW37O.js → chunk-35PNTIRN.js} +5 -1
- package/dist/chunk-35PNTIRN.js.map +1 -0
- package/dist/{chunk-OEQBHE2Z.js → chunk-HBOJLP2Z.js} +19 -4
- package/dist/chunk-HBOJLP2Z.js.map +1 -0
- package/dist/{chunk-5CMLOAEF.js → chunk-YOY5DFQS.js} +2 -2
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +2 -1
- package/dist/db/env.d.ts +2 -1
- package/dist/db/index.cjs +17 -3
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/engine/index.cjs +2 -0
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +2 -2
- package/dist/engine/index.d.ts +2 -2
- package/dist/engine/index.js +2 -2
- package/dist/{index-Ct1iiB4N.d.ts → index-B4CcpqLb.d.ts} +23 -16
- package/dist/{index-BF1f0DfA.d.ts → index-B8v6hVyU.d.ts} +1 -1
- package/dist/{index-CwaWRhyc.d.cts → index-DmVyY6N7.d.cts} +23 -16
- package/dist/{index-CoaDN9dL.d.cts → index-VsjBQ4Kw.d.cts} +1 -1
- package/dist/index.cjs +75 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +58 -49
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +1 -1
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.js +3 -3
- package/dist/openapi/index.js.map +1 -1
- package/docs/llms-full.txt +36 -5
- package/docs/schema.md +36 -5
- package/package.json +1 -1
- package/dist/chunk-OEQBHE2Z.js.map +0 -1
- package/dist/chunk-ZQRWW37O.js.map +0 -1
- /package/dist/{chunk-5CMLOAEF.js.map → chunk-YOY5DFQS.js.map} +0 -0
package/dist/engine/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { A as App, m as AuthVerifier, B as BootRefused, n as CreateAppOptions, E as EgressPolicy, p as EngineConfig, M as ModuleClients, q as RateLimiter, r as RequestDatabase, s as RouteEntry, t as RuntimeHooks, u as ScrubResult, v as SqlDriver, w as SqlTx, x as buildRouteTable, y as createApp, z as createLazyTransaction, G as createOps, H as createRequestDatabase, I as effectiveAuth, J as hostAllowed, K as installEgressFence, O as loadConfig, P as makeMemoryCache, Q as matchRoute, T as quoteIdent, U as scrubSecrets, V as withTables } from '../index-
|
|
1
|
+
export { A as App, m as AuthVerifier, B as BootRefused, n as CreateAppOptions, E as EgressPolicy, p as EngineConfig, M as ModuleClients, q as RateLimiter, r as RequestDatabase, s as RouteEntry, t as RuntimeHooks, u as ScrubResult, v as SqlDriver, w as SqlTx, x as buildRouteTable, y as createApp, z as createLazyTransaction, G as createOps, H as createRequestDatabase, I as effectiveAuth, J as hostAllowed, K as installEgressFence, O as loadConfig, P as makeMemoryCache, Q as matchRoute, T as quoteIdent, U as scrubSecrets, V as withTables } from '../index-VsjBQ4Kw.cjs';
|
|
2
2
|
import '../endpoint-BSGw1pTu.cjs';
|
|
3
3
|
import '../stack.cjs';
|
|
4
4
|
import 'node:async_hooks';
|
|
5
|
-
import '../index-
|
|
5
|
+
import '../index-DmVyY6N7.cjs';
|
|
6
6
|
import '../db/env.cjs';
|
|
7
7
|
import '../registry-CgJvDYUW.cjs';
|
|
8
8
|
import 'zod';
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { A as App, m as AuthVerifier, B as BootRefused, n as CreateAppOptions, E as EgressPolicy, p as EngineConfig, M as ModuleClients, q as RateLimiter, r as RequestDatabase, s as RouteEntry, t as RuntimeHooks, u as ScrubResult, v as SqlDriver, w as SqlTx, x as buildRouteTable, y as createApp, z as createLazyTransaction, G as createOps, H as createRequestDatabase, I as effectiveAuth, J as hostAllowed, K as installEgressFence, O as loadConfig, P as makeMemoryCache, Q as matchRoute, T as quoteIdent, U as scrubSecrets, V as withTables } from '../index-
|
|
1
|
+
export { A as App, m as AuthVerifier, B as BootRefused, n as CreateAppOptions, E as EgressPolicy, p as EngineConfig, M as ModuleClients, q as RateLimiter, r as RequestDatabase, s as RouteEntry, t as RuntimeHooks, u as ScrubResult, v as SqlDriver, w as SqlTx, x as buildRouteTable, y as createApp, z as createLazyTransaction, G as createOps, H as createRequestDatabase, I as effectiveAuth, J as hostAllowed, K as installEgressFence, O as loadConfig, P as makeMemoryCache, Q as matchRoute, T as quoteIdent, U as scrubSecrets, V as withTables } from '../index-B8v6hVyU.js';
|
|
2
2
|
import '../endpoint-DMwJjEHQ.js';
|
|
3
3
|
import '../stack.js';
|
|
4
4
|
import 'node:async_hooks';
|
|
5
|
-
import '../index-
|
|
5
|
+
import '../index-B4CcpqLb.js';
|
|
6
6
|
import '../db/env.js';
|
|
7
7
|
import '../registry-B8pld3fj.js';
|
|
8
8
|
import 'zod';
|
package/dist/engine/index.js
CHANGED
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
quoteIdent,
|
|
17
17
|
scrubSecrets,
|
|
18
18
|
withTables
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-34I4GB7D.js";
|
|
20
20
|
import "../chunk-XJ2RSHEU.js";
|
|
21
21
|
import "../chunk-XABBC7JP.js";
|
|
22
22
|
import "../chunk-P2Q27SGP.js";
|
|
23
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-35PNTIRN.js";
|
|
24
24
|
import "../chunk-7D4SUZUM.js";
|
|
25
25
|
export {
|
|
26
26
|
AuthVerifier,
|
|
@@ -32,8 +32,20 @@ interface ColumnDef {
|
|
|
32
32
|
selfRefColumn?: string;
|
|
33
33
|
/** This column OWNS the row: erasure, RLS and the `owner` relation read it. */
|
|
34
34
|
owns?: true;
|
|
35
|
-
/** Explicit
|
|
35
|
+
/** Explicit name for the FORWARD relation (child → parent), when the one
|
|
36
|
+
* derived from the column would be ambiguous or unclear. */
|
|
36
37
|
refAs?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Explicit name for the REVERSE relation (parent → children).
|
|
40
|
+
*
|
|
41
|
+
* Separate from {@link refAs} because the two directions are different facts:
|
|
42
|
+
* the forward name describes the parent this row points at (`author`), the
|
|
43
|
+
* reverse one describes the rows hanging off the parent (`posts`). One option
|
|
44
|
+
* naming both made an ordinary schema undeclarable — `posts.author_id` and
|
|
45
|
+
* `comments.author_id` both named `{ as: "author" }` collided on `users`, and
|
|
46
|
+
* the refusal asked for the `{ as }` they had both already written.
|
|
47
|
+
*/
|
|
48
|
+
reverseAs?: string;
|
|
37
49
|
/** The table this column belongs to; set by `defineTable`. */
|
|
38
50
|
ownerTable?: {
|
|
39
51
|
name: string;
|
|
@@ -197,9 +209,16 @@ declare class ColumnBuilder<K extends ColumnType = ColumnType, N extends boolean
|
|
|
197
209
|
* In a cycle, ONE side needs an explicit return type:
|
|
198
210
|
* `references((): AnyColumn => y.id)`. One side is enough — measured.
|
|
199
211
|
* For a self-reference use `selfReferences(column)`: no thunk, no annotation.
|
|
212
|
+
*
|
|
213
|
+
* `as` names the FORWARD relation (`author_id` → `author` by default);
|
|
214
|
+
* `reverseAs` names the REVERSE one on the parent, whose default is this
|
|
215
|
+
* table's own name (`users.posts`). Two foreign keys from one table onto one
|
|
216
|
+
* parent therefore need a `reverseAs` on at least one of them — the reverse
|
|
217
|
+
* names would otherwise both be this table's name.
|
|
200
218
|
*/
|
|
201
219
|
references(target: () => AnyColumn, opts?: {
|
|
202
220
|
as?: string;
|
|
221
|
+
reverseAs?: string;
|
|
203
222
|
onDelete?: OnDeleteAction;
|
|
204
223
|
}): ColumnBuilder<K, N, D, E, P, T>;
|
|
205
224
|
/**
|
|
@@ -489,7 +508,8 @@ declare const EXTENSION_DEPENDENCIES: Partial<Record<PalbaseExtension, PalbaseEx
|
|
|
489
508
|
declare function isPalbaseExtension(name: string): name is PalbaseExtension;
|
|
490
509
|
|
|
491
510
|
/**
|
|
492
|
-
* A named raw-SQL DDL object declared in db/
|
|
511
|
+
* A named raw-SQL DDL object declared in a schema file (`db/public.ts`,
|
|
512
|
+
* `db/billing.ts`, …) for anything the typed DSL
|
|
493
513
|
* cannot express (EXCLUDE, CHECK, partial/expression indexes, triggers, views).
|
|
494
514
|
* The deploy emits `up` verbatim on the privileged DDL connection — same trust
|
|
495
515
|
* posture as policy().using(). Tracked by NAME (not by diffing the body), so a
|
|
@@ -714,19 +734,6 @@ interface SchemaDef<T extends Record<string, TableDef> = Record<string, TableDef
|
|
|
714
734
|
/** Postgres extensions to install on deploy. Normalized to `[]` when absent. */
|
|
715
735
|
extensions: PalbaseExtension[];
|
|
716
736
|
}
|
|
717
|
-
/** The author-facing input to `defineSchema` — a `tables` map whose keys are
|
|
718
|
-
* the table names and whose values are `{ columns, rls?, policies? }`, plus an
|
|
719
|
-
* optional `extensions` allowlist. */
|
|
720
|
-
interface SchemaInput<T extends Record<string, TableInput> = Record<string, TableInput>> {
|
|
721
|
-
tables: T;
|
|
722
|
-
/**
|
|
723
|
-
* Postgres extensions to enable for this project, e.g. `["vector"]`.
|
|
724
|
-
* Config-as-code: installed by the deploy (CREATE EXTENSION … SCHEMA
|
|
725
|
-
* extensions) with the privileged deploy connection. The type is an
|
|
726
|
-
* allowlist union, so unsupported names fail typecheck.
|
|
727
|
-
*/
|
|
728
|
-
extensions?: PalbaseExtension[];
|
|
729
|
-
}
|
|
730
737
|
/** Map the author's `{ tables: { <name>: { columns } } }` input to the
|
|
731
738
|
* `{ tables: { <name>: TableDef<columns> } }` runtime/type shape, threading the
|
|
732
739
|
* per-table column map `T[K]["columns"]` so column-level inference survives. */
|
|
@@ -1212,4 +1219,4 @@ interface EnvTypedDatabase extends Omit<DBClient, "txPlan" | "asService"> {
|
|
|
1212
1219
|
asService(): EnvServiceDatabase;
|
|
1213
1220
|
}
|
|
1214
1221
|
|
|
1215
|
-
export { type AnyColumn as A,
|
|
1222
|
+
export { type AnyColumn as A, defineTable as B, ColumnBuilder as C, enumType as D, type EnvTypedDatabase as E, installationRef as F, integer as G, isPalbaseExtension as H, type InsertShape as I, jsonb as J, makeTypedDB as K, numeric as L, openai as M, ownedByUser as N, type OnDeleteAction as O, PALBASE_EXTENSIONS as P, policy as Q, type RawConstraintDef as R, type SchemaDef as S, TABLE_META as T, raw as U, text as V, timestamp as W, userRef as X, uuid as Y, vector as Z, type ColumnDef as a, type ColumnMap as b, type ColumnType as c, EXTENSION_DEPENDENCIES as d, type EmbeddingModelRef as e, type EnvSchemas as f, type EnvServiceDatabase as g, type EnvTables as h, type EnvTypedTable as i, type PalbaseExtension as j, PolicyBuilder as k, type PolicyCommand as l, type PolicyDef as m, type PolicyMode as n, type RowShape as o, type TableDef as p, type TableHandle as q, type TableInput as r, type TxPlan as s, type TxTables as t, type TypedDB as u, type TypedTable as v, type TypedTx as w, bigint as x, boolean as y, defineSchema as z };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Buckets, BucketTypes } from './stack.js';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
3
|
import { C as CacheClient, P as PalbaseDocsClient, a as PalbaseFlagsClient, L as Logger, b as PalbaseNotificationsClient, c as PalbaseRealtimeClient, D as DBClient, S as SecretsService, d as PalbaseStorageClient, e as PalbaseBucketClient, f as DBOps, T as TxPlanBody, g as TxPlanResponse, A as AuthSpec } from './endpoint-DMwJjEHQ.js';
|
|
4
|
-
import { E as EnvTypedDatabase } from './index-
|
|
4
|
+
import { E as EnvTypedDatabase } from './index-B4CcpqLb.js';
|
|
5
5
|
import { R as RouteMeta } from './registry-B8pld3fj.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -32,8 +32,20 @@ interface ColumnDef {
|
|
|
32
32
|
selfRefColumn?: string;
|
|
33
33
|
/** This column OWNS the row: erasure, RLS and the `owner` relation read it. */
|
|
34
34
|
owns?: true;
|
|
35
|
-
/** Explicit
|
|
35
|
+
/** Explicit name for the FORWARD relation (child → parent), when the one
|
|
36
|
+
* derived from the column would be ambiguous or unclear. */
|
|
36
37
|
refAs?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Explicit name for the REVERSE relation (parent → children).
|
|
40
|
+
*
|
|
41
|
+
* Separate from {@link refAs} because the two directions are different facts:
|
|
42
|
+
* the forward name describes the parent this row points at (`author`), the
|
|
43
|
+
* reverse one describes the rows hanging off the parent (`posts`). One option
|
|
44
|
+
* naming both made an ordinary schema undeclarable — `posts.author_id` and
|
|
45
|
+
* `comments.author_id` both named `{ as: "author" }` collided on `users`, and
|
|
46
|
+
* the refusal asked for the `{ as }` they had both already written.
|
|
47
|
+
*/
|
|
48
|
+
reverseAs?: string;
|
|
37
49
|
/** The table this column belongs to; set by `defineTable`. */
|
|
38
50
|
ownerTable?: {
|
|
39
51
|
name: string;
|
|
@@ -197,9 +209,16 @@ declare class ColumnBuilder<K extends ColumnType = ColumnType, N extends boolean
|
|
|
197
209
|
* In a cycle, ONE side needs an explicit return type:
|
|
198
210
|
* `references((): AnyColumn => y.id)`. One side is enough — measured.
|
|
199
211
|
* For a self-reference use `selfReferences(column)`: no thunk, no annotation.
|
|
212
|
+
*
|
|
213
|
+
* `as` names the FORWARD relation (`author_id` → `author` by default);
|
|
214
|
+
* `reverseAs` names the REVERSE one on the parent, whose default is this
|
|
215
|
+
* table's own name (`users.posts`). Two foreign keys from one table onto one
|
|
216
|
+
* parent therefore need a `reverseAs` on at least one of them — the reverse
|
|
217
|
+
* names would otherwise both be this table's name.
|
|
200
218
|
*/
|
|
201
219
|
references(target: () => AnyColumn, opts?: {
|
|
202
220
|
as?: string;
|
|
221
|
+
reverseAs?: string;
|
|
203
222
|
onDelete?: OnDeleteAction;
|
|
204
223
|
}): ColumnBuilder<K, N, D, E, P, T>;
|
|
205
224
|
/**
|
|
@@ -489,7 +508,8 @@ declare const EXTENSION_DEPENDENCIES: Partial<Record<PalbaseExtension, PalbaseEx
|
|
|
489
508
|
declare function isPalbaseExtension(name: string): name is PalbaseExtension;
|
|
490
509
|
|
|
491
510
|
/**
|
|
492
|
-
* A named raw-SQL DDL object declared in db/
|
|
511
|
+
* A named raw-SQL DDL object declared in a schema file (`db/public.ts`,
|
|
512
|
+
* `db/billing.ts`, …) for anything the typed DSL
|
|
493
513
|
* cannot express (EXCLUDE, CHECK, partial/expression indexes, triggers, views).
|
|
494
514
|
* The deploy emits `up` verbatim on the privileged DDL connection — same trust
|
|
495
515
|
* posture as policy().using(). Tracked by NAME (not by diffing the body), so a
|
|
@@ -714,19 +734,6 @@ interface SchemaDef<T extends Record<string, TableDef> = Record<string, TableDef
|
|
|
714
734
|
/** Postgres extensions to install on deploy. Normalized to `[]` when absent. */
|
|
715
735
|
extensions: PalbaseExtension[];
|
|
716
736
|
}
|
|
717
|
-
/** The author-facing input to `defineSchema` — a `tables` map whose keys are
|
|
718
|
-
* the table names and whose values are `{ columns, rls?, policies? }`, plus an
|
|
719
|
-
* optional `extensions` allowlist. */
|
|
720
|
-
interface SchemaInput<T extends Record<string, TableInput> = Record<string, TableInput>> {
|
|
721
|
-
tables: T;
|
|
722
|
-
/**
|
|
723
|
-
* Postgres extensions to enable for this project, e.g. `["vector"]`.
|
|
724
|
-
* Config-as-code: installed by the deploy (CREATE EXTENSION … SCHEMA
|
|
725
|
-
* extensions) with the privileged deploy connection. The type is an
|
|
726
|
-
* allowlist union, so unsupported names fail typecheck.
|
|
727
|
-
*/
|
|
728
|
-
extensions?: PalbaseExtension[];
|
|
729
|
-
}
|
|
730
737
|
/** Map the author's `{ tables: { <name>: { columns } } }` input to the
|
|
731
738
|
* `{ tables: { <name>: TableDef<columns> } }` runtime/type shape, threading the
|
|
732
739
|
* per-table column map `T[K]["columns"]` so column-level inference survives. */
|
|
@@ -1212,4 +1219,4 @@ interface EnvTypedDatabase extends Omit<DBClient, "txPlan" | "asService"> {
|
|
|
1212
1219
|
asService(): EnvServiceDatabase;
|
|
1213
1220
|
}
|
|
1214
1221
|
|
|
1215
|
-
export { type AnyColumn as A,
|
|
1222
|
+
export { type AnyColumn as A, defineTable as B, ColumnBuilder as C, enumType as D, type EnvTypedDatabase as E, installationRef as F, integer as G, isPalbaseExtension as H, type InsertShape as I, jsonb as J, makeTypedDB as K, numeric as L, openai as M, ownedByUser as N, type OnDeleteAction as O, PALBASE_EXTENSIONS as P, policy as Q, type RawConstraintDef as R, type SchemaDef as S, TABLE_META as T, raw as U, text as V, timestamp as W, userRef as X, uuid as Y, vector as Z, type ColumnDef as a, type ColumnMap as b, type ColumnType as c, EXTENSION_DEPENDENCIES as d, type EmbeddingModelRef as e, type EnvSchemas as f, type EnvServiceDatabase as g, type EnvTables as h, type EnvTypedTable as i, type PalbaseExtension as j, PolicyBuilder as k, type PolicyCommand as l, type PolicyDef as m, type PolicyMode as n, type RowShape as o, type TableDef as p, type TableHandle as q, type TableInput as r, type TxPlan as s, type TxTables as t, type TypedDB as u, type TypedTable as v, type TypedTx as w, bigint as x, boolean as y, defineSchema as z };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Buckets, BucketTypes } from './stack.cjs';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
3
|
import { C as CacheClient, P as PalbaseDocsClient, a as PalbaseFlagsClient, L as Logger, b as PalbaseNotificationsClient, c as PalbaseRealtimeClient, D as DBClient, S as SecretsService, d as PalbaseStorageClient, e as PalbaseBucketClient, f as DBOps, T as TxPlanBody, g as TxPlanResponse, A as AuthSpec } from './endpoint-BSGw1pTu.cjs';
|
|
4
|
-
import { E as EnvTypedDatabase } from './index-
|
|
4
|
+
import { E as EnvTypedDatabase } from './index-DmVyY6N7.cjs';
|
|
5
5
|
import { R as RouteMeta } from './registry-CgJvDYUW.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -1965,9 +1965,16 @@ function defineTable(name, input) {
|
|
|
1965
1965
|
}
|
|
1966
1966
|
const policies = (input.policies ?? []).map(toPolicyDef);
|
|
1967
1967
|
const rls = policies.length > 0 || input.rls !== false;
|
|
1968
|
+
const owned = {};
|
|
1969
|
+
for (const [colName, b] of Object.entries(input.columns)) {
|
|
1970
|
+
const builder = b;
|
|
1971
|
+
const clone = Object.create(Object.getPrototypeOf(builder));
|
|
1972
|
+
Object.defineProperty(clone, "_def", { value: { ...builder._def }, enumerable: true, writable: true });
|
|
1973
|
+
owned[colName] = clone;
|
|
1974
|
+
}
|
|
1968
1975
|
const def = {
|
|
1969
1976
|
name,
|
|
1970
|
-
columns:
|
|
1977
|
+
columns: owned,
|
|
1971
1978
|
rls,
|
|
1972
1979
|
policies
|
|
1973
1980
|
};
|
|
@@ -2025,10 +2032,10 @@ function defineTable(name, input) {
|
|
|
2025
2032
|
}
|
|
2026
2033
|
def.memory = input.memory;
|
|
2027
2034
|
}
|
|
2028
|
-
for (const b of Object.values(
|
|
2035
|
+
for (const b of Object.values(owned)) {
|
|
2029
2036
|
b._def.ownerTable = def;
|
|
2030
2037
|
}
|
|
2031
|
-
const handle = { ...
|
|
2038
|
+
const handle = { ...owned };
|
|
2032
2039
|
Object.defineProperty(handle, TABLE_META, { value: def, enumerable: false });
|
|
2033
2040
|
return handle;
|
|
2034
2041
|
}
|
|
@@ -2345,6 +2352,12 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
2345
2352
|
* In a cycle, ONE side needs an explicit return type:
|
|
2346
2353
|
* `references((): AnyColumn => y.id)`. One side is enough — measured.
|
|
2347
2354
|
* For a self-reference use `selfReferences(column)`: no thunk, no annotation.
|
|
2355
|
+
*
|
|
2356
|
+
* `as` names the FORWARD relation (`author_id` → `author` by default);
|
|
2357
|
+
* `reverseAs` names the REVERSE one on the parent, whose default is this
|
|
2358
|
+
* table's own name (`users.posts`). Two foreign keys from one table onto one
|
|
2359
|
+
* parent therefore need a `reverseAs` on at least one of them — the reverse
|
|
2360
|
+
* names would otherwise both be this table's name.
|
|
2348
2361
|
*/
|
|
2349
2362
|
references(target, opts) {
|
|
2350
2363
|
refuseOnVector(this._def, "references");
|
|
@@ -2355,6 +2368,7 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
2355
2368
|
}
|
|
2356
2369
|
this._def.referencesThunk = target;
|
|
2357
2370
|
if (opts?.as !== void 0) this._def.refAs = opts.as;
|
|
2371
|
+
if (opts?.reverseAs !== void 0) this._def.reverseAs = opts.reverseAs;
|
|
2358
2372
|
if (opts?.onDelete !== void 0) this._def.onDeleteAction = opts.onDelete;
|
|
2359
2373
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
2360
2374
|
}
|
|
@@ -2581,64 +2595,73 @@ function optionalOnInsert(def) {
|
|
|
2581
2595
|
function forwardName(column) {
|
|
2582
2596
|
return column.endsWith("_id") ? column.slice(0, -3) : column;
|
|
2583
2597
|
}
|
|
2584
|
-
function
|
|
2585
|
-
return
|
|
2598
|
+
function describeOrigin(o) {
|
|
2599
|
+
return o.direction === "forward" ? `the foreign key "${o.table}.${o.column}"` : `the reverse of "${o.table}.${o.column}"`;
|
|
2600
|
+
}
|
|
2601
|
+
function renameCall(o) {
|
|
2602
|
+
if (o.direction === "reverse") return `references(() => \u2026, { reverseAs: "\u2026" })`;
|
|
2603
|
+
if (o.def.owns === true) {
|
|
2604
|
+
return `ownedByUser() takes no { as } \u2014 if "${o.column}" only POINTS at a user, declare it userRef({ onDelete: \u2026 }) instead`;
|
|
2605
|
+
}
|
|
2606
|
+
const target = o.def.references?.table;
|
|
2607
|
+
if (target === "auth.users") return `userRef({ onDelete: \u2026, as: "\u2026" })`;
|
|
2608
|
+
if (target === "auth.installations") return `installationRef({ onDelete: \u2026, as: "\u2026" })`;
|
|
2609
|
+
if (o.def.selfRefColumn !== void 0) return `selfReferences("\u2026", { as: "\u2026" })`;
|
|
2610
|
+
return `references(() => \u2026, { as: "\u2026" })`;
|
|
2586
2611
|
}
|
|
2587
2612
|
function buildRelations(schemas) {
|
|
2588
2613
|
const out = /* @__PURE__ */ new Map();
|
|
2589
|
-
const
|
|
2614
|
+
const taken = /* @__PURE__ */ new Map();
|
|
2590
2615
|
for (const schema of schemas) {
|
|
2591
2616
|
for (const t of Object.values(schema.tables)) {
|
|
2592
|
-
const key =
|
|
2617
|
+
const key = qualifiedTableKey(schema.name, t.name);
|
|
2593
2618
|
out.set(key, []);
|
|
2594
|
-
|
|
2619
|
+
taken.set(key, /* @__PURE__ */ new Map());
|
|
2595
2620
|
}
|
|
2596
2621
|
}
|
|
2622
|
+
const claim = (tableKey, name, origin, edge) => {
|
|
2623
|
+
const names = taken.get(tableKey);
|
|
2624
|
+
if (names === void 0) return;
|
|
2625
|
+
const held = names.get(name);
|
|
2626
|
+
if (held !== void 0) {
|
|
2627
|
+
if (held.def.owns === true && origin.def.owns === true) {
|
|
2628
|
+
throw new Error(
|
|
2629
|
+
`table "${tableKey}" declares TWO owner columns (${held.column}, ${origin.column}) \u2014 a table has at most ONE ownedByUser(). If the other column only POINTS at a user, declare it userRef({ onDelete: \u2026 }) instead.`
|
|
2630
|
+
);
|
|
2631
|
+
}
|
|
2632
|
+
const heldFix = renameCall(held);
|
|
2633
|
+
const originFix = renameCall(origin);
|
|
2634
|
+
const remedy = heldFix === originFix ? `rename one of them: ${heldFix}` : `rename one of them \u2014 "${held.table}.${held.column}": ${heldFix}; "${origin.table}.${origin.column}": ${originFix}`;
|
|
2635
|
+
throw new Error(
|
|
2636
|
+
`table "${tableKey}": ${describeOrigin(held)} and ${describeOrigin(origin)} both resolve to the relation name "${name}" \u2014 ${remedy}.`
|
|
2637
|
+
);
|
|
2638
|
+
}
|
|
2639
|
+
names.set(name, origin);
|
|
2640
|
+
out.get(tableKey)?.push(edge);
|
|
2641
|
+
};
|
|
2597
2642
|
for (const schema of schemas) {
|
|
2598
2643
|
for (const table of Object.values(schema.tables)) {
|
|
2599
|
-
const childKey =
|
|
2600
|
-
|
|
2601
|
-
if (bucket === void 0) continue;
|
|
2602
|
-
const byTarget = /* @__PURE__ */ new Map();
|
|
2603
|
-
for (const [col, builder] of Object.entries(table.columns)) {
|
|
2604
|
-
const ref = builder._def.references;
|
|
2605
|
-
if (ref === void 0) continue;
|
|
2606
|
-
const list = byTarget.get(ref.table) ?? [];
|
|
2607
|
-
list.push(col);
|
|
2608
|
-
byTarget.set(ref.table, list);
|
|
2609
|
-
}
|
|
2610
|
-
for (const [target, cols] of byTarget) {
|
|
2611
|
-
if (cols.length < 2) continue;
|
|
2612
|
-
const unnamed = cols.filter((c) => {
|
|
2613
|
-
const d = table.columns[c]?._def;
|
|
2614
|
-
return d?.refAs === void 0 && d?.owns !== true;
|
|
2615
|
-
});
|
|
2616
|
-
if (unnamed.length > 0) {
|
|
2617
|
-
throw new Error(
|
|
2618
|
-
`table "${table.name}" declares ${cols.length} foreign keys onto "${target}" (${cols.join(", ")}) \u2014 name each one: references(() => \u2026, { as: "\u2026" })`
|
|
2619
|
-
);
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2644
|
+
const childKey = qualifiedTableKey(schema.name, table.name);
|
|
2645
|
+
if (!out.has(childKey)) continue;
|
|
2622
2646
|
for (const [col, builder] of Object.entries(table.columns)) {
|
|
2623
2647
|
const def = builder._def;
|
|
2624
2648
|
if (def.references === void 0) continue;
|
|
2649
|
+
const targetKey = def.references.table;
|
|
2625
2650
|
const name = def.owns === true ? "owner" : def.refAs ?? forwardName(col);
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
const
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
}
|
|
2641
|
-
parent.push({ name: reverse, to: childKey, kind: "many", via: col });
|
|
2651
|
+
claim(
|
|
2652
|
+
childKey,
|
|
2653
|
+
name,
|
|
2654
|
+
{ table: table.name, column: col, direction: "forward", def },
|
|
2655
|
+
{ name, to: targetKey, kind: "one", via: col }
|
|
2656
|
+
);
|
|
2657
|
+
if (!out.has(targetKey) || targetKey === childKey) continue;
|
|
2658
|
+
const reverse = def.reverseAs ?? table.name;
|
|
2659
|
+
claim(
|
|
2660
|
+
targetKey,
|
|
2661
|
+
reverse,
|
|
2662
|
+
{ table: table.name, column: col, direction: "reverse", def },
|
|
2663
|
+
{ name: reverse, to: childKey, kind: "many", via: col }
|
|
2664
|
+
);
|
|
2642
2665
|
}
|
|
2643
2666
|
}
|
|
2644
2667
|
}
|
|
@@ -2675,7 +2698,6 @@ function tableBlock(table, relations, indent) {
|
|
|
2675
2698
|
}
|
|
2676
2699
|
function makeEnvDts(schemas) {
|
|
2677
2700
|
const relations = buildRelations(schemas);
|
|
2678
|
-
const qualify2 = (schemaName, table) => schemaName === "public" ? table : `${schemaName}.${table}`;
|
|
2679
2701
|
const publicSchema = schemas.find((s) => s.name === "public");
|
|
2680
2702
|
const others = schemas.filter((s) => s.name !== "public");
|
|
2681
2703
|
const publicBlocks = Object.keys(publicSchema?.tables ?? {}).map(
|
|
@@ -2686,7 +2708,7 @@ ${publicBlocks.join("\n")}
|
|
|
2686
2708
|
` : "";
|
|
2687
2709
|
const schemaBlocks = others.map((schema) => {
|
|
2688
2710
|
const inner = Object.keys(schema.tables).map(
|
|
2689
|
-
(name) => tableBlock(schema.tables[name], relations.get(
|
|
2711
|
+
(name) => tableBlock(schema.tables[name], relations.get(qualifiedTableKey(schema.name, name)) ?? [], " ")
|
|
2690
2712
|
);
|
|
2691
2713
|
return ` ${schema.name}: {
|
|
2692
2714
|
${inner.join("\n")}
|
|
@@ -2880,6 +2902,10 @@ function recordRoom(ctor, meta) {
|
|
|
2880
2902
|
const carrier = carrierOf(ctor);
|
|
2881
2903
|
const buffer = ownRoomBuffer(carrier);
|
|
2882
2904
|
carrier[ROOM] = { ...meta, hooks: buffer.hooks, messages: buffer.messages };
|
|
2905
|
+
const g = globalThis;
|
|
2906
|
+
const REGISTRY2 = /* @__PURE__ */ Symbol.for("palbase.backend.allControllers");
|
|
2907
|
+
const all = g[REGISTRY2] ??= [];
|
|
2908
|
+
if (!all.includes(ctor)) all.push(ctor);
|
|
2883
2909
|
}
|
|
2884
2910
|
|
|
2885
2911
|
// src/decorators/controller.ts
|