@palbase/backend 9.0.1 → 10.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/{chunk-SO6YV35D.js → chunk-4WOQWFUP.js} +38 -6
- package/dist/chunk-4WOQWFUP.js.map +1 -0
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +18 -4
- package/dist/db/env.d.ts +18 -4
- package/dist/db/index.cjs +37 -5
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +1 -1
- package/dist/{endpoint-CGI5cZMg.d.cts → endpoint-Cn3ICGTf.d.cts} +26 -4
- package/dist/{endpoint-CGI5cZMg.d.ts → endpoint-Cn3ICGTf.d.ts} +26 -4
- package/dist/{index-osv2jMmZ.d.cts → index-Bt7UHkAM.d.cts} +40 -5
- package/dist/{index--dH5i4Nu.d.ts → index-V0ealeY-.d.ts} +40 -5
- package/dist/index.cjs +236 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +262 -14
- package/dist/index.d.ts +262 -14
- package/dist/index.js +194 -3
- package/dist/index.js.map +1 -1
- package/dist/test/index.d.cts +1 -1
- package/dist/test/index.d.ts +1 -1
- package/docs/README.md +12 -10
- package/docs/background.md +4 -4
- package/docs/events.md +4 -4
- package/docs/getting-started.md +6 -5
- package/docs/llms-full.txt +39 -36
- package/docs/migrations.md +10 -10
- package/docs/resources.md +3 -3
- package/package.json +1 -1
- package/dist/chunk-SO6YV35D.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(src_exports, {
|
|
|
29
29
|
Database: () => Database,
|
|
30
30
|
Delete: () => Delete,
|
|
31
31
|
Documents: () => Documents,
|
|
32
|
+
EGRESS_CONFIG_KIND: () => EGRESS_CONFIG_KIND,
|
|
32
33
|
EXTENSION_DEPENDENCIES: () => EXTENSION_DEPENDENCIES,
|
|
33
34
|
FLAGS_CONFIG_KIND: () => FLAGS_CONFIG_KIND,
|
|
34
35
|
Flags: () => Flags,
|
|
@@ -59,6 +60,7 @@ __export(src_exports, {
|
|
|
59
60
|
Resource: () => Resource,
|
|
60
61
|
STORAGE_CONFIG_KIND: () => STORAGE_CONFIG_KIND,
|
|
61
62
|
Storage: () => Storage,
|
|
63
|
+
TEST_USERS_CONFIG_KIND: () => TEST_USERS_CONFIG_KIND,
|
|
62
64
|
TooManyRequests: () => TooManyRequests,
|
|
63
65
|
TraceId: () => TraceId,
|
|
64
66
|
Unauthorized: () => Unauthorized,
|
|
@@ -77,6 +79,7 @@ __export(src_exports, {
|
|
|
77
79
|
boolean: () => boolean,
|
|
78
80
|
bucket: () => bucket,
|
|
79
81
|
buildProvider: () => buildProvider,
|
|
82
|
+
defineEgress: () => defineEgress,
|
|
80
83
|
defineError: () => defineError,
|
|
81
84
|
defineFlags: () => defineFlags,
|
|
82
85
|
defineJob: () => defineJob,
|
|
@@ -84,12 +87,14 @@ __export(src_exports, {
|
|
|
84
87
|
defineNotifications: () => defineNotifications,
|
|
85
88
|
defineSchema: () => defineSchema,
|
|
86
89
|
defineStorage: () => defineStorage,
|
|
90
|
+
defineTestUsers: () => defineTestUsers,
|
|
87
91
|
defineWebhook: () => defineWebhook,
|
|
88
92
|
defineWorker: () => defineWorker,
|
|
89
93
|
documents: () => documents,
|
|
90
94
|
enumType: () => enumType,
|
|
91
95
|
flag: () => flag,
|
|
92
96
|
getErrorRegistry: () => getErrorRegistry,
|
|
97
|
+
getRoutes: () => getRoutes,
|
|
93
98
|
integer: () => integer,
|
|
94
99
|
isPalbaseExtension: () => isPalbaseExtension,
|
|
95
100
|
jsonb: () => jsonb,
|
|
@@ -102,6 +107,7 @@ __export(src_exports, {
|
|
|
102
107
|
recordThrows: () => recordThrows,
|
|
103
108
|
reservedSecretKey: () => reservedSecretKey,
|
|
104
109
|
storage: () => storage,
|
|
110
|
+
testUser: () => testUser,
|
|
105
111
|
text: () => text,
|
|
106
112
|
timestamp: () => timestamp,
|
|
107
113
|
uuid: () => uuid,
|
|
@@ -402,12 +408,44 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
402
408
|
* `auth.users` lives in the SAME tenant database (palauth-owned), so this is
|
|
403
409
|
* a genuine cross-schema integrity constraint scoped to THIS tenant's users.
|
|
404
410
|
* The referenced `auth.users.id` is `text` (palauth ids are `usr_<uuid>`), so
|
|
405
|
-
* the referencing column must be `text()` too.
|
|
406
|
-
*
|
|
407
|
-
* `
|
|
411
|
+
* the referencing column must be `text()` too.
|
|
412
|
+
*
|
|
413
|
+
* ON DELETE is REQUIRED here and may only be `cascade` or `set null`: an
|
|
414
|
+
* account-erasure request must never be blocked by a lingering FK, so
|
|
415
|
+
* `restrict` / `no action` are not accepted (they don't type-check). Example:
|
|
416
|
+
* `text().notNull().referencesAuthUser("cascade")`, or
|
|
417
|
+
* `text().nullable().referencesAuthUser("set null")`. The server
|
|
418
|
+
* (validateAuthUserFK) enforces this — and the remaining rules the type can't
|
|
419
|
+
* express (referencing column is text, `set null` needs a nullable column) —
|
|
420
|
+
* as the real boundary; this signature is the compile-time DX mirror.
|
|
408
421
|
*/
|
|
409
|
-
referencesAuthUser() {
|
|
410
|
-
|
|
422
|
+
referencesAuthUser(onDelete) {
|
|
423
|
+
this._def.references = { table: "auth.users", column: "id" };
|
|
424
|
+
this._def.onDeleteAction = onDelete;
|
|
425
|
+
return new _ColumnBuilder(this._def.type, this._def);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Add a real DB-level foreign key to the canonical, server-minted installation
|
|
429
|
+
* anchor (`REFERENCES auth.installations(id)`) — the app-scoped verified-device
|
|
430
|
+
* root (`ins_...`). Sugar for `.references("auth.installations", "id")`.
|
|
431
|
+
*
|
|
432
|
+
* An installation is an APP INSTALL, not a user: this FK is NOT user ownership.
|
|
433
|
+
* A user-owned row STILL needs its own `.referencesAuthUser(...)` FK so account
|
|
434
|
+
* erasure removes it — an installation reference alone does not tie a row to a
|
|
435
|
+
* user's deletion. Use this only for install-scoped state (device prefs, push
|
|
436
|
+
* routing, …), alongside a separate auth-user FK where the row is user-owned.
|
|
437
|
+
*
|
|
438
|
+
* `auth.installations` lives in the SAME tenant DB (palauth-owned); its `id` is
|
|
439
|
+
* `text` (`ins_<uuid>`), so the referencing column must be `text()` too. ON
|
|
440
|
+
* DELETE is REQUIRED and may only be `cascade` or `set null` (same allowed set
|
|
441
|
+
* as an auth-user FK): an installation revoke / orphan cleanup must never be
|
|
442
|
+
* blocked by a lingering FK. The server (validateAuthAnchorFK) is the real
|
|
443
|
+
* boundary; this signature is the compile-time DX mirror.
|
|
444
|
+
*/
|
|
445
|
+
referencesInstallation(onDelete) {
|
|
446
|
+
this._def.references = { table: "auth.installations", column: "id" };
|
|
447
|
+
this._def.onDeleteAction = onDelete;
|
|
448
|
+
return new _ColumnBuilder(this._def.type, this._def);
|
|
411
449
|
}
|
|
412
450
|
/** Set the ON DELETE action for a foreign key reference. */
|
|
413
451
|
onDelete(action) {
|
|
@@ -515,7 +553,50 @@ function rowType(def) {
|
|
|
515
553
|
function optionalOnInsert(def) {
|
|
516
554
|
return def.nullable === true || def.defaultRandom === true || def.defaultNow === true || def.defaultValue !== void 0;
|
|
517
555
|
}
|
|
518
|
-
|
|
556
|
+
var AUTH_USERS_TABLE = "auth.users";
|
|
557
|
+
function ownerColumnOf(table) {
|
|
558
|
+
for (const [col, builder] of Object.entries(table.columns)) {
|
|
559
|
+
if (builder._def.references?.table === AUTH_USERS_TABLE) return col;
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
function buildChildEdges(schema) {
|
|
564
|
+
const edges = /* @__PURE__ */ new Map();
|
|
565
|
+
for (const name of Object.keys(schema.tables)) edges.set(name, []);
|
|
566
|
+
for (const childName of Object.keys(schema.tables)) {
|
|
567
|
+
const table = schema.tables[childName];
|
|
568
|
+
if (table === void 0) continue;
|
|
569
|
+
for (const [col, builder] of Object.entries(table.columns)) {
|
|
570
|
+
const ref = builder._def.references;
|
|
571
|
+
if (ref === void 0) continue;
|
|
572
|
+
if (ref.table === childName) continue;
|
|
573
|
+
const bucket2 = edges.get(ref.table);
|
|
574
|
+
if (bucket2 === void 0) continue;
|
|
575
|
+
if (bucket2.some((e) => e.child === childName)) continue;
|
|
576
|
+
bucket2.push({ child: childName, column: col });
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return edges;
|
|
580
|
+
}
|
|
581
|
+
function pruneCycles(raw2) {
|
|
582
|
+
const pruned = /* @__PURE__ */ new Map();
|
|
583
|
+
for (const table of raw2.keys()) pruned.set(table, []);
|
|
584
|
+
const state = /* @__PURE__ */ new Map();
|
|
585
|
+
function visit(table) {
|
|
586
|
+
state.set(table, "visiting");
|
|
587
|
+
for (const edge of raw2.get(table) ?? []) {
|
|
588
|
+
if (state.get(edge.child) === "visiting") continue;
|
|
589
|
+
pruned.get(table)?.push(edge);
|
|
590
|
+
if (state.get(edge.child) === void 0) visit(edge.child);
|
|
591
|
+
}
|
|
592
|
+
state.set(table, "done");
|
|
593
|
+
}
|
|
594
|
+
for (const table of raw2.keys()) {
|
|
595
|
+
if (state.get(table) === void 0) visit(table);
|
|
596
|
+
}
|
|
597
|
+
return pruned;
|
|
598
|
+
}
|
|
599
|
+
function tableBlock(table, children, indent) {
|
|
519
600
|
const cols = Object.entries(table.columns);
|
|
520
601
|
const rowLines = cols.map(([col, builder]) => {
|
|
521
602
|
return `${indent} ${col}: ${rowType(builder._def)};`;
|
|
@@ -525,6 +606,8 @@ function tableBlock(table, indent) {
|
|
|
525
606
|
const opt = optionalOnInsert(def) ? "?" : "";
|
|
526
607
|
return `${indent} ${col}${opt}: ${rowType(def)};`;
|
|
527
608
|
});
|
|
609
|
+
const owner = ownerColumnOf(table);
|
|
610
|
+
const childEntries = children.map((e) => `${JSON.stringify(e.child)}: ${JSON.stringify(e.column)}`).join("; ");
|
|
528
611
|
return [
|
|
529
612
|
`${indent}${table.name}: {`,
|
|
530
613
|
`${indent} row: {`,
|
|
@@ -533,12 +616,17 @@ function tableBlock(table, indent) {
|
|
|
533
616
|
`${indent} insert: {`,
|
|
534
617
|
...insertLines,
|
|
535
618
|
`${indent} };`,
|
|
619
|
+
`${indent} owner: ${owner === null ? "null" : JSON.stringify(owner)};`,
|
|
620
|
+
`${indent} children: {${childEntries === "" ? "" : ` ${childEntries} `}};`,
|
|
536
621
|
`${indent}};`
|
|
537
622
|
].join("\n");
|
|
538
623
|
}
|
|
539
624
|
function makeEnvDts(schema) {
|
|
540
625
|
const tableNames = Object.keys(schema.tables);
|
|
541
|
-
const
|
|
626
|
+
const children = pruneCycles(buildChildEdges(schema));
|
|
627
|
+
const blocks = tableNames.map(
|
|
628
|
+
(name) => tableBlock(schema.tables[name], children.get(name) ?? [], " ")
|
|
629
|
+
);
|
|
542
630
|
const body = blocks.length > 0 ? `
|
|
543
631
|
${blocks.join("\n")}
|
|
544
632
|
` : "";
|
|
@@ -633,6 +721,22 @@ function defineStorage(input) {
|
|
|
633
721
|
return { __config: STORAGE_CONFIG_KIND, buckets };
|
|
634
722
|
}
|
|
635
723
|
|
|
724
|
+
// src/config/egress.ts
|
|
725
|
+
var EGRESS_CONFIG_KIND = "egress";
|
|
726
|
+
function defineEgress(input) {
|
|
727
|
+
if (input === null || typeof input !== "object" || !Array.isArray(input.hosts)) {
|
|
728
|
+
throw new Error("defineEgress expects { hosts: string[] }");
|
|
729
|
+
}
|
|
730
|
+
const hosts = [];
|
|
731
|
+
for (const h of input.hosts) {
|
|
732
|
+
if (typeof h !== "string" || h.trim().length === 0) {
|
|
733
|
+
throw new Error("defineEgress: every host must be a non-empty string");
|
|
734
|
+
}
|
|
735
|
+
hosts.push(h.trim().toLowerCase());
|
|
736
|
+
}
|
|
737
|
+
return { __config: EGRESS_CONFIG_KIND, hosts };
|
|
738
|
+
}
|
|
739
|
+
|
|
636
740
|
// src/config/notifications.ts
|
|
637
741
|
var NOTIFICATIONS_CONFIG_KIND = "notifications";
|
|
638
742
|
var RESERVED_SECRET_PREFIX = "PB_NOTIFICATIONS";
|
|
@@ -744,6 +848,98 @@ function camelToUpperSnake(s) {
|
|
|
744
848
|
return s.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
745
849
|
}
|
|
746
850
|
|
|
851
|
+
// src/config/test-users.ts
|
|
852
|
+
var TEST_USERS_CONFIG_KIND = "test-users";
|
|
853
|
+
var TEST_USER_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
854
|
+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
855
|
+
var MIN_PASSWORD_LENGTH = 8;
|
|
856
|
+
function isPlainObject(value) {
|
|
857
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
858
|
+
}
|
|
859
|
+
function normalizeSeed(seed, userName) {
|
|
860
|
+
if (seed === void 0) return {};
|
|
861
|
+
if (!isPlainObject(seed)) {
|
|
862
|
+
throw new Error(`testUser ${JSON.stringify(userName)}: seed must be { <table>: [ {...} ] }`);
|
|
863
|
+
}
|
|
864
|
+
const out = {};
|
|
865
|
+
for (const [table, rows] of Object.entries(seed)) {
|
|
866
|
+
if (!Array.isArray(rows)) {
|
|
867
|
+
throw new Error(
|
|
868
|
+
`testUser ${JSON.stringify(userName)}: seed.${table} must be an array of rows`
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
if (rows.length === 0) {
|
|
872
|
+
throw new Error(
|
|
873
|
+
`testUser ${JSON.stringify(userName)}: seed.${table} is empty \u2014 remove it or add a row`
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
for (const row of rows) {
|
|
877
|
+
if (!isPlainObject(row)) {
|
|
878
|
+
throw new Error(
|
|
879
|
+
`testUser ${JSON.stringify(userName)}: every row in seed.${table} must be an object`
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
out[table] = rows;
|
|
884
|
+
}
|
|
885
|
+
return out;
|
|
886
|
+
}
|
|
887
|
+
function testUser(opts = {}) {
|
|
888
|
+
if (!isPlainObject(opts)) {
|
|
889
|
+
throw new Error("testUser() expects { email?, password?, seed? }");
|
|
890
|
+
}
|
|
891
|
+
const hasEmail = opts.email !== void 0;
|
|
892
|
+
const hasPassword = opts.password !== void 0;
|
|
893
|
+
if (hasEmail !== hasPassword) {
|
|
894
|
+
throw new Error(
|
|
895
|
+
"testUser() needs email AND password together (a fixture with stable credentials) or neither (a template the server generates credentials for)"
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
let email = null;
|
|
899
|
+
let password = null;
|
|
900
|
+
if (hasEmail) {
|
|
901
|
+
if (typeof opts.email !== "string" || !EMAIL_RE.test(opts.email)) {
|
|
902
|
+
throw new Error(`testUser email ${JSON.stringify(opts.email)} is not a valid address`);
|
|
903
|
+
}
|
|
904
|
+
if (typeof opts.password !== "string" || opts.password.length < MIN_PASSWORD_LENGTH) {
|
|
905
|
+
throw new Error(
|
|
906
|
+
`testUser password must be at least ${MIN_PASSWORD_LENGTH} characters (got ${typeof opts.password === "string" ? opts.password.length : 0})`
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
email = opts.email;
|
|
910
|
+
password = opts.password;
|
|
911
|
+
}
|
|
912
|
+
return { email, password, seed: normalizeSeed(opts.seed, email ?? "<template>") };
|
|
913
|
+
}
|
|
914
|
+
function defineTestUsers(input) {
|
|
915
|
+
if (!isPlainObject(input) || !isPlainObject(input.users)) {
|
|
916
|
+
throw new Error("defineTestUsers expects { users: { <name>: testUser({...}) } }");
|
|
917
|
+
}
|
|
918
|
+
const users = {};
|
|
919
|
+
const emails = /* @__PURE__ */ new Map();
|
|
920
|
+
for (const name of Object.keys(input.users)) {
|
|
921
|
+
if (!TEST_USER_NAME_RE.test(name)) {
|
|
922
|
+
throw new Error(
|
|
923
|
+
`test user name ${JSON.stringify(name)} is invalid \u2014 must start with a letter and contain only letters, digits, and underscores`
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
const def = input.users[name];
|
|
927
|
+
if (def === void 0) continue;
|
|
928
|
+
if (def.email !== null) {
|
|
929
|
+
const lower = def.email.toLowerCase();
|
|
930
|
+
const already = emails.get(lower);
|
|
931
|
+
if (already !== void 0) {
|
|
932
|
+
throw new Error(
|
|
933
|
+
`test users ${JSON.stringify(already)} and ${JSON.stringify(name)} declare the same e-mail ${JSON.stringify(def.email)}`
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
emails.set(lower, name);
|
|
937
|
+
}
|
|
938
|
+
users[name] = def;
|
|
939
|
+
}
|
|
940
|
+
return { __config: TEST_USERS_CONFIG_KIND, users };
|
|
941
|
+
}
|
|
942
|
+
|
|
747
943
|
// src/config/flags.ts
|
|
748
944
|
var FLAGS_CONFIG_KIND = "flags";
|
|
749
945
|
var FLAG_KEY_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
@@ -916,6 +1112,33 @@ function recordThrows(target, fnName, throws) {
|
|
|
916
1112
|
const throwsBuffer = carrier[THROWS_BUFFER];
|
|
917
1113
|
if (throwsBuffer) throwsBuffer[fnName] = throws;
|
|
918
1114
|
}
|
|
1115
|
+
function getRoutes(ctor) {
|
|
1116
|
+
const carrier = carrierOf(ctor);
|
|
1117
|
+
const routes = carrier[ROUTES] ?? [];
|
|
1118
|
+
const returnBuffer = carrier[RETURN_BUFFER];
|
|
1119
|
+
if (returnBuffer) {
|
|
1120
|
+
for (const route of routes) {
|
|
1121
|
+
const buffered = returnBuffer[route.fnName];
|
|
1122
|
+
if (buffered && route.returnSchema === void 0) {
|
|
1123
|
+
route.returnSchema = buffered;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
const throwsBuffer = carrier[THROWS_BUFFER];
|
|
1128
|
+
if (throwsBuffer) {
|
|
1129
|
+
for (const route of routes) {
|
|
1130
|
+
const buffered = throwsBuffer[route.fnName];
|
|
1131
|
+
if (buffered && route.throws === void 0) {
|
|
1132
|
+
route.throws = buffered;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return routes.map((r) => ({
|
|
1137
|
+
...r,
|
|
1138
|
+
params: r.params.slice(),
|
|
1139
|
+
...r.throws !== void 0 ? { throws: r.throws.slice() } : {}
|
|
1140
|
+
}));
|
|
1141
|
+
}
|
|
919
1142
|
|
|
920
1143
|
// src/decorators/methods.ts
|
|
921
1144
|
function makeMethodDecorator(method) {
|
|
@@ -1524,6 +1747,7 @@ var import_zod2 = require("zod");
|
|
|
1524
1747
|
Database,
|
|
1525
1748
|
Delete,
|
|
1526
1749
|
Documents,
|
|
1750
|
+
EGRESS_CONFIG_KIND,
|
|
1527
1751
|
EXTENSION_DEPENDENCIES,
|
|
1528
1752
|
FLAGS_CONFIG_KIND,
|
|
1529
1753
|
Flags,
|
|
@@ -1554,6 +1778,7 @@ var import_zod2 = require("zod");
|
|
|
1554
1778
|
Resource,
|
|
1555
1779
|
STORAGE_CONFIG_KIND,
|
|
1556
1780
|
Storage,
|
|
1781
|
+
TEST_USERS_CONFIG_KIND,
|
|
1557
1782
|
TooManyRequests,
|
|
1558
1783
|
TraceId,
|
|
1559
1784
|
Unauthorized,
|
|
@@ -1572,6 +1797,7 @@ var import_zod2 = require("zod");
|
|
|
1572
1797
|
boolean,
|
|
1573
1798
|
bucket,
|
|
1574
1799
|
buildProvider,
|
|
1800
|
+
defineEgress,
|
|
1575
1801
|
defineError,
|
|
1576
1802
|
defineFlags,
|
|
1577
1803
|
defineJob,
|
|
@@ -1579,12 +1805,14 @@ var import_zod2 = require("zod");
|
|
|
1579
1805
|
defineNotifications,
|
|
1580
1806
|
defineSchema,
|
|
1581
1807
|
defineStorage,
|
|
1808
|
+
defineTestUsers,
|
|
1582
1809
|
defineWebhook,
|
|
1583
1810
|
defineWorker,
|
|
1584
1811
|
documents,
|
|
1585
1812
|
enumType,
|
|
1586
1813
|
flag,
|
|
1587
1814
|
getErrorRegistry,
|
|
1815
|
+
getRoutes,
|
|
1588
1816
|
integer,
|
|
1589
1817
|
isPalbaseExtension,
|
|
1590
1818
|
jsonb,
|
|
@@ -1597,6 +1825,7 @@ var import_zod2 = require("zod");
|
|
|
1597
1825
|
recordThrows,
|
|
1598
1826
|
reservedSecretKey,
|
|
1599
1827
|
storage,
|
|
1828
|
+
testUser,
|
|
1600
1829
|
text,
|
|
1601
1830
|
timestamp,
|
|
1602
1831
|
uuid,
|