@palbase/backend 33.0.2 → 34.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/palbase-backend.cjs +2020 -350
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +9 -7
- package/dist/bin/palbase-backend.js.map +1 -1
- package/dist/{chunk-SI4KGEM3.js → chunk-FOWA7PF4.js} +97 -96
- package/dist/chunk-FOWA7PF4.js.map +1 -0
- package/dist/chunk-GHNC2UHS.js +20 -0
- package/dist/chunk-GHNC2UHS.js.map +1 -0
- package/dist/{chunk-AAT5G7KY.js → chunk-JJW3L62T.js} +2 -2
- package/dist/chunk-JJW3L62T.js.map +1 -0
- package/dist/{chunk-TVCCR6SO.js → chunk-LOGL2ZHD.js} +58 -9
- package/dist/chunk-LOGL2ZHD.js.map +1 -0
- package/dist/{chunk-C6COAB3E.js → chunk-MNGZE2MM.js} +1651 -186
- package/dist/chunk-MNGZE2MM.js.map +1 -0
- package/dist/{chunk-XOX6RFPZ.js → chunk-PRH45NZU.js} +46 -3
- package/dist/chunk-PRH45NZU.js.map +1 -0
- package/dist/{chunk-26GH54D2.js → chunk-RZLY4BOY.js} +5 -3
- package/dist/{chunk-26GH54D2.js.map → chunk-RZLY4BOY.js.map} +1 -1
- package/dist/{chunk-YIQ4RS4F.js → chunk-SEM36BWY.js} +283 -5
- package/dist/chunk-SEM36BWY.js.map +1 -0
- package/dist/{chunk-KATPXCJ5.js → chunk-UMESJJRS.js} +19 -40
- package/dist/chunk-UMESJJRS.js.map +1 -0
- package/dist/chunk-VXPNPVAG.js +40 -0
- package/dist/chunk-VXPNPVAG.js.map +1 -0
- package/dist/{chunk-WWUG2QXF.js → chunk-YX7UA7VC.js} +53 -4
- package/dist/chunk-YX7UA7VC.js.map +1 -0
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +2 -0
- package/dist/db/env.d.ts +2 -0
- package/dist/db/index.cjs +261 -2
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +46 -3
- package/dist/db/index.d.ts +46 -3
- package/dist/db/index.js +14 -5
- package/dist/{index-DMZG3kpo.d.ts → endpoint-DpNUx-ON.d.ts} +315 -57
- package/dist/{index-DB_nW-AV.d.cts → endpoint-kYgEHrrV.d.cts} +315 -57
- package/dist/engine/index.cjs +2026 -348
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +5 -5
- package/dist/engine/index.d.ts +5 -5
- package/dist/engine/index.js +17 -7
- package/dist/{index-D-3duy8Y.d.ts → index-JrHqNsjQ.d.ts} +108 -50
- package/dist/{index-DLveQoOf.d.cts → index-pnDsEfxJ.d.cts} +108 -50
- package/dist/index.cjs +616 -254
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +25 -15
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +7 -0
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +3 -3
- package/dist/openapi/index.d.ts +3 -3
- package/dist/openapi/index.js +4 -3
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-DSTThhKf.d.cts → registry-BcOd8Zhf.d.cts} +3 -1
- package/dist/{registry-JjF5lcj4.d.ts → registry-BoX5iNyY.d.ts} +3 -1
- package/dist/test/index.cjs +103 -66
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +3 -3
- package/dist/test/index.d.ts +3 -3
- package/dist/test/index.js +33 -7
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +308 -0
- package/docs/examples/check-query-contracts.ts +5 -0
- package/docs/examples/database-dx.contract.json +65 -0
- package/docs/examples/database-dx.ts +63 -0
- package/docs/examples/money-transfer.ts +73 -0
- package/docs/llms-full.txt +309 -1
- package/package.json +1 -2
- package/template/package.json +1 -1
- package/dist/chunk-AAT5G7KY.js.map +0 -1
- package/dist/chunk-C6COAB3E.js.map +0 -1
- package/dist/chunk-KATPXCJ5.js.map +0 -1
- package/dist/chunk-SI4KGEM3.js.map +0 -1
- package/dist/chunk-TVCCR6SO.js.map +0 -1
- package/dist/chunk-WWUG2QXF.js.map +0 -1
- package/dist/chunk-XOX6RFPZ.js.map +0 -1
- package/dist/chunk-YIQ4RS4F.js.map +0 -1
- package/stack-images.json +0 -24
package/dist/engine/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import '../
|
|
2
|
-
export { A as App, g as AuthVerifier, B as BootRefused, h as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy,
|
|
3
|
-
import '../db/env.cjs';
|
|
4
|
-
import '../stack.cjs';
|
|
1
|
+
import '../endpoint-kYgEHrrV.cjs';
|
|
2
|
+
export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-pnDsEfxJ.cjs';
|
|
5
3
|
import 'zod';
|
|
4
|
+
import '../stack.cjs';
|
|
5
|
+
import '../db/env.cjs';
|
|
6
6
|
import 'node:async_hooks';
|
|
7
7
|
import '../module-Dl1KFVtc.cjs';
|
|
8
|
-
import '../registry-
|
|
8
|
+
import '../registry-BcOd8Zhf.cjs';
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import '../
|
|
2
|
-
export { A as App, g as AuthVerifier, B as BootRefused, h as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy,
|
|
3
|
-
import '../db/env.js';
|
|
4
|
-
import '../stack.js';
|
|
1
|
+
import '../endpoint-DpNUx-ON.js';
|
|
2
|
+
export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-JrHqNsjQ.js';
|
|
5
3
|
import 'zod';
|
|
4
|
+
import '../stack.js';
|
|
5
|
+
import '../db/env.js';
|
|
6
6
|
import 'node:async_hooks';
|
|
7
7
|
import '../module-Dl1KFVtc.js';
|
|
8
|
-
import '../registry-
|
|
8
|
+
import '../registry-BoX5iNyY.js';
|
package/dist/engine/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthVerifier,
|
|
3
3
|
BootRefused,
|
|
4
|
+
COMMAND_EXECUTOR_DDL,
|
|
4
5
|
RateLimiter,
|
|
5
6
|
buildRouteTable,
|
|
6
7
|
createApp,
|
|
@@ -9,27 +10,33 @@ import {
|
|
|
9
10
|
createRequestDatabase,
|
|
10
11
|
effectiveAuth,
|
|
11
12
|
hostAllowed,
|
|
13
|
+
installCommandExecutor,
|
|
12
14
|
installEgressFence,
|
|
13
15
|
loadConfig,
|
|
14
16
|
makeMemoryCache,
|
|
15
17
|
matchRoute,
|
|
16
18
|
quoteIdent,
|
|
17
19
|
scrubSecrets,
|
|
20
|
+
setCursorKey,
|
|
21
|
+
withQueryCancellation,
|
|
18
22
|
withTables
|
|
19
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-MNGZE2MM.js";
|
|
20
24
|
import {
|
|
21
25
|
DECLARATION_REFUSAL,
|
|
22
26
|
DeclarationRefused,
|
|
23
27
|
isDeclarationRefused
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
28
|
+
} from "../chunk-YX7UA7VC.js";
|
|
29
|
+
import "../chunk-GHNC2UHS.js";
|
|
30
|
+
import "../chunk-LOGL2ZHD.js";
|
|
31
|
+
import "../chunk-PRH45NZU.js";
|
|
32
|
+
import "../chunk-FOWA7PF4.js";
|
|
33
|
+
import "../chunk-JJW3L62T.js";
|
|
34
|
+
import "../chunk-UMESJJRS.js";
|
|
35
|
+
import "../chunk-VXPNPVAG.js";
|
|
30
36
|
export {
|
|
31
37
|
AuthVerifier,
|
|
32
38
|
BootRefused,
|
|
39
|
+
COMMAND_EXECUTOR_DDL,
|
|
33
40
|
DECLARATION_REFUSAL,
|
|
34
41
|
DeclarationRefused,
|
|
35
42
|
RateLimiter,
|
|
@@ -40,6 +47,7 @@ export {
|
|
|
40
47
|
createRequestDatabase,
|
|
41
48
|
effectiveAuth,
|
|
42
49
|
hostAllowed,
|
|
50
|
+
installCommandExecutor,
|
|
43
51
|
installEgressFence,
|
|
44
52
|
isDeclarationRefused,
|
|
45
53
|
loadConfig,
|
|
@@ -47,6 +55,8 @@ export {
|
|
|
47
55
|
matchRoute,
|
|
48
56
|
quoteIdent,
|
|
49
57
|
scrubSecrets,
|
|
58
|
+
setCursorKey,
|
|
59
|
+
withQueryCancellation,
|
|
50
60
|
withTables
|
|
51
61
|
};
|
|
52
62
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, P as PreparedRead, C as CompiledRead, f as RawPageOptions, g as Page, h as TxPlanBody, i as CommandOptions, j as TxPlanResponse, A as AuthSpec, k as CacheClient, b as RuntimeServices, _ as __runWithRuntime, l as __requestALS } from './endpoint-DpNUx-ON.js';
|
|
2
2
|
import { T as Token } from './module-Dl1KFVtc.js';
|
|
3
|
-
import { R as RouteMeta } from './registry-
|
|
3
|
+
import { R as RouteMeta } from './registry-BoX5iNyY.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* engine/config.ts — settings from the environment, and the gate that refuses
|
|
@@ -47,6 +47,11 @@ interface EngineConfig {
|
|
|
47
47
|
anonKey: string;
|
|
48
48
|
/** Secret key. Used for privileged module calls. */
|
|
49
49
|
serviceRoleKey: string;
|
|
50
|
+
/** Optional dedicated cursor encryption secret, shared by all replicas. */
|
|
51
|
+
cursorSecret?: string;
|
|
52
|
+
/** Install the invoker-only PostgreSQL command helper at boot. Requires DDL
|
|
53
|
+
* rights on the connection role; execution retains each request's RLS role. */
|
|
54
|
+
enableCommands?: boolean;
|
|
50
55
|
/** HMAC the realtime broadcast token is signed with. Empty ⇒ broadcast
|
|
51
56
|
* returns a clear `realtime_unconfigured` error instead of failing silently. */
|
|
52
57
|
realtimeSecret: string;
|
|
@@ -65,6 +70,7 @@ interface EngineConfig {
|
|
|
65
70
|
*/
|
|
66
71
|
dbServiceRole: string;
|
|
67
72
|
poolMax: number;
|
|
73
|
+
databaseDiagnostics?: DatabaseDiagnosticsOptions;
|
|
68
74
|
}
|
|
69
75
|
/**
|
|
70
76
|
* THE ENVIRONMENT THIS STACK WAS HANDED IS UNUSABLE. Carries the missing names.
|
|
@@ -87,42 +93,62 @@ declare class BootRefused extends Error {
|
|
|
87
93
|
*/
|
|
88
94
|
declare function loadConfig(env: Record<string, string | undefined>): EngineConfig;
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*
|
|
121
|
-
|
|
122
|
-
|
|
96
|
+
type CancellableQuery = Promise<unknown> & {
|
|
97
|
+
cancel?: () => unknown;
|
|
98
|
+
};
|
|
99
|
+
/** Abort callback work and active statements, then let the transaction owner
|
|
100
|
+
* await rollback. COMMIT is never raced with a timer: its acknowledged result
|
|
101
|
+
* or connection failure remains authoritative. */
|
|
102
|
+
declare class TransactionControl {
|
|
103
|
+
private controller;
|
|
104
|
+
private active;
|
|
105
|
+
private cancelBackend?;
|
|
106
|
+
private cancellation;
|
|
107
|
+
private timer?;
|
|
108
|
+
private unlink;
|
|
109
|
+
private rejection;
|
|
110
|
+
readonly deadline: number | undefined;
|
|
111
|
+
get signal(): AbortSignal;
|
|
112
|
+
constructor(timeoutMs?: number, external?: AbortSignal);
|
|
113
|
+
check(): void;
|
|
114
|
+
remainingMs(): number | undefined;
|
|
115
|
+
race<T>(work: Promise<T>): Promise<T>;
|
|
116
|
+
bindBackend(cancel: () => Promise<void>): void;
|
|
117
|
+
/** Keep the application's connection parked until the cancellation request
|
|
118
|
+
* and all statements settle; a late cancel must not hit its next borrower. */
|
|
119
|
+
drainCancellation(): Promise<void>;
|
|
120
|
+
watch(query: CancellableQuery): Promise<unknown>;
|
|
121
|
+
dispose(): void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type Timing = "queueMs" | "poolMs" | "setupMs" | "sqlMs" | "commitMs" | "rollbackMs";
|
|
125
|
+
/** Allocated only when diagnostics or a budget is configured. One collector
|
|
126
|
+
* follows the request's user/service handles and independent atomic attempts. */
|
|
127
|
+
declare class DatabaseTrace {
|
|
128
|
+
private readonly options;
|
|
129
|
+
private readonly start;
|
|
130
|
+
private ended?;
|
|
131
|
+
private failure?;
|
|
132
|
+
private readonly state;
|
|
133
|
+
constructor(options: DatabaseDiagnosticsOptions);
|
|
134
|
+
check(): void;
|
|
135
|
+
time(key: Timing, started: number): void;
|
|
136
|
+
retry(): void;
|
|
137
|
+
committed(): void;
|
|
138
|
+
commitFailed(): void;
|
|
139
|
+
failed(): void;
|
|
140
|
+
rolledBack(): void;
|
|
141
|
+
private refuse;
|
|
142
|
+
private emit;
|
|
143
|
+
query(sql: string, name: string | undefined, run: () => Promise<unknown>): Promise<unknown>;
|
|
144
|
+
get snapshot(): DatabaseDiagnostics;
|
|
145
|
+
complete(outcome: "committed" | "failed"): void;
|
|
146
|
+
}
|
|
123
147
|
|
|
124
148
|
/** The slice of a SQL driver the engine uses. `Bun.sql` satisfies it. */
|
|
125
149
|
interface SqlDriver {
|
|
150
|
+
/** Optional reliable cancellation through a separate control connection. */
|
|
151
|
+
cancelBackend?(pid: number, startedAt: string): Promise<void>;
|
|
126
152
|
/** Run a parameterised statement. */
|
|
127
153
|
unsafe(sql: string, params?: unknown[]): Promise<unknown>;
|
|
128
154
|
/** Open a transaction; the driver commits when `cb` resolves and rolls back
|
|
@@ -130,7 +156,9 @@ interface SqlDriver {
|
|
|
130
156
|
begin<T>(cb: (tx: SqlTx) => Promise<T>): Promise<T>;
|
|
131
157
|
}
|
|
132
158
|
interface SqlTx {
|
|
133
|
-
unsafe(sql: string, params?: unknown[]
|
|
159
|
+
unsafe(sql: string, params?: unknown[], metadata?: {
|
|
160
|
+
name?: string;
|
|
161
|
+
}): Promise<unknown>;
|
|
134
162
|
savepoint<T>(cb: (sp: SqlTx) => Promise<T>): Promise<T>;
|
|
135
163
|
}
|
|
136
164
|
type Row = Record<string, unknown>;
|
|
@@ -147,6 +175,12 @@ declare function quoteIdent(name: string): string;
|
|
|
147
175
|
*/
|
|
148
176
|
declare function createLazyTransaction(sql: SqlDriver, role: string, claimsJson: string, options?: {
|
|
149
177
|
lockTimeout?: string;
|
|
178
|
+
statementTimeout?: string;
|
|
179
|
+
isolation?: TransactionIsolation;
|
|
180
|
+
readOnly?: boolean;
|
|
181
|
+
scope?: symbol;
|
|
182
|
+
control?: TransactionControl;
|
|
183
|
+
trace?: DatabaseTrace;
|
|
150
184
|
}): {
|
|
151
185
|
ensure: () => Promise<SqlTx>;
|
|
152
186
|
readonly opened: boolean;
|
|
@@ -186,7 +220,13 @@ interface FindManyOptions {
|
|
|
186
220
|
* refused without it — see `offsetClause`. */
|
|
187
221
|
offset?: number;
|
|
188
222
|
}
|
|
189
|
-
|
|
223
|
+
interface OpsContext {
|
|
224
|
+
readonly cursorScope?: string;
|
|
225
|
+
readonly commands?: boolean;
|
|
226
|
+
readonly trace?: DatabaseTrace;
|
|
227
|
+
}
|
|
228
|
+
declare function createOps(tx: TxLike, context?: OpsContext): {
|
|
229
|
+
diagnostics(): DatabaseDiagnostics | null;
|
|
190
230
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
191
231
|
insert(table: string, data: Row): Promise<Row>;
|
|
192
232
|
/**
|
|
@@ -203,10 +243,7 @@ declare function createOps(tx: TxLike): {
|
|
|
203
243
|
* bir satırın fazla kolonu SESSİZCE YAZILMAZDI. Eksik kolon için `null`
|
|
204
244
|
* yazın ya da varsayılanı istiyorsanız o satırları ayrı çağrıda ekleyin.
|
|
205
245
|
*/
|
|
206
|
-
insertMany
|
|
207
|
-
onConflict: readonly string[];
|
|
208
|
-
action?: "ignore" | "update";
|
|
209
|
-
}): Promise<Row[]>;
|
|
246
|
+
insertMany: DBOps["insertMany"];
|
|
210
247
|
/**
|
|
211
248
|
* Bir ADI kilitle — satırı değil (FR-054).
|
|
212
249
|
*
|
|
@@ -338,8 +375,16 @@ declare function createOps(tx: TxLike): {
|
|
|
338
375
|
groupBy?: readonly string[];
|
|
339
376
|
}): Promise<Record<string, unknown> | Record<string, unknown>[]>;
|
|
340
377
|
count(table: string, where?: Row): Promise<number>;
|
|
378
|
+
findUnique(table: string, where: Row, opts?: {
|
|
379
|
+
select?: readonly string[];
|
|
380
|
+
with?: Record<string, unknown>;
|
|
381
|
+
}): Promise<Row | null>;
|
|
341
382
|
findById(table: string, id: string): Promise<Row | null>;
|
|
383
|
+
compileQuery(query: PreparedRead): CompiledRead;
|
|
384
|
+
readQuery(query: PreparedRead): Promise<Row[]>;
|
|
385
|
+
explainQuery(query: PreparedRead): Promise<unknown[]>;
|
|
342
386
|
findMany(table: string, query?: Row, opts?: FindManyOptions): Promise<Row[]>;
|
|
387
|
+
page(table: string, query?: Row, opts?: RawPageOptions): Promise<Page<Row>>;
|
|
343
388
|
/**
|
|
344
389
|
* Tek-SQL hibrit arama (FR-014): iki kol CTE + FULL OUTER JOIN + RRF
|
|
345
390
|
* (1/(50+rank), CLAIM-N4). Operatör şema-nitelikli (C-10, M-1); GUC
|
|
@@ -495,15 +540,9 @@ declare function createOps(tx: TxLike): {
|
|
|
495
540
|
* "transport.txPlan is not a function" while every test that covered
|
|
496
541
|
* transactions passed against a mock that did implement it.
|
|
497
542
|
*/
|
|
543
|
+
command(plan: TxPlanBody, options?: CommandOptions): Promise<TxPlanResponse>;
|
|
498
544
|
txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;
|
|
499
545
|
};
|
|
500
|
-
/**
|
|
501
|
-
* Merge the typed `.tables` accessor onto a raw op surface.
|
|
502
|
-
*
|
|
503
|
-
* Mirrors what the pod runtime does, including the recursive application to the
|
|
504
|
-
* transaction callback: without it `tx.tables.rooms.insert(...)` throws
|
|
505
|
-
* "Cannot read properties of undefined".
|
|
506
|
-
*/
|
|
507
546
|
declare function withTables<T extends ReturnType<typeof createOps>>(ops: T, schema?: {
|
|
508
547
|
tables?: Record<string, {
|
|
509
548
|
name?: string;
|
|
@@ -580,7 +619,7 @@ declare function createRequestDatabase(sql: SqlDriver, identity: {
|
|
|
580
619
|
role: string;
|
|
581
620
|
serviceRole: string;
|
|
582
621
|
claimsJson: string;
|
|
583
|
-
}): RequestDatabase;
|
|
622
|
+
}, diagnostics?: DatabaseDiagnosticsOptions): RequestDatabase;
|
|
584
623
|
|
|
585
624
|
/**
|
|
586
625
|
* The two ways a stack refuses to boot — and they are two because their CURES
|
|
@@ -926,6 +965,25 @@ interface MemoryCacheOptions {
|
|
|
926
965
|
*/
|
|
927
966
|
declare function makeMemoryCache(opts?: MemoryCacheOptions): CacheClient;
|
|
928
967
|
|
|
968
|
+
/** One application secret shared by replicas. Rotation invalidates old cursors.
|
|
969
|
+
* Encryption also hides sort values omitted by the public projection. */
|
|
970
|
+
declare function setCursorKey(secret: string | null): void;
|
|
971
|
+
|
|
972
|
+
/** Statements remain sequential inside PostgreSQL. Each sees preceding writes,
|
|
973
|
+
* including triggers, unlike sibling data-modifying CTEs in one SQL statement.
|
|
974
|
+
* The exception block is a subtransaction, matching a savepoint plan. */
|
|
975
|
+
declare const COMMAND_EXECUTOR_DDL = "\nCREATE SCHEMA IF NOT EXISTS palbase_runtime;\nCREATE OR REPLACE FUNCTION palbase_runtime.command_v1(steps jsonb) RETURNS jsonb\nLANGUAGE plpgsql VOLATILE SECURITY INVOKER SET search_path = pg_catalog, public AS $pb_command$\nDECLARE\n results jsonb := '[]'::jsonb;\n step jsonb; chunk jsonb; binding jsonb; source jsonb; rows jsonb;\n statement text; rendered text; detail text; guard jsonb;\n index integer := 0; affected integer; passed boolean;\nBEGIN\n FOR step IN SELECT value FROM jsonb_array_elements(steps) LOOP\n IF step->>'empty' = 'true' THEN rows := '[]'::jsonb;\n ELSE\n statement := '';\n FOR chunk IN SELECT value FROM jsonb_array_elements(step->'chunks') LOOP\n IF jsonb_typeof(chunk) = 'string' THEN statement := statement || (chunk #>> '{}');\n ELSE\n binding := step->'bindings'->((chunk->>'bind')::integer);\n IF binding ? 'ref' THEN\n source := results->((binding->'ref'->>'op')::integer)->'rows'->0;\n IF source IS NULL OR NOT source ? (binding->'ref'->>'field') THEN\n RAISE EXCEPTION 'Command reference has no source row/column; use expectOne before reading it'\n USING ERRCODE = 'PBC02', DETAIL = jsonb_build_object('error_code','tx_ref_unresolved','op',index)::text;\n END IF;\n source := source->(binding->'ref'->>'field');\n ELSE source := binding->'value'; END IF;\n rendered := CASE WHEN source IS NULL OR source = 'null'::jsonb THEN NULL\n WHEN binding->>'json' = 'true' THEN source::text\n WHEN jsonb_typeof(source) = 'string' THEN source #>> '{}' ELSE source::text END;\n -- PostgreSQL quotes the value itself. Values reach this function as\n -- one bound JSON parameter, never as application-generated SQL text.\n statement := statement || quote_nullable(rendered);\n END IF;\n END LOOP;\n EXECUTE statement INTO rows;\n END IF;\n affected := jsonb_array_length(rows);\n guard := step->'guard';\n IF guard IS NOT NULL AND guard <> 'null'::jsonb THEN\n passed := CASE guard->>'kind'\n WHEN 'one' THEN affected = 1 WHEN 'none' THEN affected = 0\n WHEN 'atLeast' THEN affected >= (guard->>'n')::integer\n WHEN 'atMost' THEN affected <= (guard->>'n')::integer ELSE false END;\n IF NOT passed THEN\n RAISE EXCEPTION 'Command expectation failed'\n USING ERRCODE = 'PBC01', DETAIL = jsonb_build_object('error_code','tx_guard_failed','slot',guard->'slot','op',index)::text;\n END IF;\n END IF;\n results := results || jsonb_build_array(jsonb_build_object('rows',rows,'rows_affected',affected));\n index := index + 1;\n END LOOP;\n RETURN jsonb_build_object('results',results);\nEXCEPTION WHEN SQLSTATE 'PBC01' OR SQLSTATE 'PBC02' THEN\n GET STACKED DIAGNOSTICS detail = PG_EXCEPTION_DETAIL;\n RETURN jsonb_build_object('error',detail::jsonb);\nEND\n$pb_command$;\nREVOKE ALL ON FUNCTION palbase_runtime.command_v1(jsonb) FROM PUBLIC;\nCREATE OR REPLACE FUNCTION palbase_runtime.command_rows_v1(rows jsonb, guard jsonb) RETURNS jsonb\nLANGUAGE plpgsql VOLATILE SECURITY INVOKER SET search_path = pg_catalog, public AS $pb_rows$\nDECLARE affected integer := jsonb_array_length(rows); passed boolean;\nBEGIN\n IF guard IS NOT NULL AND guard <> 'null'::jsonb THEN\n passed := CASE guard->>'kind'\n WHEN 'one' THEN affected = 1 WHEN 'none' THEN affected = 0\n WHEN 'atLeast' THEN affected >= (guard->>'n')::integer\n WHEN 'atMost' THEN affected <= (guard->>'n')::integer ELSE false END;\n IF NOT passed THEN\n RAISE EXCEPTION 'Command expectation failed'\n USING ERRCODE = 'PBC01', DETAIL = jsonb_build_object('error_code','tx_guard_failed','slot',guard->'slot')::text;\n END IF;\n END IF;\n RETURN rows;\nEND\n$pb_rows$;\nREVOKE ALL ON FUNCTION palbase_runtime.command_rows_v1(jsonb,jsonb) FROM PUBLIC;\n";
|
|
976
|
+
/** Run once with a migration/owner connection. Runtime execution retains each
|
|
977
|
+
* caller's role and RLS; there is no SECURITY DEFINER capability. */
|
|
978
|
+
declare function installCommandExecutor(sql: SqlDriver, roles: readonly string[]): Promise<void>;
|
|
979
|
+
|
|
980
|
+
/** The control pool must be separate from the application pool, connect as the
|
|
981
|
+
* same session user and to the same PostgreSQL server. Cancellation must still
|
|
982
|
+
* have a connection when every application connection is occupied. */
|
|
983
|
+
declare function withQueryCancellation(application: SqlDriver, control: SqlDriver): SqlDriver & {
|
|
984
|
+
close(): Promise<void>;
|
|
985
|
+
};
|
|
986
|
+
|
|
929
987
|
/**
|
|
930
988
|
* engine/fence.ts — what the tenant's own code may reach.
|
|
931
989
|
*
|
|
@@ -1063,4 +1121,4 @@ interface App {
|
|
|
1063
1121
|
}
|
|
1064
1122
|
declare function createApp(opts: CreateAppOptions): Promise<App>;
|
|
1065
1123
|
|
|
1066
|
-
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E,
|
|
1124
|
+
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E, makeMemoryCache as F, matchRoute as G, quoteIdent as H, scrubSecrets as I, setCursorKey as J, withQueryCancellation as K, withTables as L, type ModuleClients as M, RateLimiter as R, type ScrubResult as S, DeclarationRefused as a, DiError as b, type DiKind as c, type ModulePressure as d, assertNoOrphanEntryPoints as e, buildContainer as f, AuthVerifier as g, COMMAND_EXECUTOR_DDL as h, isDeclarationRefused as i, type CreateAppOptions as j, type EngineConfig as k, type RequestDatabase as l, type RouteEntry as m, type RuntimeHooks as n, type SqlDriver as o, type SqlTx as p, buildRouteTable as q, createApp as r, createLazyTransaction as s, createOps as t, createRequestDatabase as u, effectiveAuth as v, hostAllowed as w, installCommandExecutor as x, installEgressFence as y, loadConfig as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, P as PreparedRead, C as CompiledRead, f as RawPageOptions, g as Page, h as TxPlanBody, i as CommandOptions, j as TxPlanResponse, A as AuthSpec, k as CacheClient, b as RuntimeServices, _ as __runWithRuntime, l as __requestALS } from './endpoint-kYgEHrrV.cjs';
|
|
2
2
|
import { T as Token } from './module-Dl1KFVtc.cjs';
|
|
3
|
-
import { R as RouteMeta } from './registry-
|
|
3
|
+
import { R as RouteMeta } from './registry-BcOd8Zhf.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* engine/config.ts — settings from the environment, and the gate that refuses
|
|
@@ -47,6 +47,11 @@ interface EngineConfig {
|
|
|
47
47
|
anonKey: string;
|
|
48
48
|
/** Secret key. Used for privileged module calls. */
|
|
49
49
|
serviceRoleKey: string;
|
|
50
|
+
/** Optional dedicated cursor encryption secret, shared by all replicas. */
|
|
51
|
+
cursorSecret?: string;
|
|
52
|
+
/** Install the invoker-only PostgreSQL command helper at boot. Requires DDL
|
|
53
|
+
* rights on the connection role; execution retains each request's RLS role. */
|
|
54
|
+
enableCommands?: boolean;
|
|
50
55
|
/** HMAC the realtime broadcast token is signed with. Empty ⇒ broadcast
|
|
51
56
|
* returns a clear `realtime_unconfigured` error instead of failing silently. */
|
|
52
57
|
realtimeSecret: string;
|
|
@@ -65,6 +70,7 @@ interface EngineConfig {
|
|
|
65
70
|
*/
|
|
66
71
|
dbServiceRole: string;
|
|
67
72
|
poolMax: number;
|
|
73
|
+
databaseDiagnostics?: DatabaseDiagnosticsOptions;
|
|
68
74
|
}
|
|
69
75
|
/**
|
|
70
76
|
* THE ENVIRONMENT THIS STACK WAS HANDED IS UNUSABLE. Carries the missing names.
|
|
@@ -87,42 +93,62 @@ declare class BootRefused extends Error {
|
|
|
87
93
|
*/
|
|
88
94
|
declare function loadConfig(env: Record<string, string | undefined>): EngineConfig;
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*
|
|
121
|
-
|
|
122
|
-
|
|
96
|
+
type CancellableQuery = Promise<unknown> & {
|
|
97
|
+
cancel?: () => unknown;
|
|
98
|
+
};
|
|
99
|
+
/** Abort callback work and active statements, then let the transaction owner
|
|
100
|
+
* await rollback. COMMIT is never raced with a timer: its acknowledged result
|
|
101
|
+
* or connection failure remains authoritative. */
|
|
102
|
+
declare class TransactionControl {
|
|
103
|
+
private controller;
|
|
104
|
+
private active;
|
|
105
|
+
private cancelBackend?;
|
|
106
|
+
private cancellation;
|
|
107
|
+
private timer?;
|
|
108
|
+
private unlink;
|
|
109
|
+
private rejection;
|
|
110
|
+
readonly deadline: number | undefined;
|
|
111
|
+
get signal(): AbortSignal;
|
|
112
|
+
constructor(timeoutMs?: number, external?: AbortSignal);
|
|
113
|
+
check(): void;
|
|
114
|
+
remainingMs(): number | undefined;
|
|
115
|
+
race<T>(work: Promise<T>): Promise<T>;
|
|
116
|
+
bindBackend(cancel: () => Promise<void>): void;
|
|
117
|
+
/** Keep the application's connection parked until the cancellation request
|
|
118
|
+
* and all statements settle; a late cancel must not hit its next borrower. */
|
|
119
|
+
drainCancellation(): Promise<void>;
|
|
120
|
+
watch(query: CancellableQuery): Promise<unknown>;
|
|
121
|
+
dispose(): void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type Timing = "queueMs" | "poolMs" | "setupMs" | "sqlMs" | "commitMs" | "rollbackMs";
|
|
125
|
+
/** Allocated only when diagnostics or a budget is configured. One collector
|
|
126
|
+
* follows the request's user/service handles and independent atomic attempts. */
|
|
127
|
+
declare class DatabaseTrace {
|
|
128
|
+
private readonly options;
|
|
129
|
+
private readonly start;
|
|
130
|
+
private ended?;
|
|
131
|
+
private failure?;
|
|
132
|
+
private readonly state;
|
|
133
|
+
constructor(options: DatabaseDiagnosticsOptions);
|
|
134
|
+
check(): void;
|
|
135
|
+
time(key: Timing, started: number): void;
|
|
136
|
+
retry(): void;
|
|
137
|
+
committed(): void;
|
|
138
|
+
commitFailed(): void;
|
|
139
|
+
failed(): void;
|
|
140
|
+
rolledBack(): void;
|
|
141
|
+
private refuse;
|
|
142
|
+
private emit;
|
|
143
|
+
query(sql: string, name: string | undefined, run: () => Promise<unknown>): Promise<unknown>;
|
|
144
|
+
get snapshot(): DatabaseDiagnostics;
|
|
145
|
+
complete(outcome: "committed" | "failed"): void;
|
|
146
|
+
}
|
|
123
147
|
|
|
124
148
|
/** The slice of a SQL driver the engine uses. `Bun.sql` satisfies it. */
|
|
125
149
|
interface SqlDriver {
|
|
150
|
+
/** Optional reliable cancellation through a separate control connection. */
|
|
151
|
+
cancelBackend?(pid: number, startedAt: string): Promise<void>;
|
|
126
152
|
/** Run a parameterised statement. */
|
|
127
153
|
unsafe(sql: string, params?: unknown[]): Promise<unknown>;
|
|
128
154
|
/** Open a transaction; the driver commits when `cb` resolves and rolls back
|
|
@@ -130,7 +156,9 @@ interface SqlDriver {
|
|
|
130
156
|
begin<T>(cb: (tx: SqlTx) => Promise<T>): Promise<T>;
|
|
131
157
|
}
|
|
132
158
|
interface SqlTx {
|
|
133
|
-
unsafe(sql: string, params?: unknown[]
|
|
159
|
+
unsafe(sql: string, params?: unknown[], metadata?: {
|
|
160
|
+
name?: string;
|
|
161
|
+
}): Promise<unknown>;
|
|
134
162
|
savepoint<T>(cb: (sp: SqlTx) => Promise<T>): Promise<T>;
|
|
135
163
|
}
|
|
136
164
|
type Row = Record<string, unknown>;
|
|
@@ -147,6 +175,12 @@ declare function quoteIdent(name: string): string;
|
|
|
147
175
|
*/
|
|
148
176
|
declare function createLazyTransaction(sql: SqlDriver, role: string, claimsJson: string, options?: {
|
|
149
177
|
lockTimeout?: string;
|
|
178
|
+
statementTimeout?: string;
|
|
179
|
+
isolation?: TransactionIsolation;
|
|
180
|
+
readOnly?: boolean;
|
|
181
|
+
scope?: symbol;
|
|
182
|
+
control?: TransactionControl;
|
|
183
|
+
trace?: DatabaseTrace;
|
|
150
184
|
}): {
|
|
151
185
|
ensure: () => Promise<SqlTx>;
|
|
152
186
|
readonly opened: boolean;
|
|
@@ -186,7 +220,13 @@ interface FindManyOptions {
|
|
|
186
220
|
* refused without it — see `offsetClause`. */
|
|
187
221
|
offset?: number;
|
|
188
222
|
}
|
|
189
|
-
|
|
223
|
+
interface OpsContext {
|
|
224
|
+
readonly cursorScope?: string;
|
|
225
|
+
readonly commands?: boolean;
|
|
226
|
+
readonly trace?: DatabaseTrace;
|
|
227
|
+
}
|
|
228
|
+
declare function createOps(tx: TxLike, context?: OpsContext): {
|
|
229
|
+
diagnostics(): DatabaseDiagnostics | null;
|
|
190
230
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
191
231
|
insert(table: string, data: Row): Promise<Row>;
|
|
192
232
|
/**
|
|
@@ -203,10 +243,7 @@ declare function createOps(tx: TxLike): {
|
|
|
203
243
|
* bir satırın fazla kolonu SESSİZCE YAZILMAZDI. Eksik kolon için `null`
|
|
204
244
|
* yazın ya da varsayılanı istiyorsanız o satırları ayrı çağrıda ekleyin.
|
|
205
245
|
*/
|
|
206
|
-
insertMany
|
|
207
|
-
onConflict: readonly string[];
|
|
208
|
-
action?: "ignore" | "update";
|
|
209
|
-
}): Promise<Row[]>;
|
|
246
|
+
insertMany: DBOps["insertMany"];
|
|
210
247
|
/**
|
|
211
248
|
* Bir ADI kilitle — satırı değil (FR-054).
|
|
212
249
|
*
|
|
@@ -338,8 +375,16 @@ declare function createOps(tx: TxLike): {
|
|
|
338
375
|
groupBy?: readonly string[];
|
|
339
376
|
}): Promise<Record<string, unknown> | Record<string, unknown>[]>;
|
|
340
377
|
count(table: string, where?: Row): Promise<number>;
|
|
378
|
+
findUnique(table: string, where: Row, opts?: {
|
|
379
|
+
select?: readonly string[];
|
|
380
|
+
with?: Record<string, unknown>;
|
|
381
|
+
}): Promise<Row | null>;
|
|
341
382
|
findById(table: string, id: string): Promise<Row | null>;
|
|
383
|
+
compileQuery(query: PreparedRead): CompiledRead;
|
|
384
|
+
readQuery(query: PreparedRead): Promise<Row[]>;
|
|
385
|
+
explainQuery(query: PreparedRead): Promise<unknown[]>;
|
|
342
386
|
findMany(table: string, query?: Row, opts?: FindManyOptions): Promise<Row[]>;
|
|
387
|
+
page(table: string, query?: Row, opts?: RawPageOptions): Promise<Page<Row>>;
|
|
343
388
|
/**
|
|
344
389
|
* Tek-SQL hibrit arama (FR-014): iki kol CTE + FULL OUTER JOIN + RRF
|
|
345
390
|
* (1/(50+rank), CLAIM-N4). Operatör şema-nitelikli (C-10, M-1); GUC
|
|
@@ -495,15 +540,9 @@ declare function createOps(tx: TxLike): {
|
|
|
495
540
|
* "transport.txPlan is not a function" while every test that covered
|
|
496
541
|
* transactions passed against a mock that did implement it.
|
|
497
542
|
*/
|
|
543
|
+
command(plan: TxPlanBody, options?: CommandOptions): Promise<TxPlanResponse>;
|
|
498
544
|
txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;
|
|
499
545
|
};
|
|
500
|
-
/**
|
|
501
|
-
* Merge the typed `.tables` accessor onto a raw op surface.
|
|
502
|
-
*
|
|
503
|
-
* Mirrors what the pod runtime does, including the recursive application to the
|
|
504
|
-
* transaction callback: without it `tx.tables.rooms.insert(...)` throws
|
|
505
|
-
* "Cannot read properties of undefined".
|
|
506
|
-
*/
|
|
507
546
|
declare function withTables<T extends ReturnType<typeof createOps>>(ops: T, schema?: {
|
|
508
547
|
tables?: Record<string, {
|
|
509
548
|
name?: string;
|
|
@@ -580,7 +619,7 @@ declare function createRequestDatabase(sql: SqlDriver, identity: {
|
|
|
580
619
|
role: string;
|
|
581
620
|
serviceRole: string;
|
|
582
621
|
claimsJson: string;
|
|
583
|
-
}): RequestDatabase;
|
|
622
|
+
}, diagnostics?: DatabaseDiagnosticsOptions): RequestDatabase;
|
|
584
623
|
|
|
585
624
|
/**
|
|
586
625
|
* The two ways a stack refuses to boot — and they are two because their CURES
|
|
@@ -926,6 +965,25 @@ interface MemoryCacheOptions {
|
|
|
926
965
|
*/
|
|
927
966
|
declare function makeMemoryCache(opts?: MemoryCacheOptions): CacheClient;
|
|
928
967
|
|
|
968
|
+
/** One application secret shared by replicas. Rotation invalidates old cursors.
|
|
969
|
+
* Encryption also hides sort values omitted by the public projection. */
|
|
970
|
+
declare function setCursorKey(secret: string | null): void;
|
|
971
|
+
|
|
972
|
+
/** Statements remain sequential inside PostgreSQL. Each sees preceding writes,
|
|
973
|
+
* including triggers, unlike sibling data-modifying CTEs in one SQL statement.
|
|
974
|
+
* The exception block is a subtransaction, matching a savepoint plan. */
|
|
975
|
+
declare const COMMAND_EXECUTOR_DDL = "\nCREATE SCHEMA IF NOT EXISTS palbase_runtime;\nCREATE OR REPLACE FUNCTION palbase_runtime.command_v1(steps jsonb) RETURNS jsonb\nLANGUAGE plpgsql VOLATILE SECURITY INVOKER SET search_path = pg_catalog, public AS $pb_command$\nDECLARE\n results jsonb := '[]'::jsonb;\n step jsonb; chunk jsonb; binding jsonb; source jsonb; rows jsonb;\n statement text; rendered text; detail text; guard jsonb;\n index integer := 0; affected integer; passed boolean;\nBEGIN\n FOR step IN SELECT value FROM jsonb_array_elements(steps) LOOP\n IF step->>'empty' = 'true' THEN rows := '[]'::jsonb;\n ELSE\n statement := '';\n FOR chunk IN SELECT value FROM jsonb_array_elements(step->'chunks') LOOP\n IF jsonb_typeof(chunk) = 'string' THEN statement := statement || (chunk #>> '{}');\n ELSE\n binding := step->'bindings'->((chunk->>'bind')::integer);\n IF binding ? 'ref' THEN\n source := results->((binding->'ref'->>'op')::integer)->'rows'->0;\n IF source IS NULL OR NOT source ? (binding->'ref'->>'field') THEN\n RAISE EXCEPTION 'Command reference has no source row/column; use expectOne before reading it'\n USING ERRCODE = 'PBC02', DETAIL = jsonb_build_object('error_code','tx_ref_unresolved','op',index)::text;\n END IF;\n source := source->(binding->'ref'->>'field');\n ELSE source := binding->'value'; END IF;\n rendered := CASE WHEN source IS NULL OR source = 'null'::jsonb THEN NULL\n WHEN binding->>'json' = 'true' THEN source::text\n WHEN jsonb_typeof(source) = 'string' THEN source #>> '{}' ELSE source::text END;\n -- PostgreSQL quotes the value itself. Values reach this function as\n -- one bound JSON parameter, never as application-generated SQL text.\n statement := statement || quote_nullable(rendered);\n END IF;\n END LOOP;\n EXECUTE statement INTO rows;\n END IF;\n affected := jsonb_array_length(rows);\n guard := step->'guard';\n IF guard IS NOT NULL AND guard <> 'null'::jsonb THEN\n passed := CASE guard->>'kind'\n WHEN 'one' THEN affected = 1 WHEN 'none' THEN affected = 0\n WHEN 'atLeast' THEN affected >= (guard->>'n')::integer\n WHEN 'atMost' THEN affected <= (guard->>'n')::integer ELSE false END;\n IF NOT passed THEN\n RAISE EXCEPTION 'Command expectation failed'\n USING ERRCODE = 'PBC01', DETAIL = jsonb_build_object('error_code','tx_guard_failed','slot',guard->'slot','op',index)::text;\n END IF;\n END IF;\n results := results || jsonb_build_array(jsonb_build_object('rows',rows,'rows_affected',affected));\n index := index + 1;\n END LOOP;\n RETURN jsonb_build_object('results',results);\nEXCEPTION WHEN SQLSTATE 'PBC01' OR SQLSTATE 'PBC02' THEN\n GET STACKED DIAGNOSTICS detail = PG_EXCEPTION_DETAIL;\n RETURN jsonb_build_object('error',detail::jsonb);\nEND\n$pb_command$;\nREVOKE ALL ON FUNCTION palbase_runtime.command_v1(jsonb) FROM PUBLIC;\nCREATE OR REPLACE FUNCTION palbase_runtime.command_rows_v1(rows jsonb, guard jsonb) RETURNS jsonb\nLANGUAGE plpgsql VOLATILE SECURITY INVOKER SET search_path = pg_catalog, public AS $pb_rows$\nDECLARE affected integer := jsonb_array_length(rows); passed boolean;\nBEGIN\n IF guard IS NOT NULL AND guard <> 'null'::jsonb THEN\n passed := CASE guard->>'kind'\n WHEN 'one' THEN affected = 1 WHEN 'none' THEN affected = 0\n WHEN 'atLeast' THEN affected >= (guard->>'n')::integer\n WHEN 'atMost' THEN affected <= (guard->>'n')::integer ELSE false END;\n IF NOT passed THEN\n RAISE EXCEPTION 'Command expectation failed'\n USING ERRCODE = 'PBC01', DETAIL = jsonb_build_object('error_code','tx_guard_failed','slot',guard->'slot')::text;\n END IF;\n END IF;\n RETURN rows;\nEND\n$pb_rows$;\nREVOKE ALL ON FUNCTION palbase_runtime.command_rows_v1(jsonb,jsonb) FROM PUBLIC;\n";
|
|
976
|
+
/** Run once with a migration/owner connection. Runtime execution retains each
|
|
977
|
+
* caller's role and RLS; there is no SECURITY DEFINER capability. */
|
|
978
|
+
declare function installCommandExecutor(sql: SqlDriver, roles: readonly string[]): Promise<void>;
|
|
979
|
+
|
|
980
|
+
/** The control pool must be separate from the application pool, connect as the
|
|
981
|
+
* same session user and to the same PostgreSQL server. Cancellation must still
|
|
982
|
+
* have a connection when every application connection is occupied. */
|
|
983
|
+
declare function withQueryCancellation(application: SqlDriver, control: SqlDriver): SqlDriver & {
|
|
984
|
+
close(): Promise<void>;
|
|
985
|
+
};
|
|
986
|
+
|
|
929
987
|
/**
|
|
930
988
|
* engine/fence.ts — what the tenant's own code may reach.
|
|
931
989
|
*
|
|
@@ -1063,4 +1121,4 @@ interface App {
|
|
|
1063
1121
|
}
|
|
1064
1122
|
declare function createApp(opts: CreateAppOptions): Promise<App>;
|
|
1065
1123
|
|
|
1066
|
-
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E,
|
|
1124
|
+
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E, makeMemoryCache as F, matchRoute as G, quoteIdent as H, scrubSecrets as I, setCursorKey as J, withQueryCancellation as K, withTables as L, type ModuleClients as M, RateLimiter as R, type ScrubResult as S, DeclarationRefused as a, DiError as b, type DiKind as c, type ModulePressure as d, assertNoOrphanEntryPoints as e, buildContainer as f, AuthVerifier as g, COMMAND_EXECUTOR_DDL as h, isDeclarationRefused as i, type CreateAppOptions as j, type EngineConfig as k, type RequestDatabase as l, type RouteEntry as m, type RuntimeHooks as n, type SqlDriver as o, type SqlTx as p, buildRouteTable as q, createApp as r, createLazyTransaction as s, createOps as t, createRequestDatabase as u, effectiveAuth as v, hostAllowed as w, installCommandExecutor as x, installEgressFence as y, loadConfig as z };
|