weifuwu 0.33.1 → 0.33.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
@@ -225,14 +225,14 @@ function serve(router, options) {
225
225
  if (!server.listening) return;
226
226
  server.close();
227
227
  server.closeIdleConnections();
228
- return new Promise((resolve5) => {
228
+ return new Promise((resolve3) => {
229
229
  const timer = setTimeout(() => {
230
230
  server.closeAllConnections();
231
- resolve5();
231
+ resolve3();
232
232
  }, timeoutMs);
233
233
  server.on("close", () => {
234
234
  clearTimeout(timer);
235
- resolve5();
235
+ resolve3();
236
236
  });
237
237
  });
238
238
  }
@@ -589,7 +589,6 @@ var Router = class _Router {
589
589
  _route(method, path, ...args) {
590
590
  return this._routeImpl(method, path, args);
591
591
  }
592
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
593
592
  _routeImpl(method, path, args) {
594
593
  const last = args[args.length - 1];
595
594
  if (last instanceof _Router) {
@@ -926,13 +925,13 @@ function serveStatic(root, options) {
926
925
  let fileHandle;
927
926
  try {
928
927
  fileHandle = await open(filePath, "r");
929
- let stat3 = await fileHandle.stat();
928
+ let stat = await fileHandle.stat();
930
929
  const realPath = await realpath(filePath);
931
930
  if (!realPath.startsWith(rootDir + sep) && realPath !== rootDir) {
932
931
  await fileHandle.close();
933
932
  return new Response("Forbidden", { status: 403 });
934
933
  }
935
- if (stat3.isDirectory()) {
934
+ if (stat.isDirectory()) {
936
935
  await fileHandle.close();
937
936
  const indexFile = opts.index ?? "index.html";
938
937
  filePath = resolve(filePath, indexFile);
@@ -940,29 +939,29 @@ function serveStatic(root, options) {
940
939
  return new Response("Forbidden", { status: 403 });
941
940
  }
942
941
  fileHandle = await open(filePath, "r");
943
- stat3 = await fileHandle.stat();
944
- if (!stat3.isFile()) {
942
+ stat = await fileHandle.stat();
943
+ if (!stat.isFile()) {
945
944
  await fileHandle.close();
946
945
  return new Response("Not Found", { status: 404 });
947
946
  }
948
947
  }
949
948
  const mimeType = MIME_TYPES[extname(filePath).toLowerCase()] ?? "application/octet-stream";
950
- const etag = `"${stat3.ino}-${stat3.size}-${stat3.mtimeMs}"`;
949
+ const etag = `"${stat.ino}-${stat.size}-${stat.mtimeMs}"`;
951
950
  const ifNoneMatch = req.headers.get("if-none-match");
952
951
  if (ifNoneMatch === etag) {
953
952
  await fileHandle.close();
954
953
  return new Response(null, { status: 304 });
955
954
  }
956
955
  const ifModifiedSince = req.headers.get("if-modified-since");
957
- if (ifModifiedSince && stat3.mtimeMs <= new Date(ifModifiedSince).getTime()) {
956
+ if (ifModifiedSince && stat.mtimeMs <= new Date(ifModifiedSince).getTime()) {
958
957
  await fileHandle.close();
959
958
  return new Response(null, { status: 304 });
960
959
  }
961
960
  const headers = {
962
961
  "Content-Type": mimeType,
963
- "Content-Length": String(stat3.size),
962
+ "Content-Length": String(stat.size),
964
963
  ETag: etag,
965
- "Last-Modified": stat3.mtime.toUTCString(),
964
+ "Last-Modified": stat.mtime.toUTCString(),
966
965
  "Cache-Control": opts.immutable ? `public, max-age=${opts.maxAge ?? 31536e3}, immutable` : `public, max-age=${opts.maxAge ?? 0}`
967
966
  };
968
967
  const readStream = fileHandle.createReadStream();
@@ -1181,467 +1180,6 @@ function sandbox(opts = {}) {
1181
1180
  };
1182
1181
  }
1183
1182
 
1184
- // src/middleware/esbuild-dev.ts
1185
- import { resolve as resolve3, relative, dirname } from "node:path";
1186
- import { stat, readFile as readFile2, realpath as realpath2 } from "node:fs/promises";
1187
- function escapeHtml(s) {
1188
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1189
- }
1190
- function defaultErrorTemplate(errors) {
1191
- return `<!DOCTYPE html>
1192
- <html>
1193
- <head>
1194
- <meta charset="utf-8">
1195
- <title>Build Error</title>
1196
- <style>
1197
- * { margin: 0; padding: 0; box-sizing: border-box; }
1198
- body { font-family: system-ui; background: #1a1a2e; color: #e0e0e0; padding: 2rem; }
1199
- .overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; }
1200
- .card { background: #16213e; border: 1px solid #e74c3c; border-radius: 12px; padding: 2rem; max-width: 800px; width: 100%; box-shadow: 0 8px 32px rgba(0,0,0,0.4); }
1201
- h1 { color: #e74c3c; font-size: 1.5rem; margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; }
1202
- pre { background: #0f0f23; padding: 1.5rem; border-radius: 8px; overflow: auto; font-size: 0.85rem; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
1203
- </style>
1204
- </head>
1205
- <body>
1206
- <div class="overlay">
1207
- <div class="card">
1208
- <h1>\u26A0 esbuild Build Error</h1>
1209
- <pre>${escapeHtml(errors)}</pre>
1210
- </div>
1211
- </div>
1212
- </body>
1213
- </html>`;
1214
- }
1215
- async function collectDeps(entryPath) {
1216
- const files = /* @__PURE__ */ new Map();
1217
- const visited = /* @__PURE__ */ new Set();
1218
- const queue2 = [entryPath];
1219
- while (queue2.length > 0) {
1220
- const p = queue2.shift();
1221
- try {
1222
- const real = await realpath2(p);
1223
- if (visited.has(real)) continue;
1224
- visited.add(real);
1225
- const s = await stat(real);
1226
- files.set(real, s.mtimeMs);
1227
- } catch {
1228
- continue;
1229
- }
1230
- try {
1231
- const content = await readFile2(p, "utf-8");
1232
- const importRe = /from\s+['"]([^'"]+)['"]|import\s+['"]([^'"]+)['"]/g;
1233
- let m;
1234
- while ((m = importRe.exec(content)) !== null) {
1235
- const spec = m[1] ?? m[2];
1236
- if (spec.startsWith(".") || spec.startsWith("/")) {
1237
- const dir = dirname(p);
1238
- const resolved = resolve3(dir, spec);
1239
- for (const ext of ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", "/index.ts", "/index.tsx", "/index.js"]) {
1240
- const candidate = resolved + ext;
1241
- if (!visited.has(candidate)) {
1242
- queue2.push(candidate);
1243
- break;
1244
- }
1245
- break;
1246
- }
1247
- queue2.push(resolved);
1248
- }
1249
- }
1250
- } catch {
1251
- }
1252
- }
1253
- return files;
1254
- }
1255
- function esbuildDev(opts) {
1256
- const cache = opts.cache ?? "memory";
1257
- const importmap = opts.importmap ?? false;
1258
- const importmapOverrides = opts.importmapOverrides ?? {};
1259
- const errorTemplate = opts.errorTemplate ?? defaultErrorTemplate;
1260
- const entries = Object.entries(opts.entries).map(([p, e]) => {
1261
- const path = p.startsWith("/") ? p : "/" + p;
1262
- const config = typeof e === "string" ? { entry: e } : e;
1263
- return { path, config };
1264
- });
1265
- const cacheStore = /* @__PURE__ */ new Map();
1266
- const chunkMap = /* @__PURE__ */ new Map();
1267
- let esbuild_ = null;
1268
- let esbuildLoadError = null;
1269
- async function getEsbuild() {
1270
- if (esbuild_) return esbuild_;
1271
- try {
1272
- esbuild_ = await import("esbuild");
1273
- return esbuild_;
1274
- } catch (err) {
1275
- esbuildLoadError = `esbuild is not installed. Run: npm install -D esbuild
1276
-
1277
- ${String(err)}`;
1278
- throw new Error(esbuildLoadError, { cause: err });
1279
- }
1280
- }
1281
- let importmapScript = null;
1282
- function buildImportmap() {
1283
- const mappings = {};
1284
- Object.assign(mappings, importmapOverrides);
1285
- for (const { path, config } of entries) {
1286
- const entryName = path.split("/").pop() ?? "";
1287
- if (entryName.includes("vendor") || config.external && config.external.length === 0 || !config.external && config.bundle !== false) {
1288
- if (!mappings["react"]) mappings["react"] = path;
1289
- if (!mappings["react/jsx-runtime"]) mappings["react/jsx-runtime"] = path;
1290
- if (!mappings["react-dom/client"]) mappings["react-dom/client"] = path;
1291
- if (!mappings["react-dom"]) mappings["react-dom"] = path;
1292
- }
1293
- }
1294
- const json = JSON.stringify({ imports: mappings });
1295
- return `<script type="importmap">${json}</script>`;
1296
- }
1297
- async function compile(entry) {
1298
- const esbuild = await getEsbuild();
1299
- const entryAbs = resolve3(entry.entry);
1300
- const buildOpts = {
1301
- entryPoints: [entryAbs],
1302
- bundle: entry.bundle ?? true,
1303
- external: entry.external ?? [],
1304
- minify: entry.minify ?? true,
1305
- platform: entry.platform ?? "browser",
1306
- format: entry.format ?? "esm",
1307
- sourcemap: entry.sourcemap ?? false,
1308
- splitting: entry.splitting ?? false,
1309
- ...entry.splitting ? { outdir: dirname(entryAbs) } : {},
1310
- define: entry.define,
1311
- loader: entry.loader,
1312
- write: false,
1313
- logLevel: "silent"
1314
- };
1315
- const result = await esbuild.build(buildOpts);
1316
- const msgs = [];
1317
- for (const w of result.warnings) {
1318
- const loc = w.location ? ` at ${relative(".", w.location.file ?? "")}:${w.location.line}:${w.location.column}` : "";
1319
- msgs.push(`[warn] ${w.text}${loc}`);
1320
- }
1321
- for (const e of result.errors) {
1322
- const loc = e.location ? ` at ${relative(".", e.location.file ?? "")}:${e.location.line}:${e.location.column}` : "";
1323
- msgs.push(`[error] ${e.text}${loc}`);
1324
- }
1325
- if (result.errors.length > 0) {
1326
- throw new Error(msgs.join("\n"));
1327
- }
1328
- const outputFiles = result.outputFiles;
1329
- const entryFile = outputFiles.find((f) => f.path === entryAbs) ?? outputFiles[0];
1330
- const code = entryFile?.text ?? "";
1331
- let chunks;
1332
- if (outputFiles.length > 1) {
1333
- chunks = /* @__PURE__ */ new Map();
1334
- for (const f of outputFiles) {
1335
- if (f === entryFile) continue;
1336
- const chunkName = f.path.split("/").pop() ?? f.path;
1337
- chunks.set(chunkName, { code: f.text, etag: `"esbuild-${hashCode(f.text)}"` });
1338
- }
1339
- }
1340
- const etag = `"esbuild-${hashCode(code)}"`;
1341
- if (msgs.length > 0) {
1342
- console.error("[esbuildDev]", msgs.join("\n"));
1343
- }
1344
- return { code, etag, chunks };
1345
- }
1346
- function isCacheValid2(cached) {
1347
- return Promise.all(
1348
- [...cached.files].map(async ([file, mtime]) => {
1349
- try {
1350
- const s = await stat(file);
1351
- return s.mtimeMs === mtime;
1352
- } catch {
1353
- return false;
1354
- }
1355
- })
1356
- ).then((results) => results.every(Boolean));
1357
- }
1358
- return async (req, ctx, next) => {
1359
- const url = new URL(req.url);
1360
- const pathname = url.pathname;
1361
- if (importmap && pathname === "/assets/importmap") {
1362
- if (!importmapScript) importmapScript = buildImportmap();
1363
- return new Response(importmapScript, {
1364
- headers: {
1365
- "Content-Type": "application/javascript; charset=utf-8",
1366
- "Cache-Control": "no-cache"
1367
- }
1368
- });
1369
- }
1370
- const matched = entries.find((e) => e.path === pathname);
1371
- const chunkName = pathname.split("/").pop() ?? "";
1372
- const chunkOwner = chunkMap.get(chunkName);
1373
- if (!matched && !chunkOwner) return next(req, ctx);
1374
- if (!matched && chunkOwner) {
1375
- const ownerCache = cacheStore.get(chunkOwner);
1376
- const chunk = ownerCache?.chunks?.get(chunkName);
1377
- if (chunk) {
1378
- if (req.headers.get("if-none-match") === chunk.etag) {
1379
- return new Response(null, { status: 304 });
1380
- }
1381
- return new Response(chunk.code, {
1382
- headers: {
1383
- "Content-Type": "text/javascript; charset=utf-8",
1384
- ETag: chunk.etag,
1385
- "Cache-Control": "no-cache"
1386
- }
1387
- });
1388
- }
1389
- return next(req, ctx);
1390
- }
1391
- const { config } = matched;
1392
- try {
1393
- if (cache === "memory") {
1394
- const cached = cacheStore.get(pathname);
1395
- if (cached) {
1396
- const valid = await isCacheValid2(cached);
1397
- if (valid) {
1398
- if (req.headers.get("if-none-match") === cached.etag) {
1399
- return new Response(null, { status: 304 });
1400
- }
1401
- return new Response(cached.code, {
1402
- headers: {
1403
- "Content-Type": "text/javascript; charset=utf-8",
1404
- ETag: cached.etag,
1405
- "Cache-Control": "no-cache"
1406
- }
1407
- });
1408
- }
1409
- for (const [cn] of cached.chunks ?? []) chunkMap.delete(cn);
1410
- cacheStore.delete(pathname);
1411
- }
1412
- }
1413
- const { code, etag, chunks } = await compile(config);
1414
- const deps = await collectDeps(resolve3(config.entry));
1415
- if (cache === "memory") {
1416
- cacheStore.set(pathname, { code, etag, files: deps, chunks });
1417
- if (chunks) {
1418
- for (const [cn] of chunks) chunkMap.set(cn, pathname);
1419
- }
1420
- }
1421
- return new Response(code, {
1422
- headers: {
1423
- "Content-Type": "text/javascript; charset=utf-8",
1424
- ETag: etag,
1425
- "Cache-Control": "no-cache"
1426
- }
1427
- });
1428
- } catch (err) {
1429
- const message = err instanceof Error ? err.message : String(err);
1430
- const html = errorTemplate(message);
1431
- return new Response(html, {
1432
- status: 500,
1433
- headers: { "Content-Type": "text/html; charset=utf-8" }
1434
- });
1435
- }
1436
- };
1437
- }
1438
- function hashCode(s) {
1439
- let hash = 0;
1440
- for (let i = 0; i < s.length; i++) {
1441
- const ch = s.charCodeAt(i);
1442
- hash = (hash << 5) - hash + ch;
1443
- hash |= 0;
1444
- }
1445
- return Math.abs(hash).toString(36);
1446
- }
1447
-
1448
- // src/middleware/tailwind-dev.ts
1449
- import { resolve as resolve4 } from "node:path";
1450
- import { stat as stat2, readFile as readFile3, glob } from "node:fs/promises";
1451
- function escapeHtml2(s) {
1452
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1453
- }
1454
- function defaultErrorTemplate2(errors) {
1455
- return `<!DOCTYPE html>
1456
- <html>
1457
- <head>
1458
- <meta charset="utf-8">
1459
- <title>Tailwind Build Error</title>
1460
- <style>
1461
- * { margin: 0; padding: 0; box-sizing: border-box; }
1462
- body { font-family: system-ui; background: #1a1a2e; color: #e0e0e0; padding: 2rem; }
1463
- .overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; }
1464
- .card { background: #16213e; border: 1px solid #06b6d4; border-radius: 12px; padding: 2rem; max-width: 800px; width: 100%; box-shadow: 0 8px 32px rgba(0,0,0,0.4); }
1465
- h1 { color: #06b6d4; font-size: 1.5rem; margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; }
1466
- pre { background: #0f0f23; padding: 1.5rem; border-radius: 8px; overflow: auto; font-size: 0.85rem; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
1467
- </style>
1468
- </head>
1469
- <body>
1470
- <div class="overlay">
1471
- <div class="card">
1472
- <h1>\u{1F3A8} Tailwind CSS Build Error</h1>
1473
- <pre>${escapeHtml2(errors)}</pre>
1474
- </div>
1475
- </div>
1476
- </body>
1477
- </html>`;
1478
- }
1479
- var TW_CANDIDATE_RE = /[a-z][\w-]*(?::[a-z][\w-]*)*(?:-\[[^\]]*\])*(?:\/[0-9]+)?/gi;
1480
- var CLASS_CONTEXT_RE = /(?:class(?:Name)?\s*[=:]\s*["'`]([^"'`]+)["'`]|["'`]([^"'`\n]{2,})["'`])/g;
1481
- async function extractCandidates(patterns, root) {
1482
- const seen = /* @__PURE__ */ new Set();
1483
- for (const pattern of patterns) {
1484
- const resolved = resolve4(root, pattern);
1485
- try {
1486
- for await (const file of glob(resolved)) {
1487
- try {
1488
- const content = await readFile3(file, "utf-8");
1489
- for (const m of content.matchAll(CLASS_CONTEXT_RE)) {
1490
- const str = m[1] ?? m[2];
1491
- if (!str) continue;
1492
- for (const c of str.matchAll(TW_CANDIDATE_RE)) {
1493
- seen.add(c[0]);
1494
- }
1495
- }
1496
- } catch {
1497
- }
1498
- }
1499
- } catch {
1500
- }
1501
- }
1502
- return [...seen];
1503
- }
1504
- async function collectFileMtimes(files) {
1505
- const map = /* @__PURE__ */ new Map();
1506
- await Promise.all(
1507
- files.map(async (f) => {
1508
- try {
1509
- const s = await stat2(f);
1510
- map.set(f, s.mtimeMs);
1511
- } catch {
1512
- }
1513
- })
1514
- );
1515
- return map;
1516
- }
1517
- function isCacheValid(cached) {
1518
- return Promise.all(
1519
- [...cached.files].map(async ([file, mtime]) => {
1520
- try {
1521
- const s = await stat2(file);
1522
- return s.mtimeMs === mtime;
1523
- } catch {
1524
- return false;
1525
- }
1526
- })
1527
- ).then((results) => results.every(Boolean));
1528
- }
1529
- function tailwindDev(opts) {
1530
- const cacheMode = opts.cache ?? "memory";
1531
- const errorTemplate = opts.errorTemplate ?? defaultErrorTemplate2;
1532
- const entries = Object.entries(opts.entries).map(([p, e]) => {
1533
- const path = p.startsWith("/") ? p : "/" + p;
1534
- const config = typeof e === "string" ? { entry: e } : e;
1535
- return { path, config };
1536
- });
1537
- const cacheStore = /* @__PURE__ */ new Map();
1538
- let compileFn = null;
1539
- let loadError = null;
1540
- async function getCompile() {
1541
- if (compileFn) return compileFn;
1542
- try {
1543
- const mod = await import("@tailwindcss/node");
1544
- compileFn = mod.compile;
1545
- return compileFn;
1546
- } catch (err) {
1547
- loadError = `@tailwindcss/node is not installed. Run: npm install -D tailwindcss @tailwindcss/node
1548
-
1549
- ${String(err)}`;
1550
- throw new Error(loadError, { cause: err });
1551
- }
1552
- }
1553
- async function compileCss(entry) {
1554
- const compile = await getCompile();
1555
- const entryAbs = resolve4(entry.entry);
1556
- const cssSource = await readFile3(entryAbs, "utf-8");
1557
- const baseDir = resolve4(entry.entry, "..");
1558
- const deps = [entryAbs];
1559
- const result = await compile(cssSource, {
1560
- base: baseDir,
1561
- onDependency: (p) => {
1562
- if (!deps.includes(p)) deps.push(p);
1563
- }
1564
- });
1565
- const contentPatterns = entry.content ?? [];
1566
- for (const src of result.sources) {
1567
- if (!src.negated) {
1568
- contentPatterns.push(resolve4(src.base, src.pattern));
1569
- }
1570
- }
1571
- let candidates = [];
1572
- if (contentPatterns.length > 0) {
1573
- candidates = await extractCandidates(contentPatterns, baseDir);
1574
- }
1575
- const css = result.build(candidates);
1576
- for (const pattern of contentPatterns) {
1577
- try {
1578
- for await (const file of glob(resolve4(baseDir, pattern))) {
1579
- if (!deps.includes(file)) deps.push(file);
1580
- }
1581
- } catch {
1582
- }
1583
- }
1584
- const etag = `"tw-${hashCode2(css)}"`;
1585
- return { css, etag, files: deps };
1586
- }
1587
- return async (req, ctx, next) => {
1588
- const url = new URL(req.url);
1589
- const pathname = url.pathname;
1590
- const matched = entries.find((e) => e.path === pathname);
1591
- if (!matched) return next(req, ctx);
1592
- const { config } = matched;
1593
- try {
1594
- if (cacheMode === "memory") {
1595
- const cached = cacheStore.get(pathname);
1596
- if (cached) {
1597
- const valid = await isCacheValid(cached);
1598
- if (valid) {
1599
- if (req.headers.get("if-none-match") === cached.etag) {
1600
- return new Response(null, { status: 304 });
1601
- }
1602
- return new Response(cached.css, {
1603
- headers: {
1604
- "Content-Type": "text/css; charset=utf-8",
1605
- ETag: cached.etag,
1606
- "Cache-Control": "no-cache"
1607
- }
1608
- });
1609
- }
1610
- cacheStore.delete(pathname);
1611
- }
1612
- }
1613
- const { css, etag, files } = await compileCss(config);
1614
- if (cacheMode === "memory") {
1615
- const mtimes = await collectFileMtimes(files);
1616
- cacheStore.set(pathname, { css, etag, files: mtimes });
1617
- }
1618
- return new Response(css, {
1619
- headers: {
1620
- "Content-Type": "text/css; charset=utf-8",
1621
- ETag: etag,
1622
- "Cache-Control": "no-cache"
1623
- }
1624
- });
1625
- } catch (err) {
1626
- const message = err instanceof Error ? err.message : String(err);
1627
- const html = errorTemplate(message);
1628
- return new Response(html, {
1629
- status: 500,
1630
- headers: { "Content-Type": "text/html; charset=utf-8" }
1631
- });
1632
- }
1633
- };
1634
- }
1635
- function hashCode2(s) {
1636
- let hash = 0;
1637
- for (let i = 0; i < s.length; i++) {
1638
- const ch = s.charCodeAt(i);
1639
- hash = (hash << 5) - hash + ch;
1640
- hash |= 0;
1641
- }
1642
- return Math.abs(hash).toString(36);
1643
- }
1644
-
1645
1183
  // src/middleware/rate-limit.ts
1646
1184
  function defaultKey(_req, _ctx) {
1647
1185
  const forwarded = _req.headers.get("x-forwarded-for");
@@ -4797,7 +4335,6 @@ export {
4797
4335
  createHub,
4798
4336
  currentTrace,
4799
4337
  currentTraceId,
4800
- esbuildDev,
4801
4338
  graphql,
4802
4339
  helmet,
4803
4340
  kb,
@@ -4812,7 +4349,6 @@ export {
4812
4349
  sandbox,
4813
4350
  serve,
4814
4351
  serveStatic,
4815
- tailwindDev,
4816
4352
  trace,
4817
4353
  traceElapsed,
4818
4354
  upload,
package/package.json CHANGED
@@ -1,12 +1,20 @@
1
1
  {
2
2
  "name": "weifuwu",
3
3
  "type": "module",
4
- "version": "0.33.1",
5
- "description": "Web-standard HTTP microframework for Node.js — (req, ctx) => Response",
4
+ "version": "0.33.2",
5
+ "description": "AI SaaS framework — (req, ctx) => Response",
6
6
  "exports": {
7
7
  ".": {
8
8
  "types": "./dist/index.d.ts",
9
9
  "default": "./dist/index.js"
10
+ },
11
+ "./client": {
12
+ "types": "./dist/client/index.d.ts",
13
+ "default": "./dist/client/index.js"
14
+ },
15
+ "./client/jsx-runtime": {
16
+ "types": "./dist/client/index.d.ts",
17
+ "default": "./dist/client/index.js"
10
18
  }
11
19
  },
12
20
  "files": [
@@ -30,31 +38,10 @@
30
38
  "postgres": "^3.4.9",
31
39
  "ws": "^8"
32
40
  },
33
- "peerDependencies": {
34
- "@tailwindcss/node": "^4",
35
- "esbuild": "^0.28",
36
- "tailwindcss": "^4"
37
- },
38
- "peerDependenciesMeta": {
39
- "@tailwindcss/node": {
40
- "optional": true
41
- },
42
- "esbuild": {
43
- "optional": true
44
- },
45
- "tailwindcss": {
46
- "optional": true
47
- }
48
- },
49
41
  "devDependencies": {
50
- "@eslint/js": "^10.0.1",
51
- "@tailwindcss/node": "^4.3.2",
52
42
  "@types/node": "^25",
53
43
  "@types/ws": "^8",
54
- "esbuild": "^0.28.1",
55
- "globals": "^17.7.0",
56
- "tailwindcss": "^4.3.2",
57
- "typescript-eslint": "^8.62.1"
44
+ "esbuild": "^0.28.1"
58
45
  },
59
46
  "sideEffects": false
60
47
  }
@@ -1,55 +0,0 @@
1
- /**
2
- * esbuildDev — on-the-fly esbuild compilation middleware for development.
3
- *
4
- * Compiles TypeScript/JSX/TSX client bundles in memory on first request,
5
- * caches results based on source file mtime, and serves with ETag support.
6
- *
7
- * @example
8
- * ```ts
9
- * import { esbuildDev } from 'weifuwu'
10
- *
11
- * app.use(esbuildDev({
12
- * entries: {
13
- * '/assets/vendor.js': { entry: './client/vendor.ts', bundle: true },
14
- * '/assets/client.js': { entry: './client/client.ts', external: ['react', 'react-dom/client'] },
15
- * },
16
- * importmap: true, // auto-generate importmap script
17
- * }))
18
- * ```
19
- */
20
- import type { Middleware, Context } from '../types.ts';
21
- export interface EsbuildDevEntry {
22
- /** Source entry point relative to cwd or absolute. */
23
- entry?: string;
24
- /** Bundle all dependencies (default: true). */
25
- bundle?: boolean;
26
- /** Packages to leave external (not bundled). */
27
- external?: string[];
28
- /** Minify output (default: true). */
29
- minify?: boolean;
30
- /** Target platform (default: 'browser'). */
31
- platform?: 'browser' | 'neutral' | 'node';
32
- /** Output format (default: 'esm'). */
33
- format?: 'esm' | 'iife';
34
- /** Generate sourcemaps (default: false). */
35
- sourcemap?: boolean | 'inline' | 'external' | 'linked';
36
- /** Enable code splitting for dynamic import() (default: false). */
37
- splitting?: boolean;
38
- /** Compile-time constant substitution. */
39
- define?: Record<string, string>;
40
- /** Custom loaders per file extension. */
41
- loader?: Record<string, string>;
42
- }
43
- export interface EsbuildDevOptions {
44
- /** Map of URL path → entry config (string shorthand for { entry }). */
45
- entries: Record<string, EsbuildDevEntry | string>;
46
- /** Auto-generate a /assets/importmap script that maps react → vendor */
47
- importmap?: boolean;
48
- /** Importmap overrides (e.g. { 'react': '/assets/custom-vendor.js' }). */
49
- importmapOverrides?: Record<string, string>;
50
- /** Cache strategy: 'memory' keeps compiled results, 'none' recompiles every request. */
51
- cache?: 'memory' | 'none';
52
- /** Custom HTML template for build errors (receives escaped error text). */
53
- errorTemplate?: (errors: string) => string;
54
- }
55
- export declare function esbuildDev(opts: EsbuildDevOptions): Middleware<Context, Context>;