weifuwu 0.19.6 → 0.19.8

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.
@@ -1,3 +1,3 @@
1
1
  export default function Greeting({ name }: { name: string }) {
2
- return <span className="text-red-500 font-bold">{name}!</span>
2
+ return <span className="text-green-500 font-bold">{name}!</span>
3
3
  }
package/dist/index.d.ts CHANGED
@@ -73,3 +73,5 @@ export { layout } from './layout.ts';
73
73
  export { notFound } from './not-found.ts';
74
74
  export { errorBoundary } from './error-boundary.ts';
75
75
  export { clearCompileCache } from './compile.ts';
76
+ export { ssrEntries } from './ssr-entries.ts';
77
+ export type { SsrEntry } from './ssr-entries.ts';
package/dist/index.js CHANGED
@@ -5192,7 +5192,7 @@ async function compileHotComponent(path2) {
5192
5192
  });
5193
5193
  let code = new TextDecoder().decode(result.outputFiles[0].contents);
5194
5194
  if (code.includes("__require") && (code.includes('"react"') || code.includes("'react'"))) {
5195
- code = `import __r from '/__wfw/v/bundle';
5195
+ code = `import * as __r from 'react';
5196
5196
  ` + code.replace(/__require\(["']react["']\)/g, "__r");
5197
5197
  }
5198
5198
  return { hash: h, code };
@@ -5212,16 +5212,18 @@ function getPublicEnv() {
5212
5212
  return _publicEnv;
5213
5213
  }
5214
5214
  function buildHeadPayload(opts) {
5215
- const { ctx, base, compiledTailwindCss, isDev: isDev2 } = opts;
5215
+ const { ctx, compiledTailwindCss, isDev: isDev2 } = opts;
5216
+ const rb = opts.rootBase || "";
5216
5217
  let result = "";
5217
5218
  if (isDev2) {
5219
+ const vUrl = `${rb}/__wfw/v/bundle`;
5218
5220
  result += `<script type="importmap">{
5219
5221
  "imports": {
5220
- "react": "/__wfw/v/bundle",
5221
- "react-dom": "/__wfw/v/bundle",
5222
- "react-dom/client": "/__wfw/v/bundle",
5223
- "react/jsx-runtime": "/__wfw/v/bundle",
5224
- "weifuwu/react": "/__wfw/v/bundle"
5222
+ "react": "${vUrl}",
5223
+ "react-dom": "${vUrl}",
5224
+ "react-dom/client": "${vUrl}",
5225
+ "react/jsx-runtime": "${vUrl}",
5226
+ "weifuwu/react": "${vUrl}"
5225
5227
  }
5226
5228
  }</script>
5227
5229
  `;
@@ -5231,8 +5233,8 @@ function buildHeadPayload(opts) {
5231
5233
  `;
5232
5234
  }
5233
5235
  if (compiledTailwindCss) {
5234
- const cssUrl = ctx.tailwindCssUrl || "/__wfw/style.css";
5235
- result += `<link rel="stylesheet" href="${cssUrl}" />
5236
+ const cssUrl = ctx.tailwindCssUrl;
5237
+ if (cssUrl) result += `<link rel="stylesheet" href="${cssUrl}" />
5236
5238
  `;
5237
5239
  }
5238
5240
  const localeData = ctx.parsed?.__localeData ?? globalThis.__LOCALE_DATA__;
@@ -5313,9 +5315,12 @@ function streamResponse(reactStream, opts) {
5313
5315
  const body = buildBodyScripts(opts);
5314
5316
  if (body) controller.enqueue(encoder2.encode("\n" + body));
5315
5317
  if (opts.isDev) {
5318
+ const rb = opts.rootBase || "";
5319
+ const wsUrl = `${rb}/__weifuwu/livereload`;
5320
+ const hbUrl = `${rb}/__wfw/h/`;
5316
5321
  controller.enqueue(encoder2.encode(
5317
5322
  `
5318
- <script>(function(){var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'/__weifuwu/livereload');var t=0;ws.onmessage=function(e){try{var m=JSON.parse(e.data);if(m.type==='component'){if(m.entry&&m.entry!==window.__WFW_ENTRY)return;import('/__wfw/h/'+m.hash+'?'+Date.now()).catch(function(){location.reload()});if(m.css){var s=document.querySelector('style[data-lr]')||function(){var x=document.createElement('style');x.setAttribute('data-lr','');document.head.appendChild(x);return x}();s.textContent=m.css}return}if(m.type==='css'){var s=document.querySelector('style[data-lr]')||function(){var x=document.createElement('style');x.setAttribute('data-lr','');document.head.appendChild(x);return x}();s.textContent=m.css;return}}catch(_){}if(e.data==='reload'&&Date.now()-t>1e3){t=Date.now();location.reload()}};ws.onclose=function(){if(Date.now()-t>1e3){t=Date.now();setTimeout(function(){location.reload()},500)}}})()</script>`
5323
+ <script>(function(){var ws=new WebSocket((location.protocol==='https:'?'wss:':'ws:')+'//'+location.host+'${wsUrl}');var t=0;ws.onmessage=function(e){try{var m=JSON.parse(e.data);if(m.type==='component'){if(m.entry&&m.entry!==window.__WFW_ENTRY)return;import('${hbUrl}'+m.hash+'?'+Date.now()).catch(function(){location.reload()});if(m.css){var s=document.querySelector('style[data-lr]')||function(){var x=document.createElement('style');x.setAttribute('data-lr','');document.head.appendChild(x);return x}();s.textContent=m.css}return}if(m.type==='css'){var s=document.querySelector('style[data-lr]')||function(){var x=document.createElement('style');x.setAttribute('data-lr','');document.head.appendChild(x);return x}();s.textContent=m.css;return}}catch(_){}if(e.data==='reload'&&Date.now()-t>1e3){t=Date.now();location.reload()}};ws.onclose=function(){if(Date.now()-t>1e3){t=Date.now();setTimeout(function(){location.reload()},500)}}})()</script>`
5319
5324
  ));
5320
5325
  }
5321
5326
  } catch {
@@ -5332,6 +5337,9 @@ function streamResponse(reactStream, opts) {
5332
5337
  });
5333
5338
  }
5334
5339
 
5340
+ // ssr-entries.ts
5341
+ var ssrEntries = /* @__PURE__ */ new Map();
5342
+
5335
5343
  // ssr.ts
5336
5344
  var als = new AsyncLocalStorage();
5337
5345
  __registerAls(() => als.getStore());
@@ -5408,7 +5416,9 @@ async function buildClientBundle(entryPath, layoutPaths) {
5408
5416
  }
5409
5417
  }
5410
5418
  function ssr(path2) {
5411
- const entryId = id2(resolve4(path2));
5419
+ const absPath = resolve4(path2);
5420
+ const entryId = id2(absPath);
5421
+ ssrEntries.set(entryId, { path: absPath });
5412
5422
  const bundleKey = `/__ssr/${entryId}.js`;
5413
5423
  const r = new Router();
5414
5424
  r.get("/__ssr/:path", (req, ctx) => {
@@ -5481,6 +5491,7 @@ function ssr(path2) {
5481
5491
  return streamResponse(stream, {
5482
5492
  ctx,
5483
5493
  base,
5494
+ rootBase: ctx.rootLayoutBase || "",
5484
5495
  isDev,
5485
5496
  bundle,
5486
5497
  loaderData,
@@ -5556,7 +5567,7 @@ ${src}`;
5556
5567
  // live.ts
5557
5568
  import chokidar from "chokidar";
5558
5569
  import { existsSync as existsSync4 } from "node:fs";
5559
- import { join as join4, resolve as resolve6 } from "node:path";
5570
+ import { dirname as dirname3, join as join4, resolve as resolve6 } from "node:path";
5560
5571
  var clients = /* @__PURE__ */ new Set();
5561
5572
  var hotBundleCache = /* @__PURE__ */ new Map();
5562
5573
  var hotKeys = [];
@@ -5619,6 +5630,24 @@ function liveReload(dir) {
5619
5630
  ignored: /(^|[/\\])\.|node_modules|[/\\]\.weifuwu[/\\]/,
5620
5631
  ignoreInitial: true
5621
5632
  });
5633
+ function findEntries(changedPath) {
5634
+ const matched = [];
5635
+ for (const [, entry] of ssrEntries) {
5636
+ if (!entry.path.startsWith(resolved)) continue;
5637
+ if (entry.path === changedPath) {
5638
+ matched.push(entry.path);
5639
+ } else {
5640
+ const ed = dirname3(entry.path);
5641
+ if (changedPath.startsWith(ed)) matched.push(entry.path);
5642
+ }
5643
+ }
5644
+ if (matched.length === 0) {
5645
+ for (const [, entry] of ssrEntries) {
5646
+ if (entry.path.startsWith(resolved)) matched.push(entry.path);
5647
+ }
5648
+ }
5649
+ return matched;
5650
+ }
5622
5651
  watcher.on("change", async (filePath) => {
5623
5652
  if (/\.tsx?$/i.test(filePath)) {
5624
5653
  if (filePath.endsWith("layout.tsx")) {
@@ -5626,25 +5655,28 @@ function liveReload(dir) {
5626
5655
  }
5627
5656
  clearCompileCache();
5628
5657
  markClientBundleDirty();
5658
+ const targets = existsSync4(entryPath) ? [entryPath] : findEntries(resolve6(filePath));
5659
+ if (targets.length === 0) return broadcastReload();
5629
5660
  try {
5630
- const target = existsSync4(entryPath) ? entryPath : filePath;
5631
- await compileTsxDev(target);
5632
- const { hash, code } = await compileHotComponent(target);
5633
- setHot(hash, code);
5634
5661
  let css;
5635
5662
  const cssPath = join4(resolved, "app.css");
5636
5663
  if (existsSync4(cssPath)) {
5637
5664
  css = await compileTailwindCss(cssPath, resolved);
5638
5665
  }
5639
- const entry = id(entryPath);
5640
- const msg = { type: "component", hash, entry };
5641
- if (css) msg.css = css;
5642
- const str = JSON.stringify(msg);
5643
- for (const ws of clients) {
5644
- try {
5645
- ws.send(str);
5646
- } catch {
5647
- clients.delete(ws);
5666
+ for (const target of targets) {
5667
+ await compileTsxDev(target);
5668
+ const { hash, code } = await compileHotComponent(target);
5669
+ setHot(hash, code);
5670
+ const entry = id(target);
5671
+ const msg = { type: "component", hash, entry };
5672
+ if (css) msg.css = css;
5673
+ const str = JSON.stringify(msg);
5674
+ for (const ws of clients) {
5675
+ try {
5676
+ ws.send(str);
5677
+ } catch {
5678
+ clients.delete(ws);
5679
+ }
5648
5680
  }
5649
5681
  }
5650
5682
  } catch (e) {
@@ -5675,6 +5707,7 @@ function rootLayout(dir) {
5675
5707
  r.use(async (req, ctx, next) => {
5676
5708
  const mod = await compile(layoutPath);
5677
5709
  if (mod?.default) ctx.layoutStack = [{ path: layoutPath, component: mod.default }];
5710
+ ctx.rootLayoutBase = (ctx.mountPath || "").replace(/\/$/, "");
5678
5711
  return next(req, ctx);
5679
5712
  });
5680
5713
  if (existsSync5(join5(resolved, "app.css"))) {
@@ -5986,7 +6019,7 @@ function createReadTool(ctx) {
5986
6019
  import { tool as tool5 } from "ai";
5987
6020
  import { z as z7 } from "zod";
5988
6021
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
5989
- import { resolve as resolve9, dirname as dirname3 } from "node:path";
6022
+ import { resolve as resolve9, dirname as dirname4 } from "node:path";
5990
6023
  function createWriteTool(ctx) {
5991
6024
  return tool5({
5992
6025
  description: "Create or overwrite a file. Parent directories are created automatically.",
@@ -5999,7 +6032,7 @@ function createWriteTool(ctx) {
5999
6032
  if (!isPathAllowed(resolved, ctx.workspace, ctx.permissions)) {
6000
6033
  return { error: "Path not allowed" };
6001
6034
  }
6002
- mkdirSync3(dirname3(resolved), { recursive: true });
6035
+ mkdirSync3(dirname4(resolved), { recursive: true });
6003
6036
  writeFileSync2(resolved, content, "utf-8");
6004
6037
  return { path: path2, size: content.length };
6005
6038
  }
@@ -8491,6 +8524,7 @@ export {
8491
8524
  setCookie,
8492
8525
  smoothStream,
8493
8526
  ssr,
8527
+ ssrEntries,
8494
8528
  streamObject,
8495
8529
  streamText,
8496
8530
  tenant,
package/dist/react.js CHANGED
@@ -192,7 +192,7 @@ async function navigate(href) {
192
192
  location.href = href;
193
193
  return;
194
194
  }
195
- const bundleMatch = html.match(/src="(\/__wfw\/client\/[^"]+\.js)"/);
195
+ const bundleMatch = html.match(/src="(\/__ssr\/[^"]+\.js)"/);
196
196
  const bundleUrl = bundleMatch ? bundleMatch[1] : null;
197
197
  applyHead(html);
198
198
  const currentRoot = document.getElementById("__weifuwu_root");
@@ -0,0 +1,4 @@
1
+ export interface SsrEntry {
2
+ path: string;
3
+ }
4
+ export declare const ssrEntries: Map<string, SsrEntry>;
package/dist/stream.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { Context } from './types.ts';
2
2
  export interface StreamOpts {
3
3
  ctx: Context;
4
4
  base: string;
5
+ rootBase?: string;
5
6
  compiledTailwindCss?: string;
6
7
  isDev: boolean;
7
8
  status?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weifuwu",
3
- "version": "0.19.6",
3
+ "version": "0.19.8",
4
4
  "description": "Web-standard HTTP framework for Node.js — (req, ctx) => Response",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,6 +20,8 @@
20
20
  "LICENSE"
21
21
  ],
22
22
  "scripts": {
23
+ "dev": "node --watch ./cli/template/index.ts",
24
+ "start": "NODE_ENV=production node ./cli/template/index.ts",
23
25
  "build": "esbuild index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --packages=external && esbuild cli.ts --bundle --format=esm --platform=node --outfile=dist/cli.js --packages=external && esbuild react.ts --bundle --format=esm --outfile=dist/react.js --external:react --external:react-dom",
24
26
  "prepublishOnly": "npm run build && tsc --emitDeclarationOnly --outdir dist",
25
27
  "test": "node --test 'test/**/*.test.ts'"