@palbase/backend 22.1.0 → 23.1.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 +750 -40
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +5 -5
- package/dist/{chunk-YL4C5NRY.js → chunk-HQRJDARQ.js} +2 -2
- package/dist/{chunk-74XDEF5J.js → chunk-M5MCBWJI.js} +723 -37
- package/dist/chunk-M5MCBWJI.js.map +1 -0
- package/dist/{chunk-W5ODXPY3.js → chunk-NS5V43YQ.js} +14 -1
- package/dist/chunk-NS5V43YQ.js.map +1 -0
- package/dist/{chunk-SQC5EIWY.js → chunk-OHALWEOG.js} +19 -9
- package/dist/chunk-OHALWEOG.js.map +1 -0
- package/dist/{chunk-I3ON7MYF.js → chunk-PY7YJDCT.js} +129 -18
- package/dist/chunk-PY7YJDCT.js.map +1 -0
- package/dist/{chunk-N32VDWKH.js → chunk-R3KN6RHD.js} +4 -59
- package/dist/chunk-R3KN6RHD.js.map +1 -0
- package/dist/{chunk-QMVK4X3V.js → chunk-RCLNBJCM.js} +98 -98
- package/dist/chunk-RCLNBJCM.js.map +1 -0
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +3 -21
- package/dist/db/env.d.ts +3 -21
- package/dist/db/index.cjs +140 -16
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +3 -2
- package/dist/db/index.d.ts +3 -2
- package/dist/db/index.js +2 -2
- package/dist/{endpoint-BVT6jcVW.d.cts → endpoint-CVWXh6oG.d.ts} +147 -15
- package/dist/{endpoint-BVT6jcVW.d.ts → endpoint-c9h5jriX.d.cts} +147 -15
- package/dist/engine/index.cjs +750 -40
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +6 -5
- package/dist/engine/index.d.ts +6 -5
- package/dist/engine/index.js +4 -4
- package/dist/{index-BS1gW4nV.d.cts → index-BZrJXnVh.d.ts} +142 -72
- package/dist/{index-BqCiHao8.d.cts → index-By8Dle5U.d.cts} +196 -21
- package/dist/{index-vwHoS0l2.d.ts → index-CwAJ7HEe.d.ts} +196 -21
- package/dist/{index-CCZqzych.d.ts → index-CxeQSfJP.d.cts} +142 -72
- package/dist/index.cjs +388 -1101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -1134
- package/dist/index.d.ts +89 -1134
- package/dist/index.js +133 -902
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +32 -61
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +6 -2
- package/dist/openapi/index.d.ts +6 -2
- package/dist/openapi/index.js +34 -26
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-Bsuf-orT.d.ts → registry-B3niOVYp.d.ts} +108 -170
- package/dist/{registry-BWttGlaT.d.cts → registry-CqPK2Qby.d.cts} +108 -170
- package/dist/{purchases/keys.cjs → stack.cjs} +4 -4
- package/dist/stack.cjs.map +1 -0
- package/dist/stack.d.cts +76 -0
- package/dist/stack.d.ts +76 -0
- package/dist/stack.js +1 -0
- package/dist/test/index.cjs +482 -9
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +35 -3
- package/dist/test/index.d.ts +35 -3
- package/dist/test/index.js +480 -8
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +7 -6
- package/docs/llms-full.txt +7 -260
- package/docs/llms.txt +0 -2
- package/package.json +9 -8
- package/stager/return_types.js +23 -0
- package/template/package.json +1 -1
- package/dist/chunk-74XDEF5J.js.map +0 -1
- package/dist/chunk-I3ON7MYF.js.map +0 -1
- package/dist/chunk-N32VDWKH.js.map +0 -1
- package/dist/chunk-QMVK4X3V.js.map +0 -1
- package/dist/chunk-SQC5EIWY.js.map +0 -1
- package/dist/chunk-W5ODXPY3.js.map +0 -1
- package/dist/purchases/keys.cjs.map +0 -1
- package/dist/purchases/keys.d.cts +0 -42
- package/dist/purchases/keys.d.ts +0 -42
- package/dist/purchases/keys.js +0 -1
- package/docs/config.md +0 -147
- package/docs/resources.md +0 -97
- package/template/config/secrets.ts +0 -24
- /package/dist/{chunk-YL4C5NRY.js.map → chunk-HQRJDARQ.js.map} +0 -0
- /package/dist/{purchases/keys.js.map → stack.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -18,15 +18,11 @@ import {
|
|
|
18
18
|
timestamp,
|
|
19
19
|
uuid,
|
|
20
20
|
vector
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PY7YJDCT.js";
|
|
22
22
|
import {
|
|
23
23
|
defineError,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
recordEntitlement,
|
|
27
|
-
recordSpend,
|
|
28
|
-
spendFor
|
|
29
|
-
} from "./chunk-N32VDWKH.js";
|
|
24
|
+
getErrorRegistry
|
|
25
|
+
} from "./chunk-R3KN6RHD.js";
|
|
30
26
|
import {
|
|
31
27
|
Cache,
|
|
32
28
|
Database,
|
|
@@ -34,7 +30,6 @@ import {
|
|
|
34
30
|
Flags,
|
|
35
31
|
Log,
|
|
36
32
|
Notifications,
|
|
37
|
-
Purchases,
|
|
38
33
|
Realtime,
|
|
39
34
|
Secrets,
|
|
40
35
|
Storage,
|
|
@@ -42,19 +37,19 @@ import {
|
|
|
42
37
|
__requestALS,
|
|
43
38
|
__runWithRuntime,
|
|
44
39
|
__setRuntime
|
|
45
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-OHALWEOG.js";
|
|
46
41
|
import {
|
|
47
42
|
TxPlanError,
|
|
48
43
|
TxRefError,
|
|
49
44
|
dec,
|
|
50
45
|
inc,
|
|
51
46
|
now
|
|
52
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-NS5V43YQ.js";
|
|
53
48
|
import {
|
|
54
49
|
Controller,
|
|
55
50
|
__resetRegisteredControllers,
|
|
56
51
|
getRegisteredControllers
|
|
57
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-HQRJDARQ.js";
|
|
58
53
|
import {
|
|
59
54
|
BadRequest,
|
|
60
55
|
Conflict,
|
|
@@ -68,141 +63,9 @@ import {
|
|
|
68
63
|
recordParam,
|
|
69
64
|
recordRoute,
|
|
70
65
|
recordThrows
|
|
71
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-RCLNBJCM.js";
|
|
72
67
|
import "./chunk-7D4SUZUM.js";
|
|
73
68
|
|
|
74
|
-
// src/purchases/errors.ts
|
|
75
|
-
function asPalstoreError(err) {
|
|
76
|
-
if (!(err instanceof Error)) return null;
|
|
77
|
-
const e = err;
|
|
78
|
-
if (typeof e.code !== "string" || typeof e.status !== "number") return null;
|
|
79
|
-
return { code: e.code, status: e.status, message: e.message };
|
|
80
|
-
}
|
|
81
|
-
function toHttpError(err) {
|
|
82
|
-
if (err instanceof HttpError) return err;
|
|
83
|
-
const p = asPalstoreError(err);
|
|
84
|
-
if (!p) return err;
|
|
85
|
-
switch (p.code) {
|
|
86
|
-
case "entitlement_required": {
|
|
87
|
-
const entitlement = err.entitlement ?? null;
|
|
88
|
-
return new PalError(403, "entitlement_required", p.message, { entitlement });
|
|
89
|
-
}
|
|
90
|
-
case "quota_exceeded":
|
|
91
|
-
case "credit_insufficient": {
|
|
92
|
-
const state = err.state;
|
|
93
|
-
return new PalError(429, p.code, p.message, state);
|
|
94
|
-
}
|
|
95
|
-
default:
|
|
96
|
-
return err;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// src/purchases/subject.ts
|
|
101
|
-
var subjectByRequest = /* @__PURE__ */ new WeakMap();
|
|
102
|
-
function storeEnv() {
|
|
103
|
-
return process.env.PALSTORE_STORE_ENV === "sandbox" ? "sandbox" : "production";
|
|
104
|
-
}
|
|
105
|
-
async function currentSubjectId() {
|
|
106
|
-
const store = __requestALS.getStore();
|
|
107
|
-
if (!store) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
"Purchases decorators used outside a request scope. @RequireEntitlement/@Spend resolve the subject from the request's authenticated user, so they only work inside an endpoint handler."
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
const memoized = subjectByRequest.get(store);
|
|
113
|
-
if (memoized) return memoized;
|
|
114
|
-
const userId = store.userId;
|
|
115
|
-
if (!userId) {
|
|
116
|
-
throw new Unauthorized(
|
|
117
|
-
"This endpoint requires an authenticated user: purchases entitlements and quota are per-user, and the subject is resolved from the request's identity."
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
const resolving = Purchases.resolveSubject({ userRef: userId, storeEnv: storeEnv() }).then(
|
|
121
|
-
(r) => r.subjectId
|
|
122
|
-
);
|
|
123
|
-
subjectByRequest.set(store, resolving);
|
|
124
|
-
resolving.catch(() => subjectByRequest.delete(store));
|
|
125
|
-
return resolving;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// src/purchases/decorators.ts
|
|
129
|
-
var WRAPPED = /* @__PURE__ */ Symbol.for("palbase.backend.purchases.wrapped");
|
|
130
|
-
function idempotencyKeyFor(key) {
|
|
131
|
-
const store = __requestALS.getStore();
|
|
132
|
-
const base = store?.idempotencyKey || store?.requestId;
|
|
133
|
-
if (!base) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
"@Spend needs a request-scoped idempotency key, and the runtime supplied neither an Idempotency-Key header nor a request id. Spending without one would let a retried request charge the user twice."
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
return `${base}:${key}`;
|
|
139
|
-
}
|
|
140
|
-
function ensureWrapper(target, fnName, descriptor) {
|
|
141
|
-
const original = descriptor.value;
|
|
142
|
-
if (typeof original !== "function") {
|
|
143
|
-
throw new Error(
|
|
144
|
-
`@RequireEntitlement/@Spend can only decorate a method; "${fnName}" is not one.`
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
if (original[WRAPPED]) return;
|
|
148
|
-
const wrapper = async function(...args) {
|
|
149
|
-
const ctor = this.constructor;
|
|
150
|
-
const entitlement = entitlementFor(ctor, fnName);
|
|
151
|
-
const spend = spendFor(ctor, fnName);
|
|
152
|
-
let subjectId;
|
|
153
|
-
try {
|
|
154
|
-
subjectId = await currentSubjectId();
|
|
155
|
-
} catch (err) {
|
|
156
|
-
throw toHttpError(err);
|
|
157
|
-
}
|
|
158
|
-
if (entitlement !== void 0) {
|
|
159
|
-
try {
|
|
160
|
-
await Purchases.require(subjectId, entitlement);
|
|
161
|
-
} catch (err) {
|
|
162
|
-
throw toHttpError(err);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (spend === void 0) {
|
|
166
|
-
return original.apply(this, args);
|
|
167
|
-
}
|
|
168
|
-
let handlerFailure;
|
|
169
|
-
try {
|
|
170
|
-
return await Purchases.withSpend(
|
|
171
|
-
subjectId,
|
|
172
|
-
spend.key,
|
|
173
|
-
{ count: spend.count, idempotencyKey: idempotencyKeyFor(spend.key) },
|
|
174
|
-
async () => {
|
|
175
|
-
try {
|
|
176
|
-
return await original.apply(this, args);
|
|
177
|
-
} catch (err) {
|
|
178
|
-
handlerFailure = { err };
|
|
179
|
-
throw err;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
);
|
|
183
|
-
} catch (err) {
|
|
184
|
-
if (handlerFailure !== void 0 && handlerFailure.err === err) throw err;
|
|
185
|
-
throw toHttpError(err);
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
wrapper[WRAPPED] = true;
|
|
189
|
-
descriptor.value = wrapper;
|
|
190
|
-
}
|
|
191
|
-
function RequireEntitlement(key) {
|
|
192
|
-
return function(target, propertyKey, descriptor) {
|
|
193
|
-
const fnName = String(propertyKey);
|
|
194
|
-
recordEntitlement(target, fnName, key);
|
|
195
|
-
ensureWrapper(target, fnName, descriptor);
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function Spend(key) {
|
|
199
|
-
return function(target, propertyKey, descriptor) {
|
|
200
|
-
const fnName = String(propertyKey);
|
|
201
|
-
recordSpend(target, fnName, { key, count: 1 });
|
|
202
|
-
ensureWrapper(target, fnName, descriptor);
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
69
|
// src/clients/http.ts
|
|
207
70
|
var PalbaseModuleError = class extends Error {
|
|
208
71
|
code;
|
|
@@ -548,12 +411,12 @@ function buildFlagsClient(http, cfg) {
|
|
|
548
411
|
return {
|
|
549
412
|
data: Object.keys(values).map((name) => {
|
|
550
413
|
const value = values[name];
|
|
551
|
-
const
|
|
414
|
+
const flag = {
|
|
552
415
|
name,
|
|
553
416
|
enabled: flagEnabled(value)
|
|
554
417
|
};
|
|
555
|
-
if (typeof value === "string")
|
|
556
|
-
return
|
|
418
|
+
if (typeof value === "string") flag.variant = { name: value };
|
|
419
|
+
return flag;
|
|
557
420
|
}),
|
|
558
421
|
error: null,
|
|
559
422
|
status: res.status
|
|
@@ -781,13 +644,13 @@ function buildNotificationsClient(http) {
|
|
|
781
644
|
|
|
782
645
|
// src/clients/realtime.ts
|
|
783
646
|
import { createHmac } from "crypto";
|
|
784
|
-
function mintToken(
|
|
647
|
+
function mintToken(secret) {
|
|
785
648
|
const now2 = Math.floor(Date.now() / 1e3);
|
|
786
649
|
const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
|
|
787
650
|
const payload = Buffer.from(
|
|
788
651
|
JSON.stringify({ iss: "backend-runtime", role: "service_role", iat: now2, exp: now2 + 60 })
|
|
789
652
|
).toString("base64url");
|
|
790
|
-
const sig = createHmac("sha256",
|
|
653
|
+
const sig = createHmac("sha256", secret).update(`${header}.${payload}`).digest("base64url");
|
|
791
654
|
return `${header}.${payload}.${sig}`;
|
|
792
655
|
}
|
|
793
656
|
function buildRealtimeClient(cfg) {
|
|
@@ -958,11 +821,11 @@ function validateStoragePath(p) {
|
|
|
958
821
|
);
|
|
959
822
|
}
|
|
960
823
|
}
|
|
961
|
-
function toFileObject(
|
|
824
|
+
function toFileObject(bucket, row) {
|
|
962
825
|
return {
|
|
963
826
|
name: row.path ?? "",
|
|
964
827
|
path: row.path ?? "",
|
|
965
|
-
bucket: row.bucket ??
|
|
828
|
+
bucket: row.bucket ?? bucket,
|
|
966
829
|
size: typeof row.size === "number" ? row.size : 0,
|
|
967
830
|
contentType: row.contentType ?? "",
|
|
968
831
|
checksum: row.checksum ?? "",
|
|
@@ -1078,35 +941,6 @@ function buildModuleClients(cfg) {
|
|
|
1078
941
|
};
|
|
1079
942
|
}
|
|
1080
943
|
|
|
1081
|
-
// src/purchases/keys-gen.ts
|
|
1082
|
-
function liveKeys(entries) {
|
|
1083
|
-
return Object.entries(entries ?? {}).filter(([, def]) => def?.removed !== true).map(([key]) => key).sort();
|
|
1084
|
-
}
|
|
1085
|
-
function memberName(key) {
|
|
1086
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
|
|
1087
|
-
}
|
|
1088
|
-
function members(keys) {
|
|
1089
|
-
if (keys.length === 0) return "";
|
|
1090
|
-
return `
|
|
1091
|
-
${keys.map((k) => ` ${memberName(k)}: true;`).join("\n")}
|
|
1092
|
-
`;
|
|
1093
|
-
}
|
|
1094
|
-
function makePurchasesDts(manifest) {
|
|
1095
|
-
const entitlements = liveKeys(manifest.entitlements);
|
|
1096
|
-
const limits = liveKeys({ ...manifest.limits, ...manifest.credits });
|
|
1097
|
-
return `// palbase-purchases.d.ts \u2014 GENERATED by @palbase/backend. Do not edit.
|
|
1098
|
-
// Source: the project's palstore catalog revision.
|
|
1099
|
-
|
|
1100
|
-
declare module "@palbase/backend/purchases" {
|
|
1101
|
-
interface Entitlements {${members(entitlements)}}
|
|
1102
|
-
|
|
1103
|
-
interface Limits {${members(limits)}}
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
export {};
|
|
1107
|
-
`;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
944
|
// src/db/schema-json.ts
|
|
1111
945
|
function defOf(column) {
|
|
1112
946
|
return "_def" in column ? column._def : column;
|
|
@@ -1145,9 +979,45 @@ function policyToJSON(policy2) {
|
|
|
1145
979
|
permissive: policy2.permissive !== false
|
|
1146
980
|
};
|
|
1147
981
|
}
|
|
1148
|
-
function
|
|
982
|
+
function commonSearchFields(search, out) {
|
|
983
|
+
if (search.synonyms !== void 0 && Object.keys(search.synonyms).length > 0) {
|
|
984
|
+
out.synonyms = Object.fromEntries(
|
|
985
|
+
Object.entries(search.synonyms).map(([word, alts]) => [word, [...alts]])
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
if (search.validity === true) out.validity = true;
|
|
989
|
+
}
|
|
990
|
+
function searchToJSON(search, vectorColumn) {
|
|
991
|
+
if (search.from !== void 0 && search.model !== void 0) {
|
|
992
|
+
const out2 = {};
|
|
993
|
+
const textCols = search.text === false ? void 0 : Array.isArray(search.text) && search.text.length > 0 ? search.text : search.from;
|
|
994
|
+
if (textCols !== void 0) out2.text = { columns: [...textCols] };
|
|
995
|
+
const v = { metric: search.metric ?? "cosine" };
|
|
996
|
+
if (vectorColumn !== void 0) v.column = vectorColumn;
|
|
997
|
+
v.embed = {
|
|
998
|
+
provider: search.model.provider,
|
|
999
|
+
model: search.model.model,
|
|
1000
|
+
from: [...search.from],
|
|
1001
|
+
...search.model.apiKeyName !== void 0 ? { apiKeyName: search.model.apiKeyName } : {},
|
|
1002
|
+
...search.model.dimensions !== void 0 ? { dimensions: search.model.dimensions } : {},
|
|
1003
|
+
...search.model.baseURL !== void 0 ? { baseURL: search.model.baseURL } : {}
|
|
1004
|
+
};
|
|
1005
|
+
if (search.staleness !== void 0) v.staleness = search.staleness;
|
|
1006
|
+
if (vectorColumn === void 0) {
|
|
1007
|
+
v.mode = "chunks";
|
|
1008
|
+
if (search.chunks !== void 0) {
|
|
1009
|
+
const c = {};
|
|
1010
|
+
if (search.chunks.size !== void 0 && search.chunks.size > 0) c.sizeChars = search.chunks.size;
|
|
1011
|
+
if (search.chunks.overlap !== void 0 && search.chunks.overlap > 0) c.overlapChars = search.chunks.overlap;
|
|
1012
|
+
if (Object.keys(c).length > 0) v.chunks = c;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
out2.vector = [v];
|
|
1016
|
+
commonSearchFields(search, out2);
|
|
1017
|
+
return out2;
|
|
1018
|
+
}
|
|
1149
1019
|
const out = {};
|
|
1150
|
-
if (search.text
|
|
1020
|
+
if (Array.isArray(search.text) && search.text.length > 0) out.text = { columns: [...search.text] };
|
|
1151
1021
|
const legs = search.vector === void 0 ? [] : Array.isArray(search.vector) ? search.vector : [search.vector];
|
|
1152
1022
|
if (legs.length > 0) {
|
|
1153
1023
|
out.vector = legs.map((leg) => {
|
|
@@ -1167,8 +1037,17 @@ function searchToJSON(search) {
|
|
|
1167
1037
|
return v;
|
|
1168
1038
|
});
|
|
1169
1039
|
}
|
|
1040
|
+
commonSearchFields(search, out);
|
|
1170
1041
|
return out;
|
|
1171
1042
|
}
|
|
1043
|
+
function memoryToJSON(m) {
|
|
1044
|
+
return {
|
|
1045
|
+
from: [...m.from],
|
|
1046
|
+
into: m.into,
|
|
1047
|
+
...m.subject !== void 0 ? { subject: m.subject } : {},
|
|
1048
|
+
extract: { provider: m.extract.provider, model: m.extract.model }
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1172
1051
|
function tableToJSON(table) {
|
|
1173
1052
|
const columns = {};
|
|
1174
1053
|
for (const [name, column] of Object.entries(table.columns)) {
|
|
@@ -1205,9 +1084,13 @@ function tableToJSON(table) {
|
|
|
1205
1084
|
out.indexes = table.indexes.map((i) => ({ name: i.name, columns: [...i.columns] }));
|
|
1206
1085
|
}
|
|
1207
1086
|
if (table.search !== void 0) {
|
|
1208
|
-
const
|
|
1087
|
+
const vectorColumn = Object.entries(columns).find(([, c]) => c.dimensions !== void 0)?.[0];
|
|
1088
|
+
const sj = searchToJSON(table.search, vectorColumn);
|
|
1209
1089
|
if (sj.text !== void 0 || sj.vector !== void 0) out.search = sj;
|
|
1210
1090
|
}
|
|
1091
|
+
if (table.memory !== void 0) {
|
|
1092
|
+
out.memory = memoryToJSON(table.memory);
|
|
1093
|
+
}
|
|
1211
1094
|
return out;
|
|
1212
1095
|
}
|
|
1213
1096
|
function toSchemaJSON(schema) {
|
|
@@ -1335,10 +1218,10 @@ function buildChildEdges(schema) {
|
|
|
1335
1218
|
const ref = builder._def.references;
|
|
1336
1219
|
if (ref === void 0) continue;
|
|
1337
1220
|
if (ref.table === childName) continue;
|
|
1338
|
-
const
|
|
1339
|
-
if (
|
|
1340
|
-
if (
|
|
1341
|
-
|
|
1221
|
+
const bucket = edges.get(ref.table);
|
|
1222
|
+
if (bucket === void 0) continue;
|
|
1223
|
+
if (bucket.some((e) => e.child === childName)) continue;
|
|
1224
|
+
bucket.push({ child: childName, column: col });
|
|
1342
1225
|
}
|
|
1343
1226
|
}
|
|
1344
1227
|
return edges;
|
|
@@ -1412,638 +1295,50 @@ export {};
|
|
|
1412
1295
|
`;
|
|
1413
1296
|
}
|
|
1414
1297
|
|
|
1415
|
-
// src/
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
var VARIANT_FITS = ["cover", "contain", "inside"];
|
|
1419
|
-
function normalizeVariants(input) {
|
|
1420
|
-
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
1421
|
-
throw new Error("bucket variants must be an object of { <name>: { width?, height?, format? } }");
|
|
1422
|
-
}
|
|
1423
|
-
const out = {};
|
|
1424
|
-
for (const [name, spec] of Object.entries(input)) {
|
|
1425
|
-
if (!/^[a-z0-9][a-z0-9_-]*$/i.test(name)) {
|
|
1426
|
-
throw new Error(
|
|
1427
|
-
`bucket variant name "${name}" must be alphanumeric with optional - or _ (e.g. "thumb", "card_2x")`
|
|
1428
|
-
);
|
|
1429
|
-
}
|
|
1430
|
-
if (spec === null || typeof spec !== "object" || Array.isArray(spec)) {
|
|
1431
|
-
throw new Error(`bucket variant "${name}" must be an object like { width: 100, height: 100 }`);
|
|
1432
|
-
}
|
|
1433
|
-
for (const dim of ["width", "height"]) {
|
|
1434
|
-
const value = spec[dim];
|
|
1435
|
-
if (value === void 0) continue;
|
|
1436
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
1437
|
-
throw new Error(`bucket variant "${name}" ${dim} must be a positive integer, got ${String(value)}`);
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
if (spec.width === void 0 && spec.height === void 0) {
|
|
1441
|
-
throw new Error(`bucket variant "${name}" must set width and/or height`);
|
|
1442
|
-
}
|
|
1443
|
-
if (spec.format !== void 0 && !VARIANT_FORMATS.includes(spec.format)) {
|
|
1444
|
-
throw new Error(
|
|
1445
|
-
`bucket variant "${name}" format must be one of ${VARIANT_FORMATS.join(", ")}, got "${String(spec.format)}"`
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
if (spec.fit !== void 0 && !VARIANT_FITS.includes(spec.fit)) {
|
|
1449
|
-
throw new Error(
|
|
1450
|
-
`bucket variant "${name}" fit must be one of ${VARIANT_FITS.join(", ")}, got "${String(spec.fit)}"`
|
|
1451
|
-
);
|
|
1452
|
-
}
|
|
1453
|
-
if (spec.quality !== void 0) {
|
|
1454
|
-
const q = spec.quality;
|
|
1455
|
-
if (typeof q !== "number" || !Number.isInteger(q) || q < 1 || q > 100) {
|
|
1456
|
-
throw new Error(`bucket variant "${name}" quality must be an integer 1\u2013100, got ${String(q)}`);
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
if (spec.fit === "cover" && (spec.width === void 0 || spec.height === void 0)) {
|
|
1460
|
-
throw new Error(`bucket variant "${name}" uses fit "cover", which needs BOTH width and height`);
|
|
1461
|
-
}
|
|
1462
|
-
out[name] = {
|
|
1463
|
-
...spec.width !== void 0 ? { width: spec.width } : {},
|
|
1464
|
-
...spec.height !== void 0 ? { height: spec.height } : {},
|
|
1465
|
-
...spec.fit !== void 0 ? { fit: spec.fit } : {},
|
|
1466
|
-
...spec.format !== void 0 ? { format: spec.format } : {},
|
|
1467
|
-
...spec.quality !== void 0 ? { quality: spec.quality } : {}
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
return out;
|
|
1298
|
+
// src/stack-gen.ts
|
|
1299
|
+
function liveNames(names) {
|
|
1300
|
+
return [...new Set(names)].sort();
|
|
1471
1301
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
kb: 1024,
|
|
1475
|
-
mb: 1024 ** 2,
|
|
1476
|
-
gb: 1024 ** 3,
|
|
1477
|
-
tb: 1024 ** 4
|
|
1478
|
-
};
|
|
1479
|
-
function parseFileSizeLimit(input) {
|
|
1480
|
-
if (typeof input === "number") {
|
|
1481
|
-
if (!Number.isFinite(input) || input < 0 || !Number.isInteger(input)) {
|
|
1482
|
-
throw new Error(
|
|
1483
|
-
`bucket fileSizeLimit must be a non-negative integer number of bytes, got ${input}`
|
|
1484
|
-
);
|
|
1485
|
-
}
|
|
1486
|
-
return input;
|
|
1487
|
-
}
|
|
1488
|
-
const trimmed = input.trim();
|
|
1489
|
-
const match = /^(\d+(?:\.\d+)?)\s*([a-zA-Z]+)?$/.exec(trimmed);
|
|
1490
|
-
if (!match) {
|
|
1491
|
-
throw new Error(
|
|
1492
|
-
`bucket fileSizeLimit string must be "<number><unit>" like "5MB" or "1GB", got "${input}"`
|
|
1493
|
-
);
|
|
1494
|
-
}
|
|
1495
|
-
const value = Number.parseFloat(match[1]);
|
|
1496
|
-
const unit = (match[2] ?? "b").toLowerCase();
|
|
1497
|
-
const multiplier = UNIT_BYTES[unit];
|
|
1498
|
-
if (multiplier === void 0) {
|
|
1499
|
-
throw new Error(
|
|
1500
|
-
`bucket fileSizeLimit has an unknown unit "${match[2]}" \u2014 use B, KB, MB, GB, or TB (e.g. "5MB")`
|
|
1501
|
-
);
|
|
1502
|
-
}
|
|
1503
|
-
const bytes = value * multiplier;
|
|
1504
|
-
if (!Number.isFinite(bytes) || bytes < 0) {
|
|
1505
|
-
throw new Error(`bucket fileSizeLimit resolved to an invalid byte count: ${bytes}`);
|
|
1506
|
-
}
|
|
1507
|
-
return Math.round(bytes);
|
|
1508
|
-
}
|
|
1509
|
-
var MIME_RE = /^[a-zA-Z0-9][a-zA-Z0-9!#$&^_.+-]*\/(?:\*|[a-zA-Z0-9][a-zA-Z0-9!#$&^_.+-]*)$/;
|
|
1510
|
-
function bucket(opts = {}) {
|
|
1511
|
-
const fileSizeLimit = opts.fileSizeLimit === void 0 ? null : parseFileSizeLimit(opts.fileSizeLimit);
|
|
1512
|
-
let allowedMimeTypes = null;
|
|
1513
|
-
if (opts.allowedMimeTypes !== void 0) {
|
|
1514
|
-
if (!Array.isArray(opts.allowedMimeTypes)) {
|
|
1515
|
-
throw new Error("bucket allowedMimeTypes must be an array of MIME-type strings");
|
|
1516
|
-
}
|
|
1517
|
-
for (const mime of opts.allowedMimeTypes) {
|
|
1518
|
-
if (typeof mime !== "string" || !MIME_RE.test(mime.trim())) {
|
|
1519
|
-
throw new Error(
|
|
1520
|
-
`bucket allowedMimeTypes entry "${mime}" is not a valid MIME type (expected "type/subtype", e.g. "image/png")`
|
|
1521
|
-
);
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
allowedMimeTypes = [...new Set(opts.allowedMimeTypes.map((m) => m.trim()))];
|
|
1525
|
-
}
|
|
1526
|
-
return {
|
|
1527
|
-
public: opts.public ?? false,
|
|
1528
|
-
fileSizeLimit,
|
|
1529
|
-
allowedMimeTypes,
|
|
1530
|
-
variants: opts.variants === void 0 ? null : normalizeVariants(opts.variants)
|
|
1531
|
-
};
|
|
1302
|
+
function memberName(name) {
|
|
1303
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
1532
1304
|
}
|
|
1533
|
-
function
|
|
1534
|
-
if (
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
for (const name of Object.keys(input.buckets)) {
|
|
1539
|
-
if (name.length === 0) {
|
|
1540
|
-
throw new Error("bucket name must be a non-empty string");
|
|
1541
|
-
}
|
|
1542
|
-
const def = input.buckets[name];
|
|
1543
|
-
if (def === void 0) continue;
|
|
1544
|
-
buckets[name] = def;
|
|
1545
|
-
}
|
|
1546
|
-
return { __config: STORAGE_CONFIG_KIND, buckets };
|
|
1305
|
+
function members(names) {
|
|
1306
|
+
if (names.length === 0) return "";
|
|
1307
|
+
return `
|
|
1308
|
+
${names.map((n) => ` ${memberName(n)}: true;`).join("\n")}
|
|
1309
|
+
`;
|
|
1547
1310
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
}
|
|
1563
|
-
hosts.push(h.trim().toLowerCase());
|
|
1564
|
-
}
|
|
1565
|
-
if (input.timeoutMs === void 0) {
|
|
1566
|
-
return { __config: EGRESS_CONFIG_KIND, hosts };
|
|
1567
|
-
}
|
|
1568
|
-
const timeoutMs = input.timeoutMs;
|
|
1569
|
-
if (typeof timeoutMs !== "number" || !Number.isInteger(timeoutMs)) {
|
|
1570
|
-
throw new Error("defineEgress: timeoutMs must be an integer number of milliseconds");
|
|
1571
|
-
}
|
|
1572
|
-
if (timeoutMs < EGRESS_TIMEOUT_MIN_MS || timeoutMs > EGRESS_TIMEOUT_MAX_MS) {
|
|
1573
|
-
throw new Error(
|
|
1574
|
-
`defineEgress: timeoutMs must be between ${EGRESS_TIMEOUT_MIN_MS} and ${EGRESS_TIMEOUT_MAX_MS} (got ${timeoutMs})`
|
|
1575
|
-
);
|
|
1576
|
-
}
|
|
1577
|
-
return { __config: EGRESS_CONFIG_KIND, hosts, timeoutMs };
|
|
1311
|
+
function bucketMembers(buckets) {
|
|
1312
|
+
const normalized = buckets.map((b) => typeof b === "string" ? { name: b, variants: [] } : b);
|
|
1313
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1314
|
+
for (const b of normalized) byName.set(b.name, b.variants);
|
|
1315
|
+
const names = [...byName.keys()].sort();
|
|
1316
|
+
if (names.length === 0) return "";
|
|
1317
|
+
const rows = names.map((name) => {
|
|
1318
|
+
const variants = [...new Set(byName.get(name) ?? [])].sort();
|
|
1319
|
+
const union = variants.length === 0 ? "never" : variants.map((v) => JSON.stringify(v)).join(" | ");
|
|
1320
|
+
return ` ${memberName(name)}: { variants: ${union} };`;
|
|
1321
|
+
});
|
|
1322
|
+
return `
|
|
1323
|
+
${rows.join("\n")}
|
|
1324
|
+
`;
|
|
1578
1325
|
}
|
|
1326
|
+
function makeStackDts(names) {
|
|
1327
|
+
const secrets = liveNames(names.secrets);
|
|
1328
|
+
const flags = liveNames(names.flags);
|
|
1329
|
+
return `// palbase-stack.d.ts \u2014 GENERATED by @palbase/backend. Do not edit.
|
|
1330
|
+
// Source: the linked environment's stack.
|
|
1579
1331
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
var RESERVED_SECRET_PREFIX = "PB_NOTIFICATIONS";
|
|
1583
|
-
var PROVIDER_CATALOG = {
|
|
1584
|
-
apns: {
|
|
1585
|
-
channel: "push",
|
|
1586
|
-
required: ["teamId", "keyId", "bundleId"],
|
|
1587
|
-
optional: ["isProduction"],
|
|
1588
|
-
secrets: ["p8"]
|
|
1589
|
-
},
|
|
1590
|
-
fcm: {
|
|
1591
|
-
channel: "push",
|
|
1592
|
-
required: [],
|
|
1593
|
-
optional: [],
|
|
1594
|
-
secrets: ["serviceAccount"]
|
|
1595
|
-
},
|
|
1596
|
-
sendgrid: {
|
|
1597
|
-
channel: "email",
|
|
1598
|
-
required: ["fromDomain"],
|
|
1599
|
-
optional: [],
|
|
1600
|
-
secrets: ["apiKey"]
|
|
1601
|
-
},
|
|
1602
|
-
ses: {
|
|
1603
|
-
channel: "email",
|
|
1604
|
-
required: ["region", "accessKeyId", "fromDomain"],
|
|
1605
|
-
optional: [],
|
|
1606
|
-
secrets: ["secretAccessKey"]
|
|
1607
|
-
},
|
|
1608
|
-
smtp: {
|
|
1609
|
-
channel: "email",
|
|
1610
|
-
required: ["host", "port", "fromEmail"],
|
|
1611
|
-
optional: ["username", "useStarttls"],
|
|
1612
|
-
secrets: ["password"]
|
|
1613
|
-
},
|
|
1614
|
-
acs: {
|
|
1615
|
-
channel: "email",
|
|
1616
|
-
required: ["fromEmail"],
|
|
1617
|
-
optional: ["fromName"],
|
|
1618
|
-
secrets: ["connectionString"]
|
|
1619
|
-
},
|
|
1620
|
-
twilio: {
|
|
1621
|
-
channel: "sms",
|
|
1622
|
-
// account_sid required; one of from_number / messaging_service_sid required
|
|
1623
|
-
// (enforced by the refine in buildProvider, not by the flat `required` list).
|
|
1624
|
-
required: ["accountSid"],
|
|
1625
|
-
optional: ["fromNumber", "messagingServiceSid"],
|
|
1626
|
-
secrets: ["authToken"]
|
|
1627
|
-
}
|
|
1628
|
-
};
|
|
1629
|
-
var DEFAULT_TEMPLATE_LOCALE = "en";
|
|
1630
|
-
function extractVariables(...sources) {
|
|
1631
|
-
const found = /* @__PURE__ */ new Set();
|
|
1632
|
-
for (const src of sources) {
|
|
1633
|
-
if (!src) continue;
|
|
1634
|
-
for (const match of src.matchAll(/\{\{\{?\s*([^{}]+?)\s*\}?\}\}/g)) {
|
|
1635
|
-
const token = (match[1] ?? "").trim();
|
|
1636
|
-
if (token === "" || "#/^!>&".includes(token.charAt(0)) || token === "else") continue;
|
|
1637
|
-
if (/\s/.test(token)) continue;
|
|
1638
|
-
const root = token.split(".")[0] ?? "";
|
|
1639
|
-
if (root === "" || root === "this" || root.startsWith("@")) continue;
|
|
1640
|
-
found.add(root);
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
return [...found].sort();
|
|
1644
|
-
}
|
|
1645
|
-
function buildEmailTemplate(slug, opts) {
|
|
1646
|
-
const row = (locale, c) => {
|
|
1647
|
-
if (!c.subject) throw new Error(`notifications: email template "${slug}" (${locale}) needs a subject`);
|
|
1648
|
-
if (!c.html) throw new Error(`notifications: email template "${slug}" (${locale}) needs an html body`);
|
|
1649
|
-
const def = {
|
|
1650
|
-
slug,
|
|
1651
|
-
locale,
|
|
1652
|
-
subject: c.subject,
|
|
1653
|
-
html_body: c.html,
|
|
1654
|
-
variables: c.variables ? [...c.variables] : extractVariables(c.subject, c.html, c.text)
|
|
1655
|
-
};
|
|
1656
|
-
if (c.text !== void 0) def.text_body = c.text;
|
|
1657
|
-
return def;
|
|
1658
|
-
};
|
|
1659
|
-
const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];
|
|
1660
|
-
for (const [locale, content] of Object.entries(opts.locales ?? {})) {
|
|
1661
|
-
rows.push(row(locale, content));
|
|
1662
|
-
}
|
|
1663
|
-
return rows;
|
|
1664
|
-
}
|
|
1665
|
-
function buildSmsTemplate(slug, opts) {
|
|
1666
|
-
const row = (locale, c) => {
|
|
1667
|
-
if (!c.body) throw new Error(`notifications: sms template "${slug}" (${locale}) needs a body`);
|
|
1668
|
-
return {
|
|
1669
|
-
slug,
|
|
1670
|
-
locale,
|
|
1671
|
-
body: c.body,
|
|
1672
|
-
variables: c.variables ? [...c.variables] : extractVariables(c.body)
|
|
1673
|
-
};
|
|
1674
|
-
};
|
|
1675
|
-
const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];
|
|
1676
|
-
for (const [locale, content] of Object.entries(opts.locales ?? {})) {
|
|
1677
|
-
rows.push(row(locale, content));
|
|
1678
|
-
}
|
|
1679
|
-
return rows;
|
|
1680
|
-
}
|
|
1681
|
-
function buildTemplates(input) {
|
|
1682
|
-
const out = { email: [], sms: [] };
|
|
1683
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1684
|
-
const claim = (channel, slug, locale) => {
|
|
1685
|
-
const key = `${channel}/${slug}/${locale}`;
|
|
1686
|
-
if (seen.has(key)) {
|
|
1687
|
-
throw new Error(`notifications: ${channel} template "${slug}" declares locale "${locale}" twice`);
|
|
1688
|
-
}
|
|
1689
|
-
seen.add(key);
|
|
1690
|
-
};
|
|
1691
|
-
for (const [slug, opts] of Object.entries(input.email ?? {})) {
|
|
1692
|
-
for (const row of buildEmailTemplate(slug, opts)) {
|
|
1693
|
-
claim("email", row.slug, row.locale);
|
|
1694
|
-
out.email.push(row);
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
for (const [slug, opts] of Object.entries(input.sms ?? {})) {
|
|
1698
|
-
for (const row of buildSmsTemplate(slug, opts)) {
|
|
1699
|
-
claim("sms", row.slug, row.locale);
|
|
1700
|
-
out.sms.push(row);
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1703
|
-
return out;
|
|
1704
|
-
}
|
|
1705
|
-
function buildProvider(name, opts) {
|
|
1706
|
-
const entry = PROVIDER_CATALOG[name];
|
|
1707
|
-
const src = { ...opts };
|
|
1708
|
-
const enabled = src.enabled === void 0 ? false : Boolean(src.enabled);
|
|
1709
|
-
if (!enabled) {
|
|
1710
|
-
return { enabled: false };
|
|
1711
|
-
}
|
|
1712
|
-
const def = { enabled: true };
|
|
1713
|
-
for (const field of entry.required) {
|
|
1714
|
-
const value = src[field];
|
|
1715
|
-
if (value === void 0 || value === null || value === "") {
|
|
1716
|
-
throw new Error(
|
|
1717
|
-
`notifications: provider "${name}" is enabled but missing required field "${field}"`
|
|
1718
|
-
);
|
|
1719
|
-
}
|
|
1720
|
-
def[field] = value;
|
|
1721
|
-
}
|
|
1722
|
-
for (const field of entry.optional) {
|
|
1723
|
-
if (src[field] !== void 0) {
|
|
1724
|
-
def[field] = src[field];
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
if (name === "twilio") {
|
|
1728
|
-
const hasFrom = Boolean(def.fromNumber);
|
|
1729
|
-
const hasMsg = Boolean(def.messagingServiceSid);
|
|
1730
|
-
if (!hasFrom && !hasMsg) {
|
|
1731
|
-
throw new Error(
|
|
1732
|
-
'notifications: provider "twilio" requires one of "fromNumber" or "messagingServiceSid"'
|
|
1733
|
-
);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
return def;
|
|
1737
|
-
}
|
|
1738
|
-
function defineNotifications(input) {
|
|
1739
|
-
if (input === null || typeof input !== "object") {
|
|
1740
|
-
throw new Error("defineNotifications expects { push?, email?, sms? }");
|
|
1741
|
-
}
|
|
1742
|
-
const config = {
|
|
1743
|
-
__config: NOTIFICATIONS_CONFIG_KIND,
|
|
1744
|
-
push: {},
|
|
1745
|
-
email: {},
|
|
1746
|
-
sms: {},
|
|
1747
|
-
templates: buildTemplates(input.templates ?? {})
|
|
1748
|
-
};
|
|
1749
|
-
const push = input.push ?? {};
|
|
1750
|
-
if (push.apns !== void 0) config.push.apns = buildProvider("apns", push.apns);
|
|
1751
|
-
if (push.fcm !== void 0) config.push.fcm = buildProvider("fcm", push.fcm);
|
|
1752
|
-
const email = input.email ?? {};
|
|
1753
|
-
if (email.sendgrid !== void 0) config.email.sendgrid = buildProvider("sendgrid", email.sendgrid);
|
|
1754
|
-
if (email.ses !== void 0) config.email.ses = buildProvider("ses", email.ses);
|
|
1755
|
-
if (email.smtp !== void 0) config.email.smtp = buildProvider("smtp", email.smtp);
|
|
1756
|
-
if (email.acs !== void 0) config.email.acs = buildProvider("acs", email.acs);
|
|
1757
|
-
const sms = input.sms ?? {};
|
|
1758
|
-
if (sms.twilio !== void 0) config.sms.twilio = buildProvider("twilio", sms.twilio);
|
|
1759
|
-
return config;
|
|
1760
|
-
}
|
|
1761
|
-
function reservedSecretKey(provider, secretField) {
|
|
1762
|
-
return `${RESERVED_SECRET_PREFIX}_${camelToUpperSnake(provider)}_${camelToUpperSnake(secretField)}`;
|
|
1763
|
-
}
|
|
1764
|
-
function camelToUpperSnake(s) {
|
|
1765
|
-
return s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
1766
|
-
}
|
|
1332
|
+
declare module "@palbase/backend/stack" {
|
|
1333
|
+
interface Secrets {${members(secrets)}}
|
|
1767
1334
|
|
|
1768
|
-
|
|
1769
|
-
var TEST_USERS_CONFIG_KIND = "test-users";
|
|
1770
|
-
var TEST_USER_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
1771
|
-
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1772
|
-
var E164_RE = /^\+[1-9]\d{1,14}$/;
|
|
1773
|
-
var OTP_LENGTH = 6;
|
|
1774
|
-
var OTP_RE = /^\d{6}$/;
|
|
1775
|
-
var MIN_PASSWORD_LENGTH = 8;
|
|
1776
|
-
function isPlainObject(value) {
|
|
1777
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1778
|
-
}
|
|
1779
|
-
function normalizeSeed(seed, userName) {
|
|
1780
|
-
if (seed === void 0) return {};
|
|
1781
|
-
if (!isPlainObject(seed)) {
|
|
1782
|
-
throw new Error(`testUser ${JSON.stringify(userName)}: seed must be { <table>: [ {...} ] }`);
|
|
1783
|
-
}
|
|
1784
|
-
const out = {};
|
|
1785
|
-
for (const [table, rows] of Object.entries(seed)) {
|
|
1786
|
-
if (!Array.isArray(rows)) {
|
|
1787
|
-
throw new Error(
|
|
1788
|
-
`testUser ${JSON.stringify(userName)}: seed.${table} must be an array of rows`
|
|
1789
|
-
);
|
|
1790
|
-
}
|
|
1791
|
-
if (rows.length === 0) {
|
|
1792
|
-
throw new Error(
|
|
1793
|
-
`testUser ${JSON.stringify(userName)}: seed.${table} is empty \u2014 remove it or add a row`
|
|
1794
|
-
);
|
|
1795
|
-
}
|
|
1796
|
-
for (const row of rows) {
|
|
1797
|
-
if (!isPlainObject(row)) {
|
|
1798
|
-
throw new Error(
|
|
1799
|
-
`testUser ${JSON.stringify(userName)}: every row in seed.${table} must be an object`
|
|
1800
|
-
);
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
out[table] = rows;
|
|
1804
|
-
}
|
|
1805
|
-
return out;
|
|
1806
|
-
}
|
|
1807
|
-
function testUser(opts = {}) {
|
|
1808
|
-
if (!isPlainObject(opts)) {
|
|
1809
|
-
throw new Error("testUser() expects { email?, password?, phone?, otp?, seed? }");
|
|
1810
|
-
}
|
|
1811
|
-
const hasEmail = opts.email !== void 0;
|
|
1812
|
-
const hasPassword = opts.password !== void 0;
|
|
1813
|
-
if (hasEmail !== hasPassword) {
|
|
1814
|
-
throw new Error(
|
|
1815
|
-
"testUser() needs email AND password together (a fixture with stable credentials) or neither (a template the server generates credentials for)"
|
|
1816
|
-
);
|
|
1817
|
-
}
|
|
1818
|
-
let email = null;
|
|
1819
|
-
let password = null;
|
|
1820
|
-
if (hasEmail) {
|
|
1821
|
-
if (typeof opts.email !== "string" || !EMAIL_RE.test(opts.email)) {
|
|
1822
|
-
throw new Error(`testUser email ${JSON.stringify(opts.email)} is not a valid address`);
|
|
1823
|
-
}
|
|
1824
|
-
if (typeof opts.password !== "string" || opts.password.length < MIN_PASSWORD_LENGTH) {
|
|
1825
|
-
throw new Error(
|
|
1826
|
-
`testUser password must be at least ${MIN_PASSWORD_LENGTH} characters (got ${typeof opts.password === "string" ? opts.password.length : 0})`
|
|
1827
|
-
);
|
|
1828
|
-
}
|
|
1829
|
-
email = opts.email;
|
|
1830
|
-
password = opts.password;
|
|
1831
|
-
}
|
|
1832
|
-
const hasPhone = opts.phone !== void 0;
|
|
1833
|
-
const hasOTP = opts.otp !== void 0;
|
|
1834
|
-
if (hasPhone !== hasOTP) {
|
|
1835
|
-
throw new Error(
|
|
1836
|
-
"testUser() needs phone AND otp together \u2014 nothing can receive an SMS at a fabricated number, so a phone fixture without its fixed code can never be signed in as"
|
|
1837
|
-
);
|
|
1838
|
-
}
|
|
1839
|
-
let phone = null;
|
|
1840
|
-
let otp = null;
|
|
1841
|
-
if (hasPhone) {
|
|
1842
|
-
if (typeof opts.phone !== "string" || !E164_RE.test(opts.phone)) {
|
|
1843
|
-
throw new Error(
|
|
1844
|
-
`testUser phone ${JSON.stringify(opts.phone)} must be E.164, e.g. "+905551112233"`
|
|
1845
|
-
);
|
|
1846
|
-
}
|
|
1847
|
-
if (typeof opts.otp !== "string" || !OTP_RE.test(opts.otp)) {
|
|
1848
|
-
throw new Error(
|
|
1849
|
-
`testUser otp ${JSON.stringify(opts.otp)} must be ${OTP_LENGTH} digits`
|
|
1850
|
-
);
|
|
1851
|
-
}
|
|
1852
|
-
phone = opts.phone;
|
|
1853
|
-
otp = opts.otp;
|
|
1854
|
-
}
|
|
1855
|
-
return { email, password, phone, otp, seed: normalizeSeed(opts.seed, email ?? "<template>") };
|
|
1856
|
-
}
|
|
1857
|
-
function defineTestUsers(input) {
|
|
1858
|
-
if (!isPlainObject(input) || !isPlainObject(input.users)) {
|
|
1859
|
-
throw new Error("defineTestUsers expects { users: { <name>: testUser({...}) } }");
|
|
1860
|
-
}
|
|
1861
|
-
const users = {};
|
|
1862
|
-
const emails = /* @__PURE__ */ new Map();
|
|
1863
|
-
for (const name of Object.keys(input.users)) {
|
|
1864
|
-
if (!TEST_USER_NAME_RE.test(name)) {
|
|
1865
|
-
throw new Error(
|
|
1866
|
-
`test user name ${JSON.stringify(name)} is invalid \u2014 must start with a letter and contain only letters, digits, and underscores`
|
|
1867
|
-
);
|
|
1868
|
-
}
|
|
1869
|
-
const def = input.users[name];
|
|
1870
|
-
if (def === void 0) continue;
|
|
1871
|
-
if (def.email !== null) {
|
|
1872
|
-
const lower = def.email.toLowerCase();
|
|
1873
|
-
const already = emails.get(lower);
|
|
1874
|
-
if (already !== void 0) {
|
|
1875
|
-
throw new Error(
|
|
1876
|
-
`test users ${JSON.stringify(already)} and ${JSON.stringify(name)} declare the same e-mail ${JSON.stringify(def.email)}`
|
|
1877
|
-
);
|
|
1878
|
-
}
|
|
1879
|
-
emails.set(lower, name);
|
|
1880
|
-
}
|
|
1881
|
-
users[name] = def;
|
|
1882
|
-
}
|
|
1883
|
-
return { __config: TEST_USERS_CONFIG_KIND, users };
|
|
1884
|
-
}
|
|
1335
|
+
interface Flags {${members(flags)}}
|
|
1885
1336
|
|
|
1886
|
-
|
|
1887
|
-
var FLAGS_CONFIG_KIND = "flags";
|
|
1888
|
-
var FLAG_KEY_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
1889
|
-
function valueMatchesType(type, value) {
|
|
1890
|
-
switch (type) {
|
|
1891
|
-
case "boolean":
|
|
1892
|
-
return typeof value === "boolean";
|
|
1893
|
-
case "number":
|
|
1894
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
1895
|
-
case "string":
|
|
1896
|
-
return typeof value === "string";
|
|
1897
|
-
case "json":
|
|
1898
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
function flag(opts) {
|
|
1902
|
-
if (opts === null || typeof opts !== "object") {
|
|
1903
|
-
throw new Error("flag() expects { type, default, variants?, description? }");
|
|
1904
|
-
}
|
|
1905
|
-
const { type } = opts;
|
|
1906
|
-
if (type !== "boolean" && type !== "number" && type !== "string" && type !== "json") {
|
|
1907
|
-
throw new Error(`flag type must be "boolean", "number", "string", or "json", got ${JSON.stringify(type)}`);
|
|
1908
|
-
}
|
|
1909
|
-
if (!valueMatchesType(type, opts.default)) {
|
|
1910
|
-
throw new Error(
|
|
1911
|
-
`flag default ${JSON.stringify(opts.default)} does not match type "${type}"`
|
|
1912
|
-
);
|
|
1913
|
-
}
|
|
1914
|
-
let variants = null;
|
|
1915
|
-
if (opts.variants !== void 0) {
|
|
1916
|
-
if (opts.type !== "string") {
|
|
1917
|
-
throw new Error(`flag variants are only valid for type "string" (got type "${type}")`);
|
|
1918
|
-
}
|
|
1919
|
-
if (!Array.isArray(opts.variants)) {
|
|
1920
|
-
throw new Error("flag variants must be an array of strings");
|
|
1921
|
-
}
|
|
1922
|
-
for (const v of opts.variants) {
|
|
1923
|
-
if (typeof v !== "string" || v.length === 0) {
|
|
1924
|
-
throw new Error(`flag variant ${JSON.stringify(v)} must be a non-empty string`);
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
variants = [...new Set(opts.variants)];
|
|
1928
|
-
if (variants.length === 0) {
|
|
1929
|
-
throw new Error("flag variants must be a non-empty list when supplied");
|
|
1930
|
-
}
|
|
1931
|
-
if (!variants.includes(opts.default)) {
|
|
1932
|
-
throw new Error(
|
|
1933
|
-
`flag default ${JSON.stringify(opts.default)} is not one of its variants [${variants.map((v) => JSON.stringify(v)).join(", ")}]`
|
|
1934
|
-
);
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
let conditions = null;
|
|
1938
|
-
if (opts.conditions !== void 0) {
|
|
1939
|
-
if (!Array.isArray(opts.conditions)) {
|
|
1940
|
-
throw new Error("flag conditions must be an array of { when, value }");
|
|
1941
|
-
}
|
|
1942
|
-
const compiled = [];
|
|
1943
|
-
for (const [i, branch] of opts.conditions.entries()) {
|
|
1944
|
-
if (branch === null || typeof branch !== "object") {
|
|
1945
|
-
throw new Error(`flag condition ${i} must be an object { when, value }`);
|
|
1946
|
-
}
|
|
1947
|
-
if (typeof branch.when !== "string" || branch.when.trim().length === 0) {
|
|
1948
|
-
throw new Error(`flag condition ${i} needs a non-empty "when" expression`);
|
|
1949
|
-
}
|
|
1950
|
-
if (!valueMatchesType(type, branch.value)) {
|
|
1951
|
-
throw new Error(
|
|
1952
|
-
`flag condition ${i} value ${JSON.stringify(branch.value)} does not match type "${type}"`
|
|
1953
|
-
);
|
|
1954
|
-
}
|
|
1955
|
-
if (variants !== null && !variants.includes(branch.value)) {
|
|
1956
|
-
throw new Error(
|
|
1957
|
-
`flag condition ${i} value ${JSON.stringify(branch.value)} is not one of its variants [${variants.map((v) => JSON.stringify(v)).join(", ")}]`
|
|
1958
|
-
);
|
|
1959
|
-
}
|
|
1960
|
-
compiled.push({ when: branch.when.trim(), value: branch.value });
|
|
1961
|
-
}
|
|
1962
|
-
conditions = compiled.length > 0 ? compiled : null;
|
|
1963
|
-
}
|
|
1964
|
-
let description = null;
|
|
1965
|
-
if (opts.description !== void 0) {
|
|
1966
|
-
if (typeof opts.description !== "string") {
|
|
1967
|
-
throw new Error("flag description must be a string");
|
|
1968
|
-
}
|
|
1969
|
-
const trimmed = opts.description.trim();
|
|
1970
|
-
description = trimmed.length > 0 ? trimmed : null;
|
|
1971
|
-
}
|
|
1972
|
-
return {
|
|
1973
|
-
type,
|
|
1974
|
-
default: opts.default,
|
|
1975
|
-
variants,
|
|
1976
|
-
conditions,
|
|
1977
|
-
description
|
|
1978
|
-
};
|
|
1979
|
-
}
|
|
1980
|
-
function defineFlags(input) {
|
|
1981
|
-
if (input === null || typeof input !== "object" || typeof input.flags !== "object") {
|
|
1982
|
-
throw new Error("defineFlags expects { flags: { <key>: flag({...}) } }");
|
|
1983
|
-
}
|
|
1984
|
-
const flags = {};
|
|
1985
|
-
for (const key of Object.keys(input.flags)) {
|
|
1986
|
-
if (!FLAG_KEY_RE.test(key)) {
|
|
1987
|
-
throw new Error(
|
|
1988
|
-
`flag key ${JSON.stringify(key)} is invalid \u2014 must start with a letter and contain only letters, digits, and underscores`
|
|
1989
|
-
);
|
|
1990
|
-
}
|
|
1991
|
-
const def = input.flags[key];
|
|
1992
|
-
if (def === void 0) continue;
|
|
1993
|
-
flags[key] = def;
|
|
1994
|
-
}
|
|
1995
|
-
return { __config: FLAGS_CONFIG_KIND, flags };
|
|
1337
|
+
interface Buckets {${bucketMembers(names.buckets)}}
|
|
1996
1338
|
}
|
|
1997
1339
|
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
2001
|
-
function secret(name, opts = {}) {
|
|
2002
|
-
if (typeof name !== "string" || !SECRET_NAME_RE.test(name)) {
|
|
2003
|
-
throw new Error(
|
|
2004
|
-
`secret name ${JSON.stringify(name)} is invalid \u2014 must be an environment-variable name: an uppercase letter, then uppercase letters, digits, and underscores (e.g. "NEO4J_PASSWORD")`
|
|
2005
|
-
);
|
|
2006
|
-
}
|
|
2007
|
-
if (opts === null || typeof opts !== "object") {
|
|
2008
|
-
throw new Error(`secret("${name}") expects { required?, description? }`);
|
|
2009
|
-
}
|
|
2010
|
-
let required = true;
|
|
2011
|
-
if (opts.required !== void 0) {
|
|
2012
|
-
if (typeof opts.required !== "boolean") {
|
|
2013
|
-
throw new Error(`secret("${name}") required must be a boolean`);
|
|
2014
|
-
}
|
|
2015
|
-
required = opts.required;
|
|
2016
|
-
}
|
|
2017
|
-
let description = null;
|
|
2018
|
-
if (opts.description !== void 0) {
|
|
2019
|
-
if (typeof opts.description !== "string") {
|
|
2020
|
-
throw new Error(`secret("${name}") description must be a string`);
|
|
2021
|
-
}
|
|
2022
|
-
const trimmed = opts.description.trim();
|
|
2023
|
-
description = trimmed.length > 0 ? trimmed : null;
|
|
2024
|
-
}
|
|
2025
|
-
return { name, required, description };
|
|
2026
|
-
}
|
|
2027
|
-
function defineSecrets(input) {
|
|
2028
|
-
if (input === null || typeof input !== "object" || !Array.isArray(input.secrets)) {
|
|
2029
|
-
throw new Error('defineSecrets expects { secrets: [secret("NAME"), ...] }');
|
|
2030
|
-
}
|
|
2031
|
-
const byName = /* @__PURE__ */ new Map();
|
|
2032
|
-
for (const def of input.secrets) {
|
|
2033
|
-
if (def === null || typeof def !== "object" || typeof def.name !== "string" || typeof def.required !== "boolean") {
|
|
2034
|
-
throw new Error(
|
|
2035
|
-
`defineSecrets: every entry must come from secret() \u2014 got ${JSON.stringify(def)}`
|
|
2036
|
-
);
|
|
2037
|
-
}
|
|
2038
|
-
if (byName.has(def.name)) {
|
|
2039
|
-
throw new Error(
|
|
2040
|
-
`secret "${def.name}" is declared twice in config/secrets.ts \u2014 remove one; a name has exactly one requirement`
|
|
2041
|
-
);
|
|
2042
|
-
}
|
|
2043
|
-
byName.set(def.name, def);
|
|
2044
|
-
}
|
|
2045
|
-
const secrets = [...byName.values()].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
2046
|
-
return { __config: SECRETS_CONFIG_KIND, secrets };
|
|
1340
|
+
export {};
|
|
1341
|
+
`;
|
|
2047
1342
|
}
|
|
2048
1343
|
|
|
2049
1344
|
// src/decorators/methods.ts
|
|
@@ -2240,21 +1535,36 @@ function validateUploadConfigShape(c) {
|
|
|
2240
1535
|
if (c === null || typeof c !== "object") {
|
|
2241
1536
|
throw new Error("@Upload config must be an object { bucket, pathTemplate, ... }");
|
|
2242
1537
|
}
|
|
2243
|
-
|
|
1538
|
+
const bucket = c.bucket;
|
|
1539
|
+
if (typeof bucket !== "string" || bucket.length === 0) {
|
|
2244
1540
|
throw new Error("@Upload config.bucket must be a non-empty bucket name");
|
|
2245
1541
|
}
|
|
2246
1542
|
if (typeof c.pathTemplate !== "string" || c.pathTemplate.length === 0) {
|
|
2247
1543
|
throw new Error("@Upload config.pathTemplate must be a non-empty key template");
|
|
2248
1544
|
}
|
|
2249
1545
|
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
1546
|
+
|
|
1547
|
+
// src/decorators/sse.ts
|
|
1548
|
+
function Sse(subpath = "", config) {
|
|
1549
|
+
const { auth, rateLimit, ...sseConfig } = config;
|
|
1550
|
+
const options = {
|
|
1551
|
+
sseConfig,
|
|
1552
|
+
...auth !== void 0 ? { auth } : {},
|
|
1553
|
+
...rateLimit !== void 0 ? { rateLimit } : {}
|
|
1554
|
+
};
|
|
1555
|
+
return function(target, propertyKey) {
|
|
1556
|
+
recordRoute(target, String(propertyKey), "POST", subpath, options);
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
function SseOut() {
|
|
1560
|
+
return function(target, propertyKey, parameterIndex) {
|
|
1561
|
+
recordParam(target, String(propertyKey), { index: parameterIndex, kind: "sseOut" });
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
function Signal() {
|
|
1565
|
+
return function(target, propertyKey, parameterIndex) {
|
|
1566
|
+
recordParam(target, String(propertyKey), { index: parameterIndex, kind: "signal" });
|
|
1567
|
+
};
|
|
2258
1568
|
}
|
|
2259
1569
|
|
|
2260
1570
|
// src/decorators/params.ts
|
|
@@ -2431,52 +1741,6 @@ function getJobConfig(ctor) {
|
|
|
2431
1741
|
return { schedule: meta.schedule, timeout, retry, handler: run };
|
|
2432
1742
|
}
|
|
2433
1743
|
|
|
2434
|
-
// src/resource.ts
|
|
2435
|
-
var Resource = class {
|
|
2436
|
-
/** The env-var names this resource needs. Optional; omit for none. */
|
|
2437
|
-
static secrets;
|
|
2438
|
-
};
|
|
2439
|
-
function hasSecrets(value) {
|
|
2440
|
-
if (typeof value !== "object" && typeof value !== "function") return false;
|
|
2441
|
-
const secrets = value.secrets;
|
|
2442
|
-
return secrets === void 0 || Array.isArray(secrets);
|
|
2443
|
-
}
|
|
2444
|
-
var registry = [];
|
|
2445
|
-
function __registerResource(resource) {
|
|
2446
|
-
registry.push({ resource, booted: false });
|
|
2447
|
-
}
|
|
2448
|
-
function declaredSecrets(resource) {
|
|
2449
|
-
const ctor = resource.constructor;
|
|
2450
|
-
return hasSecrets(ctor) ? ctor.secrets ?? [] : [];
|
|
2451
|
-
}
|
|
2452
|
-
async function __runResourceBoot(envMap) {
|
|
2453
|
-
for (const entry of registry) {
|
|
2454
|
-
if (entry.booted) continue;
|
|
2455
|
-
const secrets = declaredSecrets(entry.resource);
|
|
2456
|
-
const env = {};
|
|
2457
|
-
for (const name of secrets) {
|
|
2458
|
-
const value = envMap[name];
|
|
2459
|
-
if (value === void 0) {
|
|
2460
|
-
throw new Error(
|
|
2461
|
-
`Resource ${entry.resource.constructor.name} requires secret "${name}" but it is not set. Set it with \`palbase secret set ${name} ...\` (or in Studio) and redeploy.`
|
|
2462
|
-
);
|
|
2463
|
-
}
|
|
2464
|
-
env[name] = value;
|
|
2465
|
-
}
|
|
2466
|
-
await entry.resource.init(env);
|
|
2467
|
-
entry.booted = true;
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
async function __shutdownResources() {
|
|
2471
|
-
for (let i = registry.length - 1; i >= 0; i -= 1) {
|
|
2472
|
-
const entry = registry[i];
|
|
2473
|
-
if (entry.booted && entry.resource.shutdown) {
|
|
2474
|
-
await entry.resource.shutdown();
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
registry.length = 0;
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
1744
|
// src/index.ts
|
|
2481
1745
|
import { z } from "zod";
|
|
2482
1746
|
export {
|
|
@@ -2486,17 +1750,11 @@ export {
|
|
|
2486
1750
|
Client,
|
|
2487
1751
|
Conflict,
|
|
2488
1752
|
Controller,
|
|
2489
|
-
DEFAULT_TEMPLATE_LOCALE,
|
|
2490
1753
|
Database,
|
|
2491
1754
|
Delete,
|
|
2492
1755
|
Deny,
|
|
2493
1756
|
Documents,
|
|
2494
|
-
EGRESS_CONFIG_KIND,
|
|
2495
|
-
EGRESS_TIMEOUT_DEFAULT_MS,
|
|
2496
|
-
EGRESS_TIMEOUT_MAX_MS,
|
|
2497
|
-
EGRESS_TIMEOUT_MIN_MS,
|
|
2498
1757
|
EXTENSION_DEPENDENCIES,
|
|
2499
|
-
FLAGS_CONFIG_KIND,
|
|
2500
1758
|
Flags,
|
|
2501
1759
|
Forbidden,
|
|
2502
1760
|
Get,
|
|
@@ -2505,35 +1763,28 @@ export {
|
|
|
2505
1763
|
HttpError,
|
|
2506
1764
|
Job,
|
|
2507
1765
|
Log,
|
|
2508
|
-
NOTIFICATIONS_CONFIG_KIND,
|
|
2509
1766
|
NotFound,
|
|
2510
1767
|
Notifications,
|
|
2511
1768
|
On,
|
|
2512
1769
|
OptionalUser,
|
|
2513
1770
|
PALBASE_EXTENSIONS,
|
|
2514
|
-
PROVIDER_CATALOG,
|
|
2515
1771
|
PalError,
|
|
2516
1772
|
PalbaseModuleError,
|
|
2517
1773
|
Param,
|
|
2518
1774
|
Patch,
|
|
2519
1775
|
PolicyBuilder,
|
|
2520
1776
|
Post,
|
|
2521
|
-
Purchases,
|
|
2522
1777
|
Put,
|
|
2523
1778
|
Query,
|
|
2524
1779
|
QueryParams,
|
|
2525
|
-
RESERVED_SECRET_PREFIX,
|
|
2526
1780
|
Realtime,
|
|
2527
1781
|
Req,
|
|
2528
1782
|
RequestId,
|
|
2529
|
-
RequireEntitlement,
|
|
2530
|
-
Resource,
|
|
2531
|
-
SECRETS_CONFIG_KIND,
|
|
2532
|
-
STORAGE_CONFIG_KIND,
|
|
2533
1783
|
Secrets,
|
|
2534
|
-
|
|
1784
|
+
Signal,
|
|
1785
|
+
Sse,
|
|
1786
|
+
SseOut,
|
|
2535
1787
|
Storage,
|
|
2536
|
-
TEST_USERS_CONFIG_KIND,
|
|
2537
1788
|
TooManyRequests,
|
|
2538
1789
|
TraceId,
|
|
2539
1790
|
TxPlanError,
|
|
@@ -2544,33 +1795,19 @@ export {
|
|
|
2544
1795
|
User,
|
|
2545
1796
|
Webhook,
|
|
2546
1797
|
__getRuntime,
|
|
2547
|
-
__registerResource,
|
|
2548
1798
|
__requestALS,
|
|
2549
1799
|
__resetRegisteredControllers,
|
|
2550
|
-
__runResourceBoot,
|
|
2551
1800
|
__runWithRuntime,
|
|
2552
1801
|
__setRuntime,
|
|
2553
|
-
__shutdownResources,
|
|
2554
1802
|
bigint,
|
|
2555
1803
|
boolean,
|
|
2556
|
-
bucket,
|
|
2557
1804
|
buildModuleClients,
|
|
2558
|
-
buildProvider,
|
|
2559
1805
|
dec,
|
|
2560
1806
|
defineChannels,
|
|
2561
|
-
defineEgress,
|
|
2562
1807
|
defineError,
|
|
2563
|
-
defineFlags,
|
|
2564
1808
|
defineMiddleware,
|
|
2565
|
-
defineNotifications,
|
|
2566
1809
|
defineSchema,
|
|
2567
|
-
defineSecrets,
|
|
2568
|
-
defineStorage,
|
|
2569
|
-
defineTestUsers,
|
|
2570
|
-
entitlementFor,
|
|
2571
1810
|
enumType,
|
|
2572
|
-
extractVariables,
|
|
2573
|
-
flag,
|
|
2574
1811
|
getErrorRegistry,
|
|
2575
1812
|
getHookConfig,
|
|
2576
1813
|
getJobConfig,
|
|
@@ -2583,26 +1820,20 @@ export {
|
|
|
2583
1820
|
jsonb,
|
|
2584
1821
|
makeEnvDts,
|
|
2585
1822
|
makeHttpClient,
|
|
2586
|
-
|
|
1823
|
+
makeStackDts,
|
|
2587
1824
|
makeTypedDB,
|
|
2588
1825
|
now,
|
|
2589
1826
|
numeric,
|
|
2590
1827
|
openai,
|
|
2591
1828
|
ownerOnly,
|
|
2592
|
-
parseFileSizeLimit,
|
|
2593
1829
|
policy,
|
|
2594
1830
|
publicChannel,
|
|
2595
1831
|
raw,
|
|
2596
1832
|
recordThrows,
|
|
2597
|
-
reservedSecretKey,
|
|
2598
|
-
secret,
|
|
2599
|
-
spendFor,
|
|
2600
|
-
testUser,
|
|
2601
1833
|
text,
|
|
2602
1834
|
timestamp,
|
|
2603
1835
|
toSchemaJSON,
|
|
2604
1836
|
uuid,
|
|
2605
|
-
validateUploadAgainstStorage,
|
|
2606
1837
|
vector,
|
|
2607
1838
|
z
|
|
2608
1839
|
};
|