weifuwu 0.17.1 → 0.17.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/README.md CHANGED
@@ -1173,11 +1173,13 @@ app.use(preferences({
1173
1173
  }))
1174
1174
 
1175
1175
  // In handlers: ctx.t('greeting') → "Hello"
1176
+ // ctx.t('tools.uppercase.title') → "Uppercase" (nested key)
1176
1177
  // ctx.locale → "en"
1177
1178
  // ctx.theme → "light"
1178
1179
  // ctx.prefs → { locale: 'en', theme: 'light' }
1179
1180
  // ctx.setPref('locale', 'zh') → 302 + cookie
1180
1181
  // ctx.setPref('flash', '{"type":"success","message":"Done"}') → flash message
1182
+ // ctx.env → { WEIFUWU_PUBLIC_API_URL: '...' } (public env vars)
1181
1183
 
1182
1184
  // In tsx components:
1183
1185
  const { t, locale, theme } = useCtx()
@@ -1187,6 +1189,9 @@ Locale detection priority: cookie → `Accept-Language` → default.
1187
1189
  Theme detection: cookie → default (`'system'`).
1188
1190
  Flash messages: set via `ctx.setPref('flash', ...)` → auto-read from cookie → cleared after rendering.
1189
1191
 
1192
+ `ctx.t()` supports dot-path nested keys: `t('tools.uppercase.title')` traverses the JSON structure.
1193
+ `ctx.env` exposes `WEIFUWU_PUBLIC_*` environment variables on both server and client (via `useCtx().env`).
1194
+
1190
1195
  ---
1191
1196
 
1192
1197
  ## Email
@@ -1234,7 +1239,7 @@ app.get('/stream', (req, ctx) => createSSEStream(events()))
1234
1239
 
1235
1240
  | Hook / Component | Description |
1236
1241
  |-----------------|-------------|
1237
- | `useCtx()` | Unified context — `{ prefs, locale, theme, t, params, query }` (requires `preferences` middleware) |
1242
+ | `useCtx()` | Unified context — `{ prefs, locale, theme, t, params, query, env }` (requires `preferences` middleware) |
1238
1243
  | `createStore(initial)` | Zustand-compatible shared state — `getState`, `setState`, `subscribe` |
1239
1244
  | `useData(url, opts?)` | SWR-style data fetching — cache, dedup, mutate, fallback |
1240
1245
  | `useQueryState(key, default)` | URL query param sync — `?page=1` via `useSyncExternalStore` |
package/dist/index.js CHANGED
@@ -581,19 +581,20 @@ import chokidar from "chokidar";
581
581
  import { createContext, useContext } from "react";
582
582
  var TsxContext = createContext({ params: {}, query: {} });
583
583
  function useCtx() {
584
- if (typeof window !== "undefined") {
585
- const wc = window.__WEIFUWU_CTX;
586
- if (wc) {
587
- const messages2 = window.__LOCALE_DATA__;
588
- if (messages2 && !wc.t) {
589
- wc.t = (key, params) => {
590
- let msg = messages2[key] ?? key;
591
- if (params) for (const [k, v] of Object.entries(params)) msg = msg.replace(`{${k}}`, v);
592
- return msg;
593
- };
594
- }
595
- return wc;
584
+ const wc = typeof window !== "undefined" ? window.__WEIFUWU_CTX : globalThis.__WEIFUWU_CTX;
585
+ if (wc) {
586
+ const messages2 = typeof window !== "undefined" ? window.__LOCALE_DATA__ : globalThis.__LOCALE_DATA__;
587
+ if (messages2 && typeof wc.t !== "function") {
588
+ wc.t = (key, params) => {
589
+ const msg = key.split(".").reduce((o, k) => o?.[k], messages2);
590
+ if (msg === void 0 || msg === null) return key;
591
+ if (!params) return String(msg);
592
+ let result = String(msg);
593
+ for (const [k, v] of Object.entries(params)) result = result.replace(`{${k}}`, v);
594
+ return result;
595
+ };
596
596
  }
597
+ return wc;
597
598
  }
598
599
  return useContext(TsxContext);
599
600
  }
@@ -889,7 +890,8 @@ var TsxInstance = class {
889
890
  prefs: ctx.prefs,
890
891
  locale: ctx.locale,
891
892
  theme: ctx.theme,
892
- t: ctx.t
893
+ t: ctx.t,
894
+ env: ctx.env
893
895
  }
894
896
  }, createElement(NfComponent, { params: ctx.params, query: ctx.query }));
895
897
  for (let i = rootLayouts.length - 1; i >= 0; i--) {
@@ -897,6 +899,7 @@ var TsxInstance = class {
897
899
  if (!LMod) continue;
898
900
  element = createElement(LMod.default, { children: element });
899
901
  }
902
+ setGlobalCtx(ctx);
900
903
  const stream = await renderToReadableStream(element);
901
904
  return streamResponse(stream, {
902
905
  ctx,
@@ -1063,7 +1066,8 @@ ${src}`;
1063
1066
  prefs: ctx.prefs,
1064
1067
  locale: ctx.locale,
1065
1068
  theme: ctx.theme,
1066
- t: ctx.t
1069
+ t: ctx.t,
1070
+ env: ctx.env
1067
1071
  }
1068
1072
  }, createElement(Component, allProps))
1069
1073
  );
@@ -1094,6 +1098,7 @@ ${src}`;
1094
1098
  }
1095
1099
  }
1096
1100
  const bundle = await this.getOrBuildClientBundle(entryPath, layoutPaths, this.pagesDir);
1101
+ setGlobalCtx(ctx);
1097
1102
  const stream = await renderToReadableStream(element);
1098
1103
  return streamResponse(stream, {
1099
1104
  ctx,
@@ -1267,6 +1272,18 @@ ${src}`;
1267
1272
  }
1268
1273
  }
1269
1274
  };
1275
+ function setGlobalCtx(ctx) {
1276
+ ;
1277
+ globalThis.__WEIFUWU_CTX = {
1278
+ params: ctx.params,
1279
+ query: ctx.query,
1280
+ user: ctx.user,
1281
+ parsed: ctx.parsed,
1282
+ prefs: ctx.prefs,
1283
+ locale: ctx.locale,
1284
+ theme: ctx.theme
1285
+ };
1286
+ }
1270
1287
  function streamResponse(reactStream, opts) {
1271
1288
  const decoder = new TextDecoder();
1272
1289
  const encoder2 = new TextEncoder();
@@ -1349,6 +1366,15 @@ function buildHeadPayload(opts) {
1349
1366
  if (ctx.prefs) ctxData.prefs = ctx.prefs;
1350
1367
  if (ctx.locale) ctxData.locale = ctx.locale;
1351
1368
  if (ctx.theme) ctxData.theme = ctx.theme;
1369
+ const publicEnv = {};
1370
+ for (const key of Object.keys(process.env)) {
1371
+ if (key.startsWith("WEIFUWU_PUBLIC_")) {
1372
+ publicEnv[key] = process.env[key];
1373
+ }
1374
+ }
1375
+ if (Object.keys(publicEnv).length > 0) {
1376
+ ctxData.env = publicEnv;
1377
+ }
1352
1378
  result += `<script>window.__WEIFUWU_CTX=${JSON.stringify(ctxData)}</script>
1353
1379
  `;
1354
1380
  return result;
@@ -6780,9 +6806,10 @@ var defaults = {
6780
6806
  theme: { default: "system", cookie: "theme" }
6781
6807
  };
6782
6808
  function translate(msgs, key, params) {
6783
- const msg = msgs[key] ?? key;
6784
- if (!params) return msg;
6785
- let result = msg;
6809
+ const msg = key.split(".").reduce((o, k) => o?.[k], msgs);
6810
+ if (msg === void 0 || msg === null) return key;
6811
+ if (!params) return String(msg);
6812
+ let result = String(msg);
6786
6813
  for (const [k, v] of Object.entries(params)) {
6787
6814
  result = result.replace(`{${k}}`, v);
6788
6815
  }
package/dist/react.js CHANGED
@@ -319,19 +319,20 @@ async function prefetchPage(href) {
319
319
  import { createContext, useContext } from "react";
320
320
  var TsxContext = createContext({ params: {}, query: {} });
321
321
  function useCtx() {
322
- if (typeof window !== "undefined") {
323
- const wc = window.__WEIFUWU_CTX;
324
- if (wc) {
325
- const messages = window.__LOCALE_DATA__;
326
- if (messages && !wc.t) {
327
- wc.t = (key, params) => {
328
- let msg = messages[key] ?? key;
329
- if (params) for (const [k, v] of Object.entries(params)) msg = msg.replace(`{${k}}`, v);
330
- return msg;
331
- };
332
- }
333
- return wc;
322
+ const wc = typeof window !== "undefined" ? window.__WEIFUWU_CTX : globalThis.__WEIFUWU_CTX;
323
+ if (wc) {
324
+ const messages = typeof window !== "undefined" ? window.__LOCALE_DATA__ : globalThis.__LOCALE_DATA__;
325
+ if (messages && typeof wc.t !== "function") {
326
+ wc.t = (key, params) => {
327
+ const msg = key.split(".").reduce((o, k) => o?.[k], messages);
328
+ if (msg === void 0 || msg === null) return key;
329
+ if (!params) return String(msg);
330
+ let result = String(msg);
331
+ for (const [k, v] of Object.entries(params)) result = result.replace(`{${k}}`, v);
332
+ return result;
333
+ };
334
334
  }
335
+ return wc;
335
336
  }
336
337
  return useContext(TsxContext);
337
338
  }
@@ -7,5 +7,6 @@ export declare const TsxContext: import("react").Context<{
7
7
  locale?: string;
8
8
  theme?: string;
9
9
  t?: (key: string, params?: Record<string, string>) => string;
10
+ env?: Record<string, string>;
10
11
  }>;
11
12
  export declare function useCtx(): any;
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface Context {
10
10
  prefs?: Record<string, string>;
11
11
  theme?: string;
12
12
  setPref?: (name: string, value: string) => Response;
13
+ env?: Record<string, string>;
13
14
  }
14
15
  export type Handler = (req: Request, ctx: Context) => Response | Promise<Response>;
15
16
  export type Middleware = (req: Request, ctx: Context, next: Handler) => Response | Promise<Response>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weifuwu",
3
- "version": "0.17.1",
3
+ "version": "0.17.3",
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",