weifuwu 0.18.1 → 0.18.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.
package/dist/index.js CHANGED
@@ -270,6 +270,8 @@ var Router = class _Router {
270
270
  }
271
271
  node.pathMws.push(arg2);
272
272
  }
273
+ } else if (arg1 instanceof _Router) {
274
+ this._mountRouter("/", arg1);
273
275
  } else if (typeof arg1 === "function") {
274
276
  this.globalMws.push(arg1);
275
277
  }
@@ -369,13 +371,13 @@ var Router = class _Router {
369
371
  const mw = match.middlewares[index++];
370
372
  return mw(innerReq, ctx2, dispatch);
371
373
  }
372
- return await new Promise((resolve11) => {
374
+ return await new Promise((resolve12) => {
373
375
  try {
374
376
  upgradeSocket(router.wss, req, socket, head, match.handler, ctx2);
375
- resolve11(new Response(null, { status: 101 }));
377
+ resolve12(new Response(null, { status: 101 }));
376
378
  } catch {
377
379
  socket.destroy();
378
- resolve11(new Response("WebSocket upgrade failed", { status: 500 }));
380
+ resolve12(new Response("WebSocket upgrade failed", { status: 500 }));
379
381
  }
380
382
  });
381
383
  };
@@ -561,19 +563,6 @@ function sendHttpResponseOnSocket(socket, response) {
561
563
  });
562
564
  }
563
565
 
564
- // tsx-instance.ts
565
- import { createElement } from "react";
566
- import { renderToReadableStream } from "react-dom/server";
567
- import * as esbuild from "esbuild";
568
- import { readdirSync, statSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
569
- import { join, relative, resolve as resolve2, sep, dirname, basename } from "node:path";
570
- import { pathToFileURL } from "node:url";
571
- import { createHash } from "node:crypto";
572
- import vm from "node:vm";
573
- import { createRequire } from "node:module";
574
- import { AsyncLocalStorage } from "node:async_hooks";
575
- import chokidar from "chokidar";
576
-
577
566
  // tsx-context.ts
578
567
  import { createContext } from "react";
579
568
  var DEFAULT_CTX = { params: {}, query: {}, parsed: {}, prefs: {}, loaderData: {}, env: {}, user: {} };
@@ -604,845 +593,6 @@ function setCtx(value) {
604
593
  }
605
594
  var TsxContext = createContext(DEFAULT_CTX);
606
595
 
607
- // tsx-instance.ts
608
- var als = new AsyncLocalStorage();
609
- __registerAls(() => als.getStore());
610
- var liveReloadClients = /* @__PURE__ */ new Set();
611
- function broadcastReload() {
612
- for (const ws of liveReloadClients) {
613
- try {
614
- ws.send("reload");
615
- } catch {
616
- liveReloadClients.delete(ws);
617
- }
618
- }
619
- }
620
- var isDev = process.env.NODE_ENV !== "production";
621
- var _tailwindPlugin = null;
622
- var _postcss = null;
623
- var _cjsRequire = createRequire(import.meta.url);
624
- function loadSSRModule(code) {
625
- const ctx = vm.createContext(Object.create(globalThis));
626
- const mod = { exports: {} };
627
- ctx.require = (name) => _cjsRequire(name);
628
- ctx.module = mod;
629
- ctx.exports = mod.exports;
630
- new vm.Script(code).runInContext(ctx);
631
- return mod.exports;
632
- }
633
- function id(s) {
634
- return createHash("md5").update(s).digest("hex").slice(0, 8);
635
- }
636
- var _alias = null;
637
- function resolveAliases() {
638
- if (_alias) return _alias;
639
- const configFiles = ["tsconfig.json", "jsconfig.json"];
640
- for (const file of configFiles) {
641
- const p = resolve2(file);
642
- if (existsSync2(p)) {
643
- try {
644
- const config = JSON.parse(readFileSync2(p, "utf-8"));
645
- const paths = config.compilerOptions?.paths;
646
- if (paths) {
647
- const alias = {};
648
- for (const [key, values] of Object.entries(paths)) {
649
- const cleanKey = key.replace("/*", "");
650
- const val = values[0]?.replace("/*", "");
651
- if (val) alias[cleanKey] = resolve2(dirname(p), val);
652
- }
653
- _alias = alias;
654
- return alias;
655
- }
656
- } catch {
657
- }
658
- }
659
- }
660
- _alias = {};
661
- return {};
662
- }
663
- function scanPages(dir) {
664
- const pages = [];
665
- function walk(current) {
666
- let entries;
667
- try {
668
- entries = readdirSync(current);
669
- } catch {
670
- return;
671
- }
672
- const dirs = [];
673
- for (const name of entries) {
674
- const full = join(current, name);
675
- const st = statSync(full);
676
- if (st.isDirectory()) {
677
- if (!name.startsWith(".")) dirs.push(full);
678
- }
679
- }
680
- const pagePath = join(current, "page.tsx");
681
- const tsPagePath = join(current, "page.ts");
682
- let entryPath = "";
683
- if (existsSync2(pagePath)) {
684
- entryPath = pagePath;
685
- } else if (existsSync2(tsPagePath)) {
686
- entryPath = tsPagePath;
687
- }
688
- if (entryPath) {
689
- let relPath = relative(dir, entryPath).replace(sep, "/");
690
- relPath = relPath.replace(/\/page\.tsx?$/, "");
691
- relPath = relPath.replace(/^page\.tsx?$/, "");
692
- const route = filePathToRoute(relPath);
693
- const layouts = resolveLayouts(current, dir);
694
- const loadPath = existsSync2(join(current, "load.ts")) ? join(current, "load.ts") : void 0;
695
- const rPath = existsSync2(join(current, "route.ts")) ? join(current, "route.ts") : void 0;
696
- pages.push({
697
- route,
698
- entryPath,
699
- loadPath,
700
- layouts,
701
- routePath: rPath
702
- });
703
- } else {
704
- const rPath = join(current, "route.ts");
705
- if (existsSync2(rPath)) {
706
- let relPath = relative(dir, rPath).replace(sep, "/");
707
- relPath = relPath.replace(/\/route\.tsx?$/, "");
708
- const route = filePathToRoute(relPath);
709
- pages.push({
710
- route,
711
- entryPath: "",
712
- layouts: [],
713
- routePath: rPath,
714
- routeOnly: true
715
- });
716
- }
717
- }
718
- for (const d of dirs) walk(d);
719
- }
720
- walk(dir);
721
- return pages;
722
- }
723
- function filePathToRoute(relPath) {
724
- let route = relPath.replace(/\\/g, "/");
725
- route = route.replace(/\[\.\.\.(\w+)\]/g, "*");
726
- route = route.replace(/\[(\w+)\]/g, ":$1");
727
- return route.startsWith("/") ? route : "/" + route;
728
- }
729
- function resolveLayouts(dir, pagesDir) {
730
- const layouts = [];
731
- let current = dir;
732
- while (current.startsWith(pagesDir)) {
733
- const p = join(current, "layout.tsx");
734
- if (existsSync2(p)) {
735
- layouts.push(p);
736
- }
737
- const parent = dirname(current);
738
- if (parent === current) break;
739
- current = parent;
740
- }
741
- return layouts.reverse();
742
- }
743
- async function compileAll(files, outDir, platform, alias) {
744
- const entryPoints = {};
745
- for (const f of files) {
746
- entryPoints[id(f)] = f;
747
- }
748
- const isBrowser = platform === "browser";
749
- await esbuild.build({
750
- entryPoints,
751
- outdir: outDir,
752
- format: "esm",
753
- platform: "node",
754
- jsx: "automatic",
755
- jsxImportSource: "react",
756
- bundle: true,
757
- external: isBrowser ? void 0 : [
758
- "react",
759
- "react-dom",
760
- "esbuild",
761
- "graphql",
762
- "ws",
763
- "zod",
764
- "@graphql-tools/schema",
765
- "ai"
766
- ],
767
- write: true,
768
- alias,
769
- allowOverwrite: true
770
- });
771
- }
772
- function compiledUrl(filePath, outDir) {
773
- const hash = id(join(outDir, id(filePath)));
774
- const p = join(outDir, id(filePath) + ".js");
775
- return pathToFileURL(p).href;
776
- }
777
- var TsxInstance = class {
778
- uiDir;
779
- pagesDir;
780
- outDir;
781
- router;
782
- pageModules = /* @__PURE__ */ new Map();
783
- layoutModules = /* @__PURE__ */ new Map();
784
- loadModules = /* @__PURE__ */ new Map();
785
- routeModules = /* @__PURE__ */ new Map();
786
- allFiles = [];
787
- nodeEntries = {};
788
- compiledTailwindCss = "";
789
- // client bundle cache (per-instance)
790
- clientBundleCache = /* @__PURE__ */ new Map();
791
- clientBuildParams = /* @__PURE__ */ new Map();
792
- clientRouteLog = /* @__PURE__ */ new Set();
793
- // file watchers (dev mode, stored for cleanup)
794
- watcher = null;
795
- twWatcher = null;
796
- debounceTimer = null;
797
- constructor(options) {
798
- this.uiDir = resolve2(options.dir);
799
- this.pagesDir = existsSync2(join(this.uiDir, "pages")) ? join(this.uiDir, "pages") : this.uiDir;
800
- this.outDir = join(this.uiDir, ".weifuwu", "ssr");
801
- this.router = new Router();
802
- }
803
- async build() {
804
- const pages = scanPages(this.pagesDir);
805
- if (pages.length === 0) return attachStop(this.router, this);
806
- const allFiles = /* @__PURE__ */ new Set();
807
- for (const p of pages) {
808
- if (p.entryPath) allFiles.add(p.entryPath);
809
- if (p.loadPath) allFiles.add(p.loadPath);
810
- for (const lp of p.layouts) allFiles.add(lp);
811
- if (p.routePath) allFiles.add(p.routePath);
812
- }
813
- const nfPath = join(this.pagesDir, "not-found.tsx");
814
- const hasNotFound = existsSync2(nfPath);
815
- if (hasNotFound) {
816
- allFiles.add(nfPath);
817
- const rootLayouts = resolveLayouts(this.pagesDir, this.pagesDir);
818
- for (const lp of rootLayouts) allFiles.add(lp);
819
- }
820
- mkdirSync(this.outDir, { recursive: true });
821
- this.allFiles = [...allFiles];
822
- await compileAll(this.allFiles, this.outDir, "node", resolveAliases());
823
- const methods = ["POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
824
- for (const p of pages) {
825
- const nodeKey = p.entryPath || p.routePath || "";
826
- this.nodeEntries[nodeKey] = { route: p.route, entryPath: p.entryPath || "", layouts: p.layouts, loadPath: p.loadPath, routePath: p.routePath };
827
- if (p.routeOnly && p.routePath) {
828
- const rUrl = compiledUrl(p.routePath, this.outDir);
829
- const modR = await import(rUrl);
830
- const handlers = /* @__PURE__ */ new Map();
831
- for (const m of ["GET", ...methods]) {
832
- if (modR[m]) handlers.set(m, modR[m]);
833
- }
834
- this.routeModules.set(p.routePath, handlers);
835
- this.router.route(
836
- "GET",
837
- p.route,
838
- (req, ctx) => this.routeModules.get(p.routePath)?.get("GET")?.(req, ctx) ?? new Response("", { status: 501 })
839
- );
840
- for (const m of methods) {
841
- this.router.route(
842
- m,
843
- p.route,
844
- (req, ctx) => this.routeModules.get(p.routePath)?.get(m)?.(req, ctx) ?? new Response("", { status: 501 })
845
- );
846
- }
847
- continue;
848
- }
849
- const pageUrl = compiledUrl(p.entryPath, this.outDir);
850
- this.pageModules.set(p.entryPath, await import(pageUrl));
851
- if (p.loadPath) {
852
- const loadUrl = compiledUrl(p.loadPath, this.outDir);
853
- this.loadModules.set(p.loadPath, await import(loadUrl));
854
- }
855
- for (const lp of p.layouts) {
856
- const lUrl = compiledUrl(lp, this.outDir);
857
- this.layoutModules.set(lp, await import(lUrl));
858
- }
859
- if (p.routePath) {
860
- const rUrl = compiledUrl(p.routePath, this.outDir);
861
- const modR = await import(rUrl);
862
- const handlers = /* @__PURE__ */ new Map();
863
- for (const m of methods) {
864
- if (modR[m]) handlers.set(m, modR[m]);
865
- }
866
- this.routeModules.set(p.routePath, handlers);
867
- }
868
- const handler = this.makeSsrHandler(p.entryPath, p.layouts, p.loadPath);
869
- this.router.get(p.route, handler);
870
- if (p.routePath) {
871
- for (const m of methods) {
872
- this.router.route(
873
- m,
874
- p.route,
875
- (req, ctx) => this.routeModules.get(p.routePath)?.get(m)?.(req, ctx) ?? new Response("", { status: 501 })
876
- );
877
- }
878
- }
879
- }
880
- if (hasNotFound) {
881
- const nfUrl = compiledUrl(nfPath, this.outDir);
882
- this.pageModules.set(nfPath, await import(nfUrl));
883
- const rootLayouts = resolveLayouts(this.pagesDir, this.pagesDir);
884
- for (const lp of rootLayouts) {
885
- if (!this.layoutModules.has(lp)) {
886
- const lUrl = compiledUrl(lp, this.outDir);
887
- this.layoutModules.set(lp, await import(lUrl));
888
- }
889
- }
890
- const handler = async (req, ctx) => {
891
- const base = (ctx.mountPath || "").replace(/\/$/, "");
892
- const nfMod = this.pageModules.get(nfPath);
893
- if (!nfMod) return new Response("Not Found", { status: 404 });
894
- const NfComponent = nfMod.default;
895
- const ctxValue = {
896
- params: ctx.params,
897
- query: ctx.query,
898
- user: ctx.user ?? {},
899
- parsed: ctx.parsed ?? {},
900
- prefs: ctx.prefs ?? {},
901
- loaderData: {},
902
- env: ctx.env ?? {}
903
- };
904
- return als.run(ctxValue, async () => {
905
- setCtx(ctxValue);
906
- let element = createElement(
907
- TsxContext.Provider,
908
- { value: ctxValue },
909
- createElement(NfComponent, { params: ctx.params, query: ctx.query })
910
- );
911
- for (let i = rootLayouts.length - 1; i >= 0; i--) {
912
- const LMod = this.layoutModules.get(rootLayouts[i]);
913
- if (!LMod) continue;
914
- element = createElement(LMod.default, { children: element });
915
- }
916
- const stream = await renderToReadableStream(element);
917
- return streamResponse(stream, {
918
- ctx,
919
- base,
920
- compiledTailwindCss: this.compiledTailwindCss,
921
- isDev,
922
- status: 404
923
- });
924
- });
925
- };
926
- this.router.all("/*", handler);
927
- }
928
- for (const p of pages) {
929
- if (p.entryPath) {
930
- const rootLayouts = resolveLayouts(this.pagesDir, this.pagesDir);
931
- this.registerClientBundleRoute(p.entryPath, p.layouts.length > 0 ? p.layouts : rootLayouts, this.pagesDir);
932
- }
933
- }
934
- await this.setupTailwind();
935
- if (isDev) {
936
- this.router.ws("/__weifuwu/livereload", {
937
- open: (ws) => {
938
- liveReloadClients.add(ws);
939
- ws.on("close", () => liveReloadClients.delete(ws));
940
- ws.on("error", () => liveReloadClients.delete(ws));
941
- }
942
- });
943
- this.startFileWatcher();
944
- }
945
- return attachStop(this.router, this);
946
- }
947
- /**
948
- * Clean up file watchers and pending timers. Call when shutting down
949
- * to prevent resource leaks.
950
- */
951
- stop() {
952
- this.watcher?.close();
953
- this.twWatcher?.close();
954
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
955
- this.debounceTimer = null;
956
- }
957
- // ── Tailwind CSS ──────────────────────────────────────────────────────────
958
- async compileTailwind() {
959
- if (this.compiledTailwindCss) return this.compiledTailwindCss;
960
- try {
961
- _tailwindPlugin ??= (await import("@tailwindcss/postcss")).default;
962
- _postcss ??= (await import("postcss")).default;
963
- } catch {
964
- return "";
965
- }
966
- const inputFile = resolve2(this.uiDir, "app.css");
967
- if (!existsSync2(inputFile)) {
968
- mkdirSync(this.uiDir, { recursive: true });
969
- writeFileSync(inputFile, '@import "tailwindcss"\n', "utf-8");
970
- console.log("\u2139 weifuwu/tsx: created " + relative(process.cwd(), inputFile));
971
- }
972
- try {
973
- let src = readFileSync2(inputFile, "utf-8");
974
- const sourceRel = relative(this.uiDir, this.pagesDir) || ".";
975
- const sourcePath = sourceRel === "." ? "./" : `./${sourceRel}/`;
976
- src = `@source "${sourcePath}";
977
- ${src}`;
978
- const result = await _postcss([_tailwindPlugin()]).process(src, { from: inputFile });
979
- this.compiledTailwindCss = result.css;
980
- } catch (err) {
981
- console.warn("Tailwind CSS processing failed:", err.message);
982
- }
983
- return this.compiledTailwindCss;
984
- }
985
- async setupTailwind() {
986
- await this.compileTailwind();
987
- this.router.get("/__wfw/style.css", () => new Response(this.compiledTailwindCss || "", {
988
- headers: { "content-type": "text/css; charset=utf-8" }
989
- }));
990
- if (isDev) {
991
- const inputFile = resolve2(this.uiDir, "app.css");
992
- this.twWatcher = chokidar.watch(inputFile, { persistent: false });
993
- this.twWatcher.on("change", async () => {
994
- this.compiledTailwindCss = "";
995
- await this.compileTailwind();
996
- broadcastReload();
997
- });
998
- }
999
- }
1000
- // ── client bundle ─────────────────────────────────────────────────────────
1001
- async buildClientBundle(entryPath, layoutPaths, pagesDir) {
1002
- try {
1003
- const layoutImports = layoutPaths.map((p) => `import${JSON.stringify(p)};`).join("");
1004
- const _sc = `(function(){var k='__WEIFUWU_CTX_STORE';var s=typeof globalThis!='undefined'&&globalThis[k];if(!s)return function(){};return function(v){s._ctx={...s._ctx,...v};s._snapshot={params:s._ctx.params,query:s._ctx.query,user:s._ctx.user,parsed:s._ctx.parsed,prefs:s._ctx.prefs,env:s._ctx.env};s._listeners.forEach(function(fn){fn()})}})()`;
1005
- const code = [
1006
- layoutImports,
1007
- `import{hydrateRoot}from'react-dom/client';`,
1008
- `import{createElement,useState,useEffect}from'react';`,
1009
- `import{TsxContext}from'weifuwu/react';`,
1010
- `import P from${JSON.stringify(entryPath)};`,
1011
- `var setCtx=${_sc};`,
1012
- `const c=document.getElementById('__weifuwu_root');`,
1013
- `if(window.__WEIFUWU_PROPS)setCtx({loaderData:window.__WEIFUWU_PROPS});`,
1014
- `if(!window.__WFW_ROOT){`,
1015
- `function App(){`,
1016
- `const[p,setP]=useState({C:P});`,
1017
- `useEffect(()=>{window.__WFW_SET_PAGE=(C)=>{setCtx({loaderData:window.__WEIFUWU_PROPS});setP({C})}},[]);`,
1018
- `const ctx=window.__WEIFUWU_CTX||{};`,
1019
- `return createElement(TsxContext.Provider,{value:ctx},`,
1020
- `createElement(p.C,null))`,
1021
- `}`,
1022
- `window.__WFW_ROOT=hydrateRoot(c,createElement(App));`,
1023
- `}else{`,
1024
- `window.__WFW_SET_PAGE?.(P);`,
1025
- `}`
1026
- ].join("");
1027
- const publicEnv = {};
1028
- for (const key of Object.keys(process.env)) {
1029
- if (key.startsWith("WEIFUWU_PUBLIC_")) {
1030
- publicEnv[`process.env.${key}`] = JSON.stringify(process.env[key]);
1031
- }
1032
- }
1033
- const result = await esbuild.build({
1034
- stdin: { contents: code, loader: "tsx", resolveDir: pagesDir },
1035
- bundle: true,
1036
- format: "esm",
1037
- jsx: "automatic",
1038
- jsxImportSource: "react",
1039
- alias: resolveAliases(),
1040
- banner: { js: "self.process={env:{}};" },
1041
- define: Object.keys(publicEnv).length > 0 ? publicEnv : void 0,
1042
- loader: { ".node": "empty" },
1043
- write: false,
1044
- minify: true
1045
- });
1046
- return result.outputFiles[0].contents;
1047
- } catch (err) {
1048
- console.error("hydration bundle failed:", err);
1049
- return null;
1050
- }
1051
- }
1052
- async getOrBuildClientBundle(entryPath, layoutPaths, pagesDir) {
1053
- const key = id(entryPath);
1054
- const url = `/__wfw/client/${key}.js`;
1055
- this.clientBuildParams.set(key, { entryPath, layoutPaths, pagesDir });
1056
- if (!this.clientBundleCache.has(key)) {
1057
- const buf = await this.buildClientBundle(entryPath, layoutPaths, pagesDir);
1058
- if (!buf) return null;
1059
- this.clientBundleCache.set(key, buf);
1060
- }
1061
- return { url };
1062
- }
1063
- registerClientBundleRoute(entryPath, layoutPaths, pagesDir) {
1064
- const key = id(entryPath);
1065
- const url = `/__wfw/client/${key}.js`;
1066
- this.clientBuildParams.set(key, { entryPath, layoutPaths, pagesDir });
1067
- if (!this.clientRouteLog.has(url)) {
1068
- this.router.get(url, async () => {
1069
- let buf = this.clientBundleCache.get(key);
1070
- if (!buf) {
1071
- const params = this.clientBuildParams.get(key);
1072
- if (params) {
1073
- const rebuilt = await this.buildClientBundle(params.entryPath, params.layoutPaths, params.pagesDir);
1074
- if (rebuilt) {
1075
- this.clientBundleCache.set(key, rebuilt);
1076
- buf = rebuilt;
1077
- }
1078
- }
1079
- }
1080
- return buf ? new Response(buf, {
1081
- headers: { "content-type": "application/javascript; charset=utf-8" }
1082
- }) : new Response("", { status: 500 });
1083
- });
1084
- this.clientRouteLog.add(url);
1085
- }
1086
- }
1087
- // ── SSR handler ───────────────────────────────────────────────────────────
1088
- makeSsrHandler(entryPath, layoutPaths, loadPath) {
1089
- return async (req, ctx) => {
1090
- const base = (ctx.mountPath || "").replace(/\/$/, "");
1091
- const pageMod = this.pageModules.get(entryPath);
1092
- if (!pageMod) return new Response("", { status: 500 });
1093
- const Component = pageMod.default;
1094
- const loadMod = loadPath ? this.loadModules.get(loadPath) : void 0;
1095
- const loadFn = loadMod?.default;
1096
- const loadProps = loadFn ? await loadFn({ params: ctx.params, query: ctx.query }) : {};
1097
- const ctxValue = {
1098
- params: ctx.params,
1099
- query: ctx.query,
1100
- user: ctx.user ?? {},
1101
- parsed: ctx.parsed ?? {},
1102
- prefs: ctx.prefs ?? {},
1103
- loaderData: loadProps,
1104
- env: ctx.env ?? {}
1105
- };
1106
- return als.run(ctxValue, async () => {
1107
- setCtx(ctxValue);
1108
- let element = createElement(
1109
- TsxContext.Provider,
1110
- { value: ctxValue },
1111
- createElement(
1112
- "div",
1113
- { id: "__weifuwu_root" },
1114
- createElement(Component, null)
1115
- )
1116
- );
1117
- if (layoutPaths.length === 0) {
1118
- element = createElement(
1119
- "html",
1120
- { lang: "en" },
1121
- createElement(
1122
- "head",
1123
- null,
1124
- createElement("meta", { charSet: "utf-8" }),
1125
- createElement("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
1126
- createElement("title", null, "weifuwu")
1127
- ),
1128
- createElement("body", null, element)
1129
- );
1130
- } else {
1131
- for (let i = layoutPaths.length - 1; i >= 0; i--) {
1132
- const lp = layoutPaths[i];
1133
- const LMod = this.layoutModules.get(lp);
1134
- if (!LMod) continue;
1135
- const Layout = LMod.default;
1136
- const isRoot = i === 0;
1137
- element = createElement(
1138
- Layout,
1139
- { children: element }
1140
- );
1141
- }
1142
- }
1143
- const bundle = await this.getOrBuildClientBundle(entryPath, layoutPaths, this.pagesDir);
1144
- const stream = await renderToReadableStream(element);
1145
- return streamResponse(stream, {
1146
- ctx,
1147
- base,
1148
- compiledTailwindCss: this.compiledTailwindCss,
1149
- isDev,
1150
- bundle,
1151
- loaderData: loadProps
1152
- });
1153
- });
1154
- };
1155
- }
1156
- // ── dev file watcher ──────────────────────────────────────────────────────
1157
- startFileWatcher() {
1158
- const pending = /* @__PURE__ */ new Set();
1159
- this.watcher = chokidar.watch(this.uiDir, {
1160
- ignored: /(^|[/\\])\.(?!\.)|node_modules|[/\\]\.weifuwu[/\\]|[/\\]dist[/\\]/,
1161
- persistent: false,
1162
- ignoreInitial: true
1163
- });
1164
- this.watcher.on("all", async (event, filePath) => {
1165
- if (event !== "change" && event !== "add") return;
1166
- if (!/\.tsx?$/.test(filePath)) return;
1167
- pending.add(filePath);
1168
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
1169
- this.debounceTimer = setTimeout(async () => {
1170
- this.debounceTimer = null;
1171
- const files = [...pending];
1172
- pending.clear();
1173
- const exists = files.filter((f) => existsSync2(f));
1174
- const allKnown = exists.every(
1175
- (f) => this.pageModules.has(f) || this.layoutModules.has(f) || this.loadModules.has(f) || this.routeModules.has(f)
1176
- );
1177
- if (allKnown) {
1178
- for (const f of exists) await this.recompileAndSwap(f);
1179
- this.compiledTailwindCss = "";
1180
- await this.compileTailwind();
1181
- broadcastReload();
1182
- } else {
1183
- await this.recompileAll();
1184
- }
1185
- }, 50);
1186
- });
1187
- }
1188
- async recompileAndSwap(filePath) {
1189
- try {
1190
- const result = await esbuild.build({
1191
- entryPoints: { [id(filePath)]: filePath },
1192
- outdir: this.outDir,
1193
- format: "cjs",
1194
- platform: "node",
1195
- jsx: "automatic",
1196
- jsxImportSource: "react",
1197
- bundle: true,
1198
- external: ["react", "react-dom", "esbuild", "graphql", "ws", "zod", "@graphql-tools/schema", "ai"],
1199
- alias: resolveAliases(),
1200
- write: false
1201
- });
1202
- const code = new TextDecoder().decode(result.outputFiles[0].contents);
1203
- const mod = loadSSRModule(code);
1204
- const name = basename(filePath);
1205
- if (name === "layout.tsx") {
1206
- this.layoutModules.set(filePath, mod);
1207
- this.clientBundleCache.clear();
1208
- } else if (name === "route.ts") {
1209
- const handlers = /* @__PURE__ */ new Map();
1210
- for (const m of ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]) {
1211
- if (mod[m]) handlers.set(m, mod[m]);
1212
- }
1213
- this.routeModules.set(filePath, handlers);
1214
- } else if (name === "load.ts") {
1215
- this.loadModules.set(filePath, mod);
1216
- } else {
1217
- this.pageModules.set(filePath, mod);
1218
- this.clientBundleCache.delete(id(filePath));
1219
- }
1220
- } catch (err) {
1221
- console.error("recompile failed:", err.message);
1222
- }
1223
- }
1224
- async recompileAll() {
1225
- try {
1226
- const freshPages = scanPages(this.pagesDir);
1227
- const freshFiles = /* @__PURE__ */ new Set();
1228
- const nodeEntries = {};
1229
- for (const p of freshPages) {
1230
- const nodeKey = p.entryPath || p.routePath || "";
1231
- nodeEntries[nodeKey] = { route: p.route, entryPath: p.entryPath, layouts: p.layouts, loadPath: p.loadPath, routePath: p.routePath };
1232
- if (p.entryPath) freshFiles.add(p.entryPath);
1233
- if (p.loadPath) freshFiles.add(p.loadPath);
1234
- for (const lp of p.layouts) freshFiles.add(lp);
1235
- if (p.routePath) freshFiles.add(p.routePath);
1236
- }
1237
- const nfPath = join(this.pagesDir, "not-found.tsx");
1238
- if (existsSync2(nfPath)) {
1239
- freshFiles.add(nfPath);
1240
- const rootLayouts = resolveLayouts(this.pagesDir, this.pagesDir);
1241
- for (const lp of rootLayouts) freshFiles.add(lp);
1242
- }
1243
- this.allFiles = [...freshFiles];
1244
- const result = await esbuild.build({
1245
- entryPoints: Object.fromEntries(this.allFiles.map((f) => [id(f), f])),
1246
- outdir: this.outDir,
1247
- format: "cjs",
1248
- platform: "node",
1249
- jsx: "automatic",
1250
- jsxImportSource: "react",
1251
- bundle: true,
1252
- external: ["react", "react-dom", "esbuild", "graphql", "ws", "zod", "@graphql-tools/schema", "ai"],
1253
- alias: resolveAliases(),
1254
- write: false
1255
- });
1256
- for (const file of result.outputFiles) {
1257
- const code = new TextDecoder().decode(file.contents);
1258
- const mod = loadSSRModule(code);
1259
- const srcPath = this.allFiles.find((f) => file.path.endsWith(id(f) + ".js"));
1260
- if (!srcPath) continue;
1261
- const name = basename(srcPath);
1262
- if (name === "layout.tsx") {
1263
- this.layoutModules.set(srcPath, mod);
1264
- } else if (name === "route.ts") {
1265
- const handlers = /* @__PURE__ */ new Map();
1266
- for (const m of ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]) {
1267
- if (mod[m]) handlers.set(m, mod[m]);
1268
- }
1269
- this.routeModules.set(srcPath, handlers);
1270
- } else if (name === "load.ts") {
1271
- this.loadModules.set(srcPath, mod);
1272
- } else if (name !== "not-found.tsx") {
1273
- this.pageModules.set(srcPath, mod);
1274
- }
1275
- }
1276
- const methods = ["POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
1277
- for (const [key, entry] of Object.entries(nodeEntries)) {
1278
- if (this.nodeEntries[key]) continue;
1279
- if (entry.routePath && !entry.entryPath) {
1280
- this.router.route(
1281
- "GET",
1282
- entry.route,
1283
- (req, ctx) => this.routeModules.get(entry.routePath)?.get("GET")?.(req, ctx) ?? new Response("", { status: 501 })
1284
- );
1285
- for (const m of methods) {
1286
- this.router.route(
1287
- m,
1288
- entry.route,
1289
- (req, ctx) => this.routeModules.get(entry.routePath)?.get(m)?.(req, ctx) ?? new Response("", { status: 501 })
1290
- );
1291
- }
1292
- }
1293
- if (entry.entryPath) {
1294
- const handler = this.makeSsrHandler(entry.entryPath, entry.layouts, entry.loadPath);
1295
- this.router.get(entry.route, handler);
1296
- if (entry.routePath) {
1297
- for (const m of methods) {
1298
- this.router.route(
1299
- m,
1300
- entry.route,
1301
- (req, ctx) => this.routeModules.get(entry.routePath)?.get(m)?.(req, ctx) ?? new Response("", { status: 501 })
1302
- );
1303
- }
1304
- }
1305
- }
1306
- console.log("\u2139 weifuwu/tsx: registered new route " + entry.route);
1307
- }
1308
- this.nodeEntries = nodeEntries;
1309
- this.clientBundleCache.clear();
1310
- this.compiledTailwindCss = "";
1311
- await this.compileTailwind();
1312
- broadcastReload();
1313
- } catch (err) {
1314
- console.error("recompile all failed:", err.message);
1315
- }
1316
- }
1317
- };
1318
- function attachStop(router, instance) {
1319
- ;
1320
- router.stop = () => instance.stop();
1321
- return router;
1322
- }
1323
- function streamResponse(reactStream, opts) {
1324
- const decoder = new TextDecoder();
1325
- const encoder2 = new TextEncoder();
1326
- const headPayload = buildHeadPayload(opts);
1327
- let buffer = "";
1328
- let headFlushed = false;
1329
- let extractedHead = "";
1330
- const output = new ReadableStream({
1331
- async start(controller) {
1332
- try {
1333
- const reader = reactStream.getReader();
1334
- async function push(chunk) {
1335
- buffer += decoder.decode(chunk, { stream: true });
1336
- if (!extractedHead) {
1337
- const m = buffer.match(/<template id="__wfw_head">([\s\S]*?)<\/template>/);
1338
- if (m) {
1339
- extractedHead = m[1];
1340
- buffer = buffer.replace(m[0], "");
1341
- }
1342
- }
1343
- if (!headFlushed) {
1344
- const idx = buffer.indexOf("</head>");
1345
- if (idx !== -1) {
1346
- const before = buffer.slice(0, idx);
1347
- let injection = "";
1348
- if (extractedHead) injection += "\n" + extractedHead;
1349
- injection += headPayload;
1350
- controller.enqueue(encoder2.encode(before + injection));
1351
- buffer = buffer.slice(idx);
1352
- headFlushed = true;
1353
- }
1354
- return;
1355
- }
1356
- controller.enqueue(encoder2.encode(buffer));
1357
- buffer = "";
1358
- }
1359
- while (true) {
1360
- const { done, value } = await reader.read();
1361
- if (done) break;
1362
- await push(value);
1363
- }
1364
- buffer = buffer.replace(/<template id="__wfw_head">[\s\S]*?<\/template>/g, "");
1365
- if (buffer) controller.enqueue(encoder2.encode(buffer));
1366
- const body = buildBodyScripts(opts);
1367
- if (body) controller.enqueue(encoder2.encode("\n" + body));
1368
- if (opts.isDev) {
1369
- controller.enqueue(encoder2.encode(
1370
- `
1371
- <script>(function(){var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'${opts.base}/__weifuwu/livereload');ws.onmessage=function(e){if(e.data==='reload')location.reload()};ws.onclose=function(){setTimeout(function(){location.reload()},500)}})()</script>`
1372
- ));
1373
- }
1374
- } catch (err) {
1375
- const fallback = `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>500</title></head><body><h1>500 - Internal Server Error</h1></body></html>`;
1376
- controller.enqueue(encoder2.encode(fallback));
1377
- } finally {
1378
- controller.close();
1379
- }
1380
- }
1381
- });
1382
- return new Response(output, {
1383
- status: opts.status ?? 200,
1384
- headers: { "content-type": "text/html; charset=utf-8" }
1385
- });
1386
- }
1387
- var _publicEnv = null;
1388
- function getPublicEnv() {
1389
- if (_publicEnv) return _publicEnv;
1390
- _publicEnv = {};
1391
- for (const key of Object.keys(process.env)) {
1392
- if (key.startsWith("WEIFUWU_PUBLIC_")) {
1393
- _publicEnv[key] = process.env[key];
1394
- }
1395
- }
1396
- return _publicEnv;
1397
- }
1398
- function buildHeadPayload(opts) {
1399
- const { ctx, base, compiledTailwindCss } = opts;
1400
- let result = "";
1401
- if (ctx.prefs?.theme) {
1402
- result += `<script>!function(){var t=(document.cookie.match(/(?:^|;\\s*)theme=([^;]+)/)||[])[1]||'system';if(t==='system'){t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)}()</script>
1403
- `;
1404
- }
1405
- if (compiledTailwindCss) {
1406
- result += `<link rel="stylesheet" href="${base}/__wfw/style.css" />
1407
- `;
1408
- }
1409
- const localeData = ctx.parsed?.__localeData ?? globalThis.__LOCALE_DATA__;
1410
- if (localeData && Object.keys(localeData).length > 0) {
1411
- result += `<script>window.__LOCALE_DATA__=${JSON.stringify(localeData)}</script>
1412
- `;
1413
- }
1414
- const ctxData = {
1415
- params: ctx.params,
1416
- query: ctx.query,
1417
- user: ctx.user,
1418
- parsed: ctx.parsed,
1419
- prefs: ctx.prefs
1420
- };
1421
- const publicEnv = getPublicEnv();
1422
- if (Object.keys(publicEnv).length > 0) {
1423
- ctxData.env = publicEnv;
1424
- }
1425
- result += `<script>window.__WEIFUWU_CTX=${JSON.stringify(ctxData)}</script>
1426
- `;
1427
- return result;
1428
- }
1429
- function buildBodyScripts(opts) {
1430
- const parts = [];
1431
- if (opts.loaderData && Object.keys(opts.loaderData).length > 0) {
1432
- parts.push(`<script>window.__WEIFUWU_PROPS=${JSON.stringify(opts.loaderData)}</script>`);
1433
- }
1434
- if (opts.bundle) {
1435
- parts.push(`<script type="module" src="${opts.base}${opts.bundle.url}"></script>`);
1436
- }
1437
- return parts.join("\n");
1438
- }
1439
-
1440
- // tsx.ts
1441
- async function tsx(options) {
1442
- const instance = new TsxInstance(options);
1443
- return instance.build();
1444
- }
1445
-
1446
596
  // middleware.ts
1447
597
  function logger(options) {
1448
598
  return async (req, ctx, next) => {
@@ -1598,12 +748,12 @@ function auth(options) {
1598
748
  }
1599
749
 
1600
750
  // static.ts
1601
- import { createHash as createHash2 } from "node:crypto";
751
+ import { createHash } from "node:crypto";
1602
752
  import { open, realpath } from "node:fs/promises";
1603
- import { extname, resolve as resolve3, normalize, sep as sep2 } from "node:path";
753
+ import { extname, resolve as resolve2, normalize, sep } from "node:path";
1604
754
  import { Readable } from "node:stream";
1605
755
  function serveStatic(root, options) {
1606
- const rootDir = resolve3(root);
756
+ const rootDir = resolve2(root);
1607
757
  const opts = options ?? {};
1608
758
  return async (req, ctx) => {
1609
759
  const relativePath = ctx.params["*"] ?? new URL(req.url).pathname.slice(1);
@@ -1611,8 +761,8 @@ function serveStatic(root, options) {
1611
761
  if (decoded.includes("..") || decoded.includes("\0")) {
1612
762
  return new Response("Forbidden", { status: 403 });
1613
763
  }
1614
- let filePath = normalize(resolve3(rootDir, decoded));
1615
- if (!filePath.startsWith(rootDir + sep2) && filePath !== rootDir) {
764
+ let filePath = normalize(resolve2(rootDir, decoded));
765
+ if (!filePath.startsWith(rootDir + sep) && filePath !== rootDir) {
1616
766
  return new Response("Forbidden", { status: 403 });
1617
767
  }
1618
768
  let fileHandle;
@@ -1620,15 +770,15 @@ function serveStatic(root, options) {
1620
770
  fileHandle = await open(filePath, "r");
1621
771
  let stat = await fileHandle.stat();
1622
772
  const realPath = await realpath(filePath);
1623
- if (!realPath.startsWith(rootDir + sep2) && realPath !== rootDir) {
773
+ if (!realPath.startsWith(rootDir + sep) && realPath !== rootDir) {
1624
774
  await fileHandle.close();
1625
775
  return new Response("Forbidden", { status: 403 });
1626
776
  }
1627
777
  if (stat.isDirectory()) {
1628
778
  await fileHandle.close();
1629
779
  const indexFile = opts.index ?? "index.html";
1630
- filePath = resolve3(filePath, indexFile);
1631
- if (!filePath.startsWith(rootDir + sep2)) {
780
+ filePath = resolve2(filePath, indexFile);
781
+ if (!filePath.startsWith(rootDir + sep)) {
1632
782
  return new Response("Forbidden", { status: 403 });
1633
783
  }
1634
784
  fileHandle = await open(filePath, "r");
@@ -1639,7 +789,7 @@ function serveStatic(root, options) {
1639
789
  }
1640
790
  }
1641
791
  const mimeType = MIME_TYPES[extname(filePath).toLowerCase()] ?? "application/octet-stream";
1642
- const etag = `"${createHash2("md5").update(`${stat.size}-${stat.mtimeMs}`).digest("hex")}"`;
792
+ const etag = `"${createHash("md5").update(`${stat.size}-${stat.mtimeMs}`).digest("hex")}"`;
1643
793
  const ifNoneMatch = req.headers.get("if-none-match");
1644
794
  if (ifNoneMatch === etag) {
1645
795
  await fileHandle.close();
@@ -1860,7 +1010,7 @@ function deleteCookie(res, name, options) {
1860
1010
  // upload.ts
1861
1011
  import { writeFile, mkdir } from "node:fs/promises";
1862
1012
  import { randomUUID } from "node:crypto";
1863
- import { join as join2, extname as extname2 } from "node:path";
1013
+ import { join, extname as extname2 } from "node:path";
1864
1014
  var extensionMimeMap = {
1865
1015
  ".jpg": "image/jpeg",
1866
1016
  ".jpeg": "image/jpeg",
@@ -1927,7 +1077,7 @@ function upload(options) {
1927
1077
  };
1928
1078
  if (saveDir) {
1929
1079
  const safeName = value.name.replace(/[/\\\0]/g, "_");
1930
- const filePath = join2(saveDir, `${randomUUID()}-${safeName}`);
1080
+ const filePath = join(saveDir, `${randomUUID()}-${safeName}`);
1931
1081
  await writeFile(filePath, buf);
1932
1082
  uf.path = filePath;
1933
1083
  }
@@ -2117,12 +1267,12 @@ function requestId(options) {
2117
1267
  const gen = options?.generator ?? (() => crypto2.randomUUID());
2118
1268
  return async (req, ctx, next) => {
2119
1269
  const existing = req.headers.get(header);
2120
- const id2 = existing ?? gen();
2121
- ctx.requestId = id2;
1270
+ const id3 = existing ?? gen();
1271
+ ctx.requestId = id3;
2122
1272
  const res = await next(req, ctx);
2123
1273
  if (res.headers.has(header)) return res;
2124
1274
  const h = new Headers(res.headers);
2125
- h.set(header, id2);
1275
+ h.set(header, id3);
2126
1276
  return new Response(res.body, { status: res.status, statusText: res.statusText, headers: h });
2127
1277
  };
2128
1278
  }
@@ -2344,10 +1494,10 @@ function resolveRef(path2, ctx) {
2344
1494
  const after = path2.slice(7);
2345
1495
  const dot = after.indexOf(".");
2346
1496
  if (dot === -1) return ctx.nodeOutputs.get(after);
2347
- const id2 = after.slice(0, dot);
1497
+ const id3 = after.slice(0, dot);
2348
1498
  const propPath = after.slice(dot + 1);
2349
- const output = ctx.nodeOutputs.get(id2);
2350
- if (output === void 0) throw new Error(`Node "${id2}" has no output yet`);
1499
+ const output = ctx.nodeOutputs.get(id3);
1500
+ if (output === void 0) throw new Error(`Node "${id3}" has no output yet`);
2351
1501
  return getByPath(output, propPath.startsWith("output") ? propPath.slice(7).split(".").filter(Boolean) : propPath.split("."));
2352
1502
  }
2353
1503
  if (path2.startsWith("$var.")) {
@@ -2873,18 +2023,18 @@ var Table = class {
2873
2023
  `;
2874
2024
  return rows;
2875
2025
  }
2876
- async read(sql2, id2, opts) {
2026
+ async read(sql2, id3, opts) {
2877
2027
  if (opts?.select?.length) {
2878
2028
  const columns = opts.select.map((c) => `"${c}"`).join(", ");
2879
2029
  const [row2] = await sql2.unsafe(
2880
2030
  `SELECT ${columns} FROM "${this.tableName}" WHERE id = $1 LIMIT 1`,
2881
- [id2]
2031
+ [id3]
2882
2032
  );
2883
2033
  return row2 ?? void 0;
2884
2034
  }
2885
2035
  const [row] = await sql2`
2886
2036
  SELECT * FROM ${sql2(this.tableName)}
2887
- WHERE ${sql2("id")} = ${id2} LIMIT 1
2037
+ WHERE ${sql2("id")} = ${id3} LIMIT 1
2888
2038
  `;
2889
2039
  return row ?? void 0;
2890
2040
  }
@@ -2918,11 +2068,11 @@ var Table = class {
2918
2068
  const rows = await sql2.unsafe(query, values);
2919
2069
  return { count, data: rows };
2920
2070
  }
2921
- async update(sql2, id2, data) {
2071
+ async update(sql2, id3, data) {
2922
2072
  const { sets, values: setValues } = this._buildSET(data);
2923
2073
  if (sets.length === 0) return void 0;
2924
2074
  const query = `UPDATE "${this.tableName}" AS t SET ${sets.join(", ")} FROM (SELECT ctid FROM "${this.tableName}" WHERE id = $${setValues.length + 1} LIMIT 1) AS sub WHERE t.ctid = sub.ctid RETURNING t.*`;
2925
- const rows = await sql2.unsafe(query, [...setValues, id2]);
2075
+ const rows = await sql2.unsafe(query, [...setValues, id3]);
2926
2076
  return rows[0] ?? void 0;
2927
2077
  }
2928
2078
  async updateMany(sql2, where, data) {
@@ -2936,22 +2086,22 @@ var Table = class {
2936
2086
  );
2937
2087
  return rows.length;
2938
2088
  }
2939
- async delete(sql2, id2) {
2089
+ async delete(sql2, id3) {
2940
2090
  if (this.hasColumn("deleted_at")) {
2941
2091
  const [row2] = await sql2.unsafe(
2942
2092
  `UPDATE "${this.tableName}" SET "deleted_at" = NOW() WHERE id = $1 RETURNING *`,
2943
- [id2]
2093
+ [id3]
2944
2094
  );
2945
2095
  return row2 ?? void 0;
2946
2096
  }
2947
2097
  const [row] = await sql2`
2948
- DELETE FROM ${sql2(this.tableName)} WHERE ${sql2("id")} = ${id2} RETURNING *
2098
+ DELETE FROM ${sql2(this.tableName)} WHERE ${sql2("id")} = ${id3} RETURNING *
2949
2099
  `;
2950
2100
  return row ?? void 0;
2951
2101
  }
2952
- async hardDelete(sql2, id2) {
2102
+ async hardDelete(sql2, id3) {
2953
2103
  const [row] = await sql2`
2954
- DELETE FROM ${sql2(this.tableName)} WHERE ${sql2("id")} = ${id2} RETURNING *
2104
+ DELETE FROM ${sql2(this.tableName)} WHERE ${sql2("id")} = ${id3} RETURNING *
2955
2105
  `;
2956
2106
  return row ?? void 0;
2957
2107
  }
@@ -3047,23 +2197,23 @@ var BoundTable = class _BoundTable {
3047
2197
  async insertMany(data) {
3048
2198
  return await this.inner.insertMany(this.sql, data);
3049
2199
  }
3050
- async read(id2, opts) {
3051
- return await this.inner.read(this.sql, id2, opts);
2200
+ async read(id3, opts) {
2201
+ return await this.inner.read(this.sql, id3, opts);
3052
2202
  }
3053
2203
  async readMany(where, opts) {
3054
2204
  return await this.inner.readMany(this.sql, where, opts);
3055
2205
  }
3056
- async update(id2, data) {
3057
- return await this.inner.update(this.sql, id2, data);
2206
+ async update(id3, data) {
2207
+ return await this.inner.update(this.sql, id3, data);
3058
2208
  }
3059
2209
  async updateMany(where, data) {
3060
2210
  return await this.inner.updateMany(this.sql, where, data);
3061
2211
  }
3062
- async delete(id2) {
3063
- return await this.inner.delete(this.sql, id2);
2212
+ async delete(id3) {
2213
+ return await this.inner.delete(this.sql, id3);
3064
2214
  }
3065
- async hardDelete(id2) {
3066
- return await this.inner.hardDelete(this.sql, id2);
2215
+ async hardDelete(id3) {
2216
+ return await this.inner.hardDelete(this.sql, id3);
3067
2217
  }
3068
2218
  async deleteMany(where) {
3069
2219
  return await this.inner.deleteMany(this.sql, where);
@@ -3530,8 +2680,8 @@ function user(options) {
3530
2680
  const { data: rows } = await users.readMany({ email });
3531
2681
  return rows[0];
3532
2682
  }
3533
- async function findById(id2) {
3534
- return await users.read(id2);
2683
+ async function findById(id3) {
2684
+ return await users.read(id3);
3535
2685
  }
3536
2686
  async function register(data) {
3537
2687
  const { email, password, name } = RegisterSchema.parse(data);
@@ -3687,7 +2837,7 @@ function createHub(opts) {
3687
2837
  }
3688
2838
  });
3689
2839
  }
3690
- function join5(key, ws) {
2840
+ function join6(key, ws) {
3691
2841
  if (!channels.has(key)) {
3692
2842
  channels.set(key, /* @__PURE__ */ new Set());
3693
2843
  redisSub?.subscribe(`${prefix}${key}`);
@@ -3728,7 +2878,7 @@ function createHub(opts) {
3728
2878
  await redisSub.quit();
3729
2879
  }
3730
2880
  }
3731
- return { join: join5, leave, broadcast, close };
2881
+ return { join: join6, leave, broadcast, close };
3732
2882
  }
3733
2883
 
3734
2884
  // queue/index.ts
@@ -3854,7 +3004,7 @@ function queue(opts) {
3854
3004
  }
3855
3005
  }
3856
3006
  mw.add = function add(type, payload, opts2) {
3857
- const id2 = crypto4.randomUUID();
3007
+ const id3 = crypto4.randomUUID();
3858
3008
  let runAt;
3859
3009
  if (opts2?.schedule) {
3860
3010
  runAt = cronNext(opts2.schedule);
@@ -3863,9 +3013,9 @@ function queue(opts) {
3863
3013
  } else {
3864
3014
  runAt = Date.now();
3865
3015
  }
3866
- const job = { id: id2, type, payload, createdAt: Date.now(), runAt };
3016
+ const job = { id: id3, type, payload, createdAt: Date.now(), runAt };
3867
3017
  if (opts2?.schedule) job.schedule = opts2.schedule;
3868
- return redis2.zadd(jobKey, runAt, JSON.stringify(job)).then(() => id2);
3018
+ return redis2.zadd(jobKey, runAt, JSON.stringify(job)).then(() => id3);
3869
3019
  };
3870
3020
  mw.process = function process2(type, handler) {
3871
3021
  handlers.set(type, handler);
@@ -4803,8 +3953,8 @@ import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
4803
3953
  // agent/rest.ts
4804
3954
  function buildRouter2(deps) {
4805
3955
  const { agents: agentsTable, knowledge, runner } = deps;
4806
- async function getAgent(id2) {
4807
- const row = await agentsTable.read(id2);
3956
+ async function getAgent(id3) {
3957
+ const row = await agentsTable.read(id3);
4808
3958
  return row ?? null;
4809
3959
  }
4810
3960
  const r = new Router();
@@ -4831,8 +3981,8 @@ function buildRouter2(deps) {
4831
3981
  return Response.json(agent2);
4832
3982
  });
4833
3983
  r.patch("/agents/:id", async (req, ctx) => {
4834
- const id2 = parseInt(ctx.params.id, 10);
4835
- const agent2 = await getAgent(id2);
3984
+ const id3 = parseInt(ctx.params.id, 10);
3985
+ const agent2 = await getAgent(id3);
4836
3986
  if (!agent2) return Response.json({ error: "Agent not found" }, { status: 404 });
4837
3987
  const body = await req.json();
4838
3988
  const updateData = {};
@@ -4844,23 +3994,23 @@ function buildRouter2(deps) {
4844
3994
  if (Object.keys(updateData).length === 0) {
4845
3995
  return Response.json({ error: "No fields to update" }, { status: 400 });
4846
3996
  }
4847
- const row = await agentsTable.update(id2, updateData);
3997
+ const row = await agentsTable.update(id3, updateData);
4848
3998
  return Response.json(row);
4849
3999
  });
4850
4000
  r.delete("/agents/:id", async (_req, ctx) => {
4851
- const id2 = parseInt(ctx.params.id, 10);
4852
- const row = await agentsTable.delete(id2);
4001
+ const id3 = parseInt(ctx.params.id, 10);
4002
+ const row = await agentsTable.delete(id3);
4853
4003
  if (!row) return Response.json({ error: "Agent not found" }, { status: 404 });
4854
4004
  return Response.json({ ok: true });
4855
4005
  });
4856
4006
  r.post("/agents/:id/run", async (req, ctx) => {
4857
- const id2 = parseInt(ctx.params.id, 10);
4007
+ const id3 = parseInt(ctx.params.id, 10);
4858
4008
  const body = await req.json();
4859
4009
  if (!body.input && !body.messages) {
4860
4010
  return Response.json({ error: "input or messages is required" }, { status: 400 });
4861
4011
  }
4862
4012
  try {
4863
- const result = await runner.run(id2, body);
4013
+ const result = await runner.run(id3, body);
4864
4014
  if ("stream" in result) {
4865
4015
  return new Response(result.stream, {
4866
4016
  headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache" }
@@ -5271,15 +4421,15 @@ function buildRouter3(deps) {
5271
4421
  return Response.json(rows);
5272
4422
  });
5273
4423
  r.get("/channels/:id", async (_req, ctx) => {
5274
- const id2 = parseInt(ctx.params.id, 10);
5275
- const ch = await channels.read(id2);
4424
+ const id3 = parseInt(ctx.params.id, 10);
4425
+ const ch = await channels.read(id3);
5276
4426
  if (!ch) return Response.json({ error: "Channel not found" }, { status: 404 });
5277
- const { data: memberRows } = await members.readMany({ channel_id: id2 });
4427
+ const { data: memberRows } = await members.readMany({ channel_id: id3 });
5278
4428
  return Response.json({ channel: ch, members: memberRows });
5279
4429
  });
5280
4430
  r.delete("/channels/:id", async (_req, ctx) => {
5281
- const id2 = parseInt(ctx.params.id, 10);
5282
- await channels.delete(id2);
4431
+ const id3 = parseInt(ctx.params.id, 10);
4432
+ await channels.delete(id3);
5283
4433
  return Response.json({ ok: true });
5284
4434
  });
5285
4435
  r.post("/channels/:id/members", async (req, ctx) => {
@@ -5538,14 +4688,14 @@ function forkApp(opts) {
5538
4688
  return { child, port: opts.port };
5539
4689
  }
5540
4690
  function stopProcess(mp, timeout = 1e4) {
5541
- return new Promise((resolve11) => {
4691
+ return new Promise((resolve12) => {
5542
4692
  const timer = setTimeout(() => {
5543
4693
  mp.child.kill("SIGKILL");
5544
- resolve11();
4694
+ resolve12();
5545
4695
  }, timeout);
5546
4696
  mp.child.on("exit", () => {
5547
4697
  clearTimeout(timer);
5548
- resolve11();
4698
+ resolve12();
5549
4699
  });
5550
4700
  mp.child.kill("SIGTERM");
5551
4701
  });
@@ -5974,6 +5124,366 @@ function ensureCertificates(config) {
5974
5124
  // opencode/client.ts
5975
5125
  import { createOpenAI as createOpenAI3 } from "@ai-sdk/openai";
5976
5126
 
5127
+ // opencode/rest.ts
5128
+ import { join as join4 } from "node:path";
5129
+
5130
+ // ssr/ssr.ts
5131
+ import { createElement } from "react";
5132
+ import { createHash as createHash3 } from "node:crypto";
5133
+ import { dirname as dirname2, resolve as resolve4 } from "node:path";
5134
+ import { AsyncLocalStorage } from "node:async_hooks";
5135
+
5136
+ // ssr/compile.ts
5137
+ import * as esbuild from "esbuild";
5138
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
5139
+ import { join as join2, resolve as resolve3, dirname } from "node:path";
5140
+ import { pathToFileURL } from "node:url";
5141
+ import { createHash as createHash2 } from "node:crypto";
5142
+ var OUT_DIR = ".weifuwu/ssr";
5143
+ var cache = /* @__PURE__ */ new Map();
5144
+ var externals = [
5145
+ "react",
5146
+ "react-dom",
5147
+ "esbuild",
5148
+ "graphql",
5149
+ "ws",
5150
+ "zod",
5151
+ "@graphql-tools/schema",
5152
+ "ai"
5153
+ ];
5154
+ var _alias = null;
5155
+ function resolveAliases() {
5156
+ if (_alias) return _alias;
5157
+ const configFiles = ["tsconfig.json", "jsconfig.json"];
5158
+ for (const file of configFiles) {
5159
+ const p = resolve3(file);
5160
+ if (existsSync2(p)) {
5161
+ try {
5162
+ const config = JSON.parse(readFileSync2(p, "utf-8"));
5163
+ const paths = config.compilerOptions?.paths;
5164
+ if (paths) {
5165
+ const alias = {};
5166
+ for (const [key, values] of Object.entries(paths)) {
5167
+ const cleanKey = key.replace("/*", "");
5168
+ const val = values[0]?.replace("/*", "");
5169
+ if (val) alias[cleanKey] = resolve3(dirname(p), val);
5170
+ }
5171
+ _alias = alias;
5172
+ return alias;
5173
+ }
5174
+ } catch {
5175
+ }
5176
+ }
5177
+ }
5178
+ _alias = {};
5179
+ return {};
5180
+ }
5181
+ function id(s) {
5182
+ return createHash2("md5").update(s).digest("hex").slice(0, 8);
5183
+ }
5184
+ async function compileTsx(path2) {
5185
+ if (cache.has(path2)) return cache.get(path2);
5186
+ const absPath = resolve3(path2);
5187
+ mkdirSync(OUT_DIR, { recursive: true });
5188
+ const hash = id(absPath);
5189
+ const outPath = join2(OUT_DIR, hash + ".js");
5190
+ await esbuild.build({
5191
+ entryPoints: { [hash]: absPath },
5192
+ outdir: OUT_DIR,
5193
+ format: "esm",
5194
+ platform: "node",
5195
+ jsx: "automatic",
5196
+ jsxImportSource: "react",
5197
+ bundle: true,
5198
+ external: externals,
5199
+ alias: resolveAliases(),
5200
+ write: true,
5201
+ allowOverwrite: true
5202
+ });
5203
+ const mod = await import(pathToFileURL(outPath).href);
5204
+ cache.set(path2, mod);
5205
+ return mod;
5206
+ }
5207
+
5208
+ // ssr/stream.ts
5209
+ import { TextDecoder, TextEncoder as TextEncoder2 } from "node:util";
5210
+ var _publicEnv = null;
5211
+ function getPublicEnv() {
5212
+ if (_publicEnv) return _publicEnv;
5213
+ _publicEnv = {};
5214
+ for (const key of Object.keys(process.env)) {
5215
+ if (key.startsWith("WEIFUWU_PUBLIC_")) {
5216
+ _publicEnv[key] = process.env[key];
5217
+ }
5218
+ }
5219
+ return _publicEnv;
5220
+ }
5221
+ function buildHeadPayload(opts) {
5222
+ const { ctx, base, compiledTailwindCss } = opts;
5223
+ let result = "";
5224
+ if (ctx.prefs?.theme) {
5225
+ result += `<script>!function(){var t=(document.cookie.match(/(?:^|;\\s*)theme=([^;]+)/)||[])[1]||'system';if(t==='system'){t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'}document.documentElement.setAttribute('data-theme',t)}()</script>
5226
+ `;
5227
+ }
5228
+ if (compiledTailwindCss) {
5229
+ result += `<link rel="stylesheet" href="${base}/__wfw/style.css" />
5230
+ `;
5231
+ }
5232
+ const localeData = ctx.parsed?.__localeData ?? globalThis.__LOCALE_DATA__;
5233
+ if (localeData && Object.keys(localeData).length > 0) {
5234
+ result += `<script>window.__LOCALE_DATA__=${JSON.stringify(localeData)}</script>
5235
+ `;
5236
+ }
5237
+ const loaderData = opts.loaderData || {};
5238
+ const ctxData = {
5239
+ params: ctx.params,
5240
+ query: ctx.query,
5241
+ user: ctx.user,
5242
+ parsed: ctx.parsed,
5243
+ prefs: ctx.prefs,
5244
+ loaderData
5245
+ };
5246
+ const publicEnv = getPublicEnv();
5247
+ if (Object.keys(publicEnv).length > 0) {
5248
+ ctxData.env = publicEnv;
5249
+ }
5250
+ result += `<script>window.__WEIFUWU_CTX=${JSON.stringify(ctxData)}</script>
5251
+ `;
5252
+ return result;
5253
+ }
5254
+ function buildBodyScripts(opts) {
5255
+ const parts = [];
5256
+ if (opts.loaderData && Object.keys(opts.loaderData).length > 0) {
5257
+ parts.push(`<script>window.__WEIFUWU_PROPS=${JSON.stringify(opts.loaderData)}</script>`);
5258
+ }
5259
+ if (opts.bundle) {
5260
+ parts.push(`<script type="module" src="${opts.base}${opts.bundle.url}"></script>`);
5261
+ }
5262
+ return parts.join("\n");
5263
+ }
5264
+ function streamResponse(reactStream, opts) {
5265
+ const decoder = new TextDecoder();
5266
+ const encoder2 = new TextEncoder2();
5267
+ const headPayload = buildHeadPayload(opts);
5268
+ let buffer = "";
5269
+ let headFlushed = false;
5270
+ let extractedHead = "";
5271
+ const output = new ReadableStream({
5272
+ async start(controller) {
5273
+ try {
5274
+ const reader = reactStream.getReader();
5275
+ async function push(chunk) {
5276
+ buffer += decoder.decode(chunk, { stream: true });
5277
+ if (!extractedHead) {
5278
+ const m = buffer.match(/<template id="__wfw_head">([\s\S]*?)<\/template>/);
5279
+ if (m) {
5280
+ extractedHead = m[1];
5281
+ buffer = buffer.replace(m[0], "");
5282
+ }
5283
+ }
5284
+ if (!headFlushed) {
5285
+ const idx = buffer.indexOf("</head>");
5286
+ if (idx !== -1) {
5287
+ const before = buffer.slice(0, idx);
5288
+ let injection = "";
5289
+ if (extractedHead) injection += "\n" + extractedHead;
5290
+ injection += headPayload;
5291
+ controller.enqueue(encoder2.encode(before + injection));
5292
+ buffer = buffer.slice(idx);
5293
+ headFlushed = true;
5294
+ }
5295
+ return;
5296
+ }
5297
+ controller.enqueue(encoder2.encode(buffer));
5298
+ buffer = "";
5299
+ }
5300
+ while (true) {
5301
+ const { done, value } = await reader.read();
5302
+ if (done) break;
5303
+ await push(value);
5304
+ }
5305
+ buffer = buffer.replace(/<template id="__wfw_head">[\s\S]*?<\/template>/g, "");
5306
+ if (buffer) controller.enqueue(encoder2.encode(buffer));
5307
+ const body = buildBodyScripts(opts);
5308
+ if (body) controller.enqueue(encoder2.encode("\n" + body));
5309
+ if (opts.isDev) {
5310
+ controller.enqueue(encoder2.encode(
5311
+ `
5312
+ <script>(function(){var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'${opts.base}/__weifuwu/livereload');ws.onmessage=function(e){if(e.data==='reload')location.reload()};ws.onclose=function(){setTimeout(function(){location.reload()},500)}})()</script>`
5313
+ ));
5314
+ }
5315
+ } catch {
5316
+ const fallback = `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>500</title></head><body><h1>500 - Internal Server Error</h1></body></html>`;
5317
+ controller.enqueue(encoder2.encode(fallback));
5318
+ } finally {
5319
+ controller.close();
5320
+ }
5321
+ }
5322
+ });
5323
+ return new Response(output, {
5324
+ status: opts.status ?? 200,
5325
+ headers: { "content-type": "text/html; charset=utf-8" }
5326
+ });
5327
+ }
5328
+
5329
+ // ssr/ssr.ts
5330
+ var als = new AsyncLocalStorage();
5331
+ __registerAls(() => als.getStore());
5332
+ var isDev = process.env.NODE_ENV !== "production";
5333
+ function id2(s) {
5334
+ return createHash3("md5").update(s).digest("hex").slice(0, 8);
5335
+ }
5336
+ async function buildClientBundle(entryPath, layoutPaths) {
5337
+ try {
5338
+ const absEntry = resolve4(entryPath);
5339
+ const absLayouts = layoutPaths.map((p) => resolve4(p));
5340
+ const layoutImports = absLayouts.map((p) => `import${JSON.stringify(p)};`).join("");
5341
+ const _sc = `(function(){var k='__WEIFUWU_CTX_STORE';var s=typeof globalThis!='undefined'&&globalThis[k];if(!s)return function(){};return function(v){s._ctx={...s._ctx,...v};s._snapshot={params:s._ctx.params,query:s._ctx.query,user:s._ctx.user,parsed:s._ctx.parsed,prefs:s._ctx.prefs,env:s._ctx.env};s._listeners.forEach(function(fn){fn()})}})()`;
5342
+ const code = [
5343
+ layoutImports,
5344
+ `import{hydrateRoot}from'react-dom/client';`,
5345
+ `import{createElement,useState,useEffect}from'react';`,
5346
+ `import{TsxContext}from'weifuwu/react';`,
5347
+ `import P from${JSON.stringify(absEntry)};`,
5348
+ `var setCtx=${_sc};`,
5349
+ `const c=document.getElementById('__weifuwu_root');`,
5350
+ `if(window.__WEIFUWU_PROPS)setCtx({loaderData:window.__WEIFUWU_PROPS});`,
5351
+ `if(!window.__WFW_ROOT){`,
5352
+ `function App(){`,
5353
+ `const[p,setP]=useState({C:P});`,
5354
+ `useEffect(()=>{window.__WFW_SET_PAGE=(C)=>{setCtx({loaderData:window.__WEIFUWU_PROPS});setP({C})}},[]);`,
5355
+ `const ctx=window.__WEIFUWU_CTX||{};`,
5356
+ `return createElement(TsxContext.Provider,{value:ctx},`,
5357
+ `createElement(p.C,null))`,
5358
+ `}`,
5359
+ `window.__WFW_ROOT=hydrateRoot(c,createElement(App));`,
5360
+ `}else{`,
5361
+ `window.__WFW_SET_PAGE?.(P);`,
5362
+ `}`
5363
+ ].join("");
5364
+ const { default: esbuild2 } = await import("esbuild");
5365
+ const result = await esbuild2.build({
5366
+ stdin: { contents: code, loader: "tsx", resolveDir: dirname2(absEntry) },
5367
+ bundle: true,
5368
+ format: "esm",
5369
+ jsx: "automatic",
5370
+ jsxImportSource: "react",
5371
+ banner: { js: "self.process={env:{}};" },
5372
+ loader: { ".node": "empty" },
5373
+ write: false,
5374
+ minify: true
5375
+ });
5376
+ return result.outputFiles[0].contents;
5377
+ } catch (err) {
5378
+ console.error("hydration bundle failed:", err);
5379
+ return null;
5380
+ }
5381
+ }
5382
+ var bundleRegistry = /* @__PURE__ */ new Map();
5383
+ function serializeLoaderData(ctx) {
5384
+ const data = {};
5385
+ for (const key of Object.keys(ctx)) {
5386
+ if (!["params", "query", "mountPath", "layoutStack"].includes(key)) {
5387
+ data[key] = ctx[key];
5388
+ }
5389
+ }
5390
+ return data;
5391
+ }
5392
+ function ssr(path2) {
5393
+ const entryId = id2(resolve4(path2));
5394
+ const bundleKey = `/__ssr/${entryId}.js`;
5395
+ let bundleBuilt = false;
5396
+ return async (req, ctx) => {
5397
+ const pageMod = await compileTsx(path2);
5398
+ const Component = pageMod.default;
5399
+ if (!Component) return new Response("", { status: 500 });
5400
+ const layouts = ctx.layoutStack || [];
5401
+ const layoutComponents = layouts.map((l) => l.component);
5402
+ const layoutPaths = layouts.map((l) => l.path);
5403
+ const base = (ctx.mountPath || "").replace(/\/$/, "");
5404
+ const loaderData = serializeLoaderData(ctx);
5405
+ const ctxValue = {
5406
+ params: ctx.params,
5407
+ query: ctx.query,
5408
+ user: ctx.user ?? {},
5409
+ parsed: ctx.parsed ?? {},
5410
+ prefs: ctx.prefs ?? {},
5411
+ loaderData,
5412
+ env: ctx.env ?? {}
5413
+ };
5414
+ return als.run(ctxValue, async () => {
5415
+ setCtx(ctxValue);
5416
+ let element = createElement(
5417
+ TsxContext.Provider,
5418
+ { value: ctxValue },
5419
+ createElement(
5420
+ "div",
5421
+ { id: "__weifuwu_root" },
5422
+ createElement(Component, null)
5423
+ )
5424
+ );
5425
+ if (layoutComponents.length === 0) {
5426
+ element = createElement(
5427
+ "html",
5428
+ { lang: "en" },
5429
+ createElement(
5430
+ "head",
5431
+ null,
5432
+ createElement("meta", { charSet: "utf-8" }),
5433
+ createElement("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
5434
+ createElement("title", null, "weifuwu")
5435
+ ),
5436
+ createElement("body", null, element)
5437
+ );
5438
+ } else {
5439
+ for (const L of layoutComponents.toReversed()) {
5440
+ element = createElement(L, { children: element });
5441
+ }
5442
+ }
5443
+ let bundle = null;
5444
+ if (!bundleBuilt) {
5445
+ const buf = await buildClientBundle(path2, layoutPaths);
5446
+ if (buf) {
5447
+ bundleRegistry.set(bundleKey, buf);
5448
+ bundleBuilt = true;
5449
+ }
5450
+ }
5451
+ if (bundleRegistry.has(bundleKey)) {
5452
+ bundle = { url: bundleKey };
5453
+ }
5454
+ const { renderToReadableStream } = await import("react-dom/server");
5455
+ const stream = await renderToReadableStream(element);
5456
+ return streamResponse(stream, {
5457
+ ctx,
5458
+ base,
5459
+ isDev,
5460
+ bundle,
5461
+ loaderData
5462
+ });
5463
+ });
5464
+ };
5465
+ }
5466
+
5467
+ // ssr/layout.ts
5468
+ function layout(path2) {
5469
+ return async (req, ctx, next) => {
5470
+ const mod = await compileTsx(path2);
5471
+ const Component = mod.default;
5472
+ if (!Component) throw new Error(`Layout ${path2} has no default export`);
5473
+ ctx.layoutStack = [...ctx.layoutStack || [], { path: path2, component: Component }];
5474
+ return next(req, ctx);
5475
+ };
5476
+ }
5477
+
5478
+ // ssr/tailwind.ts
5479
+ var isDev2 = process.env.NODE_ENV !== "production";
5480
+
5481
+ // ssr/error-boundary.ts
5482
+ import { createElement as createElement2 } from "react";
5483
+
5484
+ // ssr/live.ts
5485
+ import chokidar from "chokidar";
5486
+
5977
5487
  // opencode/session.ts
5978
5488
  import { randomUUID as randomUUID2 } from "node:crypto";
5979
5489
  import { join as join3 } from "node:path";
@@ -6001,12 +5511,12 @@ var messages = pgTable("_opencode_messages", {
6001
5511
  created_at: timestamptz("created_at")
6002
5512
  });
6003
5513
  async function createSession(sql2, opts, cwd, mountPath) {
6004
- const id2 = randomUUID2();
6005
- const ws = computeSessionWorkspace(cwd, mountPath, id2);
5514
+ const id3 = randomUUID2();
5515
+ const ws = computeSessionWorkspace(cwd, mountPath, id3);
6006
5516
  await mkdir2(ws, { recursive: true });
6007
5517
  const [row] = await sql2`
6008
5518
  INSERT INTO "_opencode_sessions" ("id", "user_id", "title", "model", "workspace", "system_prompt")
6009
- VALUES (${id2}, ${opts.userId ?? 0}, ${opts.title ?? null}, ${opts.model ?? "deepseek-v4-flash"}, ${ws}, ${opts.systemPrompt ?? null})
5519
+ VALUES (${id3}, ${opts.userId ?? 0}, ${opts.title ?? null}, ${opts.model ?? "deepseek-v4-flash"}, ${ws}, ${opts.systemPrompt ?? null})
6010
5520
  RETURNING *
6011
5521
  `;
6012
5522
  return row;
@@ -6015,8 +5525,8 @@ function computeSessionWorkspace(cwd, mountPath, sessionId) {
6015
5525
  const name = !mountPath || mountPath === "/" ? "default" : mountPath.replace(/^\//, "");
6016
5526
  return join3(cwd, ".sessions", name, sessionId);
6017
5527
  }
6018
- async function getSession(sql2, id2) {
6019
- const { data: rows } = await sessions.readMany(sql2, { id: id2, active: true });
5528
+ async function getSession(sql2, id3) {
5529
+ const { data: rows } = await sessions.readMany(sql2, { id: id3, active: true });
6020
5530
  return rows[0] ?? null;
6021
5531
  }
6022
5532
  async function listSessions(sql2, userId) {
@@ -6028,8 +5538,8 @@ async function listSessions(sql2, userId) {
6028
5538
  const { data: rows } = await sessions.readMany(sql2, { active: true }, opts);
6029
5539
  return rows;
6030
5540
  }
6031
- async function deleteSession(sql2, id2) {
6032
- await sessions.update(sql2, id2, { active: false, updated_at: sql`NOW()` });
5541
+ async function deleteSession(sql2, id3) {
5542
+ await sessions.update(sql2, id3, { active: false, updated_at: sql`NOW()` });
6033
5543
  }
6034
5544
  async function getHistory(sql2, sessionId, limit = 50) {
6035
5545
  const { data: rows } = await messages.readMany(sql2, { session_id: sessionId }, {
@@ -6210,10 +5720,10 @@ function createBashTool(ctx) {
6210
5720
  return { stdout: "", stderr: "Command denied: potentially dangerous command", exitCode: 1 };
6211
5721
  }
6212
5722
  const cwd = workdir ? `${ctx.workspace}/${workdir}` : ctx.workspace;
6213
- return new Promise((resolve11) => {
5723
+ return new Promise((resolve12) => {
6214
5724
  const child = exec(command, { cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
6215
5725
  const truncated = stdout.length > 1e6 || stderr.length > 1e6;
6216
- resolve11({
5726
+ resolve12({
6217
5727
  stdout: stdout.slice(0, 1e6),
6218
5728
  stderr: stderr.slice(0, 1e6),
6219
5729
  exitCode: error?.code ?? 0,
@@ -6230,7 +5740,7 @@ function createBashTool(ctx) {
6230
5740
  import { tool as tool4 } from "ai";
6231
5741
  import { z as z6 } from "zod";
6232
5742
  import { readFileSync as readFileSync3 } from "node:fs";
6233
- import { resolve as resolve4 } from "node:path";
5743
+ import { resolve as resolve5 } from "node:path";
6234
5744
  function createReadTool(ctx) {
6235
5745
  return tool4({
6236
5746
  description: "Read file contents. Supports offset and limit for reading specific line ranges.",
@@ -6240,7 +5750,7 @@ function createReadTool(ctx) {
6240
5750
  limit: z6.number().optional().describe("Number of lines to read")
6241
5751
  }),
6242
5752
  execute: async ({ path: path2, offset, limit }) => {
6243
- const resolved = resolve4(ctx.workspace, path2);
5753
+ const resolved = resolve5(ctx.workspace, path2);
6244
5754
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions)) {
6245
5755
  return { error: "Path not allowed", content: null, totalLines: 0 };
6246
5756
  }
@@ -6271,8 +5781,8 @@ function createReadTool(ctx) {
6271
5781
  // opencode/tools/write.ts
6272
5782
  import { tool as tool5 } from "ai";
6273
5783
  import { z as z7 } from "zod";
6274
- import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
6275
- import { resolve as resolve5, dirname as dirname2 } from "node:path";
5784
+ import { writeFileSync, mkdirSync as mkdirSync2 } from "node:fs";
5785
+ import { resolve as resolve6, dirname as dirname3 } from "node:path";
6276
5786
  function createWriteTool(ctx) {
6277
5787
  return tool5({
6278
5788
  description: "Create or overwrite a file. Parent directories are created automatically.",
@@ -6281,12 +5791,12 @@ function createWriteTool(ctx) {
6281
5791
  content: z7.string().describe("File content")
6282
5792
  }),
6283
5793
  execute: async ({ path: path2, content }) => {
6284
- const resolved = resolve5(ctx.workspace, path2);
5794
+ const resolved = resolve6(ctx.workspace, path2);
6285
5795
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions)) {
6286
5796
  return { error: "Path not allowed" };
6287
5797
  }
6288
- mkdirSync2(dirname2(resolved), { recursive: true });
6289
- writeFileSync2(resolved, content, "utf-8");
5798
+ mkdirSync2(dirname3(resolved), { recursive: true });
5799
+ writeFileSync(resolved, content, "utf-8");
6290
5800
  return { path: path2, size: content.length };
6291
5801
  }
6292
5802
  });
@@ -6295,8 +5805,8 @@ function createWriteTool(ctx) {
6295
5805
  // opencode/tools/edit.ts
6296
5806
  import { tool as tool6 } from "ai";
6297
5807
  import { z as z8 } from "zod";
6298
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
6299
- import { resolve as resolve6 } from "node:path";
5808
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "node:fs";
5809
+ import { resolve as resolve7 } from "node:path";
6300
5810
  function createEditTool(ctx) {
6301
5811
  return tool6({
6302
5812
  description: "Perform exact string replacements in a file. If oldString appears multiple times, provide more surrounding context.",
@@ -6307,7 +5817,7 @@ function createEditTool(ctx) {
6307
5817
  replaceAll: z8.boolean().default(false).describe("Replace all occurrences")
6308
5818
  }),
6309
5819
  execute: async ({ path: path2, oldString, newString, replaceAll }) => {
6310
- const resolved = resolve6(ctx.workspace, path2);
5820
+ const resolved = resolve7(ctx.workspace, path2);
6311
5821
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions)) {
6312
5822
  return { error: "Path not allowed" };
6313
5823
  }
@@ -6318,7 +5828,7 @@ function createEditTool(ctx) {
6318
5828
  }
6319
5829
  const count = content.split(oldString).length - 1;
6320
5830
  const result2 = content.replaceAll(oldString, newString);
6321
- writeFileSync3(resolved, result2, "utf-8");
5831
+ writeFileSync2(resolved, result2, "utf-8");
6322
5832
  return { path: path2, replaced: count };
6323
5833
  }
6324
5834
  const firstIdx = content.indexOf(oldString);
@@ -6330,7 +5840,7 @@ function createEditTool(ctx) {
6330
5840
  return { error: "Found multiple matches. Provide more surrounding context in oldString.", replaced: 0 };
6331
5841
  }
6332
5842
  const result = content.replace(oldString, newString);
6333
- writeFileSync3(resolved, result, "utf-8");
5843
+ writeFileSync2(resolved, result, "utf-8");
6334
5844
  return { path: path2, replaced: 1 };
6335
5845
  }
6336
5846
  });
@@ -6340,7 +5850,7 @@ function createEditTool(ctx) {
6340
5850
  import { tool as tool7 } from "ai";
6341
5851
  import { z as z9 } from "zod";
6342
5852
  import { execFileSync } from "node:child_process";
6343
- import { resolve as resolve7 } from "node:path";
5853
+ import { resolve as resolve8 } from "node:path";
6344
5854
  import { existsSync as existsSync3 } from "node:fs";
6345
5855
  function createGrepTool(ctx) {
6346
5856
  return tool7({
@@ -6352,7 +5862,7 @@ function createGrepTool(ctx) {
6352
5862
  context: z9.number().default(0).describe("Number of context lines before and after each match")
6353
5863
  }),
6354
5864
  execute: async ({ pattern, include, path: path2, context }) => {
6355
- const searchDir = path2 ? resolve7(ctx.workspace, path2) : ctx.workspace;
5865
+ const searchDir = path2 ? resolve8(ctx.workspace, path2) : ctx.workspace;
6356
5866
  try {
6357
5867
  let stdout;
6358
5868
  if (existsSync3("/usr/bin/rg") || existsSync3("/usr/local/bin/rg")) {
@@ -6384,7 +5894,7 @@ function createGrepTool(ctx) {
6384
5894
  import { tool as tool8 } from "ai";
6385
5895
  import { z as z10 } from "zod";
6386
5896
  import { execFileSync as execFileSync2 } from "node:child_process";
6387
- import { resolve as resolve8 } from "node:path";
5897
+ import { resolve as resolve9 } from "node:path";
6388
5898
  function createGlobTool(ctx) {
6389
5899
  return tool8({
6390
5900
  description: "Find files matching a glob pattern.",
@@ -6393,7 +5903,7 @@ function createGlobTool(ctx) {
6393
5903
  path: z10.string().optional().describe("Subdirectory relative to workspace")
6394
5904
  }),
6395
5905
  execute: async ({ pattern, path: path2 }) => {
6396
- const searchDir = path2 ? resolve8(ctx.workspace, path2) : ctx.workspace;
5906
+ const searchDir = path2 ? resolve9(ctx.workspace, path2) : ctx.workspace;
6397
5907
  try {
6398
5908
  const stdout = execFileSync2("find", [
6399
5909
  searchDir,
@@ -6454,7 +5964,7 @@ function createQuestionTool(ctx) {
6454
5964
  options: z12.array(z12.string()).optional().describe("Optional multiple choice options")
6455
5965
  }),
6456
5966
  execute: async ({ question, options }, { toolCallId }) => {
6457
- return new Promise((resolve11, reject) => {
5967
+ return new Promise((resolve12, reject) => {
6458
5968
  const timeout = setTimeout(() => {
6459
5969
  ctx.pendingQuestions.delete(toolCallId);
6460
5970
  reject(new Error("Question timed out"));
@@ -6462,7 +5972,7 @@ function createQuestionTool(ctx) {
6462
5972
  ctx.pendingQuestions.set(toolCallId, {
6463
5973
  resolve: (answer) => {
6464
5974
  clearTimeout(timeout);
6465
- resolve11(answer);
5975
+ resolve12(answer);
6466
5976
  },
6467
5977
  reject: (err) => {
6468
5978
  clearTimeout(timeout);
@@ -6563,15 +6073,15 @@ async function buildRouter4(deps) {
6563
6073
  return Response.json(sessions2);
6564
6074
  });
6565
6075
  router.get("/sessions/:id", async (_req, ctx) => {
6566
- const id2 = ctx.params.id;
6567
- const session = await getSession(sql2, id2);
6076
+ const id3 = ctx.params.id;
6077
+ const session = await getSession(sql2, id3);
6568
6078
  if (!session) return new Response("Not Found", { status: 404 });
6569
- const messages2 = await getHistory(sql2, id2);
6079
+ const messages2 = await getHistory(sql2, id3);
6570
6080
  return Response.json({ session, messages: messages2 });
6571
6081
  });
6572
6082
  router.delete("/sessions/:id", async (_req, ctx) => {
6573
- const id2 = ctx.params.id;
6574
- await deleteSession(sql2, id2);
6083
+ const id3 = ctx.params.id;
6084
+ await deleteSession(sql2, id3);
6575
6085
  return new Response(null, { status: 204 });
6576
6086
  });
6577
6087
  router.post("/sessions/:id/message", async (req, ctx) => {
@@ -6609,8 +6119,8 @@ async function buildRouter4(deps) {
6609
6119
  });
6610
6120
  try {
6611
6121
  const uiDir = new URL("../opencode/ui/", import.meta.url).pathname;
6612
- const uiRouter = await tsx({ dir: uiDir });
6613
- router.use("/", uiRouter);
6122
+ router.use(layout(join4(uiDir, "layout.tsx")));
6123
+ router.get("/", ssr(join4(uiDir, "page.tsx")));
6614
6124
  } catch (e) {
6615
6125
  console.warn("[opencode] UI not available:", e);
6616
6126
  }
@@ -6745,7 +6255,7 @@ function createWSHandler2(deps) {
6745
6255
  import { readFile } from "node:fs/promises";
6746
6256
  import { glob } from "node:fs/promises";
6747
6257
  import { homedir } from "node:os";
6748
- import { resolve as resolve9 } from "node:path";
6258
+ import { resolve as resolve10 } from "node:path";
6749
6259
  import { parse as parseYaml } from "yaml";
6750
6260
  var SEARCH_DIRS = [
6751
6261
  (ws) => `${ws}/.opencode/skills`,
@@ -6783,7 +6293,7 @@ async function scanDir(dir) {
6783
6293
  try {
6784
6294
  const files = [];
6785
6295
  for await (const entry of glob("*/SKILL.md", { cwd: dir })) {
6786
- const skill = await parseSkillFile(resolve9(dir, entry));
6296
+ const skill = await parseSkillFile(resolve10(dir, entry));
6787
6297
  if (skill) files.push(skill);
6788
6298
  }
6789
6299
  return files;
@@ -7119,7 +6629,7 @@ function analytics(options) {
7119
6629
  // preferences.ts
7120
6630
  import { readFile as readFile2 } from "node:fs/promises";
7121
6631
  import { existsSync as existsSync4 } from "node:fs";
7122
- import { join as join4, resolve as resolve10 } from "node:path";
6632
+ import { join as join5, resolve as resolve11 } from "node:path";
7123
6633
  var defaults = {
7124
6634
  locale: { default: "en", cookie: "locale", fromAcceptLanguage: true },
7125
6635
  theme: { default: "system", cookie: "theme" }
@@ -7168,24 +6678,24 @@ async function handlePrefSwitch(req, value, cookieName, load) {
7168
6678
  });
7169
6679
  }
7170
6680
  function preferences(options) {
7171
- const dir = options.dir ? resolve10(options.dir) : void 0;
6681
+ const dir = options.dir ? resolve11(options.dir) : void 0;
7172
6682
  const localeOpts = { ...defaults.locale, ...options.locale };
7173
6683
  const themeOpts = { ...defaults.theme, ...options.theme };
7174
- const cache = /* @__PURE__ */ new Map();
6684
+ const cache2 = /* @__PURE__ */ new Map();
7175
6685
  function validLocale(locale) {
7176
6686
  return /^[\w-]+$/.test(locale) && !locale.includes("..");
7177
6687
  }
7178
6688
  async function load(locale) {
7179
6689
  if (!dir) return {};
7180
6690
  if (!validLocale(locale)) return {};
7181
- const cached = cache.get(locale);
6691
+ const cached = cache2.get(locale);
7182
6692
  if (cached) return cached;
7183
- const filePath = join4(dir, `${locale}.json`);
6693
+ const filePath = join5(dir, `${locale}.json`);
7184
6694
  if (!existsSync4(filePath)) return {};
7185
6695
  try {
7186
6696
  const content = await readFile2(filePath, "utf-8");
7187
6697
  const data = JSON.parse(content);
7188
- cache.set(locale, data);
6698
+ cache2.set(locale, data);
7189
6699
  return data;
7190
6700
  } catch {
7191
6701
  return {};
@@ -7532,9 +7042,9 @@ function listHandler(entries) {
7532
7042
  }
7533
7043
  function getHandler(entries) {
7534
7044
  return async (_req, ctx) => {
7535
- const id2 = ctx.params?.id;
7536
- if (!id2) return Response.json({ error: "id is required" }, { status: 400 });
7537
- const row = await entries.read(parseInt(id2));
7045
+ const id3 = ctx.params?.id;
7046
+ if (!id3) return Response.json({ error: "id is required" }, { status: 400 });
7047
+ const row = await entries.read(parseInt(id3));
7538
7048
  if (!row) return Response.json({ error: "not found" }, { status: 404 });
7539
7049
  return Response.json(parseMetadata(row));
7540
7050
  };
@@ -7752,8 +7262,8 @@ function createMemoryStore(channels) {
7752
7262
  }));
7753
7263
  return { streams, count: streams.length };
7754
7264
  },
7755
- async send(stream, group, type, data, id2) {
7756
- notify(channels, stream, group, id2 ?? "", "send", { type, data });
7265
+ async send(stream, group, type, data, id3) {
7266
+ notify(channels, stream, group, id3 ?? "", "send", { type, data });
7757
7267
  },
7758
7268
  async update(stream, group, item, ops) {
7759
7269
  const k = key(stream, group, item);
@@ -7833,8 +7343,8 @@ function createPgStore(channels, pg) {
7833
7343
  }));
7834
7344
  return { streams, count: streams.length };
7835
7345
  },
7836
- async send(stream, group, type, data, id2) {
7837
- notify(channels, stream, group, id2 ?? "", "send", { type, data });
7346
+ async send(stream, group, type, data, id3) {
7347
+ notify(channels, stream, group, id3 ?? "", "send", { type, data });
7838
7348
  },
7839
7349
  async update(stream, group, item, ops) {
7840
7350
  const { value: oldVal } = await this.get(stream, group, item);
@@ -7930,8 +7440,8 @@ function createRedisStore(channels, redis2, ttl) {
7930
7440
  }));
7931
7441
  return { streams, count: streams.length };
7932
7442
  },
7933
- async send(stream, group, type, data, id2) {
7934
- notify(channels, stream, group, id2 ?? "", "send", { type, data });
7443
+ async send(stream, group, type, data, id3) {
7444
+ notify(channels, stream, group, id3 ?? "", "send", { type, data });
7935
7445
  },
7936
7446
  async update(stream, group, item, ops) {
7937
7447
  const hk = hashKey(stream, group);
@@ -8144,9 +7654,9 @@ function iii(opts = {}) {
8144
7654
  const functions = /* @__PURE__ */ new Map();
8145
7655
  const triggers = /* @__PURE__ */ new Map();
8146
7656
  const pending = /* @__PURE__ */ new Map();
8147
- function registerBuiltin(id2, handler) {
8148
- functions.set(id2, {
8149
- id: id2,
7657
+ function registerBuiltin(id3, handler) {
7658
+ functions.set(id3, {
7659
+ id: id3,
8150
7660
  handler,
8151
7661
  workerId: "__iii__",
8152
7662
  workerName: "__iii__",
@@ -8201,34 +7711,34 @@ function iii(opts = {}) {
8201
7711
  }
8202
7712
  workers.set(workerId, reg);
8203
7713
  }
8204
- function addRemoteFunction(workerId, id2) {
7714
+ function addRemoteFunction(workerId, id3) {
8205
7715
  const worker = workers.get(workerId);
8206
7716
  if (!worker) return;
8207
7717
  const handler = async (payload) => {
8208
7718
  if (!worker.ws) throw new Error(`Worker "${worker.name}" disconnected`);
8209
7719
  const invocationId = crypto6.randomUUID();
8210
- return new Promise((resolve11, reject) => {
7720
+ return new Promise((resolve12, reject) => {
8211
7721
  const timer = setTimeout(() => {
8212
7722
  pending.delete(invocationId);
8213
- reject(new Error(`Invocation timed out for "${id2}"`));
7723
+ reject(new Error(`Invocation timed out for "${id3}"`));
8214
7724
  }, 3e4);
8215
- pending.set(invocationId, { resolve: resolve11, reject, timer });
7725
+ pending.set(invocationId, { resolve: resolve12, reject, timer });
8216
7726
  worker.ws.send(JSON.stringify({
8217
7727
  type: "invoke",
8218
7728
  invocation_id: invocationId,
8219
- function_id: id2,
7729
+ function_id: id3,
8220
7730
  payload
8221
7731
  }));
8222
7732
  });
8223
7733
  };
8224
7734
  const fnReg = {
8225
- id: id2,
7735
+ id: id3,
8226
7736
  handler,
8227
7737
  workerId,
8228
7738
  workerName: worker.name,
8229
7739
  triggers: []
8230
7740
  };
8231
- functions.set(id2, fnReg);
7741
+ functions.set(id3, fnReg);
8232
7742
  worker.functions.push(fnReg);
8233
7743
  }
8234
7744
  function removeWorker(workerId) {
@@ -8241,15 +7751,15 @@ function iii(opts = {}) {
8241
7751
  let engineRef = null;
8242
7752
  const wsHandler = createWsHandler({
8243
7753
  registerRemoteWorker(ws, name) {
8244
- const id2 = crypto6.randomUUID();
8245
- workers.set(id2, { id: id2, name, ws, functions: [], triggers: [] });
8246
- return id2;
7754
+ const id3 = crypto6.randomUUID();
7755
+ workers.set(id3, { id: id3, name, ws, functions: [], triggers: [] });
7756
+ return id3;
8247
7757
  },
8248
7758
  unregisterRemoteWorker(workerId) {
8249
7759
  removeWorker(workerId);
8250
7760
  },
8251
- registerRemoteFunction(workerId, id2) {
8252
- addRemoteFunction(workerId, id2);
7761
+ registerRemoteFunction(workerId, id3) {
7762
+ addRemoteFunction(workerId, id3);
8253
7763
  },
8254
7764
  registerRemoteTrigger(workerId, input) {
8255
7765
  const tid = crypto6.randomUUID();
@@ -8258,11 +7768,11 @@ function iii(opts = {}) {
8258
7768
  const worker = workers.get(workerId);
8259
7769
  if (worker) worker.triggers.push(reg);
8260
7770
  },
8261
- unregisterRemoteFunction(workerId, id2) {
8262
- functions.delete(id2);
7771
+ unregisterRemoteFunction(workerId, id3) {
7772
+ functions.delete(id3);
8263
7773
  const worker = workers.get(workerId);
8264
7774
  if (worker) {
8265
- worker.functions = worker.functions.filter((f) => f.id !== id2);
7775
+ worker.functions = worker.functions.filter((f) => f.id !== id3);
8266
7776
  }
8267
7777
  },
8268
7778
  unregisterRemoteTrigger(workerId, functionId) {
@@ -8397,12 +7907,12 @@ function createWorker(name) {
8397
7907
  const triggers = /* @__PURE__ */ new Map();
8398
7908
  return {
8399
7909
  name,
8400
- registerFunction(id2, handler) {
8401
- functions.set(id2, handler);
7910
+ registerFunction(id3, handler) {
7911
+ functions.set(id3, handler);
8402
7912
  return this;
8403
7913
  },
8404
- unregisterFunction(id2) {
8405
- functions.delete(id2);
7914
+ unregisterFunction(id3) {
7915
+ functions.delete(id3);
8406
7916
  return this;
8407
7917
  },
8408
7918
  registerTrigger(input) {
@@ -8414,10 +7924,10 @@ function createWorker(name) {
8414
7924
  return this;
8415
7925
  },
8416
7926
  getFunctions() {
8417
- return Array.from(functions.entries()).map(([id2, handler]) => ({ id: id2, handler }));
7927
+ return Array.from(functions.entries()).map(([id3, handler]) => ({ id: id3, handler }));
8418
7928
  },
8419
7929
  getTriggers() {
8420
- return Array.from(triggers.entries()).map(([id2, input]) => ({ id: id2, input }));
7930
+ return Array.from(triggers.entries()).map(([id3, input]) => ({ id: id3, input }));
8421
7931
  }
8422
7932
  };
8423
7933
  }
@@ -8453,8 +7963,8 @@ function registerWorker(url) {
8453
7963
  function connect() {
8454
7964
  if (intentionalClose) return;
8455
7965
  ws = new WebSocket(url);
8456
- ready = new Promise((resolve11) => {
8457
- resolveReady = resolve11;
7966
+ ready = new Promise((resolve12) => {
7967
+ resolveReady = resolve12;
8458
7968
  });
8459
7969
  ws.onopen = () => {
8460
7970
  reconnectAttempt = 0;
@@ -8537,15 +8047,15 @@ function registerWorker(url) {
8537
8047
  }
8538
8048
  connect();
8539
8049
  return {
8540
- registerFunction(id2, handler) {
8541
- handlers.set(id2, handler);
8542
- registeredFunctionIds.add(id2);
8543
- send({ type: "register_function", id: id2 });
8050
+ registerFunction(id3, handler) {
8051
+ handlers.set(id3, handler);
8052
+ registeredFunctionIds.add(id3);
8053
+ send({ type: "register_function", id: id3 });
8544
8054
  },
8545
- unregisterFunction(id2) {
8546
- handlers.delete(id2);
8547
- registeredFunctionIds.delete(id2);
8548
- send({ type: "unregister_function", id: id2 });
8055
+ unregisterFunction(id3) {
8056
+ handlers.delete(id3);
8057
+ registeredFunctionIds.delete(id3);
8058
+ send({ type: "unregister_function", id: id3 });
8549
8059
  },
8550
8060
  registerTrigger(input) {
8551
8061
  registeredTriggers.add(JSON.stringify(input));
@@ -8574,13 +8084,13 @@ function registerWorker(url) {
8574
8084
  }
8575
8085
  return Promise.resolve(fn(request.payload, ctx));
8576
8086
  }
8577
- return new Promise((resolve11, reject) => {
8087
+ return new Promise((resolve12, reject) => {
8578
8088
  const invocationId = genId();
8579
8089
  const timer = setTimeout(() => {
8580
8090
  pendingInvocations.delete(invocationId);
8581
8091
  reject(new Error(`Invocation timed out for "${request.function_id}"`));
8582
8092
  }, request.timeout_ms || 3e4);
8583
- pendingInvocations.set(invocationId, { resolve: resolve11, reject, timer });
8093
+ pendingInvocations.set(invocationId, { resolve: resolve12, reject, timer });
8584
8094
  send({
8585
8095
  type: "invoke",
8586
8096
  invocation_id: invocationId,
@@ -8655,7 +8165,6 @@ export {
8655
8165
  streamText,
8656
8166
  tenant,
8657
8167
  tool2 as tool,
8658
- tsx,
8659
8168
  upload,
8660
8169
  user,
8661
8170
  validate