weifuwu 0.24.2 → 0.24.3
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/compile.d.ts +7 -12
- package/dist/index.js +465 -312
- package/dist/module-server.d.ts +10 -0
- package/dist/server-registry.d.ts +12 -0
- package/dist/stream.d.ts +0 -5
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -65,7 +65,8 @@ function isBundled() {
|
|
|
65
65
|
return true ? true : false;
|
|
66
66
|
}
|
|
67
67
|
function isDev() {
|
|
68
|
-
|
|
68
|
+
const env2 = process.env.NODE_ENV;
|
|
69
|
+
return env2 !== "production" && env2 !== "test";
|
|
69
70
|
}
|
|
70
71
|
function isProd() {
|
|
71
72
|
return process.env.NODE_ENV === "production";
|
|
@@ -293,20 +294,20 @@ function serve(handler, options) {
|
|
|
293
294
|
process.off("SIGINT", shutdownHandler);
|
|
294
295
|
shutdownHandler = null;
|
|
295
296
|
}
|
|
296
|
-
return new Promise((
|
|
297
|
+
return new Promise((resolve16) => {
|
|
297
298
|
if (!server.listening) {
|
|
298
|
-
|
|
299
|
+
resolve16();
|
|
299
300
|
return;
|
|
300
301
|
}
|
|
301
302
|
server.close();
|
|
302
303
|
server.closeIdleConnections();
|
|
303
304
|
const timer = setTimeout(() => {
|
|
304
305
|
server.closeAllConnections();
|
|
305
|
-
|
|
306
|
+
resolve16();
|
|
306
307
|
}, timeoutMs);
|
|
307
308
|
server.on("close", () => {
|
|
308
309
|
clearTimeout(timer);
|
|
309
|
-
|
|
310
|
+
resolve16();
|
|
310
311
|
});
|
|
311
312
|
});
|
|
312
313
|
},
|
|
@@ -1487,7 +1488,7 @@ function upload(options) {
|
|
|
1487
1488
|
}
|
|
1488
1489
|
|
|
1489
1490
|
// rate-limit.ts
|
|
1490
|
-
function defaultKey(_req,
|
|
1491
|
+
function defaultKey(_req, _ctx2) {
|
|
1491
1492
|
const forwarded = _req.headers.get("x-forwarded-for");
|
|
1492
1493
|
if (forwarded) return forwarded.split(",")[0].trim();
|
|
1493
1494
|
const realIp = _req.headers.get("x-real-ip");
|
|
@@ -3317,7 +3318,7 @@ h2{color:#dc2626}.desc{color:#555}</style>
|
|
|
3317
3318
|
{ status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } }
|
|
3318
3319
|
);
|
|
3319
3320
|
}
|
|
3320
|
-
async function authorizeHandler(req,
|
|
3321
|
+
async function authorizeHandler(req, _ctx2) {
|
|
3321
3322
|
const url = new URL(req.url);
|
|
3322
3323
|
const clientId = url.searchParams.get("client_id") || "";
|
|
3323
3324
|
const redirectUri = url.searchParams.get("redirect_uri") || "";
|
|
@@ -5590,23 +5591,23 @@ function buildGraphQLHandler(sql2) {
|
|
|
5590
5591
|
});
|
|
5591
5592
|
return Response.json(result, { status: result.errors ? 400 : 200 });
|
|
5592
5593
|
});
|
|
5593
|
-
r.get("/", async (req,
|
|
5594
|
+
r.get("/", async (req, _ctx2) => {
|
|
5594
5595
|
const url = new URL(req.url);
|
|
5595
5596
|
if (url.searchParams.has("query")) {
|
|
5596
|
-
return handleGET(req,
|
|
5597
|
+
return handleGET(req, _ctx2);
|
|
5597
5598
|
}
|
|
5598
5599
|
return new Response("GraphQL endpoint. Send POST /graphql with { query, variables }", {
|
|
5599
5600
|
status: 200,
|
|
5600
5601
|
headers: { "Content-Type": "text/plain" }
|
|
5601
5602
|
});
|
|
5602
5603
|
});
|
|
5603
|
-
async function handleGET(req,
|
|
5604
|
+
async function handleGET(req, _ctx2) {
|
|
5604
5605
|
const tables = await sql2`
|
|
5605
5606
|
SELECT * FROM "_user_tables"
|
|
5606
|
-
WHERE tenant_id = ${
|
|
5607
|
+
WHERE tenant_id = ${_ctx2.tenant.id}
|
|
5607
5608
|
ORDER BY created_at ASC
|
|
5608
5609
|
`;
|
|
5609
|
-
const buildCtx = { sql: sql2, tenantId:
|
|
5610
|
+
const buildCtx = { sql: sql2, tenantId: _ctx2.tenant.id, tables, typeCache: /* @__PURE__ */ new Map() };
|
|
5610
5611
|
const schema = new GraphQLSchema({
|
|
5611
5612
|
query: new GraphQLObjectType({
|
|
5612
5613
|
name: "Query",
|
|
@@ -5626,7 +5627,7 @@ function buildGraphQLHandler(sql2) {
|
|
|
5626
5627
|
source: query,
|
|
5627
5628
|
variableValues: variables,
|
|
5628
5629
|
operationName: url.searchParams.get("operationName") || void 0,
|
|
5629
|
-
contextValue:
|
|
5630
|
+
contextValue: _ctx2
|
|
5630
5631
|
});
|
|
5631
5632
|
return Response.json(result, { status: result.errors ? 400 : 200 });
|
|
5632
5633
|
}
|
|
@@ -6653,14 +6654,14 @@ function forkApp(opts) {
|
|
|
6653
6654
|
return { child, port: opts.port };
|
|
6654
6655
|
}
|
|
6655
6656
|
function stopProcess(mp, timeout = 1e4) {
|
|
6656
|
-
return new Promise((
|
|
6657
|
+
return new Promise((resolve16) => {
|
|
6657
6658
|
const timer = setTimeout(() => {
|
|
6658
6659
|
mp.child.kill("SIGKILL");
|
|
6659
|
-
|
|
6660
|
+
resolve16();
|
|
6660
6661
|
}, timeout);
|
|
6661
6662
|
mp.child.on("exit", () => {
|
|
6662
6663
|
clearTimeout(timer);
|
|
6663
|
-
|
|
6664
|
+
resolve16();
|
|
6664
6665
|
});
|
|
6665
6666
|
mp.child.kill("SIGTERM");
|
|
6666
6667
|
});
|
|
@@ -6992,22 +6993,168 @@ import { createOpenAI as createOpenAI3 } from "@ai-sdk/openai";
|
|
|
6992
6993
|
|
|
6993
6994
|
// ssr.ts
|
|
6994
6995
|
import { createElement as createElement3 } from "react";
|
|
6995
|
-
import { createHash as
|
|
6996
|
-
import { existsSync as
|
|
6996
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
6997
|
+
import { existsSync as existsSync6, readdirSync } from "node:fs";
|
|
6997
6998
|
import { readdir, stat } from "node:fs/promises";
|
|
6998
|
-
import { dirname as
|
|
6999
|
+
import { dirname as dirname4, join as join5, resolve as resolve8, relative as relative3 } from "node:path";
|
|
6999
7000
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
7000
7001
|
|
|
7001
7002
|
// compile.ts
|
|
7002
|
-
import * as
|
|
7003
|
-
import { existsSync, mkdirSync, readFileSync as
|
|
7004
|
-
import { join as join2, resolve as
|
|
7003
|
+
import * as esbuild2 from "esbuild";
|
|
7004
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3 } from "node:fs";
|
|
7005
|
+
import { join as join2, resolve as resolve4, dirname as dirname2 } from "node:path";
|
|
7005
7006
|
import { pathToFileURL } from "node:url";
|
|
7006
7007
|
import { createHash } from "node:crypto";
|
|
7008
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
7009
|
+
|
|
7010
|
+
// server-registry.ts
|
|
7011
|
+
import * as esbuild from "esbuild";
|
|
7012
|
+
import { existsSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
7013
|
+
import { resolve as resolve3, dirname } from "node:path";
|
|
7007
7014
|
import vm from "node:vm";
|
|
7008
7015
|
import { createRequire } from "node:module";
|
|
7009
|
-
var _cjsRequire = createRequire(import.meta.url);
|
|
7010
7016
|
var _userRequire = null;
|
|
7017
|
+
function getUserRequire() {
|
|
7018
|
+
if (!_userRequire) {
|
|
7019
|
+
try {
|
|
7020
|
+
_userRequire = createRequire(resolve3(process.cwd(), "package.json"));
|
|
7021
|
+
} catch {
|
|
7022
|
+
_userRequire = createRequire(import.meta.url);
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
return _userRequire;
|
|
7026
|
+
}
|
|
7027
|
+
var _alias = null;
|
|
7028
|
+
function resolveAliases() {
|
|
7029
|
+
if (_alias) return _alias;
|
|
7030
|
+
const configFiles = ["tsconfig.json", "jsconfig.json"];
|
|
7031
|
+
for (const file of configFiles) {
|
|
7032
|
+
const p = resolve3(file);
|
|
7033
|
+
if (existsSync(p)) {
|
|
7034
|
+
try {
|
|
7035
|
+
const config = JSON.parse(readFileSync2(p, "utf-8"));
|
|
7036
|
+
const paths = config.compilerOptions?.paths;
|
|
7037
|
+
if (paths) {
|
|
7038
|
+
const alias = {};
|
|
7039
|
+
for (const [key, values] of Object.entries(paths)) {
|
|
7040
|
+
const cleanKey = key.replace("/*", "");
|
|
7041
|
+
const val = values[0]?.replace("/*", "");
|
|
7042
|
+
if (val) alias[cleanKey] = resolve3(dirname(p), val);
|
|
7043
|
+
}
|
|
7044
|
+
_alias = alias;
|
|
7045
|
+
return alias;
|
|
7046
|
+
}
|
|
7047
|
+
} catch {
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
}
|
|
7051
|
+
_alias = {};
|
|
7052
|
+
return {};
|
|
7053
|
+
}
|
|
7054
|
+
function applyAlias(id2, _moduleDir) {
|
|
7055
|
+
const aliases = resolveAliases();
|
|
7056
|
+
for (const [prefix, target] of Object.entries(aliases)) {
|
|
7057
|
+
if (id2.startsWith(prefix)) {
|
|
7058
|
+
const rest = id2.slice(prefix.length);
|
|
7059
|
+
return target + rest;
|
|
7060
|
+
}
|
|
7061
|
+
}
|
|
7062
|
+
return null;
|
|
7063
|
+
}
|
|
7064
|
+
var exts = [".tsx", ".ts", ".jsx", ".js"];
|
|
7065
|
+
function tryResolve(base) {
|
|
7066
|
+
if (existsSync(base)) {
|
|
7067
|
+
const stat3 = statSync(base);
|
|
7068
|
+
if (stat3.isFile()) return base;
|
|
7069
|
+
if (stat3.isDirectory()) {
|
|
7070
|
+
for (const ext of exts) {
|
|
7071
|
+
const p = resolve3(base, `index${ext}`);
|
|
7072
|
+
if (existsSync(p)) return p;
|
|
7073
|
+
}
|
|
7074
|
+
return null;
|
|
7075
|
+
}
|
|
7076
|
+
}
|
|
7077
|
+
for (const ext of exts) {
|
|
7078
|
+
const p = base + ext;
|
|
7079
|
+
if (existsSync(p)) return p;
|
|
7080
|
+
}
|
|
7081
|
+
return null;
|
|
7082
|
+
}
|
|
7083
|
+
var registry = /* @__PURE__ */ new Map();
|
|
7084
|
+
var _ctx = vm.createContext(Object.create(globalThis));
|
|
7085
|
+
function transformToCjs(absPath, source) {
|
|
7086
|
+
const isTsx = absPath.endsWith(".tsx");
|
|
7087
|
+
const result = esbuild.transformSync(source, {
|
|
7088
|
+
loader: isTsx ? "tsx" : "ts",
|
|
7089
|
+
format: "cjs",
|
|
7090
|
+
jsx: isTsx ? "automatic" : void 0,
|
|
7091
|
+
jsxImportSource: isTsx ? "react" : void 0,
|
|
7092
|
+
sourcemap: false
|
|
7093
|
+
});
|
|
7094
|
+
return result.code;
|
|
7095
|
+
}
|
|
7096
|
+
function makeRequire(modulePath) {
|
|
7097
|
+
const moduleDir = dirname(modulePath);
|
|
7098
|
+
return (id2) => {
|
|
7099
|
+
if (id2.startsWith(".")) {
|
|
7100
|
+
const base = resolve3(moduleDir, id2);
|
|
7101
|
+
const file = tryResolve(base);
|
|
7102
|
+
if (!file) {
|
|
7103
|
+
throw new Error(
|
|
7104
|
+
`[server-registry] Cannot resolve '${id2}' from '${modulePath}'. Tried: ${[base, ...exts.map((e) => base + e)].filter((p) => !p.endsWith(base)).join(", ")}`
|
|
7105
|
+
);
|
|
7106
|
+
}
|
|
7107
|
+
return getServerModule(file);
|
|
7108
|
+
}
|
|
7109
|
+
const aliased = applyAlias(id2, moduleDir);
|
|
7110
|
+
if (aliased) {
|
|
7111
|
+
const file = tryResolve(aliased);
|
|
7112
|
+
if (file) return getServerModule(file);
|
|
7113
|
+
}
|
|
7114
|
+
return getUserRequire()(id2);
|
|
7115
|
+
};
|
|
7116
|
+
}
|
|
7117
|
+
function evaluateModule(code, modulePath) {
|
|
7118
|
+
const mod = { exports: {} };
|
|
7119
|
+
const require2 = makeRequire(modulePath);
|
|
7120
|
+
const _dirname = dirname(modulePath);
|
|
7121
|
+
const _filename = modulePath;
|
|
7122
|
+
const wrapped = `(function(require,module,exports,__dirname,__filename){
|
|
7123
|
+
${code}
|
|
7124
|
+
})`;
|
|
7125
|
+
try {
|
|
7126
|
+
new vm.Script(wrapped).runInContext(_ctx)(require2, mod, mod.exports, _dirname, _filename);
|
|
7127
|
+
} catch (err) {
|
|
7128
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7129
|
+
const cause = err instanceof Error ? err : void 0;
|
|
7130
|
+
throw new Error(
|
|
7131
|
+
`[server-registry] Error evaluating '${modulePath}': ${msg}`,
|
|
7132
|
+
cause ? { cause } : void 0
|
|
7133
|
+
);
|
|
7134
|
+
}
|
|
7135
|
+
return mod.exports;
|
|
7136
|
+
}
|
|
7137
|
+
function getServerModule(absPath) {
|
|
7138
|
+
const normalized = resolve3(absPath);
|
|
7139
|
+
if (registry.has(normalized)) return registry.get(normalized).exports;
|
|
7140
|
+
const source = readFileSync2(normalized, "utf-8");
|
|
7141
|
+
const code = transformToCjs(normalized, source);
|
|
7142
|
+
const exports = evaluateModule(code, normalized);
|
|
7143
|
+
registry.set(normalized, { exports });
|
|
7144
|
+
return exports;
|
|
7145
|
+
}
|
|
7146
|
+
function clearServerModule(absPath) {
|
|
7147
|
+
if (absPath) {
|
|
7148
|
+
const normalized = resolve3(absPath);
|
|
7149
|
+
registry.delete(normalized);
|
|
7150
|
+
} else {
|
|
7151
|
+
registry.clear();
|
|
7152
|
+
_alias = null;
|
|
7153
|
+
}
|
|
7154
|
+
}
|
|
7155
|
+
|
|
7156
|
+
// compile.ts
|
|
7157
|
+
var _userRequire2 = null;
|
|
7011
7158
|
var OUT_DIR = ".weifuwu/ssr";
|
|
7012
7159
|
var cache = /* @__PURE__ */ new Map();
|
|
7013
7160
|
var externals = [
|
|
@@ -7020,31 +7167,31 @@ var externals = [
|
|
|
7020
7167
|
"@graphql-tools/schema",
|
|
7021
7168
|
"ai"
|
|
7022
7169
|
];
|
|
7023
|
-
var
|
|
7024
|
-
function
|
|
7025
|
-
if (
|
|
7170
|
+
var _alias2 = null;
|
|
7171
|
+
function resolveAliases2() {
|
|
7172
|
+
if (_alias2) return _alias2;
|
|
7026
7173
|
const configFiles = ["tsconfig.json", "jsconfig.json"];
|
|
7027
7174
|
for (const file of configFiles) {
|
|
7028
|
-
const p =
|
|
7029
|
-
if (
|
|
7175
|
+
const p = resolve4(file);
|
|
7176
|
+
if (existsSync2(p)) {
|
|
7030
7177
|
try {
|
|
7031
|
-
const config = JSON.parse(
|
|
7178
|
+
const config = JSON.parse(readFileSync3(p, "utf-8"));
|
|
7032
7179
|
const paths = config.compilerOptions?.paths;
|
|
7033
7180
|
if (paths) {
|
|
7034
7181
|
const alias = {};
|
|
7035
7182
|
for (const [key, values] of Object.entries(paths)) {
|
|
7036
7183
|
const cleanKey = key.replace("/*", "");
|
|
7037
7184
|
const val = values[0]?.replace("/*", "");
|
|
7038
|
-
if (val) alias[cleanKey] =
|
|
7185
|
+
if (val) alias[cleanKey] = resolve4(dirname2(p), val);
|
|
7039
7186
|
}
|
|
7040
|
-
|
|
7187
|
+
_alias2 = alias;
|
|
7041
7188
|
return alias;
|
|
7042
7189
|
}
|
|
7043
7190
|
} catch {
|
|
7044
7191
|
}
|
|
7045
7192
|
}
|
|
7046
7193
|
}
|
|
7047
|
-
|
|
7194
|
+
_alias2 = {};
|
|
7048
7195
|
return {};
|
|
7049
7196
|
}
|
|
7050
7197
|
function id(s) {
|
|
@@ -7052,16 +7199,17 @@ function id(s) {
|
|
|
7052
7199
|
}
|
|
7053
7200
|
function clearCompileCache() {
|
|
7054
7201
|
cache.clear();
|
|
7055
|
-
|
|
7202
|
+
clearServerModule();
|
|
7203
|
+
_alias2 = null;
|
|
7056
7204
|
}
|
|
7057
7205
|
async function compileTsx(path2) {
|
|
7058
|
-
const absPath =
|
|
7206
|
+
const absPath = resolve4(path2);
|
|
7059
7207
|
if (cache.has(absPath)) return cache.get(absPath);
|
|
7060
|
-
const outDir =
|
|
7208
|
+
const outDir = resolve4(OUT_DIR);
|
|
7061
7209
|
mkdirSync(outDir, { recursive: true });
|
|
7062
7210
|
const hash = id(absPath);
|
|
7063
7211
|
const outPath = join2(outDir, hash + ".js");
|
|
7064
|
-
await
|
|
7212
|
+
await esbuild2.build({
|
|
7065
7213
|
entryPoints: { [hash]: absPath },
|
|
7066
7214
|
outdir: outDir,
|
|
7067
7215
|
format: "esm",
|
|
@@ -7070,7 +7218,7 @@ async function compileTsx(path2) {
|
|
|
7070
7218
|
jsxImportSource: "react",
|
|
7071
7219
|
bundle: true,
|
|
7072
7220
|
external: externals,
|
|
7073
|
-
alias:
|
|
7221
|
+
alias: resolveAliases2(),
|
|
7074
7222
|
write: true,
|
|
7075
7223
|
allowOverwrite: true
|
|
7076
7224
|
});
|
|
@@ -7078,42 +7226,20 @@ async function compileTsx(path2) {
|
|
|
7078
7226
|
cache.set(absPath, mod);
|
|
7079
7227
|
return mod;
|
|
7080
7228
|
}
|
|
7081
|
-
function
|
|
7082
|
-
const
|
|
7083
|
-
const mod =
|
|
7084
|
-
ctx.require = (name) => _cjsRequire(name);
|
|
7085
|
-
ctx.module = mod;
|
|
7086
|
-
ctx.exports = mod.exports;
|
|
7087
|
-
new vm.Script(code).runInContext(ctx);
|
|
7088
|
-
return mod.exports;
|
|
7089
|
-
}
|
|
7090
|
-
async function compileTsxDev(path2) {
|
|
7091
|
-
const absPath = resolve3(path2);
|
|
7092
|
-
if (cache.has(absPath)) return cache.get(absPath);
|
|
7093
|
-
const result = await esbuild.build({
|
|
7094
|
-
entryPoints: { [id(absPath)]: absPath },
|
|
7095
|
-
format: "cjs",
|
|
7096
|
-
platform: "node",
|
|
7097
|
-
jsx: "automatic",
|
|
7098
|
-
jsxImportSource: "react",
|
|
7099
|
-
bundle: true,
|
|
7100
|
-
external: externals,
|
|
7101
|
-
alias: resolveAliases(),
|
|
7102
|
-
write: false
|
|
7103
|
-
});
|
|
7104
|
-
const code = new TextDecoder().decode(result.outputFiles[0].contents);
|
|
7105
|
-
const mod = loadSSRModule(code);
|
|
7229
|
+
function compileTsxDev(path2) {
|
|
7230
|
+
const absPath = resolve4(path2);
|
|
7231
|
+
const mod = getServerModule(absPath);
|
|
7106
7232
|
cache.set(absPath, mod);
|
|
7107
7233
|
return mod;
|
|
7108
7234
|
}
|
|
7109
7235
|
function compile(path2) {
|
|
7110
|
-
return isDev() ? compileTsxDev(path2) : compileTsx(path2);
|
|
7236
|
+
return isDev() ? Promise.resolve(compileTsxDev(path2)) : compileTsx(path2);
|
|
7111
7237
|
}
|
|
7112
7238
|
var vendorBundle = null;
|
|
7113
7239
|
var vendorHash = "";
|
|
7114
7240
|
async function compileVendorBundle() {
|
|
7115
7241
|
if (vendorBundle) return vendorBundle;
|
|
7116
|
-
if (!
|
|
7242
|
+
if (!_userRequire2) _userRequire2 = createRequire2(join2(process.cwd(), "package.json"));
|
|
7117
7243
|
const modules = {
|
|
7118
7244
|
react: [],
|
|
7119
7245
|
"react-dom": ["react"],
|
|
@@ -7121,13 +7247,13 @@ async function compileVendorBundle() {
|
|
|
7121
7247
|
"react/jsx-runtime": ["react"]
|
|
7122
7248
|
};
|
|
7123
7249
|
for (const request of Object.keys(modules)) {
|
|
7124
|
-
const mod =
|
|
7250
|
+
const mod = _userRequire2(request);
|
|
7125
7251
|
const keys = Object.keys(mod).filter((k) => !k.startsWith("_") && k !== "default");
|
|
7126
7252
|
modules[request] = keys;
|
|
7127
7253
|
}
|
|
7128
7254
|
const baseDir = import.meta.dirname ?? __dirname;
|
|
7129
|
-
const reactAbsPath = isBundled() ?
|
|
7130
|
-
const reactSrc =
|
|
7255
|
+
const reactAbsPath = isBundled() ? resolve4(baseDir, "react.js") : resolve4(baseDir, "react.ts");
|
|
7256
|
+
const reactSrc = readFileSync3(reactAbsPath, "utf-8");
|
|
7131
7257
|
const wfwKeys = [];
|
|
7132
7258
|
if (reactAbsPath.endsWith(".ts")) {
|
|
7133
7259
|
for (const line of reactSrc.split("\n")) {
|
|
@@ -7158,7 +7284,7 @@ async function compileVendorBundle() {
|
|
|
7158
7284
|
const uidWfw = wfwKeys.filter((k) => !used.has(k) && used.add(k));
|
|
7159
7285
|
if (uidWfw.length > 0)
|
|
7160
7286
|
stmts.push(`export { ${uidWfw.join(", ")} } from ${JSON.stringify(reactAbsPath)};`);
|
|
7161
|
-
const result = await
|
|
7287
|
+
const result = await esbuild2.build({
|
|
7162
7288
|
stdin: { contents: stmts.join("\n"), resolveDir: process.cwd() },
|
|
7163
7289
|
format: "esm",
|
|
7164
7290
|
bundle: true,
|
|
@@ -7170,95 +7296,6 @@ async function compileVendorBundle() {
|
|
|
7170
7296
|
vendorHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
7171
7297
|
return vendorBundle;
|
|
7172
7298
|
}
|
|
7173
|
-
async function compileBrowser(path2, outDir) {
|
|
7174
|
-
const absPath = resolve3(path2);
|
|
7175
|
-
const h = id(absPath);
|
|
7176
|
-
outDir = outDir ?? resolve3(OUT_DIR);
|
|
7177
|
-
const outPath = join2(outDir, h + ".js");
|
|
7178
|
-
if (!isDev() && existsSync(outPath)) return h;
|
|
7179
|
-
mkdirSync(outDir, { recursive: true });
|
|
7180
|
-
const wfwDir = resolve3(import.meta.dirname ?? __dirname);
|
|
7181
|
-
const plugin = {
|
|
7182
|
-
name: "wfw-external",
|
|
7183
|
-
setup(build2) {
|
|
7184
|
-
build2.onResolve({ filter: /./ }, (args) => {
|
|
7185
|
-
if (args.kind === "entry-point") return;
|
|
7186
|
-
const abs = args.path.startsWith(".") ? join2(args.resolveDir, args.path) : args.path;
|
|
7187
|
-
if (abs.startsWith(wfwDir) && !abs.includes("node_modules")) {
|
|
7188
|
-
const rel = abs.slice(wfwDir.length + 1);
|
|
7189
|
-
if (rel.includes("/")) return;
|
|
7190
|
-
return { path: "weifuwu/react", external: true };
|
|
7191
|
-
}
|
|
7192
|
-
});
|
|
7193
|
-
}
|
|
7194
|
-
};
|
|
7195
|
-
await esbuild.build({
|
|
7196
|
-
entryPoints: { [h]: absPath },
|
|
7197
|
-
outdir: outDir,
|
|
7198
|
-
format: "esm",
|
|
7199
|
-
platform: "browser",
|
|
7200
|
-
jsx: "automatic",
|
|
7201
|
-
jsxImportSource: "react",
|
|
7202
|
-
bundle: true,
|
|
7203
|
-
external: [
|
|
7204
|
-
"react",
|
|
7205
|
-
"react-dom",
|
|
7206
|
-
"react-dom/client",
|
|
7207
|
-
"react/jsx-runtime",
|
|
7208
|
-
"weifuwu",
|
|
7209
|
-
"weifuwu/react"
|
|
7210
|
-
],
|
|
7211
|
-
plugins: [plugin],
|
|
7212
|
-
write: true,
|
|
7213
|
-
allowOverwrite: true
|
|
7214
|
-
});
|
|
7215
|
-
return h;
|
|
7216
|
-
}
|
|
7217
|
-
async function compileHotComponent(path2) {
|
|
7218
|
-
const absPath = resolve3(path2);
|
|
7219
|
-
const h = id(absPath);
|
|
7220
|
-
const stdin = `import C from ${JSON.stringify(absPath)};
|
|
7221
|
-
(window.__WFW_REFRESH||function(){})(C)`;
|
|
7222
|
-
const wfwDir = resolve3(import.meta.dirname ?? __dirname);
|
|
7223
|
-
const plugin = {
|
|
7224
|
-
name: "wfw-external",
|
|
7225
|
-
setup(build2) {
|
|
7226
|
-
build2.onResolve({ filter: /./ }, (args) => {
|
|
7227
|
-
if (args.kind === "entry-point") return;
|
|
7228
|
-
const abs = args.path.startsWith(".") ? join2(args.resolveDir, args.path) : args.path;
|
|
7229
|
-
if (abs.startsWith(wfwDir) && !abs.includes("node_modules")) {
|
|
7230
|
-
const rel = abs.slice(wfwDir.length + 1);
|
|
7231
|
-
if (rel.includes("/")) return;
|
|
7232
|
-
return { path: "weifuwu/react", external: true };
|
|
7233
|
-
}
|
|
7234
|
-
});
|
|
7235
|
-
}
|
|
7236
|
-
};
|
|
7237
|
-
const result = await esbuild.build({
|
|
7238
|
-
stdin: { contents: stdin, loader: "tsx", resolveDir: dirname(absPath) },
|
|
7239
|
-
format: "esm",
|
|
7240
|
-
platform: "browser",
|
|
7241
|
-
jsx: "automatic",
|
|
7242
|
-
jsxImportSource: "react",
|
|
7243
|
-
bundle: true,
|
|
7244
|
-
external: [
|
|
7245
|
-
"react",
|
|
7246
|
-
"react-dom",
|
|
7247
|
-
"react-dom/client",
|
|
7248
|
-
"react/jsx-runtime",
|
|
7249
|
-
"weifuwu",
|
|
7250
|
-
"weifuwu/react"
|
|
7251
|
-
],
|
|
7252
|
-
plugins: [plugin],
|
|
7253
|
-
write: false
|
|
7254
|
-
});
|
|
7255
|
-
let code = new TextDecoder().decode(result.outputFiles[0].contents);
|
|
7256
|
-
if (code.includes("__require") && (code.includes('"react"') || code.includes("'react'"))) {
|
|
7257
|
-
code = `import * as __r from 'react';
|
|
7258
|
-
` + code.replace(/__require\(["']react["']\)/g, "__r");
|
|
7259
|
-
}
|
|
7260
|
-
return { hash: h, code };
|
|
7261
|
-
}
|
|
7262
7299
|
|
|
7263
7300
|
// stream.ts
|
|
7264
7301
|
import { TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
|
|
@@ -7276,6 +7313,8 @@ function getPublicEnv2() {
|
|
|
7276
7313
|
function buildHeadPayload(opts) {
|
|
7277
7314
|
const { ctx, base, tailwind } = opts;
|
|
7278
7315
|
let result = "";
|
|
7316
|
+
result += `<script>window.__wfw={_cache:{},_k:function(u){return u.split('?')[0]},h:async function(u){var k=this._k(u);if(this._cache[k])return this._cache[k];var m=await import(u);this._cache[k]=m;return m},_update:function(u,mod){var k=this._k(u);this._cache[k]=mod}}</script>
|
|
7317
|
+
`;
|
|
7279
7318
|
const vUrl = `${base}/__wfw/v/bundle?h=${vendorHash}`;
|
|
7280
7319
|
result += `<script type="importmap">{
|
|
7281
7320
|
"imports": {
|
|
@@ -7360,26 +7399,37 @@ function streamResponse(reactStream, opts, hydrationScript) {
|
|
|
7360
7399
|
if (built) bodyScripts += built;
|
|
7361
7400
|
if (opts.isDev) {
|
|
7362
7401
|
const wsUrl = `${opts.base}/__weifuwu/livereload`;
|
|
7363
|
-
const hbUrl = `${opts.base}/__wfw/h/`;
|
|
7364
7402
|
bodyScripts += `
|
|
7365
7403
|
<script>
|
|
7366
7404
|
(function(){
|
|
7367
7405
|
var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'${wsUrl}');
|
|
7368
7406
|
var t=0;
|
|
7407
|
+
var _w=window;
|
|
7369
7408
|
ws.onmessage=function(e){
|
|
7370
7409
|
try{
|
|
7371
7410
|
var m=JSON.parse(e.data);
|
|
7372
|
-
if(m.type==='
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7411
|
+
if(m.type==='update'&&m.url&&m.code){
|
|
7412
|
+
var blob=new Blob([m.code],{type:'application/javascript'});
|
|
7413
|
+
var blobUrl=URL.createObjectURL(blob);
|
|
7414
|
+
import(blobUrl).then(function(mod){
|
|
7415
|
+
if(_w.__wfw) _w.__wfw._update(m.url,mod);
|
|
7416
|
+
// Re-import page module so it re-evaluates its __wfw.h() imports
|
|
7417
|
+
var pageUrl=_w.__WFW_PAGE_URL;
|
|
7418
|
+
if(pageUrl&&_w.__WFW_REFRESH){
|
|
7419
|
+
import(pageUrl.split('?')[0]+'?t='+Date.now()).then(function(pageMod){
|
|
7420
|
+
if(pageMod.default) _w.__WFW_REFRESH(pageMod.default);
|
|
7421
|
+
if(m.css){
|
|
7422
|
+
var s=document.querySelector('style[data-lr]')||function(){
|
|
7423
|
+
var x=document.createElement('style');
|
|
7424
|
+
x.setAttribute('data-lr','');
|
|
7425
|
+
document.head.appendChild(x);
|
|
7426
|
+
return x
|
|
7427
|
+
}();
|
|
7428
|
+
s.textContent=m.css
|
|
7429
|
+
}
|
|
7430
|
+
});
|
|
7431
|
+
}else{location.reload()}
|
|
7432
|
+
}).catch(function(){location.reload()});
|
|
7383
7433
|
return
|
|
7384
7434
|
}
|
|
7385
7435
|
if(m.type==='css'){
|
|
@@ -7430,12 +7480,12 @@ var ssrEntries = /* @__PURE__ */ new Map();
|
|
|
7430
7480
|
|
|
7431
7481
|
// tailwind.ts
|
|
7432
7482
|
import { createHash as createHash2 } from "node:crypto";
|
|
7433
|
-
import { existsSync as
|
|
7434
|
-
import { join as join3, relative, resolve as
|
|
7483
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
7484
|
+
import { join as join3, relative, resolve as resolve5 } from "node:path";
|
|
7435
7485
|
var extraSources = /* @__PURE__ */ new Set();
|
|
7436
7486
|
var cssCache = /* @__PURE__ */ new Map();
|
|
7437
7487
|
function tailwindContext(dir) {
|
|
7438
|
-
const cssDir =
|
|
7488
|
+
const cssDir = resolve5(dir);
|
|
7439
7489
|
const cssPath = join3(cssDir, "app", "globals.css");
|
|
7440
7490
|
return async (req, ctx, next) => {
|
|
7441
7491
|
if (!cssCache.has(cssPath)) {
|
|
@@ -7449,10 +7499,10 @@ function tailwindContext(dir) {
|
|
|
7449
7499
|
};
|
|
7450
7500
|
}
|
|
7451
7501
|
function tailwindRouter(dir) {
|
|
7452
|
-
const cssDir =
|
|
7502
|
+
const cssDir = resolve5(dir);
|
|
7453
7503
|
const cssPath = join3(cssDir, "app", "globals.css");
|
|
7454
7504
|
const r = new Router();
|
|
7455
|
-
r.get("/__wfw/style/:hash.css", async (_req,
|
|
7505
|
+
r.get("/__wfw/style/:hash.css", async (_req, _ctx2) => {
|
|
7456
7506
|
if (!cssCache.has(cssPath)) {
|
|
7457
7507
|
await compileTailwindCss(cssPath, cssDir);
|
|
7458
7508
|
}
|
|
@@ -7466,13 +7516,13 @@ function tailwindRouter(dir) {
|
|
|
7466
7516
|
}
|
|
7467
7517
|
async function compileTailwindCss(cssPath, cssDir) {
|
|
7468
7518
|
try {
|
|
7469
|
-
if (!
|
|
7519
|
+
if (!existsSync3(cssPath)) {
|
|
7470
7520
|
mkdirSync2(cssDir, { recursive: true });
|
|
7471
7521
|
writeFileSync(cssPath, '@import "tailwindcss"\n', "utf-8");
|
|
7472
7522
|
}
|
|
7473
7523
|
const { default: tailwindPlugin } = await import("@tailwindcss/postcss");
|
|
7474
7524
|
const { default: postcss } = await import("postcss");
|
|
7475
|
-
let src =
|
|
7525
|
+
let src = readFileSync4(cssPath, "utf-8");
|
|
7476
7526
|
src = `@source "./";
|
|
7477
7527
|
${src}`;
|
|
7478
7528
|
for (const srcDir of extraSources) {
|
|
@@ -7492,22 +7542,151 @@ ${src}`;
|
|
|
7492
7542
|
|
|
7493
7543
|
// live.ts
|
|
7494
7544
|
import chokidar from "chokidar";
|
|
7495
|
-
import { existsSync as
|
|
7496
|
-
import {
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7545
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
7546
|
+
import { join as join4, resolve as resolve7 } from "node:path";
|
|
7547
|
+
|
|
7548
|
+
// module-server.ts
|
|
7549
|
+
import * as esbuild3 from "esbuild";
|
|
7550
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
7551
|
+
import { resolve as resolve6, dirname as dirname3, relative as relative2 } from "node:path";
|
|
7552
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
7553
|
+
var moduleCache = /* @__PURE__ */ new Map();
|
|
7554
|
+
var hashCache = /* @__PURE__ */ new Map();
|
|
7555
|
+
function clearModuleCache(filePath) {
|
|
7556
|
+
if (filePath) {
|
|
7557
|
+
const abs = resolve6(filePath);
|
|
7558
|
+
for (const key of moduleCache.keys()) {
|
|
7559
|
+
if (key.endsWith(abs)) moduleCache.delete(key);
|
|
7560
|
+
}
|
|
7561
|
+
hashCache.delete(abs);
|
|
7562
|
+
} else {
|
|
7563
|
+
moduleCache.clear();
|
|
7564
|
+
hashCache.clear();
|
|
7508
7565
|
}
|
|
7509
|
-
hotBundleCache.set(hash, code);
|
|
7510
7566
|
}
|
|
7567
|
+
var _importRoots = [];
|
|
7568
|
+
function _setImportRoots(roots) {
|
|
7569
|
+
_importRoots = roots;
|
|
7570
|
+
}
|
|
7571
|
+
function fileHash(absPath) {
|
|
7572
|
+
const cached = hashCache.get(absPath);
|
|
7573
|
+
if (cached) return cached;
|
|
7574
|
+
try {
|
|
7575
|
+
const content = readFileSync5(absPath);
|
|
7576
|
+
const h = createHash3("md5").update(content).digest("hex").slice(0, 8);
|
|
7577
|
+
hashCache.set(absPath, h);
|
|
7578
|
+
return h;
|
|
7579
|
+
} catch {
|
|
7580
|
+
return "00000000";
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
function rewriteImports(code, absPath, mountPath) {
|
|
7584
|
+
const prefix = mountPath ? `${mountPath}/__wfw/m` : "/__wfw/m";
|
|
7585
|
+
let varCounter = 0;
|
|
7586
|
+
return code.replace(
|
|
7587
|
+
/^(import|export)\s+(.+?)\s+from\s+['"]([^'"]+)['"];?\s*$/gm,
|
|
7588
|
+
(_match, keyword, clause, modPath) => {
|
|
7589
|
+
if (!modPath.startsWith(".")) return _match;
|
|
7590
|
+
const isReexport = keyword === "export";
|
|
7591
|
+
const imports = clause.replace(/^type\s+/, "");
|
|
7592
|
+
const resolved = resolve6(dirname3(absPath), modPath);
|
|
7593
|
+
for (const root of _importRoots) {
|
|
7594
|
+
const rel = relative2(root, resolved);
|
|
7595
|
+
if (!rel.startsWith("..") && !rel.startsWith("/")) {
|
|
7596
|
+
const v = fileHash(resolved);
|
|
7597
|
+
const url = `${prefix}/${rel}?v=${v}`;
|
|
7598
|
+
const defaultMatch = imports.match(/^\s*(\w[\w$]*)\s*$/);
|
|
7599
|
+
const namedMatch = imports.match(/^\s*\{\s*([\w$,\s]+)\s*\}\s*$/);
|
|
7600
|
+
const mixedMatch = imports.match(/^\s*(\w[\w$]*)\s*,\s*\{\s*([\w$,\s]+)\s*\}\s*$/);
|
|
7601
|
+
if (defaultMatch) {
|
|
7602
|
+
const name = defaultMatch[1];
|
|
7603
|
+
if (isReexport) {
|
|
7604
|
+
return `const { default: ${name} } = await __wfw.h("${url}");
|
|
7605
|
+
export { ${name} as default }`;
|
|
7606
|
+
}
|
|
7607
|
+
return `const { default: ${name} } = await __wfw.h("${url}");`;
|
|
7608
|
+
}
|
|
7609
|
+
if (namedMatch) {
|
|
7610
|
+
const names = namedMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
7611
|
+
if (isReexport) {
|
|
7612
|
+
const tmp = `__wfw$${varCounter++}`;
|
|
7613
|
+
const lines = [`const ${tmp} = await __wfw.h("${url}");`];
|
|
7614
|
+
for (const n of names) lines.push(`export const ${n} = ${tmp}.${n};`);
|
|
7615
|
+
return lines.join("\n");
|
|
7616
|
+
}
|
|
7617
|
+
const decl = names.map((n) => `${n}`).join(", ");
|
|
7618
|
+
return `const { ${decl} } = await __wfw.h("${url}");`;
|
|
7619
|
+
}
|
|
7620
|
+
if (mixedMatch) {
|
|
7621
|
+
const defaultName = mixedMatch[1];
|
|
7622
|
+
const namedNames = mixedMatch[2].split(",").map((s) => s.trim()).filter(Boolean);
|
|
7623
|
+
const varName = `__wfw$${varCounter++}`;
|
|
7624
|
+
const lines = [
|
|
7625
|
+
`const ${varName} = await __wfw.h("${url}");`,
|
|
7626
|
+
`const ${defaultName} = ${varName}.default;`
|
|
7627
|
+
];
|
|
7628
|
+
for (const n of namedNames) lines.push(`const { ${n} } = ${varName};`);
|
|
7629
|
+
return lines.join("\n");
|
|
7630
|
+
}
|
|
7631
|
+
return _match;
|
|
7632
|
+
}
|
|
7633
|
+
}
|
|
7634
|
+
return _match;
|
|
7635
|
+
}
|
|
7636
|
+
);
|
|
7637
|
+
}
|
|
7638
|
+
async function transformModule(absPath, root, mountPath) {
|
|
7639
|
+
const mp = mountPath || "";
|
|
7640
|
+
const cacheKey = mp + absPath;
|
|
7641
|
+
const cached = moduleCache.get(cacheKey);
|
|
7642
|
+
if (cached) return { url: `${mp}/__wfw/m/${relative2(root, absPath)}`, code: cached };
|
|
7643
|
+
const source = readFileSync5(absPath, "utf-8");
|
|
7644
|
+
const isTsx = absPath.endsWith(".tsx");
|
|
7645
|
+
const result = await esbuild3.transform(source, {
|
|
7646
|
+
loader: isTsx ? "tsx" : "ts",
|
|
7647
|
+
jsx: isTsx ? "automatic" : void 0,
|
|
7648
|
+
jsxImportSource: isTsx ? "react" : void 0,
|
|
7649
|
+
sourcemap: false
|
|
7650
|
+
});
|
|
7651
|
+
let code = result.code;
|
|
7652
|
+
code = rewriteImports(code, absPath, mp);
|
|
7653
|
+
moduleCache.set(cacheKey, code);
|
|
7654
|
+
const url = `${mp}/__wfw/m/${relative2(root, absPath)}`;
|
|
7655
|
+
return { url, code };
|
|
7656
|
+
}
|
|
7657
|
+
function moduleServer(opts) {
|
|
7658
|
+
const roots = Array.isArray(opts.root) ? opts.root : [opts.root];
|
|
7659
|
+
_setImportRoots(roots);
|
|
7660
|
+
const router = new Router();
|
|
7661
|
+
router.get("/__wfw/m/*", (async (req, ctx) => {
|
|
7662
|
+
const reqUrl = new URL(req.url);
|
|
7663
|
+
const filePath = (ctx.params["*"] || "").split("?")[0];
|
|
7664
|
+
const ext = filePath.split(".").pop();
|
|
7665
|
+
if (ext !== "tsx" && ext !== "ts") {
|
|
7666
|
+
return new Response("Not Found", { status: 404 });
|
|
7667
|
+
}
|
|
7668
|
+
const mountPath = ctx.mountPath || "";
|
|
7669
|
+
for (const root of roots) {
|
|
7670
|
+
const absPath = resolve6(root, filePath);
|
|
7671
|
+
if (existsSync4(absPath)) {
|
|
7672
|
+
try {
|
|
7673
|
+
const { code } = await transformModule(absPath, root, mountPath);
|
|
7674
|
+
return new Response(code, {
|
|
7675
|
+
headers: { "content-type": "application/javascript; charset=utf-8" }
|
|
7676
|
+
});
|
|
7677
|
+
} catch (err) {
|
|
7678
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7679
|
+
return new Response(`/* Error: ${msg} */`, { status: 500 });
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7682
|
+
}
|
|
7683
|
+
return new Response("Not Found", { status: 404 });
|
|
7684
|
+
}));
|
|
7685
|
+
return router;
|
|
7686
|
+
}
|
|
7687
|
+
|
|
7688
|
+
// live.ts
|
|
7689
|
+
var clients = /* @__PURE__ */ new Set();
|
|
7511
7690
|
function broadcastReload() {
|
|
7512
7691
|
for (const ws of clients) {
|
|
7513
7692
|
try {
|
|
@@ -7529,7 +7708,7 @@ function broadcastCss(css) {
|
|
|
7529
7708
|
}
|
|
7530
7709
|
function liveWs() {
|
|
7531
7710
|
return {
|
|
7532
|
-
open(ws) {
|
|
7711
|
+
open(ws, _ctx2) {
|
|
7533
7712
|
clients.add(ws);
|
|
7534
7713
|
ws.on("close", () => clients.delete(ws));
|
|
7535
7714
|
ws.on("error", () => clients.delete(ws));
|
|
@@ -7540,78 +7719,52 @@ function liveRouter(_dir) {
|
|
|
7540
7719
|
const r = new Router();
|
|
7541
7720
|
compileVendorBundle().catch(() => {
|
|
7542
7721
|
});
|
|
7543
|
-
r.get("/__wfw/h/:hash", async (req, ctx) => {
|
|
7544
|
-
const hash = ctx.params.hash.replace(/\.js$/i, "");
|
|
7545
|
-
const code = hotBundleCache.get(hash);
|
|
7546
|
-
if (!code) return new Response("", { status: 404 });
|
|
7547
|
-
return new Response(code, {
|
|
7548
|
-
headers: { "content-type": "application/javascript; charset=utf-8" }
|
|
7549
|
-
});
|
|
7550
|
-
});
|
|
7551
7722
|
return r;
|
|
7552
7723
|
}
|
|
7553
7724
|
function liveWatcher(dir) {
|
|
7554
|
-
const resolved =
|
|
7555
|
-
const entryPath = join4(resolved, "page.tsx");
|
|
7725
|
+
const resolved = resolve7(dir);
|
|
7556
7726
|
const watcher = chokidar.watch(dir, {
|
|
7557
7727
|
ignored: /(^|[/\\])\.|node_modules|[/\\]\.weifuwu[/\\]/,
|
|
7558
7728
|
ignoreInitial: true
|
|
7559
7729
|
});
|
|
7560
|
-
function findEntries(changedPath) {
|
|
7561
|
-
const matched = [];
|
|
7562
|
-
for (const [, entry] of ssrEntries) {
|
|
7563
|
-
if (!entry.path.startsWith(resolved)) continue;
|
|
7564
|
-
if (entry.path === changedPath) {
|
|
7565
|
-
matched.push(entry.path);
|
|
7566
|
-
} else {
|
|
7567
|
-
const ed = dirname2(entry.path);
|
|
7568
|
-
if (changedPath.startsWith(ed)) matched.push(entry.path);
|
|
7569
|
-
}
|
|
7570
|
-
}
|
|
7571
|
-
if (matched.length === 0) {
|
|
7572
|
-
for (const [, entry] of ssrEntries) {
|
|
7573
|
-
if (entry.path.startsWith(resolved)) matched.push(entry.path);
|
|
7574
|
-
}
|
|
7575
|
-
}
|
|
7576
|
-
return matched;
|
|
7577
|
-
}
|
|
7578
7730
|
watcher.on("change", async (filePath) => {
|
|
7579
7731
|
if (/\.tsx?$/i.test(filePath)) {
|
|
7580
7732
|
if (filePath.endsWith("layout.tsx")) {
|
|
7581
7733
|
return broadcastReload();
|
|
7582
7734
|
}
|
|
7583
7735
|
clearCompileCache();
|
|
7584
|
-
|
|
7585
|
-
if (targets.length === 0) return broadcastReload();
|
|
7736
|
+
clearModuleCache();
|
|
7586
7737
|
try {
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7738
|
+
await compileTsxDev(filePath);
|
|
7739
|
+
} catch (e) {
|
|
7740
|
+
console.error("server-side recompile failed:", e);
|
|
7741
|
+
return broadcastReload();
|
|
7742
|
+
}
|
|
7743
|
+
let css;
|
|
7744
|
+
const cssPath = join4(resolved, "app", "globals.css");
|
|
7745
|
+
if (existsSync5(cssPath)) {
|
|
7746
|
+
css = await compileTailwindCss(cssPath, resolved);
|
|
7747
|
+
}
|
|
7748
|
+
try {
|
|
7749
|
+
const absPath = resolve7(filePath);
|
|
7750
|
+
const { url, code } = await transformModule(absPath, resolved);
|
|
7751
|
+
const msg = { type: "update", url, code };
|
|
7752
|
+
if (css) msg.css = css;
|
|
7753
|
+
const str = JSON.stringify(msg);
|
|
7754
|
+
for (const ws of clients) {
|
|
7755
|
+
try {
|
|
7756
|
+
ws.send(str);
|
|
7757
|
+
} catch {
|
|
7758
|
+
clients.delete(ws);
|
|
7606
7759
|
}
|
|
7607
7760
|
}
|
|
7608
7761
|
} catch (e) {
|
|
7609
|
-
console.error("
|
|
7762
|
+
console.error("module transform failed for HMR:", e);
|
|
7610
7763
|
broadcastReload();
|
|
7611
7764
|
}
|
|
7612
7765
|
} else if (/\.css$/i.test(filePath)) {
|
|
7613
7766
|
const cssPath = join4(resolved, "app", "globals.css");
|
|
7614
|
-
if (
|
|
7767
|
+
if (existsSync5(cssPath)) {
|
|
7615
7768
|
const css = await compileTailwindCss(cssPath, resolved);
|
|
7616
7769
|
if (css) broadcastCss(css);
|
|
7617
7770
|
}
|
|
@@ -7699,7 +7852,7 @@ var isDev2 = isDev();
|
|
|
7699
7852
|
var als2 = new AsyncLocalStorage2();
|
|
7700
7853
|
__registerAls(() => als2.getStore());
|
|
7701
7854
|
function hashId(s) {
|
|
7702
|
-
return
|
|
7855
|
+
return createHash4("md5").update(s).digest("hex").slice(0, 8);
|
|
7703
7856
|
}
|
|
7704
7857
|
function serializeLoaderData(ctx) {
|
|
7705
7858
|
const ld = ctx.loaderData;
|
|
@@ -7774,7 +7927,7 @@ async function resolveRoute(ssrDir, segments, routeCache) {
|
|
|
7774
7927
|
return null;
|
|
7775
7928
|
}
|
|
7776
7929
|
const pageFile = join5(dir, "page.tsx");
|
|
7777
|
-
if (!
|
|
7930
|
+
if (!existsSync6(pageFile)) {
|
|
7778
7931
|
routeCache.set(cacheKey, null);
|
|
7779
7932
|
return null;
|
|
7780
7933
|
}
|
|
@@ -7785,28 +7938,28 @@ async function resolveRoute(ssrDir, segments, routeCache) {
|
|
|
7785
7938
|
let d = dir;
|
|
7786
7939
|
while (d.startsWith(appDir)) {
|
|
7787
7940
|
const lf = join5(d, "layout.tsx");
|
|
7788
|
-
if (
|
|
7941
|
+
if (existsSync6(lf)) layoutFiles.unshift(lf);
|
|
7789
7942
|
if (d === appDir) break;
|
|
7790
|
-
d =
|
|
7943
|
+
d = dirname4(d);
|
|
7791
7944
|
}
|
|
7792
7945
|
const errorFiles = [];
|
|
7793
7946
|
d = dir;
|
|
7794
7947
|
while (d.startsWith(appDir)) {
|
|
7795
7948
|
const ef = join5(d, "error.tsx");
|
|
7796
|
-
if (
|
|
7949
|
+
if (existsSync6(ef)) errorFiles.unshift(ef);
|
|
7797
7950
|
if (d === appDir) break;
|
|
7798
|
-
d =
|
|
7951
|
+
d = dirname4(d);
|
|
7799
7952
|
}
|
|
7800
7953
|
let notFoundFile = null;
|
|
7801
7954
|
d = dir;
|
|
7802
7955
|
while (d.startsWith(appDir)) {
|
|
7803
7956
|
const nf = join5(d, "not-found.tsx");
|
|
7804
|
-
if (
|
|
7957
|
+
if (existsSync6(nf)) {
|
|
7805
7958
|
notFoundFile = nf;
|
|
7806
7959
|
break;
|
|
7807
7960
|
}
|
|
7808
7961
|
if (d === appDir) break;
|
|
7809
|
-
d =
|
|
7962
|
+
d = dirname4(d);
|
|
7810
7963
|
}
|
|
7811
7964
|
const result = {
|
|
7812
7965
|
routePath: "/" + routeParams.join("/"),
|
|
@@ -7818,8 +7971,7 @@ async function resolveRoute(ssrDir, segments, routeCache) {
|
|
|
7818
7971
|
routeCache.set(cacheKey, result);
|
|
7819
7972
|
return result;
|
|
7820
7973
|
}
|
|
7821
|
-
function buildHydrationScript(
|
|
7822
|
-
const ssrPrefix = `${base}/__ssr`;
|
|
7974
|
+
function buildHydrationScript(pageUrl, ctxJson) {
|
|
7823
7975
|
return `
|
|
7824
7976
|
<script type="module">
|
|
7825
7977
|
import { setCtx, TsxContext } from 'weifuwu/react';
|
|
@@ -7832,10 +7984,11 @@ setCtx(_ctx);
|
|
|
7832
7984
|
const _root = document.getElementById('__weifuwu_root');
|
|
7833
7985
|
|
|
7834
7986
|
async function init() {
|
|
7835
|
-
const { default: Page } = await import('${
|
|
7836
|
-
const app = createElement(TsxContext.Provider, { value: _ctx },
|
|
7837
|
-
createElement(Page));
|
|
7987
|
+
const { default: Page } = await import('${pageUrl}');
|
|
7838
7988
|
${isDev2 ? `
|
|
7989
|
+
// Store page URL for __wfw runtime
|
|
7990
|
+
window.__WFW_PAGE_URL = '${pageUrl}';
|
|
7991
|
+
|
|
7839
7992
|
// Stable proxy \u2014 same function ref = React preserves fiber + useState state across HMR
|
|
7840
7993
|
const _pageImpl = { current: Page };
|
|
7841
7994
|
const _pageProxy = new Proxy(function __wfw_page(){}, {
|
|
@@ -7852,14 +8005,22 @@ async function init() {
|
|
|
7852
8005
|
}
|
|
7853
8006
|
renderPage();
|
|
7854
8007
|
|
|
8008
|
+
// HMR: re-render page (sub-modules resolved via __wfw.h() pick up changes)
|
|
8009
|
+
window.__WFW_RERENDER = () => {
|
|
8010
|
+
_tick++;
|
|
8011
|
+
reactRoot.render(createElement(TsxContext.Provider, { value: _ctx },
|
|
8012
|
+
createElement(_pageProxy, { __t: _tick })));
|
|
8013
|
+
};
|
|
8014
|
+
|
|
8015
|
+
// Fallback: swap entire page component
|
|
7855
8016
|
window.__WFW_REFRESH = async (NewComponent) => {
|
|
7856
8017
|
const store = globalThis.__WEIFUWU_CTX_STORE?._ctx || _ctx;
|
|
7857
8018
|
_pageImpl.current = NewComponent;
|
|
7858
|
-
|
|
7859
|
-
reactRoot.render(createElement(TsxContext.Provider, { value: store },
|
|
7860
|
-
createElement(_pageProxy, { __t: _tick })));
|
|
8019
|
+
__WFW_RERENDER();
|
|
7861
8020
|
};
|
|
7862
8021
|
` : `
|
|
8022
|
+
const app = createElement(TsxContext.Provider, { value: _ctx },
|
|
8023
|
+
createElement(Page));
|
|
7863
8024
|
hydrateRoot(_root, app);
|
|
7864
8025
|
`}
|
|
7865
8026
|
}
|
|
@@ -7867,8 +8028,8 @@ async function init() {
|
|
|
7867
8028
|
init();
|
|
7868
8029
|
</script>`;
|
|
7869
8030
|
}
|
|
7870
|
-
function renderPage(pageFile,
|
|
7871
|
-
const absPath =
|
|
8031
|
+
function renderPage(pageFile, projectDir) {
|
|
8032
|
+
const absPath = resolve8(pageFile);
|
|
7872
8033
|
const entryId = hashId(absPath);
|
|
7873
8034
|
ssrEntries.set(entryId, { path: absPath });
|
|
7874
8035
|
return async (req, ctx) => {
|
|
@@ -7897,9 +8058,10 @@ function renderPage(pageFile, outDir) {
|
|
|
7897
8058
|
loaderData,
|
|
7898
8059
|
env: ctx.env ?? {}
|
|
7899
8060
|
};
|
|
8061
|
+
const pageRelative = relative3(projectDir, absPath);
|
|
8062
|
+
const pageUrl = `${base}/__wfw/m/${pageRelative}`;
|
|
7900
8063
|
return als2.run(ctxValue, async () => {
|
|
7901
8064
|
setCtx(ctxValue);
|
|
7902
|
-
await compileBrowser(absPath, outDir);
|
|
7903
8065
|
let element = createElement3(
|
|
7904
8066
|
"div",
|
|
7905
8067
|
{ id: "__weifuwu_root" },
|
|
@@ -7917,7 +8079,7 @@ function renderPage(pageFile, outDir) {
|
|
|
7917
8079
|
loaderData,
|
|
7918
8080
|
tailwind: ctx.tailwind
|
|
7919
8081
|
},
|
|
7920
|
-
buildHydrationScript(
|
|
8082
|
+
buildHydrationScript(pageUrl, JSON.stringify(ctxValue))
|
|
7921
8083
|
);
|
|
7922
8084
|
});
|
|
7923
8085
|
};
|
|
@@ -7932,7 +8094,7 @@ function runChain(mws, handler, req, ctx) {
|
|
|
7932
8094
|
}
|
|
7933
8095
|
function discoverRoutes(dir) {
|
|
7934
8096
|
const appDir = join5(dir, "app");
|
|
7935
|
-
if (!
|
|
8097
|
+
if (!existsSync6(appDir)) return [];
|
|
7936
8098
|
const result = [];
|
|
7937
8099
|
function walk(currentDir, routePath) {
|
|
7938
8100
|
let entries;
|
|
@@ -7953,7 +8115,7 @@ function discoverRoutes(dir) {
|
|
|
7953
8115
|
} else if (entry.name === "page.tsx") {
|
|
7954
8116
|
result.push({
|
|
7955
8117
|
path: routePath || "/",
|
|
7956
|
-
file:
|
|
8118
|
+
file: relative3(appDir, join5(currentDir, entry.name))
|
|
7957
8119
|
});
|
|
7958
8120
|
}
|
|
7959
8121
|
}
|
|
@@ -7963,28 +8125,19 @@ function discoverRoutes(dir) {
|
|
|
7963
8125
|
}
|
|
7964
8126
|
function ssr(opts) {
|
|
7965
8127
|
const r = new Router();
|
|
7966
|
-
const dir =
|
|
7967
|
-
const outDir = resolve6(OUT_DIR);
|
|
8128
|
+
const dir = resolve8(opts.dir);
|
|
7968
8129
|
const routeCache = /* @__PURE__ */ new Map();
|
|
8130
|
+
const wfwRoot = resolve8(import.meta.dirname ?? __dirname);
|
|
8131
|
+
r.use("/", moduleServer({ root: [dir, wfwRoot] }));
|
|
7969
8132
|
compileVendorBundle().catch(() => {
|
|
7970
8133
|
});
|
|
7971
|
-
r.get("/__ssr/:file", (req, ctx) => {
|
|
7972
|
-
const filePath = join5(outDir, ctx.params.file);
|
|
7973
|
-
if (!filePath.startsWith(outDir) || !existsSync4(filePath)) {
|
|
7974
|
-
return new Response("Not Found", { status: 404 });
|
|
7975
|
-
}
|
|
7976
|
-
const content = readFileSync4(filePath, "utf-8");
|
|
7977
|
-
return new Response(content, {
|
|
7978
|
-
headers: { "content-type": "application/javascript; charset=utf-8" }
|
|
7979
|
-
});
|
|
7980
|
-
});
|
|
7981
8134
|
r.get("/__wfw/v/bundle", async () => {
|
|
7982
8135
|
const code = await compileVendorBundle();
|
|
7983
8136
|
return new Response(code, {
|
|
7984
8137
|
headers: { "content-type": "application/javascript; charset=utf-8" }
|
|
7985
8138
|
});
|
|
7986
8139
|
});
|
|
7987
|
-
if (
|
|
8140
|
+
if (existsSync6(join5(dir, "app", "globals.css"))) {
|
|
7988
8141
|
r.use("/", tailwindRouter(dir));
|
|
7989
8142
|
}
|
|
7990
8143
|
let devWatcher;
|
|
@@ -8020,7 +8173,7 @@ function ssr(opts) {
|
|
|
8020
8173
|
...resolved.layoutFiles.map((f) => layout(f)),
|
|
8021
8174
|
tailwindContext(dir)
|
|
8022
8175
|
];
|
|
8023
|
-
const handler = (req2, ctx2) => renderPage(resolved.pageFile,
|
|
8176
|
+
const handler = (req2, ctx2) => renderPage(resolved.pageFile, dir)(req2, ctx2);
|
|
8024
8177
|
return runChain(mws, handler, req, ctx);
|
|
8025
8178
|
});
|
|
8026
8179
|
const mod = r;
|
|
@@ -8272,13 +8425,13 @@ function createBashTool(ctx) {
|
|
|
8272
8425
|
return { stdout: "", stderr: "Command denied: potentially dangerous command", exitCode: 1 };
|
|
8273
8426
|
}
|
|
8274
8427
|
const cwd = workdir ? `${ctx.workspace}/${workdir}` : ctx.workspace;
|
|
8275
|
-
return new Promise((
|
|
8428
|
+
return new Promise((resolve16) => {
|
|
8276
8429
|
const child = exec(
|
|
8277
8430
|
command,
|
|
8278
8431
|
{ cwd, timeout: timeout * 1e3, maxBuffer: 1024 * 1024 },
|
|
8279
8432
|
(error, stdout, stderr) => {
|
|
8280
8433
|
const truncated = stdout.length > 1e6 || stderr.length > 1e6;
|
|
8281
|
-
|
|
8434
|
+
resolve16({
|
|
8282
8435
|
stdout: stdout.slice(0, 1e6),
|
|
8283
8436
|
stderr: stderr.slice(0, 1e6),
|
|
8284
8437
|
exitCode: error?.code ?? 0,
|
|
@@ -8295,8 +8448,8 @@ function createBashTool(ctx) {
|
|
|
8295
8448
|
// opencode/tools/read.ts
|
|
8296
8449
|
import { tool as tool4 } from "ai";
|
|
8297
8450
|
import { z as z6 } from "zod";
|
|
8298
|
-
import { readFileSync as
|
|
8299
|
-
import { resolve as
|
|
8451
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
8452
|
+
import { resolve as resolve9 } from "node:path";
|
|
8300
8453
|
function createReadTool(ctx) {
|
|
8301
8454
|
return tool4({
|
|
8302
8455
|
description: "Read file contents. Supports offset and limit for reading specific line ranges.",
|
|
@@ -8306,11 +8459,11 @@ function createReadTool(ctx) {
|
|
|
8306
8459
|
limit: z6.number().optional().describe("Number of lines to read")
|
|
8307
8460
|
}),
|
|
8308
8461
|
execute: async ({ path: path2, offset, limit }) => {
|
|
8309
|
-
const resolved =
|
|
8462
|
+
const resolved = resolve9(ctx.workspace, path2);
|
|
8310
8463
|
if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
|
|
8311
8464
|
return { error: "Path not allowed", content: null, totalLines: 0 };
|
|
8312
8465
|
}
|
|
8313
|
-
const content =
|
|
8466
|
+
const content = readFileSync7(resolved, "utf-8");
|
|
8314
8467
|
const lines = content.split("\n");
|
|
8315
8468
|
const totalLines = lines.length;
|
|
8316
8469
|
if (offset !== void 0) {
|
|
@@ -8338,7 +8491,7 @@ function createReadTool(ctx) {
|
|
|
8338
8491
|
import { tool as tool5 } from "ai";
|
|
8339
8492
|
import { z as z7 } from "zod";
|
|
8340
8493
|
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
|
|
8341
|
-
import { resolve as
|
|
8494
|
+
import { resolve as resolve10, dirname as dirname5 } from "node:path";
|
|
8342
8495
|
function createWriteTool(ctx) {
|
|
8343
8496
|
return tool5({
|
|
8344
8497
|
description: "Create or overwrite a file. Parent directories are created automatically.",
|
|
@@ -8347,11 +8500,11 @@ function createWriteTool(ctx) {
|
|
|
8347
8500
|
content: z7.string().describe("File content")
|
|
8348
8501
|
}),
|
|
8349
8502
|
execute: async ({ path: path2, content }) => {
|
|
8350
|
-
const resolved =
|
|
8503
|
+
const resolved = resolve10(ctx.workspace, path2);
|
|
8351
8504
|
if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
|
|
8352
8505
|
return { error: "Path not allowed" };
|
|
8353
8506
|
}
|
|
8354
|
-
mkdirSync3(
|
|
8507
|
+
mkdirSync3(dirname5(resolved), { recursive: true });
|
|
8355
8508
|
writeFileSync2(resolved, content, "utf-8");
|
|
8356
8509
|
return { path: path2, size: content.length };
|
|
8357
8510
|
}
|
|
@@ -8361,8 +8514,8 @@ function createWriteTool(ctx) {
|
|
|
8361
8514
|
// opencode/tools/edit.ts
|
|
8362
8515
|
import { tool as tool6 } from "ai";
|
|
8363
8516
|
import { z as z8 } from "zod";
|
|
8364
|
-
import { readFileSync as
|
|
8365
|
-
import { resolve as
|
|
8517
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
|
|
8518
|
+
import { resolve as resolve11 } from "node:path";
|
|
8366
8519
|
function createEditTool(ctx) {
|
|
8367
8520
|
return tool6({
|
|
8368
8521
|
description: "Perform exact string replacements in a file. If oldString appears multiple times, provide more surrounding context.",
|
|
@@ -8373,11 +8526,11 @@ function createEditTool(ctx) {
|
|
|
8373
8526
|
replaceAll: z8.boolean().default(false).describe("Replace all occurrences")
|
|
8374
8527
|
}),
|
|
8375
8528
|
execute: async ({ path: path2, oldString, newString, replaceAll }) => {
|
|
8376
|
-
const resolved =
|
|
8529
|
+
const resolved = resolve11(ctx.workspace, path2);
|
|
8377
8530
|
if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions.permissions)) {
|
|
8378
8531
|
return { error: "Path not allowed" };
|
|
8379
8532
|
}
|
|
8380
|
-
const content =
|
|
8533
|
+
const content = readFileSync8(resolved, "utf-8");
|
|
8381
8534
|
if (replaceAll) {
|
|
8382
8535
|
if (!content.includes(oldString)) {
|
|
8383
8536
|
return { error: "oldString not found in file", replaced: 0 };
|
|
@@ -8409,8 +8562,8 @@ function createEditTool(ctx) {
|
|
|
8409
8562
|
import { tool as tool7 } from "ai";
|
|
8410
8563
|
import { z as z9 } from "zod";
|
|
8411
8564
|
import { execFileSync } from "node:child_process";
|
|
8412
|
-
import { resolve as
|
|
8413
|
-
import { existsSync as
|
|
8565
|
+
import { resolve as resolve12 } from "node:path";
|
|
8566
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
8414
8567
|
function createGrepTool(ctx) {
|
|
8415
8568
|
return tool7({
|
|
8416
8569
|
description: "Search file contents using regex. Supports file type filtering and context lines.",
|
|
@@ -8421,10 +8574,10 @@ function createGrepTool(ctx) {
|
|
|
8421
8574
|
context: z9.number().default(0).describe("Number of context lines before and after each match")
|
|
8422
8575
|
}),
|
|
8423
8576
|
execute: async ({ pattern, include, path: path2, context }) => {
|
|
8424
|
-
const searchDir = path2 ?
|
|
8577
|
+
const searchDir = path2 ? resolve12(ctx.workspace, path2) : ctx.workspace;
|
|
8425
8578
|
try {
|
|
8426
8579
|
let stdout;
|
|
8427
|
-
if (
|
|
8580
|
+
if (existsSync7("/usr/bin/rg") || existsSync7("/usr/local/bin/rg")) {
|
|
8428
8581
|
const args = ["-n"];
|
|
8429
8582
|
if (context > 0) args.push("-C", String(context));
|
|
8430
8583
|
if (include) args.push("-g", include);
|
|
@@ -8457,7 +8610,7 @@ function createGrepTool(ctx) {
|
|
|
8457
8610
|
import { tool as tool8 } from "ai";
|
|
8458
8611
|
import { z as z10 } from "zod";
|
|
8459
8612
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
8460
|
-
import { resolve as
|
|
8613
|
+
import { resolve as resolve13 } from "node:path";
|
|
8461
8614
|
function createGlobTool(ctx) {
|
|
8462
8615
|
return tool8({
|
|
8463
8616
|
description: "Find files matching a glob pattern.",
|
|
@@ -8466,7 +8619,7 @@ function createGlobTool(ctx) {
|
|
|
8466
8619
|
path: z10.string().optional().describe("Subdirectory relative to workspace")
|
|
8467
8620
|
}),
|
|
8468
8621
|
execute: async ({ pattern, path: path2 }) => {
|
|
8469
|
-
const searchDir = path2 ?
|
|
8622
|
+
const searchDir = path2 ? resolve13(ctx.workspace, path2) : ctx.workspace;
|
|
8470
8623
|
try {
|
|
8471
8624
|
const stdout = execFileSync2(
|
|
8472
8625
|
"find",
|
|
@@ -8492,7 +8645,7 @@ function createGlobTool(ctx) {
|
|
|
8492
8645
|
// opencode/tools/web.ts
|
|
8493
8646
|
import { tool as tool9 } from "ai";
|
|
8494
8647
|
import { z as z11 } from "zod";
|
|
8495
|
-
function createWebTool(
|
|
8648
|
+
function createWebTool(_ctx2) {
|
|
8496
8649
|
return tool9({
|
|
8497
8650
|
description: "Fetch a URL and return the content as text.",
|
|
8498
8651
|
inputSchema: z11.object({
|
|
@@ -8528,7 +8681,7 @@ function createQuestionTool(ctx) {
|
|
|
8528
8681
|
options: z12.array(z12.string()).optional().describe("Optional multiple choice options")
|
|
8529
8682
|
}),
|
|
8530
8683
|
execute: async ({ question, options }, { toolCallId }) => {
|
|
8531
|
-
return new Promise((
|
|
8684
|
+
return new Promise((resolve16, reject) => {
|
|
8532
8685
|
const timeout = setTimeout(() => {
|
|
8533
8686
|
ctx.pendingQuestions.delete(toolCallId);
|
|
8534
8687
|
reject(new Error("Question timed out"));
|
|
@@ -8536,7 +8689,7 @@ function createQuestionTool(ctx) {
|
|
|
8536
8689
|
ctx.pendingQuestions.set(toolCallId, {
|
|
8537
8690
|
resolve: (answer) => {
|
|
8538
8691
|
clearTimeout(timeout);
|
|
8539
|
-
|
|
8692
|
+
resolve16(answer);
|
|
8540
8693
|
},
|
|
8541
8694
|
reject: (err) => {
|
|
8542
8695
|
clearTimeout(timeout);
|
|
@@ -8857,7 +9010,7 @@ function createWSHandler2(deps) {
|
|
|
8857
9010
|
clients2.delete(ws);
|
|
8858
9011
|
}
|
|
8859
9012
|
},
|
|
8860
|
-
error(ws,
|
|
9013
|
+
error(ws, _ctx2, _err) {
|
|
8861
9014
|
const client = clients2.get(ws);
|
|
8862
9015
|
if (client) {
|
|
8863
9016
|
client.abortController?.abort();
|
|
@@ -8870,7 +9023,7 @@ function createWSHandler2(deps) {
|
|
|
8870
9023
|
// opencode/skills.ts
|
|
8871
9024
|
import { readFile, glob } from "node:fs/promises";
|
|
8872
9025
|
import { homedir } from "node:os";
|
|
8873
|
-
import { resolve as
|
|
9026
|
+
import { resolve as resolve14 } from "node:path";
|
|
8874
9027
|
import { parse as parseYaml } from "yaml";
|
|
8875
9028
|
var SEARCH_DIRS = [
|
|
8876
9029
|
(ws) => `${ws}/.opencode/skills`,
|
|
@@ -8908,7 +9061,7 @@ async function scanDir(dir) {
|
|
|
8908
9061
|
try {
|
|
8909
9062
|
const files = [];
|
|
8910
9063
|
for await (const entry of glob("*/SKILL.md", { cwd: dir })) {
|
|
8911
|
-
const skill = await parseSkillFile(
|
|
9064
|
+
const skill = await parseSkillFile(resolve14(dir, entry));
|
|
8912
9065
|
if (skill) files.push(skill);
|
|
8913
9066
|
}
|
|
8914
9067
|
return files;
|
|
@@ -9335,7 +9488,7 @@ function theme(options) {
|
|
|
9335
9488
|
|
|
9336
9489
|
// i18n.ts
|
|
9337
9490
|
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
9338
|
-
import { join as join7, resolve as
|
|
9491
|
+
import { join as join7, resolve as resolve15 } from "node:path";
|
|
9339
9492
|
var DEFAULTS2 = {
|
|
9340
9493
|
default: "en",
|
|
9341
9494
|
cookie: "locale",
|
|
@@ -9353,7 +9506,7 @@ function translate(msgs, key, params, fallback) {
|
|
|
9353
9506
|
}
|
|
9354
9507
|
function i18n(options) {
|
|
9355
9508
|
const opts = { ...DEFAULTS2, ...options };
|
|
9356
|
-
const dir = opts.dir ?
|
|
9509
|
+
const dir = opts.dir ? resolve15(opts.dir) : void 0;
|
|
9357
9510
|
const cache3 = /* @__PURE__ */ new Map();
|
|
9358
9511
|
function validLocale(locale) {
|
|
9359
9512
|
return /^[\w-]+$/.test(locale) && !locale.includes("..");
|
|
@@ -10245,7 +10398,7 @@ function createWsHandler(deps) {
|
|
|
10245
10398
|
return wsToWorkerId.get(ws) || "";
|
|
10246
10399
|
}
|
|
10247
10400
|
return {
|
|
10248
|
-
open(_ws,
|
|
10401
|
+
open(_ws, _ctx2) {
|
|
10249
10402
|
},
|
|
10250
10403
|
async message(ws, ctx, data) {
|
|
10251
10404
|
let msg;
|
|
@@ -10447,12 +10600,12 @@ function iii(opts = {}) {
|
|
|
10447
10600
|
const handler = async (payload) => {
|
|
10448
10601
|
if (!worker.ws) throw new Error(`Worker "${worker.name}" disconnected`);
|
|
10449
10602
|
const invocationId = crypto8.randomUUID();
|
|
10450
|
-
return new Promise((
|
|
10603
|
+
return new Promise((resolve16, reject) => {
|
|
10451
10604
|
const timer = setTimeout(() => {
|
|
10452
10605
|
pending.delete(invocationId);
|
|
10453
10606
|
reject(new Error(`Invocation timed out for "${id2}"`));
|
|
10454
10607
|
}, 3e4);
|
|
10455
|
-
pending.set(invocationId, { resolve:
|
|
10608
|
+
pending.set(invocationId, { resolve: resolve16, reject, timer });
|
|
10456
10609
|
worker.ws.send(
|
|
10457
10610
|
JSON.stringify({
|
|
10458
10611
|
type: "invoke",
|
|
@@ -10703,8 +10856,8 @@ function registerWorker(url) {
|
|
|
10703
10856
|
function connect() {
|
|
10704
10857
|
if (intentionalClose) return;
|
|
10705
10858
|
ws = new WebSocket(url);
|
|
10706
|
-
ready = new Promise((
|
|
10707
|
-
resolveReady =
|
|
10859
|
+
ready = new Promise((resolve16) => {
|
|
10860
|
+
resolveReady = resolve16;
|
|
10708
10861
|
});
|
|
10709
10862
|
ws.onopen = () => {
|
|
10710
10863
|
reconnectAttempt = 0;
|
|
@@ -10835,13 +10988,13 @@ function registerWorker(url) {
|
|
|
10835
10988
|
}
|
|
10836
10989
|
return Promise.resolve(fn(request.payload, ctx));
|
|
10837
10990
|
}
|
|
10838
|
-
return new Promise((
|
|
10991
|
+
return new Promise((resolve16, reject) => {
|
|
10839
10992
|
const invocationId = genId();
|
|
10840
10993
|
const timer = setTimeout(() => {
|
|
10841
10994
|
pendingInvocations.delete(invocationId);
|
|
10842
10995
|
reject(new Error(`Invocation timed out for "${request.function_id}"`));
|
|
10843
10996
|
}, request.timeout_ms || 3e4);
|
|
10844
|
-
pendingInvocations.set(invocationId, { resolve:
|
|
10997
|
+
pendingInvocations.set(invocationId, { resolve: resolve16, reject, timer });
|
|
10845
10998
|
send({
|
|
10846
10999
|
type: "invoke",
|
|
10847
11000
|
invocation_id: invocationId,
|