@palbase/backend 35.0.1 → 36.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 +556 -487
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +6 -6
- package/dist/{chunk-L4R7WXLH.js → chunk-7WAGQ3VR.js} +4 -171
- package/dist/chunk-7WAGQ3VR.js.map +1 -0
- package/dist/{chunk-UMESJJRS.js → chunk-CS6NQ6PO.js} +2 -1
- package/dist/chunk-CS6NQ6PO.js.map +1 -0
- package/dist/{chunk-BOD3DT6D.js → chunk-EHKEMHB4.js} +560 -430
- package/dist/chunk-EHKEMHB4.js.map +1 -0
- package/dist/{chunk-PRH45NZU.js → chunk-FFO36MQQ.js} +2 -45
- package/dist/chunk-FFO36MQQ.js.map +1 -0
- package/dist/{chunk-P7MGSAFT.js → chunk-LFUNRWUE.js} +1 -40
- package/dist/chunk-LFUNRWUE.js.map +1 -0
- package/dist/{chunk-RZLY4BOY.js → chunk-PDD55QWN.js} +2 -2
- package/dist/{chunk-YO5GYM73.js → chunk-X7UR3VXA.js} +5 -6
- package/dist/chunk-X7UR3VXA.js.map +1 -0
- package/dist/{chunk-6FEHCEB7.js → chunk-YANGWAIM.js} +3 -3
- package/dist/db/index.cjs +1 -232
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +3 -46
- package/dist/db/index.d.ts +3 -46
- package/dist/db/index.js +4 -12
- package/dist/engine/index.cjs +556 -487
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +4 -4
- package/dist/engine/index.d.ts +4 -4
- package/dist/engine/index.js +6 -6
- package/dist/{index-DllNjpTl.d.cts → index-CI7S0Wqv.d.cts} +61 -8
- package/dist/{endpoint-BI0yGuEL.d.ts → index-CUy50OLU.d.ts} +6 -82
- package/dist/{endpoint-DaGnjt42.d.cts → index-DRx880KY.d.cts} +6 -82
- package/dist/{index-E8Sd6NFy.d.ts → index-Ogi30dbt.d.ts} +61 -8
- package/dist/index.cjs +5 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -7
- package/dist/index.d.ts +6 -7
- package/dist/index.js +7 -15
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +1 -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 +2 -2
- package/dist/{registry-BnKvIyve.d.cts → registry-C7UCkQf0.d.cts} +1 -1
- package/dist/{registry-zDCj0eOU.d.ts → registry-DJcvbomD.d.ts} +1 -1
- package/dist/test/index.cjs +3 -11
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +2 -2
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +2 -9
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +2 -60
- package/docs/examples/database-dx.ts +12 -17
- package/docs/llms-full.txt +3 -61
- package/package.json +1 -1
- package/stager/inferred_returns.js +153 -0
- package/stager/return_types.js +9 -4
- package/stager/stage.js +3 -1
- package/template/AGENTS.md +5 -5
- package/template/package.json +2 -2
- package/dist/chunk-BOD3DT6D.js.map +0 -1
- package/dist/chunk-L4R7WXLH.js.map +0 -1
- package/dist/chunk-P7MGSAFT.js.map +0 -1
- package/dist/chunk-PRH45NZU.js.map +0 -1
- package/dist/chunk-UMESJJRS.js.map +0 -1
- package/dist/chunk-YO5GYM73.js.map +0 -1
- package/docs/examples/check-query-contracts.ts +0 -5
- package/docs/examples/database-dx.contract.json +0 -65
- /package/dist/{chunk-RZLY4BOY.js.map → chunk-PDD55QWN.js.map} +0 -0
- /package/dist/{chunk-6FEHCEB7.js.map → chunk-YANGWAIM.js.map} +0 -0
|
@@ -1,6 +1,54 @@
|
|
|
1
|
-
import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps,
|
|
1
|
+
import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, f as RawPageOptions, P as Page, g as TxPlanBody, C as CommandOptions, h as TxPlanResponse, A as AuthSpec, i as CacheClient, b as RuntimeServices, _ as __runWithRuntime, j as __requestALS } from './index-CUy50OLU.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-DJcvbomD.js';
|
|
4
|
+
|
|
5
|
+
interface AdmissionLease {
|
|
6
|
+
queueMs: number;
|
|
7
|
+
release(): void;
|
|
8
|
+
}
|
|
9
|
+
/** Deployment settings, never a query/workload declaration in application code. */
|
|
10
|
+
interface DatabaseAdmissionOptions {
|
|
11
|
+
concurrency: number;
|
|
12
|
+
queueLimit?: number;
|
|
13
|
+
queueTimeoutMs?: number;
|
|
14
|
+
/** Optional signed, issuer-controlled top-level tenant claim. By default
|
|
15
|
+
* fairness uses verified sub, not the installation-wide tenant_id. */
|
|
16
|
+
tenantClaim?: string;
|
|
17
|
+
onReject?: (event: {
|
|
18
|
+
reason: "full" | "timeout" | "cancelled";
|
|
19
|
+
active: number;
|
|
20
|
+
queued: number;
|
|
21
|
+
}) => void;
|
|
22
|
+
}
|
|
23
|
+
declare class DatabaseAdmission {
|
|
24
|
+
readonly options: DatabaseAdmissionOptions;
|
|
25
|
+
private active;
|
|
26
|
+
private queued;
|
|
27
|
+
private tenants;
|
|
28
|
+
private pending;
|
|
29
|
+
private lastTenant?;
|
|
30
|
+
private accepted;
|
|
31
|
+
private rejected;
|
|
32
|
+
private readonly limit;
|
|
33
|
+
private readonly timeout;
|
|
34
|
+
constructor(options: DatabaseAdmissionOptions);
|
|
35
|
+
get snapshot(): {
|
|
36
|
+
active: number;
|
|
37
|
+
queued: number;
|
|
38
|
+
tenants: number;
|
|
39
|
+
accepted: number;
|
|
40
|
+
rejected: {
|
|
41
|
+
full: number;
|
|
42
|
+
timeout: number;
|
|
43
|
+
cancelled: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
private rejection;
|
|
47
|
+
private take;
|
|
48
|
+
private drain;
|
|
49
|
+
acquire(claimsJson: string, signal?: AbortSignal): Promise<AdmissionLease>;
|
|
50
|
+
}
|
|
51
|
+
declare function databaseAdmission(owner: object, options?: DatabaseAdmissionOptions): DatabaseAdmission;
|
|
4
52
|
|
|
5
53
|
/**
|
|
6
54
|
* engine/config.ts — settings from the environment, and the gate that refuses
|
|
@@ -70,6 +118,8 @@ interface EngineConfig {
|
|
|
70
118
|
*/
|
|
71
119
|
dbServiceRole: string;
|
|
72
120
|
poolMax: number;
|
|
121
|
+
/** Internal engine/core deployment policy; application CRUD has no capacity options. */
|
|
122
|
+
databaseAdmission?: Omit<DatabaseAdmissionOptions, "concurrency">;
|
|
73
123
|
databaseDiagnostics?: DatabaseDiagnosticsOptions;
|
|
74
124
|
}
|
|
75
125
|
/**
|
|
@@ -121,7 +171,7 @@ declare class TransactionControl {
|
|
|
121
171
|
dispose(): void;
|
|
122
172
|
}
|
|
123
173
|
|
|
124
|
-
type Timing = "queueMs" | "poolMs" | "setupMs" | "sqlMs" | "commitMs" | "rollbackMs";
|
|
174
|
+
type Timing = "queueMs" | "poolMs" | "setupMs" | "sqlMs" | "commitMs" | "rollbackMs" | "connectionMs";
|
|
125
175
|
/** Allocated only when diagnostics or a budget is configured. One collector
|
|
126
176
|
* follows the request's user/service handles and independent atomic attempts. */
|
|
127
177
|
declare class DatabaseTrace {
|
|
@@ -147,6 +197,8 @@ declare class DatabaseTrace {
|
|
|
147
197
|
|
|
148
198
|
/** The slice of a SQL driver the engine uses. `Bun.sql` satisfies it. */
|
|
149
199
|
interface SqlDriver {
|
|
200
|
+
/** Shared by every request and identity using this physical application pool. */
|
|
201
|
+
admission?: DatabaseAdmission;
|
|
150
202
|
/** Optional reliable cancellation through a separate control connection. */
|
|
151
203
|
cancelBackend?(pid: number, startedAt: string): Promise<void>;
|
|
152
204
|
/** Run a parameterised statement. */
|
|
@@ -225,7 +277,7 @@ interface OpsContext {
|
|
|
225
277
|
readonly commands?: boolean;
|
|
226
278
|
readonly trace?: DatabaseTrace;
|
|
227
279
|
}
|
|
228
|
-
declare function createOps(tx: TxLike, context?: OpsContext): {
|
|
280
|
+
declare function createOps(tx: TxLike | (() => TxLike | Promise<TxLike>), context?: OpsContext): {
|
|
229
281
|
diagnostics(): DatabaseDiagnostics | null;
|
|
230
282
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
231
283
|
insert(table: string, data: Row): Promise<Row>;
|
|
@@ -380,9 +432,6 @@ declare function createOps(tx: TxLike, context?: OpsContext): {
|
|
|
380
432
|
with?: Record<string, unknown>;
|
|
381
433
|
}): Promise<Row | null>;
|
|
382
434
|
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[]>;
|
|
386
435
|
findMany(table: string, query?: Row, opts?: FindManyOptions): Promise<Row[]>;
|
|
387
436
|
page(table: string, query?: Row, opts?: RawPageOptions): Promise<Page<Row>>;
|
|
388
437
|
/**
|
|
@@ -557,6 +606,8 @@ declare function withTables<T extends ReturnType<typeof createOps>>(ops: T, sche
|
|
|
557
606
|
interface RequestDatabase {
|
|
558
607
|
/** What the engine injects as the request's `Database` singleton. */
|
|
559
608
|
readonly client: DBClient;
|
|
609
|
+
/** @internal Core has finished its read-only authorization queries. */
|
|
610
|
+
authorizationComplete?(): void;
|
|
560
611
|
/** Commit whatever was opened. Called once, after the handler returns. */
|
|
561
612
|
commit(): Promise<void>;
|
|
562
613
|
/** Roll back whatever was opened. Called once, when the handler throws. */
|
|
@@ -619,7 +670,7 @@ declare function createRequestDatabase(sql: SqlDriver, identity: {
|
|
|
619
670
|
role: string;
|
|
620
671
|
serviceRole: string;
|
|
621
672
|
claimsJson: string;
|
|
622
|
-
}, diagnostics?: DatabaseDiagnosticsOptions): RequestDatabase;
|
|
673
|
+
}, diagnostics?: DatabaseDiagnosticsOptions, signal?: AbortSignal): RequestDatabase;
|
|
623
674
|
|
|
624
675
|
/**
|
|
625
676
|
* The two ways a stack refuses to boot — and they are two because their CURES
|
|
@@ -1100,6 +1151,8 @@ interface CreateAppOptions {
|
|
|
1100
1151
|
logger?: Pick<Console, "info" | "warn" | "error" | "debug">;
|
|
1101
1152
|
}
|
|
1102
1153
|
interface App {
|
|
1154
|
+
/** Core/operator observation of the shared physical pool's admission queue. */
|
|
1155
|
+
readonly databasePressure?: ReturnType<typeof databaseAdmission>["snapshot"];
|
|
1103
1156
|
handle: (req: Request) => Promise<Response>;
|
|
1104
1157
|
routes: readonly RouteEntry[];
|
|
1105
1158
|
config: EngineConfig;
|
package/dist/index.cjs
CHANGED
|
@@ -102,7 +102,6 @@ __export(src_exports, {
|
|
|
102
102
|
__runWithRuntime: () => __runWithRuntime,
|
|
103
103
|
__setRuntime: () => __setRuntime,
|
|
104
104
|
assertNoOrphanEntryPoints: () => assertNoOrphanEntryPoints,
|
|
105
|
-
assertQueryManifest: () => assertQueryManifest,
|
|
106
105
|
assertZeroArgConstructor: () => assertZeroArgConstructor,
|
|
107
106
|
bigint: () => bigint,
|
|
108
107
|
boolean: () => boolean,
|
|
@@ -117,10 +116,8 @@ __export(src_exports, {
|
|
|
117
116
|
defineDefaultAuth: () => defineDefaultAuth,
|
|
118
117
|
defineError: () => defineError,
|
|
119
118
|
defineMiddleware: () => defineMiddleware,
|
|
120
|
-
defineQuery: () => defineQuery,
|
|
121
119
|
defineSchema: () => defineSchema,
|
|
122
120
|
defineTable: () => defineTable,
|
|
123
|
-
defineWorkload: () => defineWorkload,
|
|
124
121
|
enumType: () => enumType,
|
|
125
122
|
exprCtx: () => exprCtx,
|
|
126
123
|
getErrorRegistry: () => getErrorRegistry,
|
|
@@ -156,7 +153,6 @@ __export(src_exports, {
|
|
|
156
153
|
ownerOnly: () => ownerOnly,
|
|
157
154
|
policy: () => policy,
|
|
158
155
|
publicChannel: () => publicChannel,
|
|
159
|
-
queryManifest: () => queryManifest,
|
|
160
156
|
raw: () => raw,
|
|
161
157
|
recordThrows: () => recordThrows,
|
|
162
158
|
resolveEffectiveAuth: () => resolveEffectiveAuth,
|
|
@@ -170,7 +166,7 @@ __export(src_exports, {
|
|
|
170
166
|
vector: () => vector,
|
|
171
167
|
webhooksOf: () => webhooksOf,
|
|
172
168
|
withRetry: () => withRetry,
|
|
173
|
-
z: () =>
|
|
169
|
+
z: () => import_zod3.z
|
|
174
170
|
});
|
|
175
171
|
module.exports = __toCommonJS(src_exports);
|
|
176
172
|
|
|
@@ -746,39 +742,6 @@ function translateRejection(err, builder) {
|
|
|
746
742
|
}
|
|
747
743
|
__name(translateRejection, "translateRejection");
|
|
748
744
|
|
|
749
|
-
// src/db/workload.ts
|
|
750
|
-
function defineWorkload(name, options) {
|
|
751
|
-
const result = {
|
|
752
|
-
name,
|
|
753
|
-
concurrency: options.concurrency,
|
|
754
|
-
queueLimit: options.queueLimit,
|
|
755
|
-
tenantConcurrency: options.tenantConcurrency ?? options.concurrency,
|
|
756
|
-
tenantQueueLimit: options.tenantQueueLimit ?? options.queueLimit,
|
|
757
|
-
queueTimeoutMs: options.queueTimeoutMs ?? 1e3,
|
|
758
|
-
tenantClaim: options.tenantClaim ?? "tenant_id"
|
|
759
|
-
};
|
|
760
|
-
validateWorkload(result);
|
|
761
|
-
return Object.freeze(result);
|
|
762
|
-
}
|
|
763
|
-
__name(defineWorkload, "defineWorkload");
|
|
764
|
-
function validateWorkload(value) {
|
|
765
|
-
if (typeof value.name !== "string" || !/^[a-zA-Z][a-zA-Z0-9_.-]{0,63}$/.test(value.name)) throw new Error("workload name must be 1\u201364 letters/digits/dots/dashes");
|
|
766
|
-
for (const name of [
|
|
767
|
-
"concurrency",
|
|
768
|
-
"tenantConcurrency",
|
|
769
|
-
"queueLimit",
|
|
770
|
-
"tenantQueueLimit",
|
|
771
|
-
"queueTimeoutMs"
|
|
772
|
-
]) {
|
|
773
|
-
const n = value[name], min = name.endsWith("Limit") ? 0 : 1;
|
|
774
|
-
const max = name === "queueTimeoutMs" ? 6e4 : name.endsWith("Limit") ? 1e4 : 1e3;
|
|
775
|
-
if (!Number.isInteger(n) || n < min || n > max) throw new Error(`workload ${name} must be an integer between ${min} and ${max}`);
|
|
776
|
-
}
|
|
777
|
-
if (value.tenantConcurrency > value.concurrency || value.tenantQueueLimit > value.queueLimit) throw new Error("workload tenant limits cannot exceed global limits");
|
|
778
|
-
if (typeof value.tenantClaim !== "string" || !/^[a-zA-Z][a-zA-Z0-9_]{0,63}$/.test(value.tenantClaim)) throw new Error("workload tenantClaim must be a top-level claim name");
|
|
779
|
-
}
|
|
780
|
-
__name(validateWorkload, "validateWorkload");
|
|
781
|
-
|
|
782
745
|
// src/db/transaction-options.ts
|
|
783
746
|
function retryBudget(value) {
|
|
784
747
|
const n = value ?? 0;
|
|
@@ -1237,7 +1200,9 @@ function makeTableProxy(ops, prefix) {
|
|
|
1237
1200
|
// Older than this run, but the run rewrote this proxy for
|
|
1238
1201
|
// `Database.schema(name).tables.*` and would have carried the gap onto
|
|
1239
1202
|
// the new surface too.
|
|
1240
|
-
updateMany: /* @__PURE__ */ __name((q) => ops().updateMany(name, q.where, q.set
|
|
1203
|
+
updateMany: /* @__PURE__ */ __name((q) => ops().updateMany(name, q.where, q.set, q.returning === void 0 ? void 0 : {
|
|
1204
|
+
returning: q.returning
|
|
1205
|
+
}), "updateMany"),
|
|
1241
1206
|
deleteMany: /* @__PURE__ */ __name((q) => ops().deleteMany(name, q.where), "deleteMany"),
|
|
1242
1207
|
count: /* @__PURE__ */ __name((q) => ops().count(name, q?.where), "count"),
|
|
1243
1208
|
search: /* @__PURE__ */ __name((params) => ops().search(name, params), "search"),
|
|
@@ -1257,9 +1222,6 @@ function makeTypedSurface(raw2) {
|
|
|
1257
1222
|
const ops = {
|
|
1258
1223
|
$query: /* @__PURE__ */ __name((sql, params) => raw2.query(sql, params), "$query"),
|
|
1259
1224
|
$diagnostics: /* @__PURE__ */ __name(() => raw2.diagnostics(), "$diagnostics"),
|
|
1260
|
-
$readQuery: /* @__PURE__ */ __name((query) => raw2.readQuery(query), "$readQuery"),
|
|
1261
|
-
$compileQuery: /* @__PURE__ */ __name((query) => raw2.compileQuery(query), "$compileQuery"),
|
|
1262
|
-
$explainQuery: /* @__PURE__ */ __name((query) => raw2.explainQuery(query), "$explainQuery"),
|
|
1263
1225
|
$insert: /* @__PURE__ */ __name((table, data) => raw2.insert(table, data), "$insert"),
|
|
1264
1226
|
$update: /* @__PURE__ */ __name((table, id, data) => raw2.update(table, id, data), "$update"),
|
|
1265
1227
|
$delete: /* @__PURE__ */ __name((table, id) => raw2.delete(table, id), "$delete"),
|
|
@@ -3057,13 +3019,6 @@ function defineTable(name, input) {
|
|
|
3057
3019
|
}
|
|
3058
3020
|
__name(defineTable, "defineTable");
|
|
3059
3021
|
var declaringSchemaOf = /* @__PURE__ */ new WeakMap();
|
|
3060
|
-
function declaredTableKey(table) {
|
|
3061
|
-
const metadata = table[TABLE_META];
|
|
3062
|
-
const schema = declaringSchemaOf.get(metadata);
|
|
3063
|
-
if (schema === void 0) throw new Error(`defineQuery: table ${metadata.name} must belong to defineSchema before defining its query`);
|
|
3064
|
-
return qualifiedTableKey(schema, metadata.name);
|
|
3065
|
-
}
|
|
3066
|
-
__name(declaredTableKey, "declaredTableKey");
|
|
3067
3022
|
function resolveReferences(tables, schemaName) {
|
|
3068
3023
|
for (const table of Object.values(tables)) {
|
|
3069
3024
|
for (const [colName, builder] of Object.entries(table.columns)) {
|
|
@@ -3667,6 +3622,7 @@ var openai = {
|
|
|
3667
3622
|
var SQLSTATE = Object.freeze({
|
|
3668
3623
|
serializationFailure: "40001",
|
|
3669
3624
|
deadlockDetected: "40P01",
|
|
3625
|
+
queryCancelled: "57014",
|
|
3670
3626
|
commandGuardFailed: "PBC01"
|
|
3671
3627
|
});
|
|
3672
3628
|
function isTransactionRollbackState(state) {
|
|
@@ -3891,9 +3847,6 @@ function makeTypedDB(schema, raw2) {
|
|
|
3891
3847
|
const result = {
|
|
3892
3848
|
tables,
|
|
3893
3849
|
diagnostics: /* @__PURE__ */ __name(() => raw2.diagnostics(), "diagnostics"),
|
|
3894
|
-
readQuery: /* @__PURE__ */ __name((query) => raw2.readQuery(query), "readQuery"),
|
|
3895
|
-
compileQuery: /* @__PURE__ */ __name((query) => raw2.compileQuery(query), "compileQuery"),
|
|
3896
|
-
explainQuery: /* @__PURE__ */ __name((query) => raw2.explainQuery(query), "explainQuery"),
|
|
3897
3850
|
command(fn, options) {
|
|
3898
3851
|
const builder = new TxPlanBuilder();
|
|
3899
3852
|
const planTables = Object.fromEntries(Object.entries(schema.tables).map(([key, table]) => [
|
|
@@ -5723,188 +5676,7 @@ function getJobConfig(ctor, container) {
|
|
|
5723
5676
|
__name(getJobConfig, "getJobConfig");
|
|
5724
5677
|
|
|
5725
5678
|
// src/index.ts
|
|
5726
|
-
var import_zod4 = require("zod");
|
|
5727
|
-
|
|
5728
|
-
// src/db/query.ts
|
|
5729
5679
|
var import_zod3 = require("zod");
|
|
5730
|
-
var import_zod_to_openapi2 = require("@asteasolutions/zod-to-openapi");
|
|
5731
|
-
|
|
5732
|
-
// src/db/query-contract.ts
|
|
5733
|
-
function queryColumnContract(column) {
|
|
5734
|
-
const def = column && typeof column === "object" && "_def" in column ? column._def : column;
|
|
5735
|
-
if (!def?.type) throw new Error("Query contract requires declared column types");
|
|
5736
|
-
if (def.transform !== void 0 && def.codec === void 0) throw new Error("Query contracts require a named codec instead of a free-form column transform");
|
|
5737
|
-
return {
|
|
5738
|
-
type: def.type,
|
|
5739
|
-
nullable: def.nullable === true,
|
|
5740
|
-
...def.codec === void 0 ? {} : {
|
|
5741
|
-
codec: def.codec
|
|
5742
|
-
},
|
|
5743
|
-
...def.enumValues === void 0 ? {} : {
|
|
5744
|
-
enumValues: [
|
|
5745
|
-
...def.enumValues
|
|
5746
|
-
]
|
|
5747
|
-
},
|
|
5748
|
-
...def.dimensions === void 0 ? {} : {
|
|
5749
|
-
dimensions: def.dimensions
|
|
5750
|
-
}
|
|
5751
|
-
};
|
|
5752
|
-
}
|
|
5753
|
-
__name(queryColumnContract, "queryColumnContract");
|
|
5754
|
-
function stableContract(value) {
|
|
5755
|
-
if (Array.isArray(value)) return `[${value.map(stableContract).join(",")}]`;
|
|
5756
|
-
if (value && typeof value === "object") return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableContract(value[key])}`).join(",")}}`;
|
|
5757
|
-
return JSON.stringify(value) ?? "null";
|
|
5758
|
-
}
|
|
5759
|
-
__name(stableContract, "stableContract");
|
|
5760
|
-
|
|
5761
|
-
// src/db/query.ts
|
|
5762
|
-
(0, import_zod_to_openapi2.extendZodWithOpenApi)(import_zod3.z);
|
|
5763
|
-
function responseColumn(column, validator) {
|
|
5764
|
-
const contract = queryColumnContract(column);
|
|
5765
|
-
let schema;
|
|
5766
|
-
if (validator) return validator;
|
|
5767
|
-
if (contract.codec === "number") schema = import_zod3.z.number().finite();
|
|
5768
|
-
else if (contract.codec === "decimal") schema = import_zod3.z.string();
|
|
5769
|
-
else switch (contract.type) {
|
|
5770
|
-
case "integer":
|
|
5771
|
-
schema = import_zod3.z.number().int().min(-2147483648).max(2147483647);
|
|
5772
|
-
break;
|
|
5773
|
-
case "boolean":
|
|
5774
|
-
schema = import_zod3.z.boolean();
|
|
5775
|
-
break;
|
|
5776
|
-
case "vector":
|
|
5777
|
-
schema = import_zod3.z.array(import_zod3.z.number().finite());
|
|
5778
|
-
break;
|
|
5779
|
-
case "enum": {
|
|
5780
|
-
const values = contract.enumValues;
|
|
5781
|
-
if (!values?.length) throw new Error("Query response requires declared enum values");
|
|
5782
|
-
schema = import_zod3.z.enum(values);
|
|
5783
|
-
break;
|
|
5784
|
-
}
|
|
5785
|
-
case "uuid":
|
|
5786
|
-
case "text":
|
|
5787
|
-
case "timestamp":
|
|
5788
|
-
case "numeric":
|
|
5789
|
-
case "bigint":
|
|
5790
|
-
schema = import_zod3.z.string();
|
|
5791
|
-
break;
|
|
5792
|
-
case "jsonb":
|
|
5793
|
-
throw new Error("Query response requires a fields validator for a selected jsonb column: its TypeScript payload is erased at runtime");
|
|
5794
|
-
default:
|
|
5795
|
-
throw new Error(`Query response does not support column type ${contract.type}`);
|
|
5796
|
-
}
|
|
5797
|
-
return contract.nullable ? schema.nullable() : schema;
|
|
5798
|
-
}
|
|
5799
|
-
__name(responseColumn, "responseColumn");
|
|
5800
|
-
function defineQuery(name, options) {
|
|
5801
|
-
if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_]{0,127}$/.test(name)) throw new Error("defineQuery requires a stable name of 1\u2013128 letters, digits or underscores");
|
|
5802
|
-
const table = declaredTableKey(options.table);
|
|
5803
|
-
const select = [
|
|
5804
|
-
...options.select
|
|
5805
|
-
];
|
|
5806
|
-
if (!select.length || new Set(select).size !== select.length) throw new Error(`Query ${name}: select must be explicit, nonempty and distinct`);
|
|
5807
|
-
const shape = {}, columns = {};
|
|
5808
|
-
for (const key of select) {
|
|
5809
|
-
if (!Object.hasOwn(options.table[TABLE_META].columns, key)) throw new Error(`Query ${name}: unknown column ${key}`);
|
|
5810
|
-
columns[key] = queryColumnContract(options.table[key]);
|
|
5811
|
-
shape[key] = responseColumn(options.table[key], options.fields?.[key]);
|
|
5812
|
-
}
|
|
5813
|
-
const response = import_zod3.z.array(import_zod3.z.object(shape).strict());
|
|
5814
|
-
const queryInput = options.input, where = options.where, limit = options.limit;
|
|
5815
|
-
const orderBy = options.orderBy === void 0 ? void 0 : JSON.parse(JSON.stringify(options.orderBy));
|
|
5816
|
-
const prepare = /* @__PURE__ */ __name((input) => {
|
|
5817
|
-
const parsed = queryInput.parse(input);
|
|
5818
|
-
const filter = where === void 0 ? {} : where(parsed);
|
|
5819
|
-
if (!filter || typeof filter !== "object" || Array.isArray(filter) || typeof filter.then === "function") {
|
|
5820
|
-
throw new Error(`Query ${name}: where must return a synchronous filter object`);
|
|
5821
|
-
}
|
|
5822
|
-
const size = typeof limit === "function" ? limit(parsed) : limit;
|
|
5823
|
-
if (limit !== void 0 && (typeof size !== "number" || !Number.isSafeInteger(size) || size < 0)) throw new Error(`Query ${name}: limit must produce a nonnegative safe integer`);
|
|
5824
|
-
return {
|
|
5825
|
-
name,
|
|
5826
|
-
table,
|
|
5827
|
-
columns: JSON.parse(JSON.stringify(columns)),
|
|
5828
|
-
where: filter,
|
|
5829
|
-
options: {
|
|
5830
|
-
select: [
|
|
5831
|
-
...select
|
|
5832
|
-
],
|
|
5833
|
-
...orderBy === void 0 ? {} : {
|
|
5834
|
-
orderBy: structuredClone(orderBy)
|
|
5835
|
-
},
|
|
5836
|
-
...limit === void 0 ? {} : {
|
|
5837
|
-
limit: size
|
|
5838
|
-
}
|
|
5839
|
-
}
|
|
5840
|
-
};
|
|
5841
|
-
}, "prepare");
|
|
5842
|
-
const attach = /* @__PURE__ */ __name((schema) => {
|
|
5843
|
-
const api = {
|
|
5844
|
-
queryName: name,
|
|
5845
|
-
input: queryInput,
|
|
5846
|
-
prepare,
|
|
5847
|
-
async run(database, input) {
|
|
5848
|
-
const request = prepare(input);
|
|
5849
|
-
const rows = await ("$readQuery" in database ? database.$readQuery(request) : database.readQuery(request));
|
|
5850
|
-
return schema.parse(rows);
|
|
5851
|
-
},
|
|
5852
|
-
sql(database, input) {
|
|
5853
|
-
const request = prepare(input);
|
|
5854
|
-
return "$compileQuery" in database ? database.$compileQuery(request) : database.compileQuery(request);
|
|
5855
|
-
},
|
|
5856
|
-
explain(database, input) {
|
|
5857
|
-
const request = prepare(input);
|
|
5858
|
-
return "$explainQuery" in database ? database.$explainQuery(request) : database.explainQuery(request);
|
|
5859
|
-
},
|
|
5860
|
-
contract() {
|
|
5861
|
-
const registry2 = new import_zod_to_openapi2.OpenAPIRegistry();
|
|
5862
|
-
registry2.register(`${name}Input`, queryInput);
|
|
5863
|
-
registry2.register(`${name}Response`, schema);
|
|
5864
|
-
return JSON.parse(JSON.stringify({
|
|
5865
|
-
name,
|
|
5866
|
-
table,
|
|
5867
|
-
select,
|
|
5868
|
-
columns,
|
|
5869
|
-
components: new import_zod_to_openapi2.OpenApiGeneratorV31(registry2.definitions).generateComponents().components
|
|
5870
|
-
}));
|
|
5871
|
-
}
|
|
5872
|
-
};
|
|
5873
|
-
for (const key of [
|
|
5874
|
-
"min",
|
|
5875
|
-
"max",
|
|
5876
|
-
"length",
|
|
5877
|
-
"describe",
|
|
5878
|
-
"openapi"
|
|
5879
|
-
]) {
|
|
5880
|
-
const modify = schema[key].bind(schema);
|
|
5881
|
-
Object.defineProperty(schema, key, {
|
|
5882
|
-
value: /* @__PURE__ */ __name((...args) => attach(modify(...args)), "value"),
|
|
5883
|
-
configurable: true
|
|
5884
|
-
});
|
|
5885
|
-
}
|
|
5886
|
-
return Object.assign(schema, api);
|
|
5887
|
-
}, "attach");
|
|
5888
|
-
return attach(response);
|
|
5889
|
-
}
|
|
5890
|
-
__name(defineQuery, "defineQuery");
|
|
5891
|
-
function queryManifest(queries) {
|
|
5892
|
-
const sorted = [
|
|
5893
|
-
...queries
|
|
5894
|
-
].sort((a, b) => a.queryName.localeCompare(b.queryName));
|
|
5895
|
-
if (new Set(sorted.map((query) => query.queryName)).size !== sorted.length) throw new Error("Query manifest contains duplicate names");
|
|
5896
|
-
return JSON.parse(stableContract({
|
|
5897
|
-
version: 1,
|
|
5898
|
-
queries: sorted.map((query) => query.contract())
|
|
5899
|
-
}));
|
|
5900
|
-
}
|
|
5901
|
-
__name(queryManifest, "queryManifest");
|
|
5902
|
-
function assertQueryManifest(queries, baseline) {
|
|
5903
|
-
if (stableContract(queryManifest(queries)) !== stableContract(baseline)) {
|
|
5904
|
-
throw new Error("Query contract drift: compare queryManifest() with the committed manifest and review the API/client changes before updating it");
|
|
5905
|
-
}
|
|
5906
|
-
}
|
|
5907
|
-
__name(assertQueryManifest, "assertQueryManifest");
|
|
5908
5680
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5909
5681
|
0 && (module.exports = {
|
|
5910
5682
|
Auth,
|
|
@@ -5988,7 +5760,6 @@ __name(assertQueryManifest, "assertQueryManifest");
|
|
|
5988
5760
|
__runWithRuntime,
|
|
5989
5761
|
__setRuntime,
|
|
5990
5762
|
assertNoOrphanEntryPoints,
|
|
5991
|
-
assertQueryManifest,
|
|
5992
5763
|
assertZeroArgConstructor,
|
|
5993
5764
|
bigint,
|
|
5994
5765
|
boolean,
|
|
@@ -6003,10 +5774,8 @@ __name(assertQueryManifest, "assertQueryManifest");
|
|
|
6003
5774
|
defineDefaultAuth,
|
|
6004
5775
|
defineError,
|
|
6005
5776
|
defineMiddleware,
|
|
6006
|
-
defineQuery,
|
|
6007
5777
|
defineSchema,
|
|
6008
5778
|
defineTable,
|
|
6009
|
-
defineWorkload,
|
|
6010
5779
|
enumType,
|
|
6011
5780
|
exprCtx,
|
|
6012
5781
|
getErrorRegistry,
|
|
@@ -6042,7 +5811,6 @@ __name(assertQueryManifest, "assertQueryManifest");
|
|
|
6042
5811
|
ownerOnly,
|
|
6043
5812
|
policy,
|
|
6044
5813
|
publicChannel,
|
|
6045
|
-
queryManifest,
|
|
6046
5814
|
raw,
|
|
6047
5815
|
recordThrows,
|
|
6048
5816
|
resolveEffectiveAuth,
|