@palbase/backend 27.1.0 → 28.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 +133 -38
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +4 -4
- package/dist/{chunk-JVZQCC77.js → chunk-3TUJWHC2.js} +8 -3
- package/dist/chunk-3TUJWHC2.js.map +1 -0
- package/dist/{chunk-EB3TUX5J.js → chunk-75YROPRZ.js} +102 -38
- package/dist/chunk-75YROPRZ.js.map +1 -0
- package/dist/{chunk-XABHGMUT.js → chunk-IVZERLTM.js} +2 -2
- package/dist/{chunk-BQN723PL.js → chunk-RVP6BTEZ.js} +63 -6
- package/dist/chunk-RVP6BTEZ.js.map +1 -0
- package/dist/{chunk-OZKSM3JW.js → chunk-SNDXY565.js} +3 -2
- package/dist/chunk-SNDXY565.js.map +1 -0
- package/dist/db/index.cjs +4 -1
- 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 +3 -3
- package/dist/engine/index.cjs +143 -38
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +3 -3
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +11 -4
- package/dist/{index-H-0qv5d4.d.cts → index-9C3JHxg-.d.cts} +112 -5
- package/dist/{index-CAKOgAlP.d.ts → index-BbvOoZFr.d.ts} +112 -5
- package/dist/{index-CgE4sVhg.d.cts → index-DtISj9QX.d.cts} +94 -11
- package/dist/{index-V7QRh1wg.d.ts → index-dTTLlHIn.d.ts} +94 -11
- package/dist/index.cjs +67 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -22
- package/dist/index.d.ts +6 -22
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/{registry-4EI8aaFs.d.ts → registry-JQNIX-eA.d.ts} +1 -1
- package/dist/{registry-DHsPDY0_.d.cts → registry-qIPM5BQe.d.cts} +1 -1
- package/dist/test/index.cjs +73 -6
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +70 -6
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +69 -1
- package/docs/llms-full.txt +70 -2
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/chunk-BQN723PL.js.map +0 -1
- package/dist/chunk-EB3TUX5J.js.map +0 -1
- package/dist/chunk-JVZQCC77.js.map +0 -1
- package/dist/chunk-OZKSM3JW.js.map +0 -1
- /package/dist/{chunk-XABHGMUT.js.map → chunk-IVZERLTM.js.map} +0 -0
package/dist/engine/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import '../index-
|
|
2
|
-
export { A as App,
|
|
1
|
+
import '../index-DtISj9QX.cjs';
|
|
2
|
+
export { A as App, g as AuthVerifier, B as BootRefused, h as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, j as EngineConfig, M as ModuleClients, R as RateLimiter, k as RequestDatabase, l as RouteEntry, m as RuntimeHooks, S as ScrubResult, n as SqlDriver, o as SqlTx, p as buildRouteTable, q as createApp, r as createLazyTransaction, s as createOps, t as createRequestDatabase, u as effectiveAuth, v as hostAllowed, w as installEgressFence, i as isDeclarationRefused, x as loadConfig, y as makeMemoryCache, z as matchRoute, F as quoteIdent, G as scrubSecrets, H as withTables } from '../index-9C3JHxg-.cjs';
|
|
3
3
|
import '../db/env.cjs';
|
|
4
4
|
import '../stack.cjs';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'node:async_hooks';
|
|
7
7
|
import '../module-Dl1KFVtc.cjs';
|
|
8
|
-
import '../registry-
|
|
8
|
+
import '../registry-qIPM5BQe.cjs';
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import '../index-
|
|
2
|
-
export { A as App,
|
|
1
|
+
import '../index-dTTLlHIn.js';
|
|
2
|
+
export { A as App, g as AuthVerifier, B as BootRefused, h as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, j as EngineConfig, M as ModuleClients, R as RateLimiter, k as RequestDatabase, l as RouteEntry, m as RuntimeHooks, S as ScrubResult, n as SqlDriver, o as SqlTx, p as buildRouteTable, q as createApp, r as createLazyTransaction, s as createOps, t as createRequestDatabase, u as effectiveAuth, v as hostAllowed, w as installEgressFence, i as isDeclarationRefused, x as loadConfig, y as makeMemoryCache, z as matchRoute, F as quoteIdent, G as scrubSecrets, H as withTables } from '../index-BbvOoZFr.js';
|
|
3
3
|
import '../db/env.js';
|
|
4
4
|
import '../stack.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'node:async_hooks';
|
|
7
7
|
import '../module-Dl1KFVtc.js';
|
|
8
|
-
import '../registry-
|
|
8
|
+
import '../registry-JQNIX-eA.js';
|
package/dist/engine/index.js
CHANGED
|
@@ -16,16 +16,22 @@ import {
|
|
|
16
16
|
quoteIdent,
|
|
17
17
|
scrubSecrets,
|
|
18
18
|
withTables
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
} from "../chunk-75YROPRZ.js";
|
|
20
|
+
import {
|
|
21
|
+
DECLARATION_REFUSAL,
|
|
22
|
+
DeclarationRefused,
|
|
23
|
+
isDeclarationRefused
|
|
24
|
+
} from "../chunk-RVP6BTEZ.js";
|
|
25
|
+
import "../chunk-SNDXY565.js";
|
|
26
|
+
import "../chunk-3TUJWHC2.js";
|
|
23
27
|
import "../chunk-VVMJEVQP.js";
|
|
24
28
|
import "../chunk-CGNN2PUH.js";
|
|
25
29
|
import "../chunk-VXPNPVAG.js";
|
|
26
30
|
export {
|
|
27
31
|
AuthVerifier,
|
|
28
32
|
BootRefused,
|
|
33
|
+
DECLARATION_REFUSAL,
|
|
34
|
+
DeclarationRefused,
|
|
29
35
|
RateLimiter,
|
|
30
36
|
buildRouteTable,
|
|
31
37
|
createApp,
|
|
@@ -35,6 +41,7 @@ export {
|
|
|
35
41
|
effectiveAuth,
|
|
36
42
|
hostAllowed,
|
|
37
43
|
installEgressFence,
|
|
44
|
+
isDeclarationRefused,
|
|
38
45
|
loadConfig,
|
|
39
46
|
makeMemoryCache,
|
|
40
47
|
matchRoute,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as DBClient, a as DBOps, T as TxPlanBody, b as TxPlanResponse, A as AuthSpec, C as CacheClient, c as RuntimeServices, _ as __runWithRuntime, d as __requestALS } from './index-
|
|
1
|
+
import { D as DBClient, a as DBOps, T as TxPlanBody, b as TxPlanResponse, A as AuthSpec, C as CacheClient, c as RuntimeServices, _ as __runWithRuntime, d as __requestALS } from './index-DtISj9QX.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-qIPM5BQe.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* engine/config.ts — settings from the environment, and the gate that refuses
|
|
@@ -66,7 +66,15 @@ interface EngineConfig {
|
|
|
66
66
|
dbServiceRole: string;
|
|
67
67
|
poolMax: number;
|
|
68
68
|
}
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* THE ENVIRONMENT THIS STACK WAS HANDED IS UNUSABLE. Carries the missing names.
|
|
71
|
+
*
|
|
72
|
+
* ONLY the environment. A refusal about the author's own declarations is
|
|
73
|
+
* `DeclarationRefused` (see `src/refusals.ts`) and the difference is not
|
|
74
|
+
* severity, it is the CURE: no push fixes a missing DATABASE_URL, so the
|
|
75
|
+
* runtime must keep treating this one as fatal rather than waiting for an
|
|
76
|
+
* artifact that would change nothing.
|
|
77
|
+
*/
|
|
70
78
|
declare class BootRefused extends Error {
|
|
71
79
|
readonly missing: readonly string[];
|
|
72
80
|
constructor(missing: readonly string[], message: string);
|
|
@@ -171,10 +179,27 @@ interface FindManyOptions {
|
|
|
171
179
|
* refused without it — see `offsetClause`. */
|
|
172
180
|
offset?: number;
|
|
173
181
|
}
|
|
174
|
-
/** The six string-keyed operations, plus an interactive `transaction`. */
|
|
175
182
|
declare function createOps(tx: TxLike): {
|
|
176
183
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
177
184
|
insert(table: string, data: Row): Promise<Row>;
|
|
185
|
+
/**
|
|
186
|
+
* Çok satırı TEK statement'la ekle.
|
|
187
|
+
*
|
|
188
|
+
* Motor bunu zaten yapıyordu ve yalnız PLAN yolundan erişilebiliyordu
|
|
189
|
+
* (`tx.public.x.insertMany`). Dışarıda tek kapı `insert(row)` olduğu için
|
|
190
|
+
* "şu 200 satırı yaz" ya 200 gidiş-dönüş ya da ham SQL oluyordu — ölçüldü:
|
|
191
|
+
* bir müşteri projesinde bir seed rutini satırları tek tek siliyor
|
|
192
|
+
* (`deleteMany` VARKEN) ve tek tek ekliyor.
|
|
193
|
+
*
|
|
194
|
+
* SATIRLARIN ANAHTAR KÜMESİ AYNI OLMAK ZORUNDA. Kolon listesi tek bir
|
|
195
|
+
* statement'ta paylaşıldığı için ilk satırdan türer; farklı anahtar taşıyan
|
|
196
|
+
* bir satırın fazla kolonu SESSİZCE YAZILMAZDI. Eksik kolon için `null`
|
|
197
|
+
* yazın ya da varsayılanı istiyorsanız o satırları ayrı çağrıda ekleyin.
|
|
198
|
+
*/
|
|
199
|
+
insertMany(table: string, rows: readonly Row[], opts?: {
|
|
200
|
+
onConflict: readonly string[];
|
|
201
|
+
action?: "ignore" | "update";
|
|
202
|
+
}): Promise<Row[]>;
|
|
178
203
|
/**
|
|
179
204
|
* Bir ADI kilitle — satırı değil (FR-054).
|
|
180
205
|
*
|
|
@@ -527,6 +552,80 @@ declare function createRequestDatabase(sql: SqlDriver, identity: {
|
|
|
527
552
|
claimsJson: string;
|
|
528
553
|
}): RequestDatabase;
|
|
529
554
|
|
|
555
|
+
/**
|
|
556
|
+
* The two ways a stack refuses to boot — and they are two because their CURES
|
|
557
|
+
* are two.
|
|
558
|
+
*
|
|
559
|
+
* A LEAF MODULE ON PURPOSE. `db/` does not import from `engine/` and must not
|
|
560
|
+
* start: the schema layer is below the engine, and a refusal both of them raise
|
|
561
|
+
* cannot live in either. Anything imported here would invert that.
|
|
562
|
+
*
|
|
563
|
+
* WHY THE SPLIT EXISTS AT ALL — measured live on 2026-09-04.
|
|
564
|
+
*
|
|
565
|
+
* `8qitbtucm` ran for days on an image whose `setSchema` did not build
|
|
566
|
+
* relations. Moved onto one that does, the same artifact hit
|
|
567
|
+
* `buildRelations` at boot, threw a bare `Error`, and the runtime — which waits
|
|
568
|
+
* only on its own `ArtifactRefused` — treated it as fatal. The supervisor took
|
|
569
|
+
* the pod down, palsvc with it. CrashLoopBackOff, back-off 5m, and palsvc is
|
|
570
|
+
* THE PROCESS THAT ACCEPTS THE PUSH the message asks for.
|
|
571
|
+
*
|
|
572
|
+
* That is verbatim the lesson `v2/runtime/src/loader.ts` already carries for
|
|
573
|
+
* ABI refusals: *"the cure was named in the error and made impossible by the
|
|
574
|
+
* exit that carried it."* It cost a tenant a third time because the second
|
|
575
|
+
* refusal had no type to be recognised by.
|
|
576
|
+
*
|
|
577
|
+
* SO THE RULE IS THE CURE, NOT THE SEVERITY:
|
|
578
|
+
*
|
|
579
|
+
* {@link DeclarationRefused} — what was PUSHED cannot be built. Restarting
|
|
580
|
+
* re-reads the same bytes and fails identically; only a new artifact
|
|
581
|
+
* changes the answer. The runtime WAITS on this, keeps palsvc alive, and
|
|
582
|
+
* says the reason out loud.
|
|
583
|
+
*
|
|
584
|
+
* {@link BootRefused} — the ENVIRONMENT this stack was handed is unusable
|
|
585
|
+
* (no DATABASE_URL, an unparseable PORT, no SQL driver). No push fixes it;
|
|
586
|
+
* waiting for one would be a lie told in a log line forever. Stays fatal.
|
|
587
|
+
*
|
|
588
|
+
* NOT A MESSAGE PATTERN. The runtime's loader already says why: *"The
|
|
589
|
+
* distinction is the loader's TYPE, not a pattern over its wording."* A gate
|
|
590
|
+
* that reads wording drifts from the thing it claims to measure the first time
|
|
591
|
+
* someone improves an error message.
|
|
592
|
+
*/
|
|
593
|
+
/**
|
|
594
|
+
* The tag that survives a realm boundary.
|
|
595
|
+
*
|
|
596
|
+
* `instanceof` compares constructor identity, and identity is per module
|
|
597
|
+
* instance. In the pod today the runtime and the bundle share one install
|
|
598
|
+
* (measured: both frames resolve to `/app/node_modules/@palbase/backend`), so
|
|
599
|
+
* `instanceof` would work — but it works by a coincidence of packaging, and a
|
|
600
|
+
* bundle that ever carries its own copy would make every declaration refusal
|
|
601
|
+
* silently fatal again. `Symbol.for` reads from the process-wide registry, so
|
|
602
|
+
* the tag means the same thing in every copy.
|
|
603
|
+
*
|
|
604
|
+
* Exported so the runtime can recognise the refusal without importing the
|
|
605
|
+
* class — see {@link isDeclarationRefused}.
|
|
606
|
+
*/
|
|
607
|
+
declare const DECLARATION_REFUSAL: unique symbol;
|
|
608
|
+
/**
|
|
609
|
+
* What was pushed cannot be built. The cure is a NEW ARTIFACT.
|
|
610
|
+
*
|
|
611
|
+
* Thrown by the declaration layer — relation naming, ownership, entry points —
|
|
612
|
+
* wherever a fact about the author's code makes the app impossible to
|
|
613
|
+
* construct. Never thrown for anything the environment could change.
|
|
614
|
+
*/
|
|
615
|
+
declare class DeclarationRefused extends Error {
|
|
616
|
+
/** @see DECLARATION_REFUSAL — realm-safe, unlike `instanceof`. */
|
|
617
|
+
readonly [DECLARATION_REFUSAL]: true;
|
|
618
|
+
constructor(message: string);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* True for a refusal whose only cure is a new artifact — across realms.
|
|
622
|
+
*
|
|
623
|
+
* Takes `unknown` because every caller is a `catch`. A non-object, a null, a
|
|
624
|
+
* plain `Error`: all false, and false is the safe answer — it means "keep
|
|
625
|
+
* treating this as fatal", which is what the code did before this type existed.
|
|
626
|
+
*/
|
|
627
|
+
declare function isDeclarationRefused(e: unknown): e is DeclarationRefused;
|
|
628
|
+
|
|
530
629
|
/**
|
|
531
630
|
* How a container refuses.
|
|
532
631
|
*
|
|
@@ -550,6 +649,14 @@ declare class DiError extends Error {
|
|
|
550
649
|
readonly path: string[];
|
|
551
650
|
readonly at: string;
|
|
552
651
|
readonly fixes: string[];
|
|
652
|
+
/**
|
|
653
|
+
* EVERY `DiKind` IS A FACT ABOUT THE AUTHOR'S DECLARATIONS — an unresolvable
|
|
654
|
+
* dependency, a cycle, a class no module owns. Not one of them is something
|
|
655
|
+
* the environment could change, so restarting re-reads the same bytes and
|
|
656
|
+
* fails identically. The cure is a new artifact, and the tag is how the
|
|
657
|
+
* runtime learns that without matching on wording.
|
|
658
|
+
*/
|
|
659
|
+
readonly [DECLARATION_REFUSAL]: true;
|
|
553
660
|
constructor(kind: DiKind, path: string[], at: string, detail: string, fixes: string[]);
|
|
554
661
|
}
|
|
555
662
|
/** How often a module appears in the OTHERS' `imports`. */
|
|
@@ -927,4 +1034,4 @@ interface App {
|
|
|
927
1034
|
*/
|
|
928
1035
|
declare function createApp(opts: CreateAppOptions): Promise<App>;
|
|
929
1036
|
|
|
930
|
-
export { type App as A, BootRefused as B, type Container as C,
|
|
1037
|
+
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E, quoteIdent as F, scrubSecrets as G, withTables as H, 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, type CreateAppOptions as h, isDeclarationRefused as i, type EngineConfig as j, type RequestDatabase as k, type RouteEntry as l, type RuntimeHooks as m, type SqlDriver as n, type SqlTx as o, buildRouteTable as p, createApp as q, createLazyTransaction as r, createOps as s, createRequestDatabase as t, effectiveAuth as u, hostAllowed as v, installEgressFence as w, loadConfig as x, makeMemoryCache as y, matchRoute as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as DBClient, a as DBOps, T as TxPlanBody, b as TxPlanResponse, A as AuthSpec, C as CacheClient, c as RuntimeServices, _ as __runWithRuntime, d as __requestALS } from './index-
|
|
1
|
+
import { D as DBClient, a as DBOps, T as TxPlanBody, b as TxPlanResponse, A as AuthSpec, C as CacheClient, c as RuntimeServices, _ as __runWithRuntime, d as __requestALS } from './index-dTTLlHIn.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-JQNIX-eA.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* engine/config.ts — settings from the environment, and the gate that refuses
|
|
@@ -66,7 +66,15 @@ interface EngineConfig {
|
|
|
66
66
|
dbServiceRole: string;
|
|
67
67
|
poolMax: number;
|
|
68
68
|
}
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* THE ENVIRONMENT THIS STACK WAS HANDED IS UNUSABLE. Carries the missing names.
|
|
71
|
+
*
|
|
72
|
+
* ONLY the environment. A refusal about the author's own declarations is
|
|
73
|
+
* `DeclarationRefused` (see `src/refusals.ts`) and the difference is not
|
|
74
|
+
* severity, it is the CURE: no push fixes a missing DATABASE_URL, so the
|
|
75
|
+
* runtime must keep treating this one as fatal rather than waiting for an
|
|
76
|
+
* artifact that would change nothing.
|
|
77
|
+
*/
|
|
70
78
|
declare class BootRefused extends Error {
|
|
71
79
|
readonly missing: readonly string[];
|
|
72
80
|
constructor(missing: readonly string[], message: string);
|
|
@@ -171,10 +179,27 @@ interface FindManyOptions {
|
|
|
171
179
|
* refused without it — see `offsetClause`. */
|
|
172
180
|
offset?: number;
|
|
173
181
|
}
|
|
174
|
-
/** The six string-keyed operations, plus an interactive `transaction`. */
|
|
175
182
|
declare function createOps(tx: TxLike): {
|
|
176
183
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
177
184
|
insert(table: string, data: Row): Promise<Row>;
|
|
185
|
+
/**
|
|
186
|
+
* Çok satırı TEK statement'la ekle.
|
|
187
|
+
*
|
|
188
|
+
* Motor bunu zaten yapıyordu ve yalnız PLAN yolundan erişilebiliyordu
|
|
189
|
+
* (`tx.public.x.insertMany`). Dışarıda tek kapı `insert(row)` olduğu için
|
|
190
|
+
* "şu 200 satırı yaz" ya 200 gidiş-dönüş ya da ham SQL oluyordu — ölçüldü:
|
|
191
|
+
* bir müşteri projesinde bir seed rutini satırları tek tek siliyor
|
|
192
|
+
* (`deleteMany` VARKEN) ve tek tek ekliyor.
|
|
193
|
+
*
|
|
194
|
+
* SATIRLARIN ANAHTAR KÜMESİ AYNI OLMAK ZORUNDA. Kolon listesi tek bir
|
|
195
|
+
* statement'ta paylaşıldığı için ilk satırdan türer; farklı anahtar taşıyan
|
|
196
|
+
* bir satırın fazla kolonu SESSİZCE YAZILMAZDI. Eksik kolon için `null`
|
|
197
|
+
* yazın ya da varsayılanı istiyorsanız o satırları ayrı çağrıda ekleyin.
|
|
198
|
+
*/
|
|
199
|
+
insertMany(table: string, rows: readonly Row[], opts?: {
|
|
200
|
+
onConflict: readonly string[];
|
|
201
|
+
action?: "ignore" | "update";
|
|
202
|
+
}): Promise<Row[]>;
|
|
178
203
|
/**
|
|
179
204
|
* Bir ADI kilitle — satırı değil (FR-054).
|
|
180
205
|
*
|
|
@@ -527,6 +552,80 @@ declare function createRequestDatabase(sql: SqlDriver, identity: {
|
|
|
527
552
|
claimsJson: string;
|
|
528
553
|
}): RequestDatabase;
|
|
529
554
|
|
|
555
|
+
/**
|
|
556
|
+
* The two ways a stack refuses to boot — and they are two because their CURES
|
|
557
|
+
* are two.
|
|
558
|
+
*
|
|
559
|
+
* A LEAF MODULE ON PURPOSE. `db/` does not import from `engine/` and must not
|
|
560
|
+
* start: the schema layer is below the engine, and a refusal both of them raise
|
|
561
|
+
* cannot live in either. Anything imported here would invert that.
|
|
562
|
+
*
|
|
563
|
+
* WHY THE SPLIT EXISTS AT ALL — measured live on 2026-09-04.
|
|
564
|
+
*
|
|
565
|
+
* `8qitbtucm` ran for days on an image whose `setSchema` did not build
|
|
566
|
+
* relations. Moved onto one that does, the same artifact hit
|
|
567
|
+
* `buildRelations` at boot, threw a bare `Error`, and the runtime — which waits
|
|
568
|
+
* only on its own `ArtifactRefused` — treated it as fatal. The supervisor took
|
|
569
|
+
* the pod down, palsvc with it. CrashLoopBackOff, back-off 5m, and palsvc is
|
|
570
|
+
* THE PROCESS THAT ACCEPTS THE PUSH the message asks for.
|
|
571
|
+
*
|
|
572
|
+
* That is verbatim the lesson `v2/runtime/src/loader.ts` already carries for
|
|
573
|
+
* ABI refusals: *"the cure was named in the error and made impossible by the
|
|
574
|
+
* exit that carried it."* It cost a tenant a third time because the second
|
|
575
|
+
* refusal had no type to be recognised by.
|
|
576
|
+
*
|
|
577
|
+
* SO THE RULE IS THE CURE, NOT THE SEVERITY:
|
|
578
|
+
*
|
|
579
|
+
* {@link DeclarationRefused} — what was PUSHED cannot be built. Restarting
|
|
580
|
+
* re-reads the same bytes and fails identically; only a new artifact
|
|
581
|
+
* changes the answer. The runtime WAITS on this, keeps palsvc alive, and
|
|
582
|
+
* says the reason out loud.
|
|
583
|
+
*
|
|
584
|
+
* {@link BootRefused} — the ENVIRONMENT this stack was handed is unusable
|
|
585
|
+
* (no DATABASE_URL, an unparseable PORT, no SQL driver). No push fixes it;
|
|
586
|
+
* waiting for one would be a lie told in a log line forever. Stays fatal.
|
|
587
|
+
*
|
|
588
|
+
* NOT A MESSAGE PATTERN. The runtime's loader already says why: *"The
|
|
589
|
+
* distinction is the loader's TYPE, not a pattern over its wording."* A gate
|
|
590
|
+
* that reads wording drifts from the thing it claims to measure the first time
|
|
591
|
+
* someone improves an error message.
|
|
592
|
+
*/
|
|
593
|
+
/**
|
|
594
|
+
* The tag that survives a realm boundary.
|
|
595
|
+
*
|
|
596
|
+
* `instanceof` compares constructor identity, and identity is per module
|
|
597
|
+
* instance. In the pod today the runtime and the bundle share one install
|
|
598
|
+
* (measured: both frames resolve to `/app/node_modules/@palbase/backend`), so
|
|
599
|
+
* `instanceof` would work — but it works by a coincidence of packaging, and a
|
|
600
|
+
* bundle that ever carries its own copy would make every declaration refusal
|
|
601
|
+
* silently fatal again. `Symbol.for` reads from the process-wide registry, so
|
|
602
|
+
* the tag means the same thing in every copy.
|
|
603
|
+
*
|
|
604
|
+
* Exported so the runtime can recognise the refusal without importing the
|
|
605
|
+
* class — see {@link isDeclarationRefused}.
|
|
606
|
+
*/
|
|
607
|
+
declare const DECLARATION_REFUSAL: unique symbol;
|
|
608
|
+
/**
|
|
609
|
+
* What was pushed cannot be built. The cure is a NEW ARTIFACT.
|
|
610
|
+
*
|
|
611
|
+
* Thrown by the declaration layer — relation naming, ownership, entry points —
|
|
612
|
+
* wherever a fact about the author's code makes the app impossible to
|
|
613
|
+
* construct. Never thrown for anything the environment could change.
|
|
614
|
+
*/
|
|
615
|
+
declare class DeclarationRefused extends Error {
|
|
616
|
+
/** @see DECLARATION_REFUSAL — realm-safe, unlike `instanceof`. */
|
|
617
|
+
readonly [DECLARATION_REFUSAL]: true;
|
|
618
|
+
constructor(message: string);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* True for a refusal whose only cure is a new artifact — across realms.
|
|
622
|
+
*
|
|
623
|
+
* Takes `unknown` because every caller is a `catch`. A non-object, a null, a
|
|
624
|
+
* plain `Error`: all false, and false is the safe answer — it means "keep
|
|
625
|
+
* treating this as fatal", which is what the code did before this type existed.
|
|
626
|
+
*/
|
|
627
|
+
declare function isDeclarationRefused(e: unknown): e is DeclarationRefused;
|
|
628
|
+
|
|
530
629
|
/**
|
|
531
630
|
* How a container refuses.
|
|
532
631
|
*
|
|
@@ -550,6 +649,14 @@ declare class DiError extends Error {
|
|
|
550
649
|
readonly path: string[];
|
|
551
650
|
readonly at: string;
|
|
552
651
|
readonly fixes: string[];
|
|
652
|
+
/**
|
|
653
|
+
* EVERY `DiKind` IS A FACT ABOUT THE AUTHOR'S DECLARATIONS — an unresolvable
|
|
654
|
+
* dependency, a cycle, a class no module owns. Not one of them is something
|
|
655
|
+
* the environment could change, so restarting re-reads the same bytes and
|
|
656
|
+
* fails identically. The cure is a new artifact, and the tag is how the
|
|
657
|
+
* runtime learns that without matching on wording.
|
|
658
|
+
*/
|
|
659
|
+
readonly [DECLARATION_REFUSAL]: true;
|
|
553
660
|
constructor(kind: DiKind, path: string[], at: string, detail: string, fixes: string[]);
|
|
554
661
|
}
|
|
555
662
|
/** How often a module appears in the OTHERS' `imports`. */
|
|
@@ -927,4 +1034,4 @@ interface App {
|
|
|
927
1034
|
*/
|
|
928
1035
|
declare function createApp(opts: CreateAppOptions): Promise<App>;
|
|
929
1036
|
|
|
930
|
-
export { type App as A, BootRefused as B, type Container as C,
|
|
1037
|
+
export { type App as A, BootRefused as B, type Container as C, DECLARATION_REFUSAL as D, type EgressPolicy as E, quoteIdent as F, scrubSecrets as G, withTables as H, 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, type CreateAppOptions as h, isDeclarationRefused as i, type EngineConfig as j, type RequestDatabase as k, type RouteEntry as l, type RuntimeHooks as m, type SqlDriver as n, type SqlTx as o, buildRouteTable as p, createApp as q, createLazyTransaction as r, createOps as s, createRequestDatabase as t, effectiveAuth as u, hostAllowed as v, installEgressFence as w, loadConfig as x, makeMemoryCache as y, matchRoute as z };
|
|
@@ -2825,7 +2825,12 @@ type RowShape<T extends TableDef> = {
|
|
|
2825
2825
|
};
|
|
2826
2826
|
/** A typed table accessor that mirrors the runtime DBClient surface. */
|
|
2827
2827
|
interface TypedTable<T extends TableDef> {
|
|
2828
|
-
insert(data: InsertShape<T
|
|
2828
|
+
insert(data: InsertValues<InsertShape<T>>): Promise<RowShape<T>>;
|
|
2829
|
+
/** Çok satır, TEK statement. Satırların anahtar kümesi aynı olmalı. */
|
|
2830
|
+
insertMany(rows: readonly InsertValues<InsertShape<T>>[], opts?: {
|
|
2831
|
+
onConflict: readonly string[];
|
|
2832
|
+
action?: "ignore" | "update";
|
|
2833
|
+
}): Promise<RowShape<T>[]>;
|
|
2829
2834
|
put(q: {
|
|
2830
2835
|
data: InsertShape<T>;
|
|
2831
2836
|
onConflict: readonly string[];
|
|
@@ -2837,7 +2842,7 @@ interface TypedTable<T extends TableDef> {
|
|
|
2837
2842
|
where: {
|
|
2838
2843
|
id: string;
|
|
2839
2844
|
};
|
|
2840
|
-
set:
|
|
2845
|
+
set: SetShape<InsertShape<T>>;
|
|
2841
2846
|
}): Promise<RowShape<T> | null>;
|
|
2842
2847
|
delete(id: string): Promise<void>;
|
|
2843
2848
|
findById(id: string): Promise<RowShape<T> | null>;
|
|
@@ -2974,9 +2979,39 @@ declare function col<const N extends string>(name: N): ColRef<N>;
|
|
|
2974
2979
|
* kabul, `numeric ↔ text` ret olur ve ikisi de DOĞRU olur. Defterde teklif.
|
|
2975
2980
|
*/
|
|
2976
2981
|
type PgFamily<V> = [NonNullable<V>] extends [boolean] ? "bool" : [NonNullable<V>] extends [readonly (number | string)[]] ? "array" : [NonNullable<V>] extends [Date] ? "date" : [NonNullable<V>] extends [string | number] ? "scalar" : "opaque";
|
|
2977
|
-
/**
|
|
2982
|
+
/**
|
|
2983
|
+
* Kolonun BİLDİRİLMİŞ Postgres tipi — `env-gen`'in bastığı markadan.
|
|
2984
|
+
*
|
|
2985
|
+
* Marka yoksa `"?"`: elle yazılmış bir `Tables` (testler) ya da yeniden
|
|
2986
|
+
* üretilmemiş bir `palbase-env.d.ts`. O durumda eski TS-tipi sezgiseline
|
|
2987
|
+
* düşülüyor, çünkü marka olmadan söylenebilecek daha doğru bir şey yok.
|
|
2988
|
+
*/
|
|
2989
|
+
type PgTag<V> = [NonNullable<V>] extends [{
|
|
2990
|
+
readonly __pg?: infer N;
|
|
2991
|
+
}] ? [N] extends [string] ? N : "?" : "?";
|
|
2992
|
+
/**
|
|
2993
|
+
* Postgres'te birbirleriyle karşılaştırılabilen tipler tek "cins".
|
|
2994
|
+
*
|
|
2995
|
+
* `integer`, `bigint` ve `numeric` örtük sayısal dönüşümle karşılaştırılır;
|
|
2996
|
+
* geri kalan her tip yalnız kendisiyle. `uuid ↔ text` ve `enum ↔ text`
|
|
2997
|
+
* Postgres'te `operator does not exist` verir — D-021'de CANLI ölçülmüştü ve
|
|
2998
|
+
* tip bunu göremediği için kabul ediyordu.
|
|
2999
|
+
*/
|
|
3000
|
+
type PgKind<P> = P extends "integer" | "bigint" | "numeric" ? "num" : P;
|
|
3001
|
+
/** İki tarafın da markası var mı — yoksa sezgisele düşülür. */
|
|
3002
|
+
type BothBranded<A, B> = "?" extends PgTag<A> ? false : "?" extends PgTag<B> ? false : true;
|
|
3003
|
+
type PgSameKind<A, B> = [PgKind<PgTag<A>>] extends [PgKind<PgTag<B>>] ? [PgKind<PgTag<B>>] extends [PgKind<PgTag<A>>] ? true : false : false;
|
|
3004
|
+
/**
|
|
3005
|
+
* `A` kolonu `B` ile karşılaştırılabilir mi.
|
|
3006
|
+
*
|
|
3007
|
+
* Marka varsa CEVAP KESİN: ne yanlış ret ne yanlış kabul. D-021 bu kuralı
|
|
3008
|
+
* "doğru olamaz" diye kaydetmişti çünkü tipte ayırt edecek bilgi yoktu; bilgi
|
|
3009
|
+
* artık tipte.
|
|
3010
|
+
*/
|
|
3011
|
+
type ColComparable<A, B> = BothBranded<A, B> extends true ? PgSameKind<A, B> : [PgFamily<A>] extends [PgFamily<B>] ? true : false;
|
|
3012
|
+
/** `Row`'un `V` ile karşılaştırılabilir kolonları. */
|
|
2978
3013
|
type ColumnsComparableTo<Row, V> = {
|
|
2979
|
-
[K in keyof Row]-?:
|
|
3014
|
+
[K in keyof Row]-?: ColComparable<Row[K], V> extends true ? K : never;
|
|
2980
3015
|
}[keyof Row];
|
|
2981
3016
|
/**
|
|
2982
3017
|
* Bu satırın kolonlarından birine referans. `Row` bilinmiyorsa hiçbiri.
|
|
@@ -3063,7 +3098,7 @@ type TextOps<V> = V extends string ? {
|
|
|
3063
3098
|
* kolonunda YASAKLAMAK yazarı bu yüzden `sqlFragment`e düşürürdü — ve bu
|
|
3064
3099
|
* özelliğin var olma nedeni tam olarak o düşüşü kaldırmak.
|
|
3065
3100
|
*/
|
|
3066
|
-
type NowComparable<V> = [NonNullable<V>] extends [string | Date] ? TxNow : never;
|
|
3101
|
+
type NowComparable<V> = "?" extends PgTag<V> ? [NonNullable<V>] extends [string | Date] ? TxNow : never : PgTag<V> extends "timestamp" ? TxNow : never;
|
|
3067
3102
|
type WhereOpBody<V, C> = {
|
|
3068
3103
|
gt?: V | C | NowComparable<V>;
|
|
3069
3104
|
gte?: V | C | NowComparable<V>;
|
|
@@ -3257,7 +3292,25 @@ type MutateInput<Row, Insert, Rels = unknown> = {
|
|
|
3257
3292
|
* string de sayısal sayılır; ayrımı burada yapamayız, ama D-007 zaten miktarın
|
|
3258
3293
|
* JS `number`'a hiç uğramamasını istiyor.
|
|
3259
3294
|
*/
|
|
3260
|
-
|
|
3295
|
+
/** `increment()`/`decrement()` HANGİ kolonlarda anlamlı — bildirilmiş PG tipine
|
|
3296
|
+
* göre. Marka yoksa eski sezgisel (`number | string`), ki o `text` kolonda da
|
|
3297
|
+
* izin veriyordu: Postgres `text + 1` demez. */
|
|
3298
|
+
type NumericCol<V> = "?" extends PgTag<V> ? NonNullable<V> extends number | string ? TxColumnExpr : never : PgKind<PgTag<V>> extends "num" ? TxColumnExpr : never;
|
|
3299
|
+
/**
|
|
3300
|
+
* Bir EKLEME yolunda yazılabilecek değer.
|
|
3301
|
+
*
|
|
3302
|
+
* Kolonun kendi tipi ya da — zaman kolonlarında — sunucu saati. `increment()`
|
|
3303
|
+
* burada YOK ve olamaz: satır henüz yokken "kolonun şu anki değeri" diye bir
|
|
3304
|
+
* şey yok, motor da bunu adıyla reddediyor.
|
|
3305
|
+
*
|
|
3306
|
+
* Var olma nedeni ölçülmüş: introspect edilmiş şemalarda zaman kolonlarının
|
|
3307
|
+
* çoğu varsayılansız (`timestamp()`), yani "eklerken sunucu saatini yaz"ın tek
|
|
3308
|
+
* karşılığı istemci saatiydi — 33 tablolu bir projede 12 yerde.
|
|
3309
|
+
*/
|
|
3310
|
+
type InsertValues<Insert> = {
|
|
3311
|
+
[K in keyof Insert]: Insert[K] | NowComparable<Insert[K]>;
|
|
3312
|
+
};
|
|
3313
|
+
type SetValue<V> = V | NumericCol<V> | NowComparable<V>;
|
|
3261
3314
|
/** Bir update'in `set`'i: insert şeklinin herhangi bir alt kümesi, ifadelerle. */
|
|
3262
3315
|
type SetShape<Insert> = {
|
|
3263
3316
|
[K in keyof Insert]?: SetValue<Insert[K]>;
|
|
@@ -3340,7 +3393,30 @@ type RelsOf<T> = T extends {
|
|
|
3340
3393
|
} ? R : unknown;
|
|
3341
3394
|
/** Temel tablo erişimcisi — search'süz beş op. */
|
|
3342
3395
|
interface EnvTypedTableBase<T extends TableTypes> {
|
|
3343
|
-
insert(data: T["insert"]): Promise<T["row"]>;
|
|
3396
|
+
insert(data: InsertValues<T["insert"]>): Promise<T["row"]>;
|
|
3397
|
+
/**
|
|
3398
|
+
* Çok satırı TEK statement'la ekle (tek gidiş-dönüş).
|
|
3399
|
+
*
|
|
3400
|
+
* ```ts
|
|
3401
|
+
* await Database.public.journey_stops.insertMany(
|
|
3402
|
+
* stops.map((s, i) => ({ journey_id, name: s.name, sort_order: i })),
|
|
3403
|
+
* );
|
|
3404
|
+
* ```
|
|
3405
|
+
*
|
|
3406
|
+
* Satırların anahtar kümesi AYNI olmalı: tek statement kolon listesini
|
|
3407
|
+
* paylaşır, yani farklı şekilli bir satırın fazla kolonu sessizce yazılmaz
|
|
3408
|
+
* ve eksiği yanlış sütuna kayardı. Eksik alan için `null` yazın.
|
|
3409
|
+
*
|
|
3410
|
+
* Boş dizi boş sonuç döner — hata değil: "eklenecek bir şey yoktu".
|
|
3411
|
+
*/
|
|
3412
|
+
insertMany(rows: readonly InsertValues<T["insert"]>[], opts?: {
|
|
3413
|
+
/** Çakışmanın ARANDIĞI kolonlar — benzersiz bir kısıt ya da index taşımalı. */
|
|
3414
|
+
onConflict: readonly Extract<keyof T["row"], string>[];
|
|
3415
|
+
/** `"ignore"` (VARSAYILAN, plan yoluyla aynı) çakışanı atlar ve o satır
|
|
3416
|
+
* SONUÇTA DÖNMEZ — Postgres yalnız yazdıklarını döndürür; `"update"`
|
|
3417
|
+
* üzerine yazar. */
|
|
3418
|
+
action?: "ignore" | "update";
|
|
3419
|
+
}): Promise<T["row"][]>;
|
|
3344
3420
|
/**
|
|
3345
3421
|
* Bir idempotency anahtarını sahiplen (FR-033).
|
|
3346
3422
|
*
|
|
@@ -3356,7 +3432,7 @@ interface EnvTypedTableBase<T extends TableTypes> {
|
|
|
3356
3432
|
* İlk argüman satırı BULAN alanlar, ikincisi yalnız yazılanlar — ikinci çağrı
|
|
3357
3433
|
* farklı bir yük gönderse bile satır anahtarla bulunur.
|
|
3358
3434
|
*/
|
|
3359
|
-
claim(unique: Partial<T["insert"]>, extra?: Partial<T["insert"]
|
|
3435
|
+
claim(unique: Partial<T["insert"]>, extra?: Partial<InsertValues<T["insert"]>>): Promise<{
|
|
3360
3436
|
inserted: boolean;
|
|
3361
3437
|
row: T["row"];
|
|
3362
3438
|
}>;
|
|
@@ -3381,7 +3457,7 @@ interface EnvTypedTableBase<T extends TableTypes> {
|
|
|
3381
3457
|
* seçmeyi kolay yapıyordu.
|
|
3382
3458
|
*/
|
|
3383
3459
|
put(q: {
|
|
3384
|
-
data: T["insert"]
|
|
3460
|
+
data: InsertValues<T["insert"]>;
|
|
3385
3461
|
onConflict: readonly Extract<keyof T["row"], string>[];
|
|
3386
3462
|
}): Promise<T["row"]>;
|
|
3387
3463
|
/** Update the row by id; resolves to the updated row, or `null` if no row
|
|
@@ -3391,7 +3467,7 @@ interface EnvTypedTableBase<T extends TableTypes> {
|
|
|
3391
3467
|
where: {
|
|
3392
3468
|
id: string;
|
|
3393
3469
|
};
|
|
3394
|
-
set:
|
|
3470
|
+
set: SetShape<T["insert"]>;
|
|
3395
3471
|
}): Promise<T["row"] | null>;
|
|
3396
3472
|
delete(id: string): Promise<void>;
|
|
3397
3473
|
findById(id: string): Promise<T["row"] | null>;
|
|
@@ -3426,7 +3502,7 @@ interface EnvTypedTableBase<T extends TableTypes> {
|
|
|
3426
3502
|
* kapanır (valid_to/superseded_by), yenisi TEK savepoint'te eklenir; dönüş
|
|
3427
3503
|
* yeni satır. Validity beyanı olmayan tabloda adlandırılmış çalışma-zamanı
|
|
3428
3504
|
* hatası — tip düzeyinde ayrım env `Tables` bayrağı taşımadığından yapılamaz. */
|
|
3429
|
-
supersede(id: string, row: T["insert"]): Promise<T["row"]>;
|
|
3505
|
+
supersede(id: string, row: InsertValues<T["insert"]>): Promise<T["row"]>;
|
|
3430
3506
|
}
|
|
3431
3507
|
/** Tablo erişimcisi: env girdisi `searchable: true` taşıyorsa (vector kolonu ya da
|
|
3432
3508
|
* search beyanı — env-gen üretir) `search()` üyesi VARDIR; yoksa üye hiç yoktur ve
|
|
@@ -4362,6 +4438,13 @@ interface DBOps {
|
|
|
4362
4438
|
*/
|
|
4363
4439
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
4364
4440
|
insert(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
4441
|
+
/** Çok satır, TEK statement. Satırların anahtar kümesi aynı olmalı — kolon
|
|
4442
|
+
* listesi paylaşıldığı için farklı şekilli bir satırın kolonu sessizce
|
|
4443
|
+
* yazılmazdı. */
|
|
4444
|
+
insertMany(table: string, rows: readonly Record<string, unknown>[], opts?: {
|
|
4445
|
+
onConflict: readonly string[];
|
|
4446
|
+
action?: "ignore" | "update";
|
|
4447
|
+
}): Promise<Record<string, unknown>[]>;
|
|
4365
4448
|
/**
|
|
4366
4449
|
* Insert the row, or update it when it collides on `onConflict` — one
|
|
4367
4450
|
* statement, so two concurrent callers cannot both lose.
|