weifuwu 0.24.0 → 0.24.2

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.
Files changed (76) hide show
  1. package/README.md +970 -756
  2. package/cli/template/app.ts +5 -1
  3. package/cli/template/index.ts +4 -1
  4. package/cli/template/locales/en.json +6 -1
  5. package/cli/template/locales/zh-CN.json +6 -1
  6. package/cli/template/locales/zh-TW.json +6 -1
  7. package/cli/template/locales/zh.json +6 -1
  8. package/cli/template/ui/app/globals.css +1 -1
  9. package/cli/template/ui/app/page.tsx +55 -16
  10. package/cli.ts +148 -104
  11. package/dist/agent/rest.d.ts +1 -1
  12. package/dist/agent/run.d.ts +2 -2
  13. package/dist/agent/types.d.ts +2 -1
  14. package/dist/ai/workflow.d.ts +1 -1
  15. package/dist/ai-sdk.d.ts +1 -1
  16. package/dist/analytics.d.ts +2 -2
  17. package/dist/cache.d.ts +4 -4
  18. package/dist/cli.js +135 -97
  19. package/dist/cookie.d.ts +24 -0
  20. package/dist/cors.d.ts +2 -2
  21. package/dist/deploy/types.d.ts +2 -2
  22. package/dist/fts.d.ts +5 -5
  23. package/dist/helmet.d.ts +2 -2
  24. package/dist/hub.d.ts +2 -1
  25. package/dist/iii/index.d.ts +1 -1
  26. package/dist/iii/register-worker.d.ts +1 -1
  27. package/dist/iii/types.d.ts +4 -4
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.js +905 -442
  30. package/dist/kb/types.d.ts +8 -0
  31. package/dist/live.d.ts +2 -3
  32. package/dist/logdb/rest.d.ts +1 -1
  33. package/dist/logdb/types.d.ts +2 -1
  34. package/dist/mailer.d.ts +3 -2
  35. package/dist/messager/agent.d.ts +2 -2
  36. package/dist/messager/rest.d.ts +3 -3
  37. package/dist/messager/types.d.ts +2 -1
  38. package/dist/messager/ws.d.ts +3 -3
  39. package/dist/opencode/index.d.ts +1 -1
  40. package/dist/opencode/permissions.d.ts +1 -1
  41. package/dist/opencode/run.d.ts +1 -1
  42. package/dist/opencode/session.d.ts +9 -9
  43. package/dist/opencode/tools/web.d.ts +1 -1
  44. package/dist/opencode/types.d.ts +2 -1
  45. package/dist/opencode/ws.d.ts +1 -2
  46. package/dist/permissions.d.ts +4 -4
  47. package/dist/postgres/module.d.ts +5 -4
  48. package/dist/postgres/schema/index.d.ts +1 -1
  49. package/dist/postgres/schema/table.d.ts +22 -20
  50. package/dist/postgres/types.d.ts +6 -6
  51. package/dist/queue/types.d.ts +3 -3
  52. package/dist/rate-limit.d.ts +1 -1
  53. package/dist/react.d.ts +1 -1
  54. package/dist/react.js +141 -96
  55. package/dist/redis/types.d.ts +2 -2
  56. package/dist/router.d.ts +10 -10
  57. package/dist/seo.d.ts +2 -2
  58. package/dist/serve.d.ts +1 -1
  59. package/dist/session.d.ts +8 -5
  60. package/dist/tailwind.d.ts +9 -0
  61. package/dist/tenant/graphql.d.ts +2 -2
  62. package/dist/tenant/index.d.ts +1 -1
  63. package/dist/tenant/rest.d.ts +2 -2
  64. package/dist/tenant/types.d.ts +3 -3
  65. package/dist/test-utils.d.ts +3 -3
  66. package/dist/types.d.ts +8 -0
  67. package/dist/upload.d.ts +4 -2
  68. package/dist/user/index.d.ts +1 -1
  69. package/dist/user/oauth-login.d.ts +2 -2
  70. package/dist/user/types.d.ts +2 -2
  71. package/dist/vendor.d.ts +4 -0
  72. package/opencode/ui/app/globals.css +1 -1
  73. package/opencode/ui/app/layout.tsx +2 -3
  74. package/opencode/ui/app/page.tsx +302 -73
  75. package/package.json +33 -10
  76. package/cli/template/.weifuwu/ssr/2e3a7e60.js +0 -112
package/dist/index.js CHANGED
@@ -183,8 +183,8 @@ async function sendResponse(res, response, opts) {
183
183
  }
184
184
  res.end();
185
185
  }
186
- async function createTestServer(handler) {
187
- const server = serve(handler, { port: 0, shutdown: false });
186
+ async function createTestServer(handler, options) {
187
+ const server = serve(handler, { ...options, port: options?.port ?? 0, shutdown: false });
188
188
  await server.ready;
189
189
  return { server, url: `http://localhost:${server.port}` };
190
190
  }
@@ -262,9 +262,13 @@ function serve(handler, options) {
262
262
  }
263
263
  };
264
264
  }
265
- options.signal.addEventListener("abort", () => {
266
- server.close();
267
- }, { once: true });
265
+ options.signal.addEventListener(
266
+ "abort",
267
+ () => {
268
+ server.close();
269
+ },
270
+ { once: true }
271
+ );
268
272
  }
269
273
  server.on("error", (err) => {
270
274
  console.error("Failed to start server:", err.message);
@@ -488,7 +492,8 @@ var Router = class _Router {
488
492
  }
489
493
  } else if (typeof arg1 === "function") {
490
494
  this.globalMws.push(arg1);
491
- } else if (typeof arg1 === "object" && arg1 !== null && "middleware" in arg1 && typeof arg1.middleware === "function" && arg1 instanceof _Router) {
495
+ } else if (typeof arg1 === "object" && arg1 !== null && "middleware" in arg1 && // eslint-disable-next-line @typescript-eslint/no-explicit-any
496
+ typeof arg1.middleware === "function" && arg1 instanceof _Router) {
492
497
  const mod = arg1;
493
498
  this.globalMws.push(mod.middleware());
494
499
  this._mountRouter("/", mod);
@@ -529,6 +534,7 @@ var Router = class _Router {
529
534
  return this._routeImpl(method, path2, args);
530
535
  }
531
536
  /** Internal route registration — no type constraints (used by _mountRouter). */
537
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
532
538
  _routeImpl(method, path2, args) {
533
539
  const last = args[args.length - 1];
534
540
  if (last instanceof _Router) {
@@ -554,9 +560,7 @@ var Router = class _Router {
554
560
  node = getOrCreateChild(node, segment, createTrieNode, false);
555
561
  }
556
562
  if (!isProd() && node.handlers.has(method)) {
557
- console.warn(
558
- `[router] route conflict: ${method} ${path2} overwrites existing handler`
559
- );
563
+ console.warn(`[router] route conflict: ${method} ${path2} overwrites existing handler`);
560
564
  }
561
565
  node.handlers.set(method, handler);
562
566
  if (middlewares.length > 0) node.middlewares.set(method, middlewares);
@@ -591,7 +595,7 @@ var Router = class _Router {
591
595
  return result;
592
596
  }
593
597
  _collectRoutes(node, prefix, result) {
594
- for (const [method, handler] of node.handlers) {
598
+ for (const [method] of node.handlers) {
595
599
  const m = method === "*" ? "ANY" : method;
596
600
  const path2 = (prefix || "/") + (node.wildcard ? "/*" : "");
597
601
  const middlewares = node.middlewares.get(method);
@@ -669,7 +673,12 @@ var Router = class _Router {
669
673
  const wsRoutes = [];
670
674
  this._collectWs(sub.wsRoot, "", wsRoutes);
671
675
  for (const { path: path2, handler, middlewares } of wsRoutes) {
672
- this.ws(base + path2, ...allExtra, ...middlewares, handler);
676
+ this.ws(
677
+ base + path2,
678
+ ...allExtra,
679
+ ...middlewares,
680
+ handler
681
+ );
673
682
  }
674
683
  }
675
684
  mergeMws(base, extra) {
@@ -682,7 +691,12 @@ var Router = class _Router {
682
691
  for (const [method, handler] of node.handlers) {
683
692
  const rmws = node.middlewares.get(method) || [];
684
693
  const suffix = node.wildcard ? "/*" : "";
685
- result.push({ method, path: (prefix || "/") + suffix, handler, middlewares: this.mergeMws(mws, rmws) });
694
+ result.push({
695
+ method,
696
+ path: (prefix || "/") + suffix,
697
+ handler,
698
+ middlewares: this.mergeMws(mws, rmws)
699
+ });
686
700
  }
687
701
  for (const [seg, child] of node.children) {
688
702
  const next = seg === ":" ? `/:${child.param}` : `/${seg}`;
@@ -744,7 +758,12 @@ var Router = class _Router {
744
758
  return { handler: wildcardHandler, middlewares: wildcardMws, pathMws, params };
745
759
  }
746
760
  if (node.handlers.size > 0) {
747
- return { middlewares: [], pathMws, params, allowedMethods: [...node.handlers.keys()].filter((k) => k !== "*") };
761
+ return {
762
+ middlewares: [],
763
+ pathMws,
764
+ params,
765
+ allowedMethods: [...node.handlers.keys()].filter((k) => k !== "*")
766
+ };
748
767
  }
749
768
  return null;
750
769
  }
@@ -779,38 +798,54 @@ var Router = class _Router {
779
798
  if (match.allowedMethods && match.allowedMethods.length > 0) {
780
799
  if (this.globalMws.length > 0) {
781
800
  try {
782
- return await this.runChain(this.globalMws, () => new Response("Method Not Allowed", {
783
- status: 405,
784
- headers: { "Allow": match.allowedMethods.join(", ") }
785
- }), req, ctx);
801
+ return await this.runChain(
802
+ this.globalMws,
803
+ () => new Response("Method Not Allowed", {
804
+ status: 405,
805
+ headers: { Allow: match.allowedMethods.join(", ") }
806
+ }),
807
+ req,
808
+ ctx
809
+ );
786
810
  } catch (e) {
787
811
  return this.handleError(e, req, ctx);
788
812
  }
789
813
  }
790
814
  return new Response("Method Not Allowed", {
791
815
  status: 405,
792
- headers: { "Allow": match.allowedMethods.join(", ") }
816
+ headers: { Allow: match.allowedMethods.join(", ") }
793
817
  });
794
818
  }
795
819
  }
796
820
  if (this.globalMws.length > 0) {
797
821
  try {
798
- return await this.runChain(this.globalMws, () => {
799
- if (!isProd()) {
800
- return Response.json({ error: "Not Found", path: "/" + segments.join("/"), method: req.method }, { status: 404 });
801
- }
802
- return new Response("Not Found", { status: 404 });
803
- }, req, ctx);
822
+ return await this.runChain(
823
+ this.globalMws,
824
+ () => {
825
+ if (!isProd()) {
826
+ return Response.json(
827
+ { error: "Not Found", path: "/" + segments.join("/"), method: req.method },
828
+ { status: 404 }
829
+ );
830
+ }
831
+ return new Response("Not Found", { status: 404 });
832
+ },
833
+ req,
834
+ ctx
835
+ );
804
836
  } catch (e) {
805
837
  return this.handleError(e, req, ctx);
806
838
  }
807
839
  }
808
840
  if (!isProd()) {
809
- return Response.json({
810
- error: "Not Found",
811
- path: "/" + segments.join("/"),
812
- method: req.method
813
- }, { status: 404 });
841
+ return Response.json(
842
+ {
843
+ error: "Not Found",
844
+ path: "/" + segments.join("/"),
845
+ method: req.method
846
+ },
847
+ { status: 404 }
848
+ );
814
849
  }
815
850
  return new Response("Not Found", { status: 404 });
816
851
  }
@@ -825,7 +860,9 @@ function runChainLoop(middlewares, index, finalHandler, req, ctx) {
825
860
  let called = false;
826
861
  const dispatch = (r, c) => {
827
862
  if (called) {
828
- console.warn("[router] next() called more than once in middleware \u2014 ignoring duplicate call");
863
+ console.warn(
864
+ "[router] next() called more than once in middleware \u2014 ignoring duplicate call"
865
+ );
829
866
  return Promise.resolve(new Response("Internal Server Error", { status: 500 }));
830
867
  }
831
868
  called = true;
@@ -849,7 +886,7 @@ function upgradeSocket(wss, req, socket, head, handler, ctx, hub) {
849
886
  join(room) {
850
887
  hub.join(room, ws);
851
888
  },
852
- leave(room) {
889
+ leave(_room) {
853
890
  hub.leave(ws);
854
891
  },
855
892
  sendRoom(room, data) {
@@ -899,7 +936,15 @@ function sendHttpResponseOnSocket(socket, response) {
899
936
 
900
937
  // tsx-context.ts
901
938
  import { useSyncExternalStore, createContext } from "react";
902
- var DEFAULT_CTX = { params: {}, query: {}, parsed: {}, loaderData: {}, env: {}, user: {}, flash: {} };
939
+ var DEFAULT_CTX = {
940
+ params: {},
941
+ query: {},
942
+ parsed: {},
943
+ loaderData: {},
944
+ env: {},
945
+ user: {},
946
+ flash: {}
947
+ };
903
948
  var KEY = "__WEIFUWU_CTX_STORE";
904
949
  function getStore() {
905
950
  if (typeof globalThis !== "undefined" && globalThis[KEY]) {
@@ -907,12 +952,22 @@ function getStore() {
907
952
  }
908
953
  const s = {
909
954
  _ctx: DEFAULT_CTX,
910
- _snapshot: { params: DEFAULT_CTX.params, query: DEFAULT_CTX.query, user: DEFAULT_CTX.user, parsed: DEFAULT_CTX.parsed, theme: DEFAULT_CTX.theme, i18n: DEFAULT_CTX.i18n, loaderData: DEFAULT_CTX.loaderData, env: DEFAULT_CTX.env },
955
+ _snapshot: {
956
+ params: DEFAULT_CTX.params,
957
+ query: DEFAULT_CTX.query,
958
+ user: DEFAULT_CTX.user,
959
+ parsed: DEFAULT_CTX.parsed,
960
+ theme: DEFAULT_CTX.theme,
961
+ i18n: DEFAULT_CTX.i18n,
962
+ loaderData: DEFAULT_CTX.loaderData,
963
+ env: DEFAULT_CTX.env
964
+ },
911
965
  _listeners: /* @__PURE__ */ new Set(),
912
966
  _rebuilders: [],
913
967
  _alsGetStore: null
914
968
  };
915
969
  if (typeof globalThis !== "undefined") {
970
+ ;
916
971
  globalThis[KEY] = s;
917
972
  }
918
973
  return s;
@@ -929,7 +984,16 @@ function setCtx(value) {
929
984
  }
930
985
  }
931
986
  store._ctx = { ...store._ctx, ...value };
932
- store._snapshot = { params: store._ctx.params, query: store._ctx.query, user: store._ctx.user, parsed: store._ctx.parsed, theme: store._ctx.theme, i18n: store._ctx.i18n, loaderData: store._ctx.loaderData, env: store._ctx.env };
987
+ store._snapshot = {
988
+ params: store._ctx.params,
989
+ query: store._ctx.query,
990
+ user: store._ctx.user,
991
+ parsed: store._ctx.parsed,
992
+ theme: store._ctx.theme,
993
+ i18n: store._ctx.i18n,
994
+ loaderData: store._ctx.loaderData,
995
+ env: store._ctx.env
996
+ };
933
997
  if (typeof window !== "undefined") {
934
998
  ;
935
999
  window.__WEIFUWU_CTX = { ...window.__WEIFUWU_CTX, ...value };
@@ -1014,7 +1078,8 @@ function cors(options) {
1014
1078
  const headers = new Headers(res.headers);
1015
1079
  headers.set("Access-Control-Allow-Origin", acao);
1016
1080
  if (opts.credentials) headers.set("Access-Control-Allow-Credentials", "true");
1017
- if (opts.exposedHeaders?.length) headers.set("Access-Control-Expose-Headers", opts.exposedHeaders.join(", "));
1081
+ if (opts.exposedHeaders?.length)
1082
+ headers.set("Access-Control-Expose-Headers", opts.exposedHeaders.join(", "));
1018
1083
  if (acao !== "*") headers.set("Vary", "Origin");
1019
1084
  return new Response(res.body, { status: res.status, statusText: res.statusText, headers });
1020
1085
  }
@@ -1091,7 +1156,7 @@ function serveStatic(root, options) {
1091
1156
  const headers = {
1092
1157
  "Content-Type": mimeType,
1093
1158
  "Content-Length": String(stat3.size),
1094
- "ETag": etag,
1159
+ ETag: etag,
1095
1160
  "Last-Modified": stat3.mtime.toUTCString(),
1096
1161
  "Cache-Control": opts.immutable ? `public, max-age=${opts.maxAge ?? 31536e3}, immutable` : `public, max-age=${opts.maxAge ?? 0}`
1097
1162
  };
@@ -1181,10 +1246,12 @@ function validate(schemas) {
1181
1246
  if (result.success) {
1182
1247
  parsed.params = result.data;
1183
1248
  } else {
1184
- issues.push(...result.error.issues.map((i) => ({
1185
- path: ["params", ...i.path.map(String)],
1186
- message: i.message
1187
- })));
1249
+ issues.push(
1250
+ ...result.error.issues.map((i) => ({
1251
+ path: ["params", ...i.path.map(String)],
1252
+ message: i.message
1253
+ }))
1254
+ );
1188
1255
  }
1189
1256
  }
1190
1257
  if (schemas?.query) {
@@ -1192,10 +1259,12 @@ function validate(schemas) {
1192
1259
  if (result.success) {
1193
1260
  parsed.query = result.data;
1194
1261
  } else {
1195
- issues.push(...result.error.issues.map((i) => ({
1196
- path: ["query", ...i.path.map(String)],
1197
- message: i.message
1198
- })));
1262
+ issues.push(
1263
+ ...result.error.issues.map((i) => ({
1264
+ path: ["query", ...i.path.map(String)],
1265
+ message: i.message
1266
+ }))
1267
+ );
1199
1268
  }
1200
1269
  }
1201
1270
  if (schemas?.headers) {
@@ -1207,10 +1276,12 @@ function validate(schemas) {
1207
1276
  if (result.success) {
1208
1277
  parsed.headers = result.data;
1209
1278
  } else {
1210
- issues.push(...result.error.issues.map((i) => ({
1211
- path: ["headers", ...i.path.map(String)],
1212
- message: i.message
1213
- })));
1279
+ issues.push(
1280
+ ...result.error.issues.map((i) => ({
1281
+ path: ["headers", ...i.path.map(String)],
1282
+ message: i.message
1283
+ }))
1284
+ );
1214
1285
  }
1215
1286
  }
1216
1287
  if (req.method !== "GET" && req.method !== "HEAD") {
@@ -1234,10 +1305,12 @@ function validate(schemas) {
1234
1305
  if (result.success) {
1235
1306
  parsed.body = result.data;
1236
1307
  } else {
1237
- issues.push(...result.error.issues.map((i) => ({
1238
- path: ["body", ...i.path.map(String)],
1239
- message: i.message
1240
- })));
1308
+ issues.push(
1309
+ ...result.error.issues.map((i) => ({
1310
+ path: ["body", ...i.path.map(String)],
1311
+ message: i.message
1312
+ }))
1313
+ );
1241
1314
  }
1242
1315
  } else {
1243
1316
  parsed.body = bodyValue;
@@ -1305,11 +1378,14 @@ function setCookie(res, name, value, options) {
1305
1378
  }
1306
1379
  function deleteCookie(res, name, options) {
1307
1380
  const headers = new Headers(res.headers);
1308
- headers.append("Set-Cookie", serializeCookie(name, "", {
1309
- ...options,
1310
- maxAge: 0,
1311
- expires: /* @__PURE__ */ new Date(0)
1312
- }));
1381
+ headers.append(
1382
+ "Set-Cookie",
1383
+ serializeCookie(name, "", {
1384
+ ...options,
1385
+ maxAge: 0,
1386
+ expires: /* @__PURE__ */ new Date(0)
1387
+ })
1388
+ );
1313
1389
  return new Response(res.body, {
1314
1390
  status: res.status,
1315
1391
  statusText: res.statusText,
@@ -1433,21 +1509,24 @@ function rateLimit(options) {
1433
1509
  const keyPrefix = options?.prefix ?? "ratelimit:";
1434
1510
  const MAX_ENTRIES2 = 1e4;
1435
1511
  const hits = /* @__PURE__ */ new Map();
1436
- const interval = storeType === "memory" ? setInterval(() => {
1437
- const now = Date.now();
1438
- for (const [key, entry] of hits) {
1439
- if (entry.reset < now) hits.delete(key);
1440
- }
1441
- if (hits.size > MAX_ENTRIES2) {
1442
- const toDelete = hits.size - MAX_ENTRIES2;
1443
- let deleted = 0;
1444
- for (const key of hits.keys()) {
1445
- if (deleted >= toDelete) break;
1446
- hits.delete(key);
1447
- deleted++;
1512
+ const interval = storeType === "memory" ? setInterval(
1513
+ () => {
1514
+ const now = Date.now();
1515
+ for (const [key, entry] of hits) {
1516
+ if (entry.reset < now) hits.delete(key);
1517
+ }
1518
+ if (hits.size > MAX_ENTRIES2) {
1519
+ const toDelete = hits.size - MAX_ENTRIES2;
1520
+ let deleted = 0;
1521
+ for (const key of hits.keys()) {
1522
+ if (deleted >= toDelete) break;
1523
+ hits.delete(key);
1524
+ deleted++;
1525
+ }
1448
1526
  }
1449
- }
1450
- }, Math.min(window2, 3e4)) : null;
1527
+ },
1528
+ Math.min(window2, 3e4)
1529
+ ) : null;
1451
1530
  if (interval?.unref) interval.unref();
1452
1531
  async function checkAndIncrement(key) {
1453
1532
  const now = Date.now();
@@ -1461,7 +1540,7 @@ function rateLimit(options) {
1461
1540
  const reset = pttl > 0 ? now + pttl : now + window2;
1462
1541
  return { count, reset };
1463
1542
  }
1464
- let entry = hits.get(key);
1543
+ const entry = hits.get(key);
1465
1544
  if (!entry || entry.reset < now) {
1466
1545
  hits.set(key, { count: 1, reset: now + window2 });
1467
1546
  return { count: 1, reset: now + window2 };
@@ -1492,7 +1571,6 @@ function rateLimit(options) {
1492
1571
  if (interval) clearInterval(interval);
1493
1572
  hits.clear();
1494
1573
  };
1495
- mw.stop = mw.close;
1496
1574
  mw.stats = () => ({
1497
1575
  store: storeType,
1498
1576
  entries: storeType === "memory" ? hits.size : void 0,
@@ -1536,7 +1614,9 @@ function compress(options) {
1536
1614
  let compressed;
1537
1615
  try {
1538
1616
  if (encoding === "br") {
1539
- compressed = await brotliCompressAsync(body, { params: { [constants.BROTLI_PARAM_QUALITY]: Math.min(level, 11) } });
1617
+ compressed = await brotliCompressAsync(body, {
1618
+ params: { [constants.BROTLI_PARAM_QUALITY]: Math.min(level, 11) }
1619
+ });
1540
1620
  } else if (encoding === "gzip") {
1541
1621
  compressed = await gzipAsync(body, { level: Math.min(level, 9) });
1542
1622
  } else {
@@ -1650,9 +1730,7 @@ function createSSEStream(iterable, opts) {
1650
1730
  }
1651
1731
  } catch (e) {
1652
1732
  if (e.name !== "AbortError") {
1653
- controller.enqueue(
1654
- encoder.encode(formatSSE("error", { error: e.message }))
1655
- );
1733
+ controller.enqueue(encoder.encode(formatSSE("error", { error: e.message })));
1656
1734
  }
1657
1735
  } finally {
1658
1736
  controller.close();
@@ -1777,26 +1855,31 @@ var TestApp = class {
1777
1855
  }
1778
1856
  /** Register a GET route — supports route-level middleware via spread args. */
1779
1857
  get(path2, ...args) {
1858
+ ;
1780
1859
  this.router.get(path2, ...args);
1781
1860
  return this;
1782
1861
  }
1783
1862
  /** Register a POST route. */
1784
1863
  post(path2, ...args) {
1864
+ ;
1785
1865
  this.router.post(path2, ...args);
1786
1866
  return this;
1787
1867
  }
1788
1868
  /** Register a PUT route. */
1789
1869
  put(path2, ...args) {
1870
+ ;
1790
1871
  this.router.put(path2, ...args);
1791
1872
  return this;
1792
1873
  }
1793
1874
  /** Register a PATCH route. */
1794
1875
  patch(path2, ...args) {
1876
+ ;
1795
1877
  this.router.patch(path2, ...args);
1796
1878
  return this;
1797
1879
  }
1798
1880
  /** Register a DELETE route. */
1799
1881
  delete(path2, ...args) {
1882
+ ;
1800
1883
  this.router.delete(path2, ...args);
1801
1884
  return this;
1802
1885
  }
@@ -1879,7 +1962,12 @@ async function withTestDb(optionsOrFn, fn) {
1879
1962
  }
1880
1963
 
1881
1964
  // graphql.ts
1882
- import { buildSchema, graphql as executeGraphQL, validate as validateQuery, parse } from "graphql";
1965
+ import {
1966
+ buildSchema,
1967
+ graphql as executeGraphQL,
1968
+ validate as validateQuery,
1969
+ parse
1970
+ } from "graphql";
1883
1971
  import { makeExecutableSchema } from "@graphql-tools/schema";
1884
1972
  function parseParamsFromGet(url) {
1885
1973
  const query = url.searchParams.get("query");
@@ -1940,11 +2028,17 @@ async function executeQuery(schema, params, options, req, ctx) {
1940
2028
  const doc = parse(params.query);
1941
2029
  const depth = queryDepth(doc);
1942
2030
  if (depth > maxDepth) {
1943
- return Response.json({ errors: [{ message: `Query depth ${depth} exceeds limit ${maxDepth}` }] }, { status: 400 });
2031
+ return Response.json(
2032
+ { errors: [{ message: `Query depth ${depth} exceeds limit ${maxDepth}` }] },
2033
+ { status: 400 }
2034
+ );
1944
2035
  }
1945
2036
  const validationErrors = validateQuery(schema, doc);
1946
2037
  if (validationErrors.length > 0) {
1947
- return Response.json({ errors: validationErrors.map((e) => ({ message: e.message })) }, { status: 400 });
2038
+ return Response.json(
2039
+ { errors: validationErrors.map((e) => ({ message: e.message })) },
2040
+ { status: 400 }
2041
+ );
1948
2042
  }
1949
2043
  } catch (err) {
1950
2044
  const msg = err instanceof Error ? err.message : String(err);
@@ -2125,7 +2219,10 @@ function resolveRef(path2, ctx) {
2125
2219
  const propPath = after.slice(dot + 1);
2126
2220
  const output = ctx.nodeOutputs.get(id2);
2127
2221
  if (output === void 0) throw new Error(`Node "${id2}" has no output yet`);
2128
- return getByPath(output, propPath.startsWith("output") ? propPath.slice(7).split(".").filter(Boolean) : propPath.split("."));
2222
+ return getByPath(
2223
+ output,
2224
+ propPath.startsWith("output") ? propPath.slice(7).split(".").filter(Boolean) : propPath.split(".")
2225
+ );
2129
2226
  }
2130
2227
  if (path2.startsWith("$var.")) {
2131
2228
  const name = path2.slice(5);
@@ -2145,7 +2242,8 @@ function resolveValue(v, ctx) {
2145
2242
  if (Array.isArray(v)) return v.map((item) => resolveValue(item, ctx));
2146
2243
  if (typeof v === "object" && v !== null) {
2147
2244
  const result = {};
2148
- for (const [k, val] of Object.entries(v)) result[k] = resolveValue(val, ctx);
2245
+ for (const [k, val] of Object.entries(v))
2246
+ result[k] = resolveValue(val, ctx);
2149
2247
  return result;
2150
2248
  }
2151
2249
  return v;
@@ -2241,7 +2339,7 @@ async function executeNode(node, ctx) {
2241
2339
  iters++;
2242
2340
  ctx.stepCount++;
2243
2341
  if (ctx.stepCount > ctx.maxSteps) throw new Error(`Step limit exceeded`);
2244
- if (!Boolean(evaluateExpression(conditionExpr, ctx))) break;
2342
+ if (!evaluateExpression(conditionExpr, ctx)) break;
2245
2343
  for (const n of body ?? []) {
2246
2344
  last = await executeNode(n, ctx);
2247
2345
  ctx.nodeOutputs.set(n.id, last);
@@ -2273,7 +2371,10 @@ async function executeNode(node, ctx) {
2273
2371
  signal: controller.signal
2274
2372
  });
2275
2373
  const ct = res.headers.get("content-type") ?? "";
2276
- return { status: res.status, body: ct.includes("json") ? await res.json() : await res.text() };
2374
+ return {
2375
+ status: res.status,
2376
+ body: ct.includes("json") ? await res.json() : await res.text()
2377
+ };
2277
2378
  } finally {
2278
2379
  clearTimeout(timer);
2279
2380
  }
@@ -2293,20 +2394,25 @@ function runWorkflow(opts = {}) {
2293
2394
  description: "Execute a multi-step workflow. Supports eval, set, get, if, while, call, http nodes. Use $var.x for variables, $nodes.id.output for previous node results, $input.x for input parameters. Call nodes invoke registered tools.",
2294
2395
  inputSchema: z.object({
2295
2396
  goal: z.string().describe("What the workflow should accomplish"),
2296
- nodes: z.array(z.object({
2297
- id: z.string(),
2298
- tool: z.string(),
2299
- input: z.record(z.string(), z.unknown()).optional(),
2300
- conditions: z.array(z.object({ test: z.any(), body: z.any() })).optional(),
2301
- body: z.array(z.any()).optional()
2302
- })).optional().describe("Workflow nodes. Skip this and provide model for LLM to generate from goal.")
2397
+ nodes: z.array(
2398
+ z.object({
2399
+ id: z.string(),
2400
+ tool: z.string(),
2401
+ input: z.record(z.string(), z.unknown()).optional(),
2402
+ conditions: z.array(z.object({ test: z.any(), body: z.any() })).optional(),
2403
+ body: z.array(z.any()).optional()
2404
+ })
2405
+ ).optional().describe("Workflow nodes. Skip this and provide model for LLM to generate from goal.")
2303
2406
  }),
2304
2407
  execute: async (input) => {
2305
2408
  let nodes;
2306
2409
  if (input.nodes && input.nodes.length > 0) {
2307
2410
  nodes = input.nodes;
2308
2411
  } else {
2309
- if (!opts.provider && !opts.model) throw new Error('Provide either "nodes", a "model", or a "provider" with a model to generate the workflow from "goal"');
2412
+ if (!opts.provider && !opts.model)
2413
+ throw new Error(
2414
+ 'Provide either "nodes", a "model", or a "provider" with a model to generate the workflow from "goal"'
2415
+ );
2310
2416
  const toolsDesc = Object.entries(opts.tools ?? {}).map(([k, t]) => `- ${k}: ${t.description}`).join("\n");
2311
2417
  const system = [
2312
2418
  "You are a workflow generator. Given a user goal and available tools, output a workflow JSON.",
@@ -2318,7 +2424,10 @@ function runWorkflow(opts = {}) {
2318
2424
  "Reference syntax: $var.name, $nodes.id.output, $nodes.id.output.field, $input.field",
2319
2425
  "Output ONLY valid JSON. No explanation, no markdown."
2320
2426
  ].filter(Boolean).join("\n");
2321
- const genParams = { system, messages: [{ role: "user", content: input.goal }] };
2427
+ const genParams = {
2428
+ system,
2429
+ messages: [{ role: "user", content: input.goal }]
2430
+ };
2322
2431
  const result = opts.provider ? await opts.provider.generateText(genParams) : await generateText({ ...genParams, model: opts.model });
2323
2432
  const text2 = result.text.trim();
2324
2433
  const jsonStart = text2.indexOf("{");
@@ -2411,10 +2520,7 @@ import {
2411
2520
  embedMany,
2412
2521
  smoothStream
2413
2522
  } from "ai";
2414
- import {
2415
- openai,
2416
- createOpenAI as createOpenAI2
2417
- } from "@ai-sdk/openai";
2523
+ import { openai, createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
2418
2524
 
2419
2525
  // postgres/client.ts
2420
2526
  import postgresFactory from "postgres";
@@ -2657,7 +2763,10 @@ var Table = class {
2657
2763
  const using = opts?.type ? `USING ${opts.type.toUpperCase()}` : "";
2658
2764
  const colList = cols.map((c) => opts?.desc ? `"${c}" DESC` : `"${c}"`).join(", ");
2659
2765
  const operator = opts?.operator ? ` ${opts.operator}` : "";
2660
- const ddl = `CREATE ${unique} INDEX IF NOT EXISTS ${name} ON "${this.tableName}" ${using} (${colList}${operator})`.replace(/\s+/g, " ");
2766
+ const ddl = `CREATE ${unique} INDEX IF NOT EXISTS ${name} ON "${this.tableName}" ${using} (${colList}${operator})`.replace(
2767
+ /\s+/g,
2768
+ " "
2769
+ );
2661
2770
  await sql2.unsafe(ddl);
2662
2771
  }
2663
2772
  async createUniqueIndex(sql2, columns) {
@@ -2695,9 +2804,10 @@ var Table = class {
2695
2804
  _buildSET(data) {
2696
2805
  const sets = [];
2697
2806
  const values = [];
2807
+ const d = data;
2698
2808
  for (const { prop, db } of this.colEntries) {
2699
- if (prop in data && data[prop] !== void 0) {
2700
- const val = data[prop];
2809
+ if (prop in d && d[prop] !== void 0) {
2810
+ const val = d[prop];
2701
2811
  if (val instanceof SQL) {
2702
2812
  sets.push(`"${db}" = ${val.toSQL()}`);
2703
2813
  } else {
@@ -2706,7 +2816,7 @@ var Table = class {
2706
2816
  }
2707
2817
  }
2708
2818
  }
2709
- if (this.hasColumn("updated_at") && !data.updated_at) {
2819
+ if (this.hasColumn("updated_at") && !d.updated_at) {
2710
2820
  sets.push('"updated_at" = NOW()');
2711
2821
  }
2712
2822
  return { sets, values };
@@ -2760,7 +2870,10 @@ var Table = class {
2760
2870
  const softDel = this._softDeleteFilter(where, opts);
2761
2871
  if (softDel) conditions.push(softDel);
2762
2872
  const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
2763
- const [countRow] = await sql2.unsafe(`SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`, values);
2873
+ const [countRow] = await sql2.unsafe(
2874
+ `SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`,
2875
+ values
2876
+ );
2764
2877
  const count = Number(countRow._total);
2765
2878
  if (conditions.length === 0 && !opts?.orderBy && !opts?.limit && !opts?.offset && !opts?.select) {
2766
2879
  const rows2 = await sql2`SELECT * FROM ${sql2(this.tableName)}`;
@@ -2793,7 +2906,10 @@ var Table = class {
2793
2906
  async updateMany(sql2, where, data) {
2794
2907
  const { sets, values: setValues } = this._buildSET(data);
2795
2908
  if (sets.length === 0) return 0;
2796
- const { conditions: wConditions, values: wValues } = this._buildConditions(where, setValues.length);
2909
+ const { conditions: wConditions, values: wValues } = this._buildConditions(
2910
+ where,
2911
+ setValues.length
2912
+ );
2797
2913
  if (wConditions.length === 0) return 0;
2798
2914
  const rows = await sql2.unsafe(
2799
2915
  `UPDATE "${this.tableName}" SET ${sets.join(", ")} WHERE ${wConditions.join(" AND ")} RETURNING 1`,
@@ -2882,13 +2998,20 @@ var Table = class {
2882
2998
  const softDel = this._softDeleteFilter(where);
2883
2999
  if (softDel) conditions.push(softDel);
2884
3000
  const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
2885
- const [row] = await sql2.unsafe(`SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`, values);
3001
+ const [row] = await sql2.unsafe(
3002
+ `SELECT COUNT(*) AS _total FROM "${this.tableName}"${whereClause}`,
3003
+ values
3004
+ );
2886
3005
  return Number(row._total);
2887
3006
  }
2888
3007
  };
2889
3008
  var BoundTable = class _BoundTable {
2890
3009
  inner;
2891
3010
  sql;
3011
+ /** The underlying table name. */
3012
+ get tableName() {
3013
+ return this.inner.tableName;
3014
+ }
2892
3015
  constructor(sql2, tableName, builders) {
2893
3016
  this.inner = new Table(tableName, builders);
2894
3017
  this.sql = sql2;
@@ -2976,13 +3099,17 @@ function postgres(opts) {
2976
3099
  connect_timeout: options.connect_timeout
2977
3100
  });
2978
3101
  if (options.signal) {
2979
- options.signal.addEventListener("abort", () => {
2980
- sql2.end();
2981
- }, { once: true });
3102
+ options.signal.addEventListener(
3103
+ "abort",
3104
+ () => {
3105
+ sql2.end();
3106
+ },
3107
+ { once: true }
3108
+ );
2982
3109
  }
2983
3110
  const closeTimeout = options.closeTimeout ?? 5;
2984
- let _active = 0;
2985
- let _waiting = 0;
3111
+ const _active = 0;
3112
+ const _waiting = 0;
2986
3113
  const poolMax = options.max ?? 10;
2987
3114
  const mw = ((req, ctx, next) => {
2988
3115
  ctx.sql = sql2;
@@ -3010,10 +3137,9 @@ function postgres(opts) {
3010
3137
  );
3011
3138
  };
3012
3139
  mw.isMigrated = async (moduleName) => {
3013
- const [row] = await sql2.unsafe(
3014
- `SELECT 1 FROM "${MIGRATIONS_TABLE}" WHERE name = $1`,
3015
- [moduleName]
3016
- );
3140
+ const [row] = await sql2.unsafe(`SELECT 1 FROM "${MIGRATIONS_TABLE}" WHERE name = $1`, [
3141
+ moduleName
3142
+ ]);
3017
3143
  return !!row;
3018
3144
  };
3019
3145
  mw.transaction = (async (fn, retryOpts) => {
@@ -3145,10 +3271,9 @@ function createOAuth2Server(deps) {
3145
3271
  return null;
3146
3272
  }
3147
3273
  function consentPage(client, params) {
3148
- const fields = Object.entries(params).map(
3149
- ([k, v]) => `<input type="hidden" name="${k}" value="${v.replace(/"/g, "&quot;")}">`
3150
- ).join("\n ");
3151
- return new Response(`<!DOCTYPE html>
3274
+ const fields = Object.entries(params).map(([k, v]) => `<input type="hidden" name="${k}" value="${v.replace(/"/g, "&quot;")}">`).join("\n ");
3275
+ return new Response(
3276
+ `<!DOCTYPE html>
3152
3277
  <html lang="en">
3153
3278
  <head><meta charset="utf-8"><title>Authorize</title>
3154
3279
  <style>
@@ -3175,17 +3300,22 @@ function createOAuth2Server(deps) {
3175
3300
  </form>
3176
3301
  </div>
3177
3302
  </body>
3178
- </html>`, { headers: { "Content-Type": "text/html; charset=utf-8" } });
3303
+ </html>`,
3304
+ { headers: { "Content-Type": "text/html; charset=utf-8" } }
3305
+ );
3179
3306
  }
3180
3307
  function errorPage2(error, description) {
3181
- return new Response(`<!DOCTYPE html>
3308
+ return new Response(
3309
+ `<!DOCTYPE html>
3182
3310
  <html lang="en">
3183
3311
  <head><meta charset="utf-8"><title>Error</title>
3184
3312
  <style>body{font-family:sans-serif;max-width:480px;margin:80px auto;padding:0 20px}
3185
3313
  h2{color:#dc2626}.desc{color:#555}</style>
3186
3314
  </head>
3187
3315
  <body><h2>${error}</h2>${description ? `<p class="desc">${description}</p>` : ""}</body>
3188
- </html>`, { status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } });
3316
+ </html>`,
3317
+ { status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } }
3318
+ );
3189
3319
  }
3190
3320
  async function authorizeHandler(req, _ctx) {
3191
3321
  const url = new URL(req.url);
@@ -3204,7 +3334,10 @@ h2{color:#dc2626}.desc{color:#555}</style>
3204
3334
  return errorPage2("Invalid client_id", "No client found with the given client_id.");
3205
3335
  }
3206
3336
  if (!client.redirectUris.includes(redirectUri)) {
3207
- return errorPage2("Invalid redirect_uri", "The redirect_uri is not registered for this client.");
3337
+ return errorPage2(
3338
+ "Invalid redirect_uri",
3339
+ "The redirect_uri is not registered for this client."
3340
+ );
3208
3341
  }
3209
3342
  const user2 = extractUser(req);
3210
3343
  if (!user2) {
@@ -3231,7 +3364,7 @@ h2{color:#dc2626}.desc{color:#555}</style>
3231
3364
  const redirectUri = form.get("redirect_uri") || "";
3232
3365
  const scope = form.get("scope") || "";
3233
3366
  const state = form.get("state") || "";
3234
- const userId = parseInt(form.get("user_id") || "0", 10);
3367
+ const userId2 = parseInt(form.get("user_id") || "0", 10);
3235
3368
  const codeChallenge = form.get("code_challenge") || "";
3236
3369
  const codeChallengeMethod = form.get("code_challenge_method") || "";
3237
3370
  if (!approve) {
@@ -3242,7 +3375,7 @@ h2{color:#dc2626}.desc{color:#555}</style>
3242
3375
  const expiresAt = new Date(Date.now() + 10 * 60 * 1e3);
3243
3376
  await pg.sql`
3244
3377
  INSERT INTO "_oauth2_codes" ("code", "client_id", "user_id", "redirect_uri", "code_challenge", "code_challenge_method", "scope", "expires_at")
3245
- VALUES (${code}, ${clientId}, ${userId}, ${redirectUri}, ${codeChallenge || null}, ${codeChallengeMethod || null}, ${scope || null}, ${expiresAt})
3378
+ VALUES (${code}, ${clientId}, ${userId2}, ${redirectUri}, ${codeChallenge || null}, ${codeChallengeMethod || null}, ${scope || null}, ${expiresAt})
3246
3379
  `;
3247
3380
  const loc = `${redirectUri}?code=${code}${state ? `&state=${state}` : ""}`;
3248
3381
  return Response.redirect(loc, 302);
@@ -3290,14 +3423,23 @@ h2{color:#dc2626}.desc{color:#555}</style>
3290
3423
  return Response.json({ error: "invalid_grant" }, { status: 400 });
3291
3424
  }
3292
3425
  if (new Date(stored.expires_at) < /* @__PURE__ */ new Date()) {
3293
- return Response.json({ error: "invalid_grant", error_description: "Code expired" }, { status: 400 });
3426
+ return Response.json(
3427
+ { error: "invalid_grant", error_description: "Code expired" },
3428
+ { status: 400 }
3429
+ );
3294
3430
  }
3295
3431
  if (stored.redirect_uri !== redirectUri) {
3296
- return Response.json({ error: "invalid_grant", error_description: "redirect_uri mismatch" }, { status: 400 });
3432
+ return Response.json(
3433
+ { error: "invalid_grant", error_description: "redirect_uri mismatch" },
3434
+ { status: 400 }
3435
+ );
3297
3436
  }
3298
3437
  if (stored.code_challenge) {
3299
3438
  if (!codeVerifier) {
3300
- return Response.json({ error: "invalid_grant", error_description: "code_verifier required" }, { status: 400 });
3439
+ return Response.json(
3440
+ { error: "invalid_grant", error_description: "code_verifier required" },
3441
+ { status: 400 }
3442
+ );
3301
3443
  }
3302
3444
  let expected;
3303
3445
  if (stored.code_challenge_method === "plain") {
@@ -3306,7 +3448,10 @@ h2{color:#dc2626}.desc{color:#555}</style>
3306
3448
  expected = crypto4.createHash("sha256").update(codeVerifier).digest().toString("base64url");
3307
3449
  }
3308
3450
  if (expected !== stored.code_challenge) {
3309
- return Response.json({ error: "invalid_grant", error_description: "code_verifier mismatch" }, { status: 400 });
3451
+ return Response.json(
3452
+ { error: "invalid_grant", error_description: "code_verifier mismatch" },
3453
+ { status: 400 }
3454
+ );
3310
3455
  }
3311
3456
  }
3312
3457
  await pg.sql`UPDATE "_oauth2_codes" SET "used" = TRUE WHERE "id" = ${stored.id}`;
@@ -3418,12 +3563,12 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3418
3563
  );
3419
3564
  return row ?? null;
3420
3565
  }
3421
- async function linkProvider(userId, provider, providerId, email, name, avatarUrl) {
3566
+ async function linkProvider(userId2, provider, providerId, email, name, avatarUrl) {
3422
3567
  await sql2.unsafe(
3423
3568
  `INSERT INTO ${escapeIdent(providerTable)} (user_id, provider, provider_id, email, name, avatar_url)
3424
3569
  VALUES ($1, $2, $3, $4, $5, $6)
3425
3570
  ON CONFLICT (provider, provider_id) DO NOTHING`,
3426
- [userId, provider, providerId, email, name, avatarUrl]
3571
+ [userId2, provider, providerId, email, name, avatarUrl]
3427
3572
  );
3428
3573
  }
3429
3574
  async function findOrCreateUser(provider, providerId, email, name, avatarUrl) {
@@ -3511,7 +3656,7 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3511
3656
  try {
3512
3657
  tokenRes = await fetch(meta.tokenUrl, {
3513
3658
  method: "POST",
3514
- headers: { "Content-Type": "application/json", "Accept": "application/json" },
3659
+ headers: { "Content-Type": "application/json", Accept: "application/json" },
3515
3660
  body: JSON.stringify({
3516
3661
  code,
3517
3662
  client_id: config.clientId,
@@ -3521,7 +3666,10 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3521
3666
  })
3522
3667
  });
3523
3668
  } catch (err) {
3524
- console.error(`[oauth] token exchange network error for ${providerName}:`, err.message);
3669
+ console.error(
3670
+ `[oauth] token exchange network error for ${providerName}:`,
3671
+ err.message
3672
+ );
3525
3673
  return Response.json({ error: "Failed to connect to OAuth provider" }, { status: 502 });
3526
3674
  }
3527
3675
  if (!tokenRes.ok) {
@@ -3538,7 +3686,10 @@ function registerOAuthLoginRoutes(router, deps, providers) {
3538
3686
  try {
3539
3687
  userRes = await fetch(meta.userUrl, { headers: { Authorization: "Bearer " + accessToken } });
3540
3688
  } catch (err) {
3541
- console.error("[oauth] user info network error for " + providerName + ":", err.message);
3689
+ console.error(
3690
+ "[oauth] user info network error for " + providerName + ":",
3691
+ err.message
3692
+ );
3542
3693
  return Response.json({ error: "Failed to connect to OAuth provider" }, { status: 502 });
3543
3694
  }
3544
3695
  if (!userRes.ok) {
@@ -3706,11 +3857,9 @@ function user(options) {
3706
3857
  await tokens.create();
3707
3858
  }
3708
3859
  function signToken(user2) {
3709
- return jwt2.sign(
3710
- { sub: user2.id, email: user2.email, role: user2.role },
3711
- secret,
3712
- { expiresIn }
3713
- );
3860
+ return jwt2.sign({ sub: user2.id, email: user2.email, role: user2.role }, secret, {
3861
+ expiresIn
3862
+ });
3714
3863
  }
3715
3864
  function stripPassword(row) {
3716
3865
  const { password: _, ...user2 } = row;
@@ -3765,7 +3914,7 @@ function user(options) {
3765
3914
  const payload = jwt2.verify(token, secret);
3766
3915
  if (payload.token_type === "client_credentials") return null;
3767
3916
  if (!hasDb || !findById) return null;
3768
- const row = await findById(payload.sub);
3917
+ const row = await findById(Number(payload.sub));
3769
3918
  if (!row) return null;
3770
3919
  return stripPassword(row);
3771
3920
  } catch {
@@ -3774,27 +3923,26 @@ function user(options) {
3774
3923
  }
3775
3924
  const headerName = options.header ?? "Authorization";
3776
3925
  async function resolveUser(req, ctx) {
3777
- const sessionUserId = ctx.session?.userId;
3926
+ const s = ctx;
3927
+ const sessionUserId = s.session?.userId;
3778
3928
  if (sessionUserId !== void 0 && sessionUserId !== null) {
3779
3929
  if (hasDb) {
3780
3930
  const row = await findById(sessionUserId);
3781
3931
  if (row) {
3782
3932
  return stripPassword(row);
3783
3933
  }
3784
- if (typeof ctx.session?.destroy === "function") {
3785
- ;
3786
- ctx.session.destroy();
3787
- } else {
3788
- delete ctx.session?.userId;
3934
+ if (typeof s.session?.destroy === "function") {
3935
+ s.session.destroy();
3936
+ } else if (s.session) {
3937
+ delete s.session.userId;
3789
3938
  }
3790
3939
  } else if (options.resolveUser) {
3791
3940
  const userData = await options.resolveUser(sessionUserId);
3792
3941
  if (userData) {
3793
3942
  return userData;
3794
3943
  }
3795
- if (typeof ctx.session?.destroy === "function") {
3796
- ;
3797
- ctx.session.destroy();
3944
+ if (typeof s.session?.destroy === "function") {
3945
+ s.session.destroy();
3798
3946
  }
3799
3947
  console.warn(`[${currentTraceId()}] user: session userId ${sessionUserId} resolved to null`);
3800
3948
  } else {
@@ -3854,7 +4002,7 @@ function user(options) {
3854
4002
  try {
3855
4003
  const payload = jwt2.verify(token, secret);
3856
4004
  if (payload.token_type === "client_credentials") return null;
3857
- const row = await findById(payload.sub);
4005
+ const row = await findById(Number(payload.sub));
3858
4006
  if (row) return stripPassword(row);
3859
4007
  } catch {
3860
4008
  }
@@ -3879,6 +4027,7 @@ function user(options) {
3879
4027
  return async (req, ctx, next) => {
3880
4028
  const userData = await resolveUser(req, ctx);
3881
4029
  if (userData) {
4030
+ ;
3882
4031
  ctx.user = userData;
3883
4032
  }
3884
4033
  return next(req, ctx);
@@ -3915,13 +4064,13 @@ function user(options) {
3915
4064
  try {
3916
4065
  const body = await parseBody2(req);
3917
4066
  const result = await login(body);
3918
- if (ctx.session) {
3919
- ;
3920
- ctx.session.userId = result.user.id;
3921
- ctx.session.role = result.user.role;
4067
+ const s = ctx;
4068
+ if (s.session) {
4069
+ s.session.userId = result.user.id;
4070
+ s.session.role = result.user.role;
3922
4071
  }
3923
4072
  const res = Response.json(result);
3924
- if (!ctx.session) {
4073
+ if (!s.session) {
3925
4074
  res.headers.set("Set-Cookie", `session=${result.token}; HttpOnly; SameSite=Lax; Path=/`);
3926
4075
  }
3927
4076
  return res;
@@ -3940,18 +4089,22 @@ function user(options) {
3940
4089
  r.post("/oauth/token", (req) => oauth2.tokenHandler(req));
3941
4090
  }
3942
4091
  if (hasDb && options.oauthLogin) {
3943
- registerOAuthLoginRoutes(r, {
3944
- sql: _pg.sql,
3945
- jwtSecret: secret,
3946
- expiresIn,
3947
- usersTable: table,
3948
- providerTable: "_auth_providers",
3949
- redirectUrl: options.oauthLogin.redirectUrl || "/",
3950
- signToken,
3951
- createPlaceholderUser,
3952
- findUserById: findById,
3953
- findUserByEmail: findByEmail
3954
- }, options.oauthLogin.providers);
4092
+ registerOAuthLoginRoutes(
4093
+ r,
4094
+ {
4095
+ sql: _pg.sql,
4096
+ jwtSecret: secret,
4097
+ expiresIn,
4098
+ usersTable: table,
4099
+ providerTable: "_auth_providers",
4100
+ redirectUrl: options.oauthLogin.redirectUrl || "/",
4101
+ signToken,
4102
+ createPlaceholderUser,
4103
+ findUserById: findById,
4104
+ findUserByEmail: findByEmail
4105
+ },
4106
+ options.oauthLogin.providers
4107
+ );
3955
4108
  }
3956
4109
  const mod = r;
3957
4110
  mod.middleware = middleware;
@@ -4048,9 +4201,7 @@ var FIELD_RANGES = [
4048
4201
  function parsePattern(pattern) {
4049
4202
  const fields = pattern.trim().split(/\s+/);
4050
4203
  if (fields.length !== 5) {
4051
- throw new Error(
4052
- `Invalid cron pattern "${pattern}": expected 5 fields, got ${fields.length}`
4053
- );
4204
+ throw new Error(`Invalid cron pattern "${pattern}": expected 5 fields, got ${fields.length}`);
4054
4205
  }
4055
4206
  return fields.map((f, i) => parseField(f, FIELD_RANGES[i][0], FIELD_RANGES[i][1]));
4056
4207
  }
@@ -4059,7 +4210,7 @@ function matches(fields, date) {
4059
4210
  }
4060
4211
  function cronNext(expr, from = /* @__PURE__ */ new Date()) {
4061
4212
  const fields = parsePattern(expr);
4062
- let candidate = new Date(from.getTime() + 6e4);
4213
+ const candidate = new Date(from.getTime() + 6e4);
4063
4214
  candidate.setSeconds(0, 0);
4064
4215
  for (let i = 0; i < 525600; i++) {
4065
4216
  if (fields[4].has(candidate.getDay()) && fields[3].has(candidate.getMonth() + 1) && fields[2].has(candidate.getDate()) && fields[1].has(candidate.getHours()) && fields[0].has(candidate.getMinutes())) {
@@ -4122,7 +4273,12 @@ function createMemoryQueue(opts) {
4122
4273
  }
4123
4274
  if (job.schedule) {
4124
4275
  try {
4125
- insertJob({ ...job, id: crypto6.randomUUID(), runAt: cronNext(job.schedule), createdAt: Date.now() });
4276
+ insertJob({
4277
+ ...job,
4278
+ id: crypto6.randomUUID(),
4279
+ runAt: cronNext(job.schedule),
4280
+ createdAt: Date.now()
4281
+ });
4126
4282
  } catch (e) {
4127
4283
  console.error("[queue] cron re-queue failed:", e.message);
4128
4284
  }
@@ -4210,7 +4366,14 @@ function createMemoryQueue(opts) {
4210
4366
  mw.dashboard = function dashboard() {
4211
4367
  return buildDashboard(q);
4212
4368
  };
4213
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4369
+ mw.stats = () => ({
4370
+ running,
4371
+ inflight,
4372
+ processed: _processed,
4373
+ failed: _failed,
4374
+ handlers: handlers.size,
4375
+ maxConcurrent: MAX_CONCURRENT
4376
+ });
4214
4377
  attachCron(q, handlers);
4215
4378
  return q;
4216
4379
  }
@@ -4225,8 +4388,12 @@ function createPgQueue(opts) {
4225
4388
  const MAX_FAILED = 1e3;
4226
4389
  async function ensureTable() {
4227
4390
  if (ready) return;
4228
- await sql2.unsafe(`CREATE TABLE IF NOT EXISTS ${escapeIdent3(table)} (id UUID PRIMARY KEY, type TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}', run_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), schedule TEXT, status TEXT NOT NULL DEFAULT 'pending', error TEXT, failed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW())`);
4229
- await sql2.unsafe(`CREATE INDEX IF NOT EXISTS ${escapeIdent3(table + "_run_at_idx")} ON ${escapeIdent3(table)} (run_at, status)`);
4391
+ await sql2.unsafe(
4392
+ `CREATE TABLE IF NOT EXISTS ${escapeIdent3(table)} (id UUID PRIMARY KEY, type TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}', run_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), schedule TEXT, status TEXT NOT NULL DEFAULT 'pending', error TEXT, failed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW())`
4393
+ );
4394
+ await sql2.unsafe(
4395
+ `CREATE INDEX IF NOT EXISTS ${escapeIdent3(table + "_run_at_idx")} ON ${escapeIdent3(table)} (run_at, status)`
4396
+ );
4230
4397
  ready = true;
4231
4398
  }
4232
4399
  async function processJob(job, handler) {
@@ -4239,14 +4406,26 @@ function createPgQueue(opts) {
4239
4406
  _failed++;
4240
4407
  const msg = e.message;
4241
4408
  console.error("[queue] handler error:", msg);
4242
- await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'failed', error = $2, failed_at = NOW() WHERE id = $1`, [job.id, msg]);
4409
+ await sql2.unsafe(
4410
+ `UPDATE ${escapeIdent3(table)} SET status = 'failed', error = $2, failed_at = NOW() WHERE id = $1`,
4411
+ [job.id, msg]
4412
+ );
4243
4413
  } finally {
4244
4414
  inflight--;
4245
4415
  }
4246
4416
  if (job.schedule) {
4247
4417
  try {
4248
4418
  const nextRun = cronNext(job.schedule);
4249
- await sql2.unsafe(`INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`, [crypto6.randomUUID(), job.type, JSON.stringify(job.payload), new Date(nextRun).toISOString(), job.schedule]);
4419
+ await sql2.unsafe(
4420
+ `INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`,
4421
+ [
4422
+ crypto6.randomUUID(),
4423
+ job.type,
4424
+ JSON.stringify(job.payload),
4425
+ new Date(nextRun).toISOString(),
4426
+ job.schedule
4427
+ ]
4428
+ );
4250
4429
  } catch (e) {
4251
4430
  console.error("[queue] cron re-queue failed:", e.message);
4252
4431
  }
@@ -4256,10 +4435,20 @@ function createPgQueue(opts) {
4256
4435
  if (!running) return;
4257
4436
  try {
4258
4437
  while (running && inflight < MAX_CONCURRENT) {
4259
- const rows = await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'running' WHERE id = (SELECT id FROM ${escapeIdent3(table)} WHERE run_at <= NOW() AND status = 'pending' ORDER BY run_at LIMIT 1 FOR UPDATE SKIP LOCKED) RETURNING *`);
4438
+ const rows = await sql2.unsafe(
4439
+ `UPDATE ${escapeIdent3(table)} SET status = 'running' WHERE id = (SELECT id FROM ${escapeIdent3(table)} WHERE run_at <= NOW() AND status = 'pending' ORDER BY run_at LIMIT 1 FOR UPDATE SKIP LOCKED) RETURNING *`
4440
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4441
+ );
4260
4442
  if (rows.length === 0) break;
4261
4443
  const row = rows[0];
4262
- const job = { id: row.id, type: row.type, payload: typeof row.payload === "string" ? JSON.parse(row.payload) : row.payload, createdAt: new Date(row.created_at).getTime(), runAt: new Date(row.run_at).getTime(), schedule: row.schedule || void 0 };
4444
+ const job = {
4445
+ id: row.id,
4446
+ type: row.type,
4447
+ payload: typeof row.payload === "string" ? JSON.parse(row.payload) : row.payload,
4448
+ createdAt: new Date(row.created_at).getTime(),
4449
+ runAt: new Date(row.run_at).getTime(),
4450
+ schedule: row.schedule || void 0
4451
+ };
4263
4452
  const handler = handlers.get(job.type);
4264
4453
  if (handler) processJob(job, handler);
4265
4454
  }
@@ -4294,7 +4483,10 @@ function createPgQueue(opts) {
4294
4483
  } else {
4295
4484
  runAt = /* @__PURE__ */ new Date();
4296
4485
  }
4297
- await sql2.unsafe(`INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`, [id2, type, JSON.stringify(payload), runAt.toISOString(), opts2?.schedule || null]);
4486
+ await sql2.unsafe(
4487
+ `INSERT INTO ${escapeIdent3(table)} (id, type, payload, run_at, schedule) VALUES ($1, $2, $3::jsonb, $4, $5)`,
4488
+ [id2, type, JSON.stringify(payload), runAt.toISOString(), opts2?.schedule || null]
4489
+ );
4298
4490
  return id2;
4299
4491
  })();
4300
4492
  };
@@ -4320,25 +4512,64 @@ function createPgQueue(opts) {
4320
4512
  while (inflight > 0) await new Promise((r) => setTimeout(r, 50));
4321
4513
  };
4322
4514
  mw.jobs = async function jobs(limit) {
4323
- const rows = await sql2.unsafe(`SELECT * FROM ${escapeIdent3(table)} WHERE status = 'pending' ORDER BY run_at LIMIT $1`, [limit ?? 50]);
4324
- return rows.map((r) => ({ id: r.id, type: r.type, payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload, createdAt: new Date(r.created_at).getTime(), runAt: new Date(r.run_at).getTime(), schedule: r.schedule || void 0 }));
4515
+ const rows = await sql2.unsafe(
4516
+ `SELECT * FROM ${escapeIdent3(table)} WHERE status = 'pending' ORDER BY run_at LIMIT $1`,
4517
+ [limit ?? 50]
4518
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4519
+ );
4520
+ return rows.map((r) => ({
4521
+ id: r.id,
4522
+ type: r.type,
4523
+ payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload,
4524
+ createdAt: new Date(r.created_at).getTime(),
4525
+ runAt: new Date(r.run_at).getTime(),
4526
+ schedule: r.schedule || void 0
4527
+ }));
4325
4528
  };
4326
4529
  mw.failedJobs = async function failedJobs(limit) {
4327
- const rows = await sql2.unsafe(`SELECT * FROM ${escapeIdent3(table)} WHERE status = 'failed' ORDER BY failed_at DESC LIMIT $1`, [limit ?? 50]);
4328
- return rows.map((r) => ({ id: r.id, type: r.type, payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload, createdAt: new Date(r.created_at).getTime(), runAt: new Date(r.run_at).getTime(), schedule: r.schedule || void 0, error: r.error || "", failedAt: new Date(r.failed_at).getTime() }));
4530
+ const rows = await sql2.unsafe(
4531
+ `SELECT * FROM ${escapeIdent3(table)} WHERE status = 'failed' ORDER BY failed_at DESC LIMIT $1`,
4532
+ [limit ?? 50]
4533
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4534
+ );
4535
+ return rows.map((r) => ({
4536
+ id: r.id,
4537
+ type: r.type,
4538
+ payload: typeof r.payload === "string" ? JSON.parse(r.payload) : r.payload,
4539
+ createdAt: new Date(r.created_at).getTime(),
4540
+ runAt: new Date(r.run_at).getTime(),
4541
+ schedule: r.schedule || void 0,
4542
+ error: r.error || "",
4543
+ failedAt: new Date(r.failed_at).getTime()
4544
+ }));
4329
4545
  };
4330
4546
  mw.retryFailed = async function retryFailed(jobId) {
4331
- const result = await sql2.unsafe(`UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE id = $1 AND status = 'failed' RETURNING id`, [jobId]);
4547
+ const result = await sql2.unsafe(
4548
+ `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE id = $1 AND status = 'failed' RETURNING id`,
4549
+ [jobId]
4550
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4551
+ );
4332
4552
  return result.length > 0;
4333
4553
  };
4334
4554
  mw.retryAllFailed = async function retryAllFailed(type) {
4335
- const result = await sql2.unsafe(type ? `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' AND type = $1 RETURNING id` : `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' RETURNING id`, type ? [type] : []);
4555
+ const result = await sql2.unsafe(
4556
+ type ? `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' AND type = $1 RETURNING id` : `UPDATE ${escapeIdent3(table)} SET status = 'pending', error = NULL, failed_at = NULL, run_at = NOW() WHERE status = 'failed' RETURNING id`,
4557
+ type ? [type] : []
4558
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4559
+ );
4336
4560
  return result.length;
4337
4561
  };
4338
4562
  mw.dashboard = function dashboard() {
4339
4563
  return buildDashboard(q);
4340
4564
  };
4341
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4565
+ mw.stats = () => ({
4566
+ running,
4567
+ inflight,
4568
+ processed: _processed,
4569
+ failed: _failed,
4570
+ handlers: handlers.size,
4571
+ maxConcurrent: MAX_CONCURRENT
4572
+ });
4342
4573
  attachCron(q, handlers);
4343
4574
  return q;
4344
4575
  }
@@ -4367,7 +4598,16 @@ function createRedisQueue(opts) {
4367
4598
  if (job.schedule) {
4368
4599
  try {
4369
4600
  const nextRun = cronNext(job.schedule);
4370
- await redis2.zadd(jobKey, nextRun, JSON.stringify({ ...job, id: crypto6.randomUUID(), runAt: nextRun, createdAt: Date.now() }));
4601
+ await redis2.zadd(
4602
+ jobKey,
4603
+ nextRun,
4604
+ JSON.stringify({
4605
+ ...job,
4606
+ id: crypto6.randomUUID(),
4607
+ runAt: nextRun,
4608
+ createdAt: Date.now()
4609
+ })
4610
+ );
4371
4611
  } catch (e) {
4372
4612
  console.error("[queue] cron re-queue failed:", e.message);
4373
4613
  }
@@ -4501,7 +4741,14 @@ function createRedisQueue(opts) {
4501
4741
  mw.dashboard = function dashboard() {
4502
4742
  return buildDashboard(q);
4503
4743
  };
4504
- mw.stats = () => ({ running, inflight, processed: _processed, failed: _failed, handlers: handlers.size, maxConcurrent: MAX_CONCURRENT });
4744
+ mw.stats = () => ({
4745
+ running,
4746
+ inflight,
4747
+ processed: _processed,
4748
+ failed: _failed,
4749
+ handlers: handlers.size,
4750
+ maxConcurrent: MAX_CONCURRENT
4751
+ });
4505
4752
  attachCron(q, handlers);
4506
4753
  return q;
4507
4754
  }
@@ -4649,10 +4896,14 @@ function createIndexesSQL(tenantId, slug, fields) {
4649
4896
  const name = internalTableName(tenantId, slug);
4650
4897
  const statements = [];
4651
4898
  statements.push(`CREATE INDEX IF NOT EXISTS "${name}_tenant_idx" ON "${name}" ("tenant_id")`);
4652
- statements.push(`CREATE INDEX IF NOT EXISTS "${name}_tenant_id_idx" ON "${name}" ("tenant_id", "id")`);
4899
+ statements.push(
4900
+ `CREATE INDEX IF NOT EXISTS "${name}_tenant_id_idx" ON "${name}" ("tenant_id", "id")`
4901
+ );
4653
4902
  for (const f of fields) {
4654
4903
  if (f.unique) {
4655
- statements.push(`CREATE UNIQUE INDEX IF NOT EXISTS "${name}_${f.name}_uidx" ON "${name}" ("${f.name}")`);
4904
+ statements.push(
4905
+ `CREATE UNIQUE INDEX IF NOT EXISTS "${name}_${f.name}_uidx" ON "${name}" ("${f.name}")`
4906
+ );
4656
4907
  } else if (f.index === "hnsw") {
4657
4908
  statements.push(
4658
4909
  `CREATE INDEX IF NOT EXISTS "${name}_${f.name}_hnsw_idx" ON "${name}" USING hnsw ("${f.name}" vector_cosine_ops)`
@@ -4695,6 +4946,27 @@ function buildColumnDDL(tenantId, field) {
4695
4946
  }
4696
4947
 
4697
4948
  // tenant/rest.ts
4949
+ function userId(ctx) {
4950
+ return ctx.user?.id ?? null;
4951
+ }
4952
+ function extractCount(rows) {
4953
+ return Number(rows[0]?.count ?? 0);
4954
+ }
4955
+ function asJson(val) {
4956
+ return val;
4957
+ }
4958
+ function tableRef(s, name) {
4959
+ return s(name);
4960
+ }
4961
+ function withTenant(ctx, data) {
4962
+ ;
4963
+ data.tenant_id = ctx.tenant.id;
4964
+ return data;
4965
+ }
4966
+ function withoutTenant(data) {
4967
+ delete data.tenant_id;
4968
+ return data;
4969
+ }
4698
4970
  function zodType(field) {
4699
4971
  let t;
4700
4972
  switch (field.type) {
@@ -4752,7 +5024,7 @@ function buildRouter(sql2, usersTable) {
4752
5024
  `;
4753
5025
  await sql2`
4754
5026
  INSERT INTO "_tenant_members" ("tenant_id", "user_id", "role")
4755
- VALUES (${tenant2.id}, ${ctx.user.id}, 'admin')
5027
+ VALUES (${tenant2.id}, ${userId(ctx)}, 'admin')
4756
5028
  `;
4757
5029
  return Response.json(tenant2, { status: 201 });
4758
5030
  });
@@ -4760,7 +5032,7 @@ function buildRouter(sql2, usersTable) {
4760
5032
  const rows = await sql2`
4761
5033
  SELECT t.*, tm.role FROM "_tenants" t
4762
5034
  JOIN "_tenant_members" tm ON tm.tenant_id = t.id
4763
- WHERE tm.user_id = ${ctx.user.id}
5035
+ WHERE tm.user_id = ${userId(ctx)}
4764
5036
  `;
4765
5037
  return Response.json(rows);
4766
5038
  });
@@ -4769,7 +5041,7 @@ function buildRouter(sql2, usersTable) {
4769
5041
  if (err) return err;
4770
5042
  const { email, role = "member" } = await req.json();
4771
5043
  const [user2] = await sql2`
4772
- SELECT id FROM ${sql2(usersTable)} WHERE "email" = ${email} LIMIT 1
5044
+ SELECT id FROM ${tableRef(sql2, usersTable)} WHERE "email" = ${email} LIMIT 1
4773
5045
  `;
4774
5046
  if (!user2) return Response.json({ error: "User not found" }, { status: 404 });
4775
5047
  const [existing] = await sql2`
@@ -4786,10 +5058,10 @@ function buildRouter(sql2, usersTable) {
4786
5058
  r.delete("/sys/tenants/members/:userId", async (req, ctx) => {
4787
5059
  const err = requireAdmin(ctx);
4788
5060
  if (err) return err;
4789
- const userId = parseInt(ctx.params.userId, 10);
5061
+ const userId2 = parseInt(ctx.params.userId, 10);
4790
5062
  await sql2`
4791
5063
  DELETE FROM "_tenant_members"
4792
- WHERE tenant_id = ${ctx.tenant.id} AND user_id = ${userId}
5064
+ WHERE tenant_id = ${ctx.tenant.id} AND user_id = ${userId2}
4793
5065
  `;
4794
5066
  return Response.json({ ok: true });
4795
5067
  });
@@ -4815,7 +5087,7 @@ function buildRouter(sql2, usersTable) {
4815
5087
  }
4816
5088
  const [row] = await sql2`
4817
5089
  INSERT INTO "_user_tables" ("tenant_id", "slug", "label", "fields")
4818
- VALUES (${ctx.tenant.id}, ${body.slug}, ${body.label || ""}, ${body.fields})
5090
+ VALUES (${ctx.tenant.id}, ${body.slug}, ${body.label || ""}, ${asJson(body.fields)})
4819
5091
  RETURNING *
4820
5092
  `;
4821
5093
  return Response.json(row, { status: 201 });
@@ -4850,7 +5122,7 @@ function buildRouter(sql2, usersTable) {
4850
5122
  const merged = [...table.fields, ...newFields];
4851
5123
  await sql2`
4852
5124
  UPDATE "_user_tables"
4853
- SET fields = ${merged}
5125
+ SET fields = ${asJson(merged)}
4854
5126
  WHERE id = ${table.id}
4855
5127
  `;
4856
5128
  return Response.json({ ...table, fields: merged });
@@ -4893,12 +5165,11 @@ function buildRouter(sql2, usersTable) {
4893
5165
  `SELECT *, "${searchField}" ${operator} $1::vector AS "_distance" FROM "${name2}" WHERE tenant_id = $2 ORDER BY "_distance" LIMIT $3 OFFSET $4`,
4894
5166
  [parsed, ctx.tenant.id, limit, offset]
4895
5167
  ),
4896
- sql2.unsafe(
4897
- `SELECT count(*) as count FROM "${name2}" WHERE tenant_id = $1`,
4898
- [ctx.tenant.id]
4899
- )
5168
+ sql2.unsafe(`SELECT count(*) as count FROM "${name2}" WHERE tenant_id = $1`, [
5169
+ ctx.tenant.id
5170
+ ])
4900
5171
  ]);
4901
- return Response.json({ rows: rows2, count: Number(countResult2[0]?.count ?? 0) });
5172
+ return Response.json({ rows: rows2, count: extractCount(countResult2) });
4902
5173
  } catch {
4903
5174
  return Response.json({ error: "Invalid search_vector" }, { status: 400 });
4904
5175
  }
@@ -4909,12 +5180,9 @@ function buildRouter(sql2, usersTable) {
4909
5180
  `SELECT * FROM "${name}" WHERE tenant_id = $1 ORDER BY "${orderCol}" ${orderDir} LIMIT $2 OFFSET $3`,
4910
5181
  [ctx.tenant.id, limit, offset]
4911
5182
  ),
4912
- sql2.unsafe(
4913
- `SELECT count(*) as count FROM "${name}" WHERE tenant_id = $1`,
4914
- [ctx.tenant.id]
4915
- )
5183
+ sql2.unsafe(`SELECT count(*) as count FROM "${name}" WHERE tenant_id = $1`, [ctx.tenant.id])
4916
5184
  ]);
4917
- return Response.json({ rows, count: Number(countResult[0]?.count ?? 0) });
5185
+ return Response.json({ rows, count: extractCount(countResult) });
4918
5186
  });
4919
5187
  r.post("/:_slug", async (req, ctx) => {
4920
5188
  const table = await resolveTable(ctx);
@@ -4925,11 +5193,10 @@ function buildRouter(sql2, usersTable) {
4925
5193
  shape[f.name] = zodType(f);
4926
5194
  }
4927
5195
  const zodSchema = z3.object(shape);
4928
- const parsed = zodSchema.parse(data);
4929
- parsed.tenant_id = ctx.tenant.id;
5196
+ const parsed = withTenant(ctx, zodSchema.parse(data));
4930
5197
  delete parsed.id;
4931
5198
  const name = internalName(ctx);
4932
- const [row] = await sql2`INSERT INTO ${sql2(name)} ${sql2(parsed)} RETURNING *`;
5199
+ const [row] = await sql2`INSERT INTO ${tableRef(sql2, name)} ${sql2(parsed)} RETURNING *`;
4933
5200
  return Response.json(row, { status: 201 });
4934
5201
  });
4935
5202
  r.get("/:_slug/:id", async (_req, ctx) => {
@@ -4937,7 +5204,7 @@ function buildRouter(sql2, usersTable) {
4937
5204
  if (!table) return Response.json({ error: "Table not found" }, { status: 404 });
4938
5205
  const name = internalName(ctx);
4939
5206
  const [row] = await sql2`
4940
- SELECT * FROM ${sql2(name)}
5207
+ SELECT * FROM ${tableRef(sql2, name)}
4941
5208
  WHERE id = ${parseInt(ctx.params.id, 10)} AND tenant_id = ${ctx.tenant.id}
4942
5209
  LIMIT 1
4943
5210
  `;
@@ -4953,13 +5220,12 @@ function buildRouter(sql2, usersTable) {
4953
5220
  shape[f.name] = zodType(f);
4954
5221
  }
4955
5222
  const zodSchema = z3.object(shape).partial();
4956
- const parsed = zodSchema.parse(data);
5223
+ const parsed = withoutTenant(zodSchema.parse(data));
4957
5224
  delete parsed.id;
4958
- delete parsed.tenant_id;
4959
5225
  if (Object.keys(parsed).length === 0) {
4960
5226
  const name2 = internalName(ctx);
4961
5227
  const [row2] = await sql2`
4962
- SELECT * FROM ${sql2(name2)}
5228
+ SELECT * FROM ${tableRef(sql2, name2)}
4963
5229
  WHERE id = ${parseInt(ctx.params.id, 10)} AND tenant_id = ${ctx.tenant.id}
4964
5230
  LIMIT 1
4965
5231
  `;
@@ -4967,7 +5233,7 @@ function buildRouter(sql2, usersTable) {
4967
5233
  }
4968
5234
  const name = internalName(ctx);
4969
5235
  const [row] = await sql2`
4970
- UPDATE ${sql2(name)} SET ${sql2(parsed)}
5236
+ UPDATE ${tableRef(sql2, name)} SET ${sql2(parsed)}
4971
5237
  WHERE id = ${parseInt(ctx.params.id, 10)} AND tenant_id = ${ctx.tenant.id}
4972
5238
  RETURNING *
4973
5239
  `;
@@ -4977,7 +5243,7 @@ function buildRouter(sql2, usersTable) {
4977
5243
  r.delete("/:_slug/:id", async (_req, ctx) => {
4978
5244
  const name = internalName(ctx);
4979
5245
  const result = await sql2`
4980
- DELETE FROM ${sql2(name)}
5246
+ DELETE FROM ${tableRef(sql2, name)}
4981
5247
  WHERE id = ${parseInt(ctx.params.id, 10)} AND tenant_id = ${ctx.tenant.id}
4982
5248
  RETURNING 1
4983
5249
  `;
@@ -4996,7 +5262,10 @@ function buildRouter(sql2, usersTable) {
4996
5262
  if (!childTable) return Response.json({ error: "Nested table not found" }, { status: 404 });
4997
5263
  const relField = findRelation(childTable.fields, ctx.params["_slug"]);
4998
5264
  if (!relField) {
4999
- return Response.json({ error: `No relation from "${nestedSlug}" to "${ctx.params["_slug"]}"` }, { status: 400 });
5265
+ return Response.json(
5266
+ { error: `No relation from "${nestedSlug}" to "${ctx.params["_slug"]}"` },
5267
+ { status: 400 }
5268
+ );
5000
5269
  }
5001
5270
  const relFields = getRelationFields(childTable.fields);
5002
5271
  if (relFields.length === 2) {
@@ -5018,7 +5287,7 @@ function buildRouter(sql2, usersTable) {
5018
5287
  [parentId2, ctx.tenant.id]
5019
5288
  )
5020
5289
  ]);
5021
- return Response.json({ rows, count: Number(countResult[0]?.count ?? 0) });
5290
+ return Response.json({ rows, count: extractCount(countResult) });
5022
5291
  }
5023
5292
  return Response.json({ error: "POST not supported on M2M nested routes" }, { status: 400 });
5024
5293
  }
@@ -5035,7 +5304,7 @@ function buildRouter(sql2, usersTable) {
5035
5304
  [parentId, ctx.tenant.id]
5036
5305
  )
5037
5306
  ]);
5038
- return Response.json({ rows, count: Number(countResult[0]?.count ?? 0) });
5307
+ return Response.json({ rows, count: extractCount(countResult) });
5039
5308
  }
5040
5309
  const body = await req.json();
5041
5310
  const shape = {};
@@ -5047,7 +5316,7 @@ function buildRouter(sql2, usersTable) {
5047
5316
  parsed.tenant_id = ctx.tenant.id;
5048
5317
  parsed[relField.name] = parentId;
5049
5318
  delete parsed.id;
5050
- const [row] = await sql2`INSERT INTO ${sql2(childName)} ${sql2(parsed)} RETURNING *`;
5319
+ const [row] = await sql2`INSERT INTO ${tableRef(sql2, childName)} ${sql2(parsed)} RETURNING *`;
5051
5320
  return Response.json(row, { status: 201 });
5052
5321
  }
5053
5322
  r.get("/:_slug/:id/:_nested", async (req, ctx) => handleNested(req, ctx, "GET"));
@@ -5067,11 +5336,11 @@ import {
5067
5336
  GraphQLID,
5068
5337
  GraphQLList,
5069
5338
  GraphQLNonNull,
5070
- GraphQLEnumType
5339
+ GraphQLEnumType,
5340
+ graphql as executeGraphQL2
5071
5341
  } from "graphql";
5072
- import { graphql as executeGraphQL2 } from "graphql";
5073
5342
  function graphqlType(field, required) {
5074
- let t;
5343
+ let t = GraphQLString;
5075
5344
  switch (field.type) {
5076
5345
  case "integer":
5077
5346
  t = GraphQLInt;
@@ -5088,15 +5357,11 @@ function graphqlType(field, required) {
5088
5357
  name: `Enum_${field.name}`,
5089
5358
  values: Object.fromEntries(field.options.map((o) => [o, { value: o }]))
5090
5359
  });
5091
- } else {
5092
- t = GraphQLString;
5093
5360
  }
5094
5361
  break;
5095
5362
  case "vector":
5096
5363
  t = GraphQLString;
5097
5364
  break;
5098
- default:
5099
- t = GraphQLString;
5100
5365
  }
5101
5366
  return required ? new GraphQLNonNull(t) : t;
5102
5367
  }
@@ -5117,13 +5382,13 @@ function buildObjectType(table, ctx) {
5117
5382
  if (other.id === table.id) continue;
5118
5383
  const relField = findRelation(other.fields, table.slug);
5119
5384
  if (relField) {
5120
- const otherName = pascalCase(other.slug);
5121
5385
  fields[other.slug] = {
5122
5386
  type: new GraphQLList(new GraphQLNonNull(buildObjectType(other, ctx))),
5123
5387
  args: {
5124
5388
  limit: { type: GraphQLInt, defaultValue: 20 },
5125
5389
  offset: { type: GraphQLInt, defaultValue: 0 }
5126
5390
  },
5391
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5127
5392
  resolve: async (parent) => {
5128
5393
  const childName = internalTableName(ctx.tenantId, other.slug);
5129
5394
  const rows = await ctx.sql.unsafe(
@@ -5146,6 +5411,7 @@ function buildObjectType(table, ctx) {
5146
5411
  limit: { type: GraphQLInt, defaultValue: 20 },
5147
5412
  offset: { type: GraphQLInt, defaultValue: 0 }
5148
5413
  },
5414
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5149
5415
  resolve: async (parent) => {
5150
5416
  const childName = internalTableName(ctx.tenantId, other.slug);
5151
5417
  const targetName = internalTableName(ctx.tenantId, targetSlug);
@@ -5167,6 +5433,7 @@ function buildObjectType(table, ctx) {
5167
5433
  if (!targetTable) continue;
5168
5434
  fields[targetSlug] = {
5169
5435
  type: buildObjectType(targetTable, ctx),
5436
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5170
5437
  resolve: async (parent) => {
5171
5438
  const name = internalTableName(ctx.tenantId, targetSlug);
5172
5439
  const [row] = await ctx.sql.unsafe(
@@ -5187,9 +5454,7 @@ function buildInputType(table, prefix) {
5187
5454
  const typeName = pascalCase(`${prefix}_${table.slug}`) + "Input";
5188
5455
  return new GraphQLInputObjectType({
5189
5456
  name: typeName,
5190
- fields: Object.fromEntries(
5191
- table.fields.map((f) => [f.name, { type: inputGraphqlType(f) }])
5192
- )
5457
+ fields: Object.fromEntries(table.fields.map((f) => [f.name, { type: inputGraphqlType(f) }]))
5193
5458
  });
5194
5459
  }
5195
5460
  function buildQueryFields(tables, ctx) {
@@ -5204,6 +5469,7 @@ function buildQueryFields(tables, ctx) {
5204
5469
  limit: { type: GraphQLInt, defaultValue: 20 },
5205
5470
  offset: { type: GraphQLInt, defaultValue: 0 }
5206
5471
  },
5472
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5207
5473
  resolve: async (_, args) => {
5208
5474
  const name = internalTableName(ctx.tenantId, slug);
5209
5475
  const rows = await ctx.sql.unsafe(
@@ -5216,6 +5482,7 @@ function buildQueryFields(tables, ctx) {
5216
5482
  fields[`get${pascal}`] = {
5217
5483
  type: objType,
5218
5484
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
5485
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5219
5486
  resolve: async (_, args) => {
5220
5487
  const name = internalTableName(ctx.tenantId, slug);
5221
5488
  const [row] = await ctx.sql.unsafe(
@@ -5238,6 +5505,7 @@ function buildMutationFields(tables, ctx) {
5238
5505
  fields[`create${pascal}`] = {
5239
5506
  type: objType,
5240
5507
  args: { data: { type: new GraphQLNonNull(inputType) } },
5508
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5241
5509
  resolve: async (_, args) => {
5242
5510
  const name = internalTableName(ctx.tenantId, table.slug);
5243
5511
  const data = { ...args.data, tenant_id: ctx.tenantId };
@@ -5254,6 +5522,7 @@ function buildMutationFields(tables, ctx) {
5254
5522
  id: { type: new GraphQLNonNull(GraphQLID) },
5255
5523
  data: { type: new GraphQLNonNull(patchType) }
5256
5524
  },
5525
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5257
5526
  resolve: async (_, args) => {
5258
5527
  const name = internalTableName(ctx.tenantId, table.slug);
5259
5528
  const setClauses = table.fields.filter((f) => args.data[f.name] !== void 0).map((f, i) => `"${f.name}" = $${i + 1}`);
@@ -5276,6 +5545,7 @@ function buildMutationFields(tables, ctx) {
5276
5545
  fields[`delete${pascal}`] = {
5277
5546
  type: GraphQLBoolean,
5278
5547
  args: { id: { type: new GraphQLNonNull(GraphQLID) } },
5548
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5279
5549
  resolve: async (_, args) => {
5280
5550
  const name = internalTableName(ctx.tenantId, table.slug);
5281
5551
  const result = await ctx.sql.unsafe(
@@ -5386,7 +5656,9 @@ function tenant(options) {
5386
5656
  });
5387
5657
  await members.create();
5388
5658
  await members.createIndex("user_id");
5389
- await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_tenant_members_unique_idx" ON "_tenant_members" ("tenant_id", "user_id")`);
5659
+ await sql2.unsafe(
5660
+ `CREATE UNIQUE INDEX IF NOT EXISTS "_tenant_members_unique_idx" ON "_tenant_members" ("tenant_id", "user_id")`
5661
+ );
5390
5662
  const tables = pg.table("_user_tables", {
5391
5663
  id: serial("id").primaryKey(),
5392
5664
  tenant_id: text("tenant_id").notNull().references("_tenants", "id", "cascade"),
@@ -5397,7 +5669,9 @@ function tenant(options) {
5397
5669
  });
5398
5670
  await tables.create();
5399
5671
  await tables.createIndex("tenant_id");
5400
- await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_user_tables_unique_idx" ON "_user_tables" ("tenant_id", "slug")`);
5672
+ await sql2.unsafe(
5673
+ `CREATE UNIQUE INDEX IF NOT EXISTS "_user_tables_unique_idx" ON "_user_tables" ("tenant_id", "slug")`
5674
+ );
5401
5675
  }
5402
5676
  function middleware() {
5403
5677
  return async (req, ctx, next) => {
@@ -5421,10 +5695,13 @@ function tenant(options) {
5421
5695
  }
5422
5696
  const headerId = req.headers.get("X-Tenant-ID");
5423
5697
  if (!headerId) {
5424
- return Response.json({
5425
- error: "Multiple tenants. Set X-Tenant-ID header.",
5426
- tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
5427
- }, { status: 300 });
5698
+ return Response.json(
5699
+ {
5700
+ error: "Multiple tenants. Set X-Tenant-ID header.",
5701
+ tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
5702
+ },
5703
+ { status: 300 }
5704
+ );
5428
5705
  }
5429
5706
  const member = members.find((m) => m.id === headerId);
5430
5707
  if (!member) {
@@ -5465,7 +5742,9 @@ function buildRouter2(deps) {
5465
5742
  return Response.json(row, { status: 201 });
5466
5743
  });
5467
5744
  r.get("/agents", async () => {
5468
- const { data: rows } = await agentsTable.readMany(void 0, { orderBy: { created_at: "desc" } });
5745
+ const { data: rows } = await agentsTable.readMany(void 0, {
5746
+ orderBy: { created_at: "desc" }
5747
+ });
5469
5748
  return Response.json(rows);
5470
5749
  });
5471
5750
  r.get("/agents/:id", async (_req, ctx) => {
@@ -5479,7 +5758,14 @@ function buildRouter2(deps) {
5479
5758
  if (!agent2) return Response.json({ error: "Agent not found" }, { status: 404 });
5480
5759
  const body = await req.json();
5481
5760
  const updateData = {};
5482
- for (const key of ["name", "description", "type", "model", "system_prompt", "active"]) {
5761
+ for (const key of [
5762
+ "name",
5763
+ "description",
5764
+ "type",
5765
+ "model",
5766
+ "system_prompt",
5767
+ "active"
5768
+ ]) {
5483
5769
  if (body[key] !== void 0) {
5484
5770
  updateData[key] = body[key];
5485
5771
  }
@@ -5616,7 +5902,9 @@ function chunkContent(content, chunkSize, overlap) {
5616
5902
 
5617
5903
  // agent/run.ts
5618
5904
  function hasKnowledgeDocs(sql2, agentId) {
5619
- return sql2`SELECT 1 FROM "_knowledge_documents" WHERE agent_id = ${agentId} LIMIT 1`.then((r) => r.length > 0);
5905
+ return sql2`SELECT 1 FROM "_knowledge_documents" WHERE agent_id = ${agentId} LIMIT 1`.then(
5906
+ (r) => r.length > 0
5907
+ );
5620
5908
  }
5621
5909
  async function searchKnowledge(sql2, provider, agentId, query, limit = 5) {
5622
5910
  const embedding = await provider.embed(query);
@@ -5632,7 +5920,7 @@ async function loadAgent(agents, agentId) {
5632
5920
  return row ?? null;
5633
5921
  }
5634
5922
  function createRunner(deps) {
5635
- const { sql: sql2, agents, runs, provider, modelName, userTools } = deps;
5923
+ const { sql: sql2, agents, runs, provider, userTools } = deps;
5636
5924
  function truncate(s, max = 200) {
5637
5925
  return s.length > max ? s.slice(0, max) + "..." : s;
5638
5926
  }
@@ -5790,7 +6078,14 @@ function agent(options) {
5790
6078
  trace_id: text("trace_id"),
5791
6079
  created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
5792
6080
  });
5793
- const runner = createRunner({ sql: sql2, agents: agentsTable, runs: runsTable, knowledge: knowledgeTable, provider: resolvedProvider, userTools: options.tools });
6081
+ const runner = createRunner({
6082
+ sql: sql2,
6083
+ agents: agentsTable,
6084
+ runs: runsTable,
6085
+ knowledge: knowledgeTable,
6086
+ provider: resolvedProvider,
6087
+ userTools: options.tools
6088
+ });
5794
6089
  const base = new PgModule(pg);
5795
6090
  const r = buildRouter2({ agents: agentsTable, runs: runsTable, knowledge: knowledgeTable, runner });
5796
6091
  const mod = r;
@@ -5942,32 +6237,32 @@ function createWSHandler(deps) {
5942
6237
  prefix: "messager:"
5943
6238
  });
5944
6239
  const userConnections = /* @__PURE__ */ new Map();
5945
- function trackConnection(userId, ws) {
5946
- let conns = userConnections.get(userId);
6240
+ function trackConnection(userId2, ws) {
6241
+ let conns = userConnections.get(userId2);
5947
6242
  if (!conns) {
5948
6243
  conns = /* @__PURE__ */ new Set();
5949
- userConnections.set(userId, conns);
6244
+ userConnections.set(userId2, conns);
5950
6245
  }
5951
6246
  conns.add(ws);
5952
6247
  }
5953
6248
  function untrackConnection(ws) {
5954
- for (const [userId, conns] of userConnections) {
6249
+ for (const [userId2, conns] of userConnections) {
5955
6250
  conns.delete(ws);
5956
- if (conns.size === 0) userConnections.delete(userId);
6251
+ if (conns.size === 0) userConnections.delete(userId2);
5957
6252
  }
5958
6253
  }
5959
6254
  return {
5960
6255
  handler: {
5961
6256
  open(ws, ctx) {
5962
- const userId = ctx.user?.id;
5963
- if (!userId) {
6257
+ const userId2 = ctx.user?.id;
6258
+ if (!userId2) {
5964
6259
  ws.close(4001, "Unauthorized");
5965
6260
  return;
5966
6261
  }
5967
6262
  },
5968
6263
  async message(ws, ctx, data) {
5969
- const userId = ctx.user?.id;
5970
- if (!userId) return;
6264
+ const userId2 = ctx.user?.id;
6265
+ if (!userId2) return;
5971
6266
  let msg;
5972
6267
  try {
5973
6268
  msg = JSON.parse(data.toString());
@@ -5981,12 +6276,12 @@ function createWSHandler(deps) {
5981
6276
  if (!content || !channel_id) return;
5982
6277
  const [row] = await sql2`
5983
6278
  INSERT INTO "_messages" ("channel_id", "sender_id", "sender_type", "content")
5984
- VALUES (${channel_id}, ${userId}, 'user', ${content})
6279
+ VALUES (${channel_id}, ${userId2}, 'user', ${content})
5985
6280
  RETURNING *
5986
6281
  `;
5987
6282
  const message = row;
5988
6283
  hub.join(`messager:${channel_id}`, ws);
5989
- trackConnection(userId, ws);
6284
+ trackConnection(userId2, ws);
5990
6285
  broadcastToChannel(hub, channel_id, { type: "message", data: message });
5991
6286
  if (agents) {
5992
6287
  const insertMsg = (data2) => sql2`
@@ -6005,7 +6300,7 @@ function createWSHandler(deps) {
6005
6300
  broadcastToChannel(hub, channel_id, {
6006
6301
  type: "typing",
6007
6302
  channel_id,
6008
- user_id: userId,
6303
+ user_id: userId2,
6009
6304
  is_typing: is_typing ?? false
6010
6305
  });
6011
6306
  break;
@@ -6016,12 +6311,12 @@ function createWSHandler(deps) {
6016
6311
  await sql2`
6017
6312
  UPDATE "_channel_members"
6018
6313
  SET last_read_id = ${last_message_id}, last_read_at = NOW()
6019
- WHERE channel_id = ${channel_id} AND member_id = ${userId} AND member_type = 'user'
6314
+ WHERE channel_id = ${channel_id} AND member_id = ${userId2} AND member_type = 'user'
6020
6315
  `;
6021
6316
  broadcastToChannel(hub, channel_id, {
6022
6317
  type: "read",
6023
6318
  channel_id,
6024
- user_id: userId,
6319
+ user_id: userId2,
6025
6320
  last_message_id
6026
6321
  });
6027
6322
  break;
@@ -6075,7 +6370,7 @@ function buildRouter3(deps) {
6075
6370
  return Response.json(channel, { status: 201 });
6076
6371
  });
6077
6372
  r.get("/channels", async (_req, ctx) => {
6078
- const userId = ctx.user?.id ?? 1;
6373
+ const userId2 = ctx.user?.id ?? 1;
6079
6374
  const rows = await sql2`
6080
6375
  SELECT c.*, (
6081
6376
  SELECT content FROM "_messages"
@@ -6084,7 +6379,7 @@ function buildRouter3(deps) {
6084
6379
  ) AS last_message
6085
6380
  FROM "_channels" c
6086
6381
  JOIN "_channel_members" m ON m.channel_id = c.id
6087
- WHERE m.member_id = ${userId} AND m.member_type = 'user'
6382
+ WHERE m.member_id = ${userId2} AND m.member_type = 'user'
6088
6383
  ORDER BY c.created_at DESC
6089
6384
  `;
6090
6385
  return Response.json(rows);
@@ -6157,9 +6452,9 @@ function buildRouter3(deps) {
6157
6452
  r.post("/channels/:id/read", async (req, ctx) => {
6158
6453
  const channelId = parseInt(ctx.params.id, 10);
6159
6454
  const body = await req.json();
6160
- const userId = body.user_id ?? ctx.user?.id ?? 1;
6455
+ const userId2 = body.user_id ?? ctx.user?.id ?? 1;
6161
6456
  await members.updateMany(
6162
- [eq("channel_id", channelId), eq("member_id", userId), eq("member_type", "user")],
6457
+ [eq("channel_id", channelId), eq("member_id", userId2), eq("member_type", "user")],
6163
6458
  { last_read_id: body.last_message_id }
6164
6459
  );
6165
6460
  return Response.json({ ok: true });
@@ -6559,12 +6854,24 @@ async function deploy(config) {
6559
6854
  if (ac.ports && old?.process) {
6560
6855
  targetPort = old.currentPort === ac.ports[0] ? ac.ports[1] : ac.ports[0];
6561
6856
  }
6562
- const mp = await forkAndCheck(name, appDir, ac.entry, targetPort, ac.env, log, ac.healthEndpoint);
6857
+ const mp = await forkAndCheck(
6858
+ name,
6859
+ appDir,
6860
+ ac.entry,
6861
+ targetPort,
6862
+ ac.env,
6863
+ log,
6864
+ ac.healthEndpoint
6865
+ );
6563
6866
  if (!mp) {
6564
6867
  log("[deploy] new process failed to start, keeping old running");
6565
6868
  if (old?.process) apps.set(name, old);
6566
6869
  else {
6567
- setAppRuntime(name, ac, logs, { status: "error", port: targetPort, error: "failed to start" });
6870
+ setAppRuntime(name, ac, logs, {
6871
+ status: "error",
6872
+ port: targetPort,
6873
+ error: "failed to start"
6874
+ });
6568
6875
  }
6569
6876
  return;
6570
6877
  }
@@ -6607,7 +6914,7 @@ async function deploy(config) {
6607
6914
  function setAppRuntime(name, ac, logs, overrides) {
6608
6915
  apps.set(name, {
6609
6916
  config: ac,
6610
- status: { name, ...overrides },
6917
+ status: { name, status: "starting", port: 0, ...overrides },
6611
6918
  logs,
6612
6919
  process: null,
6613
6920
  currentPort: overrides.port ?? ac.port ?? 0,
@@ -6808,7 +7115,7 @@ async function compileVendorBundle() {
6808
7115
  if (vendorBundle) return vendorBundle;
6809
7116
  if (!_userRequire) _userRequire = createRequire(join2(process.cwd(), "package.json"));
6810
7117
  const modules = {
6811
- "react": [],
7118
+ react: [],
6812
7119
  "react-dom": ["react"],
6813
7120
  "react-dom/client": ["react"],
6814
7121
  "react/jsx-runtime": ["react"]
@@ -6845,10 +7152,12 @@ async function compileVendorBundle() {
6845
7152
  const stmts = [""];
6846
7153
  for (const [request, keys] of Object.entries(modules)) {
6847
7154
  const unique = keys.filter((k) => !used.has(k) && used.add(k));
6848
- if (unique.length > 0) stmts.push(`export { ${unique.join(", ")} } from ${JSON.stringify(request)};`);
7155
+ if (unique.length > 0)
7156
+ stmts.push(`export { ${unique.join(", ")} } from ${JSON.stringify(request)};`);
6849
7157
  }
6850
7158
  const uidWfw = wfwKeys.filter((k) => !used.has(k) && used.add(k));
6851
- if (uidWfw.length > 0) stmts.push(`export { ${uidWfw.join(", ")} } from ${JSON.stringify(reactAbsPath)};`);
7159
+ if (uidWfw.length > 0)
7160
+ stmts.push(`export { ${uidWfw.join(", ")} } from ${JSON.stringify(reactAbsPath)};`);
6852
7161
  const result = await esbuild.build({
6853
7162
  stdin: { contents: stmts.join("\n"), resolveDir: process.cwd() },
6854
7163
  format: "esm",
@@ -6891,7 +7200,14 @@ async function compileBrowser(path2, outDir) {
6891
7200
  jsx: "automatic",
6892
7201
  jsxImportSource: "react",
6893
7202
  bundle: true,
6894
- external: ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "weifuwu", "weifuwu/react"],
7203
+ external: [
7204
+ "react",
7205
+ "react-dom",
7206
+ "react-dom/client",
7207
+ "react/jsx-runtime",
7208
+ "weifuwu",
7209
+ "weifuwu/react"
7210
+ ],
6895
7211
  plugins: [plugin],
6896
7212
  write: true,
6897
7213
  allowOverwrite: true
@@ -6925,7 +7241,14 @@ async function compileHotComponent(path2) {
6925
7241
  jsx: "automatic",
6926
7242
  jsxImportSource: "react",
6927
7243
  bundle: true,
6928
- external: ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "weifuwu", "weifuwu/react"],
7244
+ external: [
7245
+ "react",
7246
+ "react-dom",
7247
+ "react-dom/client",
7248
+ "react/jsx-runtime",
7249
+ "weifuwu",
7250
+ "weifuwu/react"
7251
+ ],
6929
7252
  plugins: [plugin],
6930
7253
  write: false
6931
7254
  });
@@ -7129,7 +7452,7 @@ function tailwindRouter(dir) {
7129
7452
  const cssDir = resolve4(dir);
7130
7453
  const cssPath = join3(cssDir, "app", "globals.css");
7131
7454
  const r = new Router();
7132
- r.get("/__wfw/style/:hash.css", async (req, ctx) => {
7455
+ r.get("/__wfw/style/:hash.css", async (_req, _ctx) => {
7133
7456
  if (!cssCache.has(cssPath)) {
7134
7457
  await compileTailwindCss(cssPath, cssDir);
7135
7458
  }
@@ -7213,7 +7536,7 @@ function liveWs() {
7213
7536
  }
7214
7537
  };
7215
7538
  }
7216
- function liveRouter(dir) {
7539
+ function liveRouter(_dir) {
7217
7540
  const r = new Router();
7218
7541
  compileVendorBundle().catch(() => {
7219
7542
  });
@@ -7349,8 +7672,9 @@ function errorBoundary(errorPath) {
7349
7672
  const mod = await compile(errorPath);
7350
7673
  const ErrorComponent = mod.default;
7351
7674
  if (!ErrorComponent) throw err;
7352
- const layouts = (ctx.layoutStack || []).map((l) => l.component);
7353
- const base = (ctx.mountPath || "").replace(/\/$/, "");
7675
+ const ctx2 = ctx;
7676
+ const layouts = (ctx2.layoutStack || []).map((l) => l.component);
7677
+ const base = (ctx2.mountPath || "").replace(/\/$/, "");
7354
7678
  let element = createElement2(ErrorComponent, {
7355
7679
  error: err instanceof Error ? err : new Error(String(err)),
7356
7680
  reset: () => {
@@ -7360,10 +7684,10 @@ function errorBoundary(errorPath) {
7360
7684
  const { renderToReadableStream } = await import("react-dom/server");
7361
7685
  const stream = await renderToReadableStream(element);
7362
7686
  return streamResponse(stream, {
7363
- ctx,
7687
+ ctx: ctx2,
7364
7688
  base,
7365
7689
  isDev: isDev(),
7366
- tailwind: ctx.tailwind,
7690
+ tailwind: ctx2.tailwind,
7367
7691
  status: 500
7368
7692
  });
7369
7693
  }
@@ -7484,7 +7808,13 @@ async function resolveRoute(ssrDir, segments, routeCache) {
7484
7808
  if (d === appDir) break;
7485
7809
  d = dirname3(d);
7486
7810
  }
7487
- const result = { routePath: "/" + routeParams.join("/"), pageFile, layoutFiles, errorFiles, notFoundFile };
7811
+ const result = {
7812
+ routePath: "/" + routeParams.join("/"),
7813
+ pageFile,
7814
+ layoutFiles,
7815
+ errorFiles,
7816
+ notFoundFile
7817
+ };
7488
7818
  routeCache.set(cacheKey, result);
7489
7819
  return result;
7490
7820
  }
@@ -7541,7 +7871,6 @@ function renderPage(pageFile, outDir) {
7541
7871
  const absPath = resolve6(pageFile);
7542
7872
  const entryId = hashId(absPath);
7543
7873
  ssrEntries.set(entryId, { path: absPath });
7544
- const bundleKey = `/__ssr/${entryId}.js`;
7545
7874
  return async (req, ctx) => {
7546
7875
  let pageMod;
7547
7876
  try {
@@ -7555,7 +7884,6 @@ function renderPage(pageFile, outDir) {
7555
7884
  if (!Component) return errorPage("Missing default export", pageFile);
7556
7885
  const layouts = ctx.layoutStack || [];
7557
7886
  const layoutComponents = layouts.map((l) => l.component);
7558
- const layoutPaths = layouts.map((l) => l.path);
7559
7887
  const base = (ctx.mountPath || "").replace(/\/$/, "");
7560
7888
  const loaderData = serializeLoaderData(ctx);
7561
7889
  const ctxValue = {
@@ -7575,22 +7903,22 @@ function renderPage(pageFile, outDir) {
7575
7903
  let element = createElement3(
7576
7904
  "div",
7577
7905
  { id: "__weifuwu_root" },
7578
- createElement3(
7579
- TsxContext.Provider,
7580
- { value: ctxValue },
7581
- createElement3(Component, null)
7582
- )
7906
+ createElement3(TsxContext.Provider, { value: ctxValue }, createElement3(Component, null))
7583
7907
  );
7584
7908
  element = buildHtmlShell("weifuwu", element, layoutComponents);
7585
7909
  const { renderToReadableStream } = await import("react-dom/server");
7586
7910
  const stream = await renderToReadableStream(element);
7587
- return streamResponse(stream, {
7588
- ctx,
7589
- base,
7590
- isDev: isDev2,
7591
- loaderData,
7592
- tailwind: ctx.tailwind
7593
- }, buildHydrationScript(entryId, JSON.stringify(ctxValue), base));
7911
+ return streamResponse(
7912
+ stream,
7913
+ {
7914
+ ctx,
7915
+ base,
7916
+ isDev: isDev2,
7917
+ loaderData,
7918
+ tailwind: ctx.tailwind
7919
+ },
7920
+ buildHydrationScript(entryId, JSON.stringify(ctxValue), base)
7921
+ );
7594
7922
  });
7595
7923
  };
7596
7924
  }
@@ -7674,13 +8002,16 @@ function ssr(opts) {
7674
8002
  if (!resolved) {
7675
8003
  if (isDev2) {
7676
8004
  const pages = discoverRoutes(dir).map((p) => p.path).sort();
7677
- return Response.json({
7678
- error: "Not Found",
7679
- path: "/" + segments.join("/"),
7680
- method: req.method,
7681
- hint: "Available SSR pages",
7682
- pages
7683
- }, { status: 404 });
8005
+ return Response.json(
8006
+ {
8007
+ error: "Not Found",
8008
+ path: "/" + segments.join("/"),
8009
+ method: req.method,
8010
+ hint: "Available SSR pages",
8011
+ pages
8012
+ },
8013
+ { status: 404 }
8014
+ );
7684
8015
  }
7685
8016
  return new Response("Not Found", { status: 404 });
7686
8017
  }
@@ -7743,10 +8074,14 @@ async function getSession(sql2, id2) {
7743
8074
  const { data: rows } = await sessions.readMany(sql2, { id: id2, active: true });
7744
8075
  return rows[0] ?? null;
7745
8076
  }
7746
- async function listSessions(sql2, userId) {
8077
+ async function listSessions(sql2, userId2) {
7747
8078
  const opts = { orderBy: { updated_at: "desc" } };
7748
- if (userId !== void 0) {
7749
- const { data: rows2 } = await sessions.readMany(sql2, { user_id: userId, active: true }, opts);
8079
+ if (userId2 !== void 0) {
8080
+ const { data: rows2 } = await sessions.readMany(
8081
+ sql2,
8082
+ { user_id: userId2, active: true },
8083
+ opts
8084
+ );
7750
8085
  return rows2;
7751
8086
  }
7752
8087
  const { data: rows } = await sessions.readMany(sql2, { active: true }, opts);
@@ -7825,7 +8160,14 @@ async function* executeGenerator(opts) {
7825
8160
  totalTokens: result2.usage?.totalTokens ?? 0
7826
8161
  };
7827
8162
  try {
7828
- await addTextMessage(sql2, sessionId, "assistant", currentAssistantText, currentUsage.promptTokens, currentUsage.completionTokens);
8163
+ await addTextMessage(
8164
+ sql2,
8165
+ sessionId,
8166
+ "assistant",
8167
+ currentAssistantText,
8168
+ currentUsage.promptTokens,
8169
+ currentUsage.completionTokens
8170
+ );
7829
8171
  } catch (e) {
7830
8172
  console.error("[opencode] save message failed:", e);
7831
8173
  }
@@ -7868,11 +8210,7 @@ var DENIED_COMMANDS = [
7868
8210
  /^:\(\)\{.*\}:;$/,
7869
8211
  /^fork\s+bomb/i
7870
8212
  ];
7871
- var DENIED_PATHS = [
7872
- /\/\.env$/,
7873
- /\/\.env\.\w+$/,
7874
- /\/node_modules\//
7875
- ];
8213
+ var DENIED_PATHS = [/\/\.env$/, /\/\.env\.\w+$/, /\/node_modules\//];
7876
8214
  function isCommandAllowed(command) {
7877
8215
  const trimmed = command.trim();
7878
8216
  for (const re of DENIED_COMMANDS) {
@@ -7880,7 +8218,7 @@ function isCommandAllowed(command) {
7880
8218
  }
7881
8219
  return true;
7882
8220
  }
7883
- function isPathAllowed(resolvedPath, workspace, perms) {
8221
+ function isPathAllowed(resolvedPath, workspace, _perms) {
7884
8222
  if (!resolvedPath.startsWith(workspace)) return false;
7885
8223
  for (const re of DENIED_PATHS) {
7886
8224
  if (re.test(resolvedPath)) return false;
@@ -7935,16 +8273,20 @@ function createBashTool(ctx) {
7935
8273
  }
7936
8274
  const cwd = workdir ? `${ctx.workspace}/${workdir}` : ctx.workspace;
7937
8275
  return new Promise((resolve14) => {
7938
- const child = exec(command, { cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
7939
- const truncated = stdout.length > 1e6 || stderr.length > 1e6;
7940
- resolve14({
7941
- stdout: stdout.slice(0, 1e6),
7942
- stderr: stderr.slice(0, 1e6),
7943
- exitCode: error?.code ?? 0,
7944
- signal: error?.signal ?? null,
7945
- truncated
7946
- });
7947
- });
8276
+ const child = exec(
8277
+ command,
8278
+ { cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 },
8279
+ (error, stdout, stderr) => {
8280
+ const truncated = stdout.length > 1e6 || stderr.length > 1e6;
8281
+ resolve14({
8282
+ stdout: stdout.slice(0, 1e6),
8283
+ stderr: stderr.slice(0, 1e6),
8284
+ exitCode: error?.code ?? 0,
8285
+ signal: error?.signal ?? null,
8286
+ truncated
8287
+ });
8288
+ }
8289
+ );
7948
8290
  });
7949
8291
  }
7950
8292
  });
@@ -8051,7 +8393,10 @@ function createEditTool(ctx) {
8051
8393
  }
8052
8394
  const secondIdx = content.indexOf(oldString, firstIdx + 1);
8053
8395
  if (secondIdx !== -1) {
8054
- return { error: "Found multiple matches. Provide more surrounding context in oldString.", replaced: 0 };
8396
+ return {
8397
+ error: "Found multiple matches. Provide more surrounding context in oldString.",
8398
+ replaced: 0
8399
+ };
8055
8400
  }
8056
8401
  const result = content.replace(oldString, newString);
8057
8402
  writeFileSync3(resolved, result, "utf-8");
@@ -8093,7 +8438,11 @@ function createGrepTool(ctx) {
8093
8438
  stdout = execFileSync("grep", args, { timeout: 15e3, maxBuffer: 1024 * 1024 }).toString();
8094
8439
  }
8095
8440
  const lines = stdout.split("\n").filter(Boolean);
8096
- return { matches: lines.length, results: lines.slice(0, 200), truncated: lines.length > 200 };
8441
+ return {
8442
+ matches: lines.length,
8443
+ results: lines.slice(0, 200),
8444
+ truncated: lines.length > 200
8445
+ };
8097
8446
  } catch (e) {
8098
8447
  if (e.status === 1) {
8099
8448
  return { matches: 0, results: [], truncated: false };
@@ -8119,19 +8468,20 @@ function createGlobTool(ctx) {
8119
8468
  execute: async ({ pattern, path: path2 }) => {
8120
8469
  const searchDir = path2 ? resolve11(ctx.workspace, path2) : ctx.workspace;
8121
8470
  try {
8122
- const stdout = execFileSync2("find", [
8123
- searchDir,
8124
- "-name",
8125
- pattern,
8126
- "-not",
8127
- "-path",
8128
- "*/node_modules/*"
8129
- ], {
8130
- timeout: 1e4,
8131
- maxBuffer: 1024 * 1024
8132
- }).toString();
8471
+ const stdout = execFileSync2(
8472
+ "find",
8473
+ [searchDir, "-name", pattern, "-not", "-path", "*/node_modules/*"],
8474
+ {
8475
+ timeout: 1e4,
8476
+ maxBuffer: 1024 * 1024
8477
+ }
8478
+ ).toString();
8133
8479
  const lines = stdout.split("\n").filter(Boolean).slice(0, 200);
8134
- return { files: lines, total: lines.length, truncated: stdout.split("\n").filter(Boolean).length > 200 };
8480
+ return {
8481
+ files: lines,
8482
+ total: lines.length,
8483
+ truncated: stdout.split("\n").filter(Boolean).length > 200
8484
+ };
8135
8485
  } catch {
8136
8486
  return { files: [], total: 0, truncated: false };
8137
8487
  }
@@ -8142,7 +8492,7 @@ function createGlobTool(ctx) {
8142
8492
  // opencode/tools/web.ts
8143
8493
  import { tool as tool9 } from "ai";
8144
8494
  import { z as z11 } from "zod";
8145
- function createWebTool(ctx) {
8495
+ function createWebTool(_ctx) {
8146
8496
  return tool9({
8147
8497
  description: "Fetch a URL and return the content as text.",
8148
8498
  inputSchema: z11.object({
@@ -8271,15 +8621,29 @@ function createTools(ctx) {
8271
8621
 
8272
8622
  // opencode/rest.ts
8273
8623
  async function buildRouter4(deps) {
8274
- const { sql: sql2, model, workspace, systemPrompt, skills, skillsRegistry, permissions: permissions2, pendingQuestions } = deps;
8624
+ const {
8625
+ sql: sql2,
8626
+ model,
8627
+ workspace,
8628
+ systemPrompt,
8629
+ skills,
8630
+ skillsRegistry,
8631
+ permissions: permissions2,
8632
+ pendingQuestions
8633
+ } = deps;
8275
8634
  const router = new Router();
8276
8635
  router.post("/sessions", async (req, ctx) => {
8277
8636
  const body = await req.json().catch(() => ({}));
8278
- const session2 = await createSession(sql2, {
8279
- title: body.title,
8280
- model: body.model,
8281
- systemPrompt: body.systemPrompt || systemPrompt
8282
- }, workspace, ctx.mountPath || "");
8637
+ const session2 = await createSession(
8638
+ sql2,
8639
+ {
8640
+ title: body.title,
8641
+ model: body.model,
8642
+ systemPrompt: body.systemPrompt || systemPrompt
8643
+ },
8644
+ workspace,
8645
+ ctx.mountPath || ""
8646
+ );
8283
8647
  return Response.json(session2, { status: 201 });
8284
8648
  });
8285
8649
  router.get("/sessions", async () => {
@@ -8343,7 +8707,11 @@ async function buildRouter4(deps) {
8343
8707
  FROM "_opencode_messages"
8344
8708
  WHERE session_id = ${sessionId}
8345
8709
  `;
8346
- const stats = rows[0] || { message_count: 0, total_tokens_in: 0, total_tokens_out: 0 };
8710
+ const stats = rows[0] || {
8711
+ message_count: 0,
8712
+ total_tokens_in: 0,
8713
+ total_tokens_out: 0
8714
+ };
8347
8715
  return Response.json({
8348
8716
  session_id: sessionId,
8349
8717
  message_count: stats.message_count,
@@ -8364,12 +8732,21 @@ async function buildRouter4(deps) {
8364
8732
  // opencode/ws.ts
8365
8733
  var clients2 = /* @__PURE__ */ new WeakMap();
8366
8734
  function createWSHandler2(deps) {
8367
- const { sql: sql2, model, workspace, systemPrompt, skills, skillsRegistry, permissions: permissions2, pendingQuestions } = deps;
8735
+ const {
8736
+ sql: sql2,
8737
+ model,
8738
+ workspace,
8739
+ systemPrompt,
8740
+ skills,
8741
+ skillsRegistry,
8742
+ permissions: permissions2,
8743
+ pendingQuestions
8744
+ } = deps;
8368
8745
  return {
8369
8746
  open(ws, ctx) {
8370
- const userId = ctx.user?.id ?? 0;
8747
+ const userId2 = ctx.user?.id ?? 0;
8371
8748
  const mountPath = ctx.mountPath ?? "";
8372
- clients2.set(ws, { userId, mountPath });
8749
+ clients2.set(ws, { userId: userId2, mountPath });
8373
8750
  },
8374
8751
  async message(ws, ctx, data) {
8375
8752
  const client = clients2.get(ws);
@@ -8384,12 +8761,17 @@ function createWSHandler2(deps) {
8384
8761
  switch (msg.type) {
8385
8762
  case "create": {
8386
8763
  try {
8387
- const session2 = await createSession(sql2, {
8388
- userId: client.userId,
8389
- title: msg.title,
8390
- model: msg.model,
8391
- systemPrompt: msg.systemPrompt || systemPrompt
8392
- }, workspace, client.mountPath);
8764
+ const session2 = await createSession(
8765
+ sql2,
8766
+ {
8767
+ userId: client.userId,
8768
+ title: msg.title,
8769
+ model: msg.model,
8770
+ systemPrompt: msg.systemPrompt || systemPrompt
8771
+ },
8772
+ workspace,
8773
+ client.mountPath
8774
+ );
8393
8775
  ws.send(JSON.stringify({ type: "session_created", session: session2 }));
8394
8776
  } catch (e) {
8395
8777
  ws.send(JSON.stringify({ type: "error", error: e.message }));
@@ -8486,8 +8868,7 @@ function createWSHandler2(deps) {
8486
8868
  }
8487
8869
 
8488
8870
  // opencode/skills.ts
8489
- import { readFile } from "node:fs/promises";
8490
- import { glob } from "node:fs/promises";
8871
+ import { readFile, glob } from "node:fs/promises";
8491
8872
  import { homedir } from "node:os";
8492
8873
  import { resolve as resolve12 } from "node:path";
8493
8874
  import { parse as parseYaml } from "yaml";
@@ -8584,7 +8965,16 @@ async function opencode(options) {
8584
8965
  const model = provider.chat(modelName);
8585
8966
  const pendingQuestions = /* @__PURE__ */ new Map();
8586
8967
  const base = new PgModule(pg);
8587
- const r = await buildRouter4({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions: permissions2, pendingQuestions });
8968
+ const r = await buildRouter4({
8969
+ sql: sql2,
8970
+ model,
8971
+ workspace,
8972
+ systemPrompt,
8973
+ skills: manualSkills,
8974
+ skillsRegistry,
8975
+ permissions: permissions2,
8976
+ pendingQuestions
8977
+ });
8588
8978
  const mod = r;
8589
8979
  mod.migrate = async () => {
8590
8980
  const sessions2 = pg.table("_opencode_sessions", {
@@ -8617,7 +9007,16 @@ async function opencode(options) {
8617
9007
  await messages2.create();
8618
9008
  await messages2.createIndex(["session_id", "created_at"]);
8619
9009
  };
8620
- mod.wsHandler = () => createWSHandler2({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions: permissions2, pendingQuestions });
9010
+ mod.wsHandler = () => createWSHandler2({
9011
+ sql: sql2,
9012
+ model,
9013
+ workspace,
9014
+ systemPrompt,
9015
+ skills: manualSkills,
9016
+ skillsRegistry,
9017
+ permissions: permissions2,
9018
+ pendingQuestions
9019
+ });
8621
9020
  mod.close = () => base.close();
8622
9021
  return mod;
8623
9022
  }
@@ -8726,7 +9125,10 @@ var MemStore = class {
8726
9125
  daily,
8727
9126
  top_pages: topPages,
8728
9127
  referrers: [...refMap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10).map(([domain, count]) => ({ domain, count })),
8729
- devices: { mobile: Math.round(totalMobile / total * 1e3) / 10, desktop: Math.round(totalDesktop / total * 1e3) / 10 }
9128
+ devices: {
9129
+ mobile: Math.round(totalMobile / total * 1e3) / 10,
9130
+ desktop: Math.round(totalDesktop / total * 1e3) / 10
9131
+ }
8730
9132
  };
8731
9133
  }
8732
9134
  };
@@ -8779,7 +9181,10 @@ async function queryPg(sql2, days) {
8779
9181
  daily: daily.map((d) => ({ date: d.date, pv: d.pv, uv: d.uv })),
8780
9182
  top_pages: pageRows.map((p) => ({ path: p.path, pv: p.pv })),
8781
9183
  referrers: [],
8782
- devices: { mobile: Math.round(t.total_mobile / denom * 1e3) / 10, desktop: Math.round(t.total_desktop / denom * 1e3) / 10 }
9184
+ devices: {
9185
+ mobile: Math.round(t.total_mobile / denom * 1e3) / 10,
9186
+ desktop: Math.round(t.total_desktop / denom * 1e3) / 10
9187
+ }
8783
9188
  };
8784
9189
  }
8785
9190
  function escapeHtml2(s) {
@@ -8794,9 +9199,7 @@ function renderDashboard(days, data) {
8794
9199
  const rows = top_pages.map(
8795
9200
  (p, i) => `<tr><td class="num">${i + 1}</td><td class="path">${escapeHtml2(p.path)}</td><td class="num">${p.pv}</td></tr>`
8796
9201
  ).join("");
8797
- const refRows = referrers.map(
8798
- (r) => `<tr><td>${escapeHtml2(r.domain)}</td><td class="num">${r.count}</td></tr>`
8799
- ).join("");
9202
+ const refRows = referrers.map((r) => `<tr><td>${escapeHtml2(r.domain)}</td><td class="num">${r.count}</td></tr>`).join("");
8800
9203
  return `<!DOCTYPE html><html lang="en">
8801
9204
  <head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Analytics - weifuwu</title>
8802
9205
  <style>*,:before,:after{box-sizing:border-box;margin:0;padding:0}
@@ -8878,7 +9281,7 @@ function analytics(options) {
8878
9281
  if (pg) await migratePg(pg.sql, pg.table);
8879
9282
  };
8880
9283
  const close = async () => {
8881
- if (store2) store2.stopCleanup();
9284
+ store2?.stopCleanup();
8882
9285
  };
8883
9286
  const mod = r;
8884
9287
  mod.middleware = middleware;
@@ -9003,7 +9406,10 @@ function i18n(options) {
9003
9406
  set: (value, loc) => {
9004
9407
  const cookie = `${opts.cookie}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`;
9005
9408
  const location = loc ?? (req.headers.get("referer") || "/");
9006
- return new Response(null, { status: 302, headers: { Location: location, "Set-Cookie": cookie } });
9409
+ return new Response(null, {
9410
+ status: 302,
9411
+ headers: { Location: location, "Set-Cookie": cookie }
9412
+ });
9007
9413
  }
9008
9414
  };
9009
9415
  return next(req, ctx);
@@ -9022,7 +9428,11 @@ function i18n(options) {
9022
9428
  const accept = req.headers.get("accept") ?? "";
9023
9429
  if (accept.includes("application/json")) {
9024
9430
  return Response.json(
9025
- { ok: true, locale: value, messages: Object.keys(messages2).length > 0 ? messages2 : void 0 },
9431
+ {
9432
+ ok: true,
9433
+ locale: value,
9434
+ messages: Object.keys(messages2).length > 0 ? messages2 : void 0
9435
+ },
9026
9436
  { headers: { "Set-Cookie": cookie } }
9027
9437
  );
9028
9438
  }
@@ -9340,10 +9750,11 @@ function listHandler(entries) {
9340
9750
  if (before) conditions.push(lt("created_at", before));
9341
9751
  const limit = parseInt(url.searchParams.get("limit") ?? "50", 10);
9342
9752
  const offset = parseInt(url.searchParams.get("offset") ?? "0", 10);
9343
- const { count, data } = await entries.readMany(
9344
- conditions.length > 0 ? conditions : void 0,
9345
- { orderBy: { created_at: "desc" }, limit, offset }
9346
- );
9753
+ const { count, data } = await entries.readMany(conditions.length > 0 ? conditions : void 0, {
9754
+ orderBy: { created_at: "desc" },
9755
+ limit,
9756
+ offset
9757
+ });
9347
9758
  return Response.json({ entries: data.map(parseMetadata), total: count });
9348
9759
  };
9349
9760
  }
@@ -9454,12 +9865,15 @@ import crypto8 from "node:crypto";
9454
9865
 
9455
9866
  // iii/stream.ts
9456
9867
  function notify(channels, stream, group, item, event, data) {
9457
- const keys = [
9458
- `${stream}`,
9459
- `${stream}:${group}`,
9460
- `${stream}:${group}:${item}`
9461
- ];
9462
- const msg = JSON.stringify({ type: "stream", stream_name: stream, group_id: group, item_id: item, event, data });
9868
+ const keys = [`${stream}`, `${stream}:${group}`, `${stream}:${group}:${item}`];
9869
+ const msg = JSON.stringify({
9870
+ type: "stream",
9871
+ stream_name: stream,
9872
+ group_id: group,
9873
+ item_id: item,
9874
+ event,
9875
+ data
9876
+ });
9463
9877
  for (const key of keys) {
9464
9878
  const subs = channels.get(key);
9465
9879
  if (!subs) continue;
@@ -9678,10 +10092,13 @@ function createRedisStore(channels, redis2, ttl) {
9678
10092
  async set(stream, group, item, data) {
9679
10093
  const hk = hashKey(stream, group);
9680
10094
  const oldRaw = await redis2.hget(hk, item);
9681
- let old = oldRaw ? JSON.parse(oldRaw) : null;
10095
+ const old = oldRaw ? JSON.parse(oldRaw) : null;
9682
10096
  await redis2.hset(hk, item, JSON.stringify(data));
9683
10097
  setTTL(hk);
9684
- await redis2.publish(`iii:stream:${stream}`, JSON.stringify({ event: "set", group, item, data }));
10098
+ await redis2.publish(
10099
+ `iii:stream:${stream}`,
10100
+ JSON.stringify({ event: "set", group, item, data })
10101
+ );
9685
10102
  notify(channels, stream, group, item, "set", data);
9686
10103
  return { old_value: old, new_value: deepClone(data) };
9687
10104
  },
@@ -9757,7 +10174,10 @@ function createRedisStore(channels, redis2, ttl) {
9757
10174
  const newVal = applyOps(old, ops);
9758
10175
  await redis2.hset(hk, item, JSON.stringify(newVal));
9759
10176
  setTTL(hk);
9760
- await redis2.publish(`iii:stream:${stream}`, JSON.stringify({ event: "update", group, item, data: newVal }));
10177
+ await redis2.publish(
10178
+ `iii:stream:${stream}`,
10179
+ JSON.stringify({ event: "update", group, item, data: newVal })
10180
+ );
9761
10181
  notify(channels, stream, group, item, "update", newVal);
9762
10182
  return { old_value: old, new_value: deepClone(newVal) };
9763
10183
  }
@@ -9837,10 +10257,7 @@ function createWsHandler(deps) {
9837
10257
  }
9838
10258
  switch (msg.type) {
9839
10259
  case "register_worker": {
9840
- const workerId = deps.registerRemoteWorker(
9841
- ws,
9842
- msg.worker_name || `remote-${Date.now()}`
9843
- );
10260
+ const workerId = deps.registerRemoteWorker(ws, msg.worker_name || `remote-${Date.now()}`);
9844
10261
  wsToWorkerId.set(ws, workerId);
9845
10262
  ws.send(JSON.stringify({ type: "registered", worker_id: workerId }));
9846
10263
  break;
@@ -9944,10 +10361,7 @@ function buildRouter5(engine, wsHandler) {
9944
10361
  }
9945
10362
  return Response.json(result);
9946
10363
  } catch (err) {
9947
- return Response.json(
9948
- { error: err.message || "Internal error" },
9949
- { status: 500 }
9950
- );
10364
+ return Response.json({ error: err.message || "Internal error" }, { status: 500 });
9951
10365
  }
9952
10366
  });
9953
10367
  r.ws("/worker", wsHandler);
@@ -9970,14 +10384,23 @@ function iii(opts = {}) {
9970
10384
  triggers: []
9971
10385
  });
9972
10386
  }
9973
- registerBuiltin("stream::set", (p) => stream.set(p.stream_name, p.group_id, p.item_id, p.data));
10387
+ registerBuiltin(
10388
+ "stream::set",
10389
+ (p) => stream.set(p.stream_name, p.group_id, p.item_id, p.data)
10390
+ );
9974
10391
  registerBuiltin("stream::get", (p) => stream.get(p.stream_name, p.group_id, p.item_id));
9975
10392
  registerBuiltin("stream::delete", (p) => stream.delete(p.stream_name, p.group_id, p.item_id));
9976
10393
  registerBuiltin("stream::list", (p) => stream.list(p.stream_name, p.group_id));
9977
10394
  registerBuiltin("stream::list_groups", (p) => stream.list_groups(p.stream_name));
9978
10395
  registerBuiltin("stream::list_all", () => stream.list_all());
9979
- registerBuiltin("stream::send", (p) => stream.send(p.stream_name, p.group_id, p.type, p.data, p.id));
9980
- registerBuiltin("stream::update", (p) => stream.update(p.stream_name, p.group_id, p.item_id, p.ops));
10396
+ registerBuiltin(
10397
+ "stream::send",
10398
+ (p) => stream.send(p.stream_name, p.group_id, p.type, p.data, p.id)
10399
+ );
10400
+ registerBuiltin(
10401
+ "stream::update",
10402
+ (p) => stream.update(p.stream_name, p.group_id, p.item_id, p.ops)
10403
+ );
9981
10404
  function addLocalWorker(worker) {
9982
10405
  const workerId = crypto8.randomUUID();
9983
10406
  const reg = {
@@ -10030,12 +10453,14 @@ function iii(opts = {}) {
10030
10453
  reject(new Error(`Invocation timed out for "${id2}"`));
10031
10454
  }, 3e4);
10032
10455
  pending.set(invocationId, { resolve: resolve14, reject, timer });
10033
- worker.ws.send(JSON.stringify({
10034
- type: "invoke",
10035
- invocation_id: invocationId,
10036
- function_id: id2,
10037
- payload
10038
- }));
10456
+ worker.ws.send(
10457
+ JSON.stringify({
10458
+ type: "invoke",
10459
+ invocation_id: invocationId,
10460
+ function_id: id2,
10461
+ payload
10462
+ })
10463
+ );
10039
10464
  });
10040
10465
  };
10041
10466
  const fnReg = {
@@ -10119,18 +10544,26 @@ function iii(opts = {}) {
10119
10544
  handleInvoke(ws, invocationId, functionId, payload) {
10120
10545
  const fn = functions.get(functionId);
10121
10546
  if (!fn) {
10122
- ws.send(JSON.stringify({
10123
- type: "invoke_error",
10124
- invocation_id: invocationId,
10125
- error: `Function "${functionId}" not found`
10126
- }));
10547
+ ws.send(
10548
+ JSON.stringify({
10549
+ type: "invoke_error",
10550
+ invocation_id: invocationId,
10551
+ error: `Function "${functionId}" not found`
10552
+ })
10553
+ );
10127
10554
  return;
10128
10555
  }
10129
10556
  const ctx = { engine: engineRef, functionId, workerName: fn.workerName };
10130
10557
  Promise.resolve(fn.handler(payload, ctx)).then((result) => {
10131
10558
  ws.send(JSON.stringify({ type: "invoke_result", invocation_id: invocationId, result }));
10132
10559
  }).catch((err) => {
10133
- ws.send(JSON.stringify({ type: "invoke_error", invocation_id: invocationId, error: err.message }));
10560
+ ws.send(
10561
+ JSON.stringify({
10562
+ type: "invoke_error",
10563
+ invocation_id: invocationId,
10564
+ error: err.message
10565
+ })
10566
+ );
10134
10567
  });
10135
10568
  }
10136
10569
  });
@@ -10193,7 +10626,7 @@ function iii(opts = {}) {
10193
10626
  mod.migrate = async () => {
10194
10627
  await stream.migrate();
10195
10628
  };
10196
- mod.shutdown = async () => {
10629
+ mod.close = async () => {
10197
10630
  for (const [, p] of pending) {
10198
10631
  clearTimeout(p.timer);
10199
10632
  p.reject(new Error("Engine shutting down"));
@@ -10205,7 +10638,6 @@ function iii(opts = {}) {
10205
10638
  triggers.clear();
10206
10639
  await stream.close();
10207
10640
  };
10208
- mod.close = mod.shutdown;
10209
10641
  return mod;
10210
10642
  }
10211
10643
 
@@ -10295,25 +10727,31 @@ function registerWorker(url) {
10295
10727
  case "invoke": {
10296
10728
  const handler = handlers.get(msg.function_id);
10297
10729
  if (!handler) {
10298
- ws?.send(JSON.stringify({
10299
- type: "invoke_error",
10300
- invocation_id: msg.invocation_id,
10301
- error: `Function "${msg.function_id}" not found`
10302
- }));
10730
+ ws?.send(
10731
+ JSON.stringify({
10732
+ type: "invoke_error",
10733
+ invocation_id: msg.invocation_id,
10734
+ error: `Function "${msg.function_id}" not found`
10735
+ })
10736
+ );
10303
10737
  return;
10304
10738
  }
10305
10739
  Promise.resolve(handler(msg.payload, {})).then((result) => {
10306
- ws?.send(JSON.stringify({
10307
- type: "invoke_result",
10308
- invocation_id: msg.invocation_id,
10309
- result
10310
- }));
10740
+ ws?.send(
10741
+ JSON.stringify({
10742
+ type: "invoke_result",
10743
+ invocation_id: msg.invocation_id,
10744
+ result
10745
+ })
10746
+ );
10311
10747
  }).catch((err) => {
10312
- ws?.send(JSON.stringify({
10313
- type: "invoke_error",
10314
- invocation_id: msg.invocation_id,
10315
- error: err.message
10316
- }));
10748
+ ws?.send(
10749
+ JSON.stringify({
10750
+ type: "invoke_error",
10751
+ invocation_id: msg.invocation_id,
10752
+ error: err.message
10753
+ })
10754
+ );
10317
10755
  });
10318
10756
  break;
10319
10757
  }
@@ -10367,7 +10805,12 @@ function registerWorker(url) {
10367
10805
  },
10368
10806
  registerTrigger(input) {
10369
10807
  registeredTriggers.add(JSON.stringify(input));
10370
- send({ type: "register_trigger", function_id: input.function_id, trigger_type: input.type, config: input.config });
10808
+ send({
10809
+ type: "register_trigger",
10810
+ function_id: input.function_id,
10811
+ trigger_type: input.type,
10812
+ config: input.config
10813
+ });
10371
10814
  },
10372
10815
  unregisterTrigger(functionId) {
10373
10816
  for (const key of registeredTriggers) {
@@ -10410,7 +10853,7 @@ function registerWorker(url) {
10410
10853
  onStream(handler) {
10411
10854
  handlers.set("__stream__", handler);
10412
10855
  },
10413
- shutdown() {
10856
+ close() {
10414
10857
  intentionalClose = true;
10415
10858
  if (reconnectTimer) clearTimeout(reconnectTimer);
10416
10859
  ws?.close();
@@ -10459,7 +10902,7 @@ var MemoryStore = class {
10459
10902
  if (entry.expires < now) this.store.delete(key);
10460
10903
  }
10461
10904
  }
10462
- close() {
10905
+ async close() {
10463
10906
  clearInterval(this.interval);
10464
10907
  this.store.clear();
10465
10908
  }
@@ -10495,6 +10938,9 @@ var RedisStore = class {
10495
10938
  async destroy(sid) {
10496
10939
  await this.redis.del(this.key(sid));
10497
10940
  }
10941
+ async close() {
10942
+ this.redis.disconnect();
10943
+ }
10498
10944
  };
10499
10945
  var COOKIE_SEPARATOR = ".";
10500
10946
  function signSessionId(sid, secret) {
@@ -10539,8 +10985,18 @@ function createSessionObject(data, sid, store2, ttl, createdAt) {
10539
10985
  enumerable: false,
10540
10986
  configurable: false
10541
10987
  });
10542
- Object.defineProperty(obj, "save", { enumerable: false, configurable: true, writable: true, value: obj.save });
10543
- Object.defineProperty(obj, "destroy", { enumerable: false, configurable: true, writable: true, value: obj.destroy });
10988
+ Object.defineProperty(obj, "save", {
10989
+ enumerable: false,
10990
+ configurable: true,
10991
+ writable: true,
10992
+ value: obj.save
10993
+ });
10994
+ Object.defineProperty(obj, "destroy", {
10995
+ enumerable: false,
10996
+ configurable: true,
10997
+ writable: true,
10998
+ value: obj.destroy
10999
+ });
10544
11000
  return obj;
10545
11001
  }
10546
11002
  function isSessionActive(session2) {
@@ -10568,6 +11024,7 @@ function session(options) {
10568
11024
  } else if (options?.store === "redis") {
10569
11025
  if (!options.redis) throw new Error('session: redis client required when store: "redis"');
10570
11026
  store2 = new RedisStore(options.redis);
11027
+ closeStore = () => store2.close();
10571
11028
  } else {
10572
11029
  const mem = new MemoryStore();
10573
11030
  store2 = mem;
@@ -10647,8 +11104,8 @@ function session(options) {
10647
11104
  }
10648
11105
  return res;
10649
11106
  });
10650
- mw.close = () => {
10651
- closeStore?.();
11107
+ mw.close = async () => {
11108
+ await closeStore?.();
10652
11109
  };
10653
11110
  mw.store = store2;
10654
11111
  return mw;
@@ -10742,7 +11199,7 @@ var MemoryCache = class {
10742
11199
  }
10743
11200
  }
10744
11201
  }
10745
- close() {
11202
+ async close() {
10746
11203
  clearInterval(this.interval);
10747
11204
  this.store.clear();
10748
11205
  this.tagIndex.clear();
@@ -10883,8 +11340,8 @@ function cache2(options) {
10883
11340
  mw.store = store2;
10884
11341
  mw.invalidate = async (tag) => store2.invalidate(tag);
10885
11342
  mw.flush = async () => store2.flush();
10886
- mw.close = () => {
10887
- closeStore?.();
11343
+ mw.close = async () => {
11344
+ await closeStore?.();
10888
11345
  };
10889
11346
  return mw;
10890
11347
  }
@@ -10909,7 +11366,8 @@ function createStripeVerifier(config) {
10909
11366
  }, {});
10910
11367
  const timestamp = parts["t"];
10911
11368
  const signature = parts["v1"];
10912
- if (!timestamp || !signature) return { valid: false, provider: "stripe", event: "", id: void 0 };
11369
+ if (!timestamp || !signature)
11370
+ return { valid: false, provider: "stripe", event: "", id: void 0 };
10913
11371
  const signed = `${timestamp}.${body}`;
10914
11372
  const expected = crypto11.createHmac("sha256", config.secret).update(signed).digest("hex");
10915
11373
  const valid = timingSafeEqual2(signature, expected);
@@ -10930,7 +11388,7 @@ function createGitHubVerifier(config) {
10930
11388
  if (!sig) return { valid: false, provider: "github", event: "", id: void 0 };
10931
11389
  const expected = `sha256=${crypto11.createHmac("sha256", config.secret).update(body).digest("hex")}`;
10932
11390
  const valid = timingSafeEqual2(sig, expected);
10933
- let event = headers["x-github-event"] ?? "";
11391
+ const event = headers["x-github-event"] ?? "";
10934
11392
  let id2;
10935
11393
  try {
10936
11394
  const parsed = JSON.parse(body);
@@ -10944,7 +11402,8 @@ function createSlackVerifier(config) {
10944
11402
  return (body, headers) => {
10945
11403
  const signature = headers["x-slack-signature"];
10946
11404
  const timestamp = headers["x-slack-request-timestamp"];
10947
- if (!signature || !timestamp) return { valid: false, provider: "slack", event: "", id: void 0 };
11405
+ if (!signature || !timestamp)
11406
+ return { valid: false, provider: "slack", event: "", id: void 0 };
10948
11407
  const now = Math.floor(Date.now() / 1e3);
10949
11408
  const ts = parseInt(timestamp, 10);
10950
11409
  if (isNaN(ts) || Math.abs(now - ts) > 300) {
@@ -11106,11 +11565,7 @@ __export(fts_exports, {
11106
11565
  suggest: () => suggest
11107
11566
  });
11108
11567
  function resolveTableName(table) {
11109
- const name = table.inner?.tableName ?? table.tableName;
11110
- if (!name || typeof name !== "string") {
11111
- throw new Error("fts: could not determine table name. Ensure you pass a pg.table() result.");
11112
- }
11113
- return name;
11568
+ return table.tableName;
11114
11569
  }
11115
11570
  function escapeIdent4(s) {
11116
11571
  return `"${s.replace(/"/g, '""')}"`;
@@ -11322,7 +11777,15 @@ function escapeIdent5(s) {
11322
11777
  return `"${s.replace(/"/g, '""')}"`;
11323
11778
  }
11324
11779
  function knowledgeBase(options) {
11325
- const { pg, provider, table = "_kb_docs", chunkSize = 512, chunkOverlap = 64, searchLimit = 5, searchThreshold = 0 } = options;
11780
+ const {
11781
+ pg,
11782
+ provider,
11783
+ table = "_kb_docs",
11784
+ chunkSize = 512,
11785
+ chunkOverlap = 64,
11786
+ searchLimit = 5,
11787
+ searchThreshold = 0
11788
+ } = options;
11326
11789
  const sql2 = pg.sql;
11327
11790
  const dimension = provider.dimension;
11328
11791
  const docsTable = pg.table(table, {
@@ -11468,17 +11931,17 @@ function permissions(options) {
11468
11931
  );
11469
11932
  return created.id;
11470
11933
  }
11471
- async function assignRole(userId, role) {
11934
+ async function assignRole(userId2, role) {
11472
11935
  const roleId = await ensureRole(role);
11473
11936
  await sql2.unsafe(
11474
11937
  `INSERT INTO ${escapeIdent6(userRolesTable)} (user_id, role_id) VALUES ($1, $2) ON CONFLICT DO NOTHING`,
11475
- [userId, roleId]
11938
+ [userId2, roleId]
11476
11939
  );
11477
11940
  }
11478
- async function removeRole(userId, role) {
11941
+ async function removeRole(userId2, role) {
11479
11942
  await sql2.unsafe(
11480
11943
  `DELETE FROM ${escapeIdent6(userRolesTable)} WHERE user_id = $1 AND role_id = (SELECT id FROM ${escapeIdent6(rolesTable)} WHERE name = $2)`,
11481
- [userId, role]
11944
+ [userId2, role]
11482
11945
  );
11483
11946
  }
11484
11947
  async function grantPermission(role, permission) {
@@ -11494,31 +11957,31 @@ function permissions(options) {
11494
11957
  [role, permission]
11495
11958
  );
11496
11959
  }
11497
- async function getUserRoles(userId) {
11960
+ async function getUserRoles(userId2) {
11498
11961
  const rows = await sql2.unsafe(
11499
11962
  `SELECT r.name FROM ${escapeIdent6(userRolesTable)} ur
11500
11963
  JOIN ${escapeIdent6(rolesTable)} r ON r.id = ur.role_id
11501
11964
  WHERE ur.user_id = $1 ORDER BY r.name`,
11502
- [userId]
11965
+ [userId2]
11503
11966
  );
11504
11967
  return rows.map((r) => r.name);
11505
11968
  }
11506
- async function getUserPermissions(userId) {
11969
+ async function getUserPermissions(userId2) {
11507
11970
  const rows = await sql2.unsafe(
11508
11971
  `SELECT DISTINCT rp.permission FROM ${escapeIdent6(userRolesTable)} ur
11509
11972
  JOIN ${escapeIdent6(rolePermsTable)} rp ON rp.role_id = ur.role_id
11510
11973
  WHERE ur.user_id = $1 ORDER BY rp.permission`,
11511
- [userId]
11974
+ [userId2]
11512
11975
  );
11513
11976
  return rows.map((r) => r.permission);
11514
11977
  }
11515
11978
  const mw = (async (req, ctx, next) => {
11516
- const userId = ctx.user?.id;
11979
+ const userId2 = ctx.user?.id;
11517
11980
  let roles = /* @__PURE__ */ new Set();
11518
11981
  let perms = /* @__PURE__ */ new Set();
11519
- if (userId) {
11520
- const userRoles = await getUserRoles(userId);
11521
- const userPerms = userId ? await getUserPermissions(userId) : [];
11982
+ if (userId2) {
11983
+ const userRoles = await getUserRoles(userId2);
11984
+ const userPerms = userId2 ? await getUserPermissions(userId2) : [];
11522
11985
  roles = new Set(userRoles);
11523
11986
  perms = new Set(userPerms);
11524
11987
  const hasWildcard = userPerms.includes("*");