weifuwu 0.17.3 → 0.17.4

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.d.ts CHANGED
@@ -4,7 +4,7 @@ export { serve, createTestServer } from './serve.ts';
4
4
  export type { ServeOptions, Server } from './serve.ts';
5
5
  export { Router } from './router.ts';
6
6
  export type { WebSocketHandler } from './router.ts';
7
- export { tsx, TsxContext, useCtx } from './tsx.ts';
7
+ export { tsx, TsxContext, useCtx, setCtx } from './tsx.ts';
8
8
  export type { TsxOptions } from './tsx.ts';
9
9
  export { auth, cors, logger } from './middleware.ts';
10
10
  export type { AuthOptions, CORSOptions, LoggerOptions } from './middleware.ts';
package/dist/index.js CHANGED
@@ -578,26 +578,43 @@ import { createRequire } from "node:module";
578
578
  import chokidar from "chokidar";
579
579
 
580
580
  // tsx-context.ts
581
- import { createContext, useContext } from "react";
582
- var TsxContext = createContext({ params: {}, query: {} });
581
+ import { useSyncExternalStore, createContext } from "react";
582
+ var _ctx = { params: {}, query: {} };
583
+ var _listeners = /* @__PURE__ */ new Set();
584
+ function setCtx(value) {
585
+ _ctx = { ..._ctx, ...value };
586
+ _listeners.forEach((fn) => fn());
587
+ }
588
+ function _buildT() {
589
+ const messages2 = typeof window !== "undefined" ? window.__LOCALE_DATA__ : globalThis.__LOCALE_DATA__;
590
+ if (!messages2) return void 0;
591
+ return (key, params, fallback) => {
592
+ const msg = key.split(".").reduce((o, k) => o?.[k], messages2);
593
+ if (msg === void 0 || msg === null) return fallback ?? key;
594
+ if (!params) return String(msg);
595
+ let result = String(msg);
596
+ for (const [k, v] of Object.entries(params)) result = result.replace(`{${k}}`, v);
597
+ return result;
598
+ };
599
+ }
583
600
  function useCtx() {
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;
601
+ useSyncExternalStore(
602
+ (cb) => {
603
+ _listeners.add(cb);
604
+ return () => {
605
+ _listeners.delete(cb);
595
606
  };
596
- }
597
- return wc;
598
- }
599
- return useContext(TsxContext);
607
+ },
608
+ () => _ctx,
609
+ () => _ctx
610
+ );
611
+ const data = typeof window !== "undefined" ? window.__WEIFUWU_CTX : null;
612
+ const t = data?.t ?? _ctx.t ?? _buildT();
613
+ const result = { ..._ctx, ...data };
614
+ if (t) result.t = t;
615
+ return result;
600
616
  }
617
+ var TsxContext = createContext({ params: {}, query: {} });
601
618
 
602
619
  // tsx-instance.ts
603
620
  var liveReloadClients = /* @__PURE__ */ new Set();
@@ -881,25 +898,23 @@ var TsxInstance = class {
881
898
  const nfMod = this.pageModules.get(nfPath);
882
899
  if (!nfMod) return new Response("Not Found", { status: 404 });
883
900
  const NfComponent = nfMod.default;
884
- let element = createElement(TsxContext.Provider, {
885
- value: {
886
- params: ctx.params,
887
- query: ctx.query,
888
- user: ctx.user,
889
- parsed: ctx.parsed,
890
- prefs: ctx.prefs,
891
- locale: ctx.locale,
892
- theme: ctx.theme,
893
- t: ctx.t,
894
- env: ctx.env
895
- }
896
- }, createElement(NfComponent, { params: ctx.params, query: ctx.query }));
901
+ setCtx({
902
+ params: ctx.params,
903
+ query: ctx.query,
904
+ user: ctx.user,
905
+ parsed: ctx.parsed,
906
+ prefs: ctx.prefs,
907
+ locale: ctx.locale,
908
+ theme: ctx.theme,
909
+ t: ctx.t,
910
+ env: ctx.env
911
+ });
912
+ let element = createElement(NfComponent, { params: ctx.params, query: ctx.query });
897
913
  for (let i = rootLayouts.length - 1; i >= 0; i--) {
898
914
  const LMod = this.layoutModules.get(rootLayouts[i]);
899
915
  if (!LMod) continue;
900
916
  element = createElement(LMod.default, { children: element });
901
917
  }
902
- setGlobalCtx(ctx);
903
918
  const stream = await renderToReadableStream(element);
904
919
  return streamResponse(stream, {
905
920
  ctx,
@@ -1054,22 +1069,21 @@ ${src}`;
1054
1069
  const loadFn = loadMod?.default;
1055
1070
  const loadProps = loadFn ? await loadFn({ params: ctx.params, query: ctx.query }) : {};
1056
1071
  const allProps = { ...loadProps, params: ctx.params, query: ctx.query };
1072
+ setCtx({
1073
+ params: ctx.params,
1074
+ query: ctx.query,
1075
+ user: ctx.user,
1076
+ parsed: ctx.parsed,
1077
+ prefs: ctx.prefs,
1078
+ locale: ctx.locale,
1079
+ theme: ctx.theme,
1080
+ t: ctx.t,
1081
+ env: ctx.env
1082
+ });
1057
1083
  let element = createElement(
1058
1084
  "div",
1059
1085
  { id: "__weifuwu_root" },
1060
- createElement(TsxContext.Provider, {
1061
- value: {
1062
- params: ctx.params,
1063
- query: ctx.query,
1064
- user: ctx.user,
1065
- parsed: ctx.parsed,
1066
- prefs: ctx.prefs,
1067
- locale: ctx.locale,
1068
- theme: ctx.theme,
1069
- t: ctx.t,
1070
- env: ctx.env
1071
- }
1072
- }, createElement(Component, allProps))
1086
+ createElement(Component, allProps)
1073
1087
  );
1074
1088
  if (layoutPaths.length === 0) {
1075
1089
  element = createElement(
@@ -1093,12 +1107,11 @@ ${src}`;
1093
1107
  const isRoot = i === 0;
1094
1108
  element = createElement(
1095
1109
  Layout,
1096
- isRoot ? { children: element, req, ctx } : { children: element }
1110
+ isRoot ? { children: element, req } : { children: element }
1097
1111
  );
1098
1112
  }
1099
1113
  }
1100
1114
  const bundle = await this.getOrBuildClientBundle(entryPath, layoutPaths, this.pagesDir);
1101
- setGlobalCtx(ctx);
1102
1115
  const stream = await renderToReadableStream(element);
1103
1116
  return streamResponse(stream, {
1104
1117
  ctx,
@@ -1272,18 +1285,6 @@ ${src}`;
1272
1285
  }
1273
1286
  }
1274
1287
  };
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
- }
1287
1288
  function streamResponse(reactStream, opts) {
1288
1289
  const decoder = new TextDecoder();
1289
1290
  const encoder2 = new TextEncoder();
@@ -3208,7 +3209,7 @@ h2{color:#dc2626}.desc{color:#555}</style>
3208
3209
  <body><h2>${error}</h2>${description ? `<p class="desc">${description}</p>` : ""}</body>
3209
3210
  </html>`, { status: 400, headers: { "Content-Type": "text/html; charset=utf-8" } });
3210
3211
  }
3211
- async function authorizeHandler(req, _ctx) {
3212
+ async function authorizeHandler(req, _ctx2) {
3212
3213
  const url = new URL(req.url);
3213
3214
  const clientId = url.searchParams.get("client_id") || "";
3214
3215
  const redirectUri = url.searchParams.get("redirect_uri") || "";
@@ -4593,23 +4594,23 @@ function buildGraphQLHandler(sql2) {
4593
4594
  });
4594
4595
  return Response.json(result, { status: result.errors ? 400 : 200 });
4595
4596
  });
4596
- r.get("/", async (req, _ctx) => {
4597
+ r.get("/", async (req, _ctx2) => {
4597
4598
  const url = new URL(req.url);
4598
4599
  if (url.searchParams.has("query")) {
4599
- return handleGET(req, _ctx);
4600
+ return handleGET(req, _ctx2);
4600
4601
  }
4601
4602
  return new Response("GraphQL endpoint. Send POST /graphql with { query, variables }", {
4602
4603
  status: 200,
4603
4604
  headers: { "Content-Type": "text/plain" }
4604
4605
  });
4605
4606
  });
4606
- async function handleGET(req, _ctx) {
4607
+ async function handleGET(req, _ctx2) {
4607
4608
  const tables = await sql2`
4608
4609
  SELECT * FROM "_user_tables"
4609
- WHERE tenant_id = ${_ctx.tenant.id}
4610
+ WHERE tenant_id = ${_ctx2.tenant.id}
4610
4611
  ORDER BY created_at ASC
4611
4612
  `;
4612
- const buildCtx = { sql: sql2, tenantId: _ctx.tenant.id, tables };
4613
+ const buildCtx = { sql: sql2, tenantId: _ctx2.tenant.id, tables };
4613
4614
  const schema = new GraphQLSchema({
4614
4615
  query: new GraphQLObjectType({
4615
4616
  name: "Query",
@@ -4629,7 +4630,7 @@ function buildGraphQLHandler(sql2) {
4629
4630
  source: query,
4630
4631
  variableValues: variables,
4631
4632
  operationName: url.searchParams.get("operationName") || void 0,
4632
- contextValue: _ctx
4633
+ contextValue: _ctx2
4633
4634
  });
4634
4635
  return Response.json(result, { status: result.errors ? 400 : 200 });
4635
4636
  }
@@ -6633,7 +6634,7 @@ function createWSHandler2(deps) {
6633
6634
  clients.delete(ws);
6634
6635
  }
6635
6636
  },
6636
- error(ws, _ctx, _err) {
6637
+ error(ws, _ctx2, _err) {
6637
6638
  const client = clients.get(ws);
6638
6639
  if (client) {
6639
6640
  client.abortController?.abort();
@@ -6805,9 +6806,9 @@ var defaults = {
6805
6806
  locale: { default: "en", cookie: "locale", fromAcceptLanguage: true },
6806
6807
  theme: { default: "system", cookie: "theme" }
6807
6808
  };
6808
- function translate(msgs, key, params) {
6809
+ function translate(msgs, key, params, fallback) {
6809
6810
  const msg = key.split(".").reduce((o, k) => o?.[k], msgs);
6810
- if (msg === void 0 || msg === null) return key;
6811
+ if (msg === void 0 || msg === null) return fallback ?? key;
6811
6812
  if (!params) return String(msg);
6812
6813
  let result = String(msg);
6813
6814
  for (const [k, v] of Object.entries(params)) {
@@ -6852,7 +6853,7 @@ function preferences(options) {
6852
6853
  ctx.theme = theme;
6853
6854
  if (dir) {
6854
6855
  const msgs = await load(locale);
6855
- ctx.t = (key, params) => translate(msgs, key, params);
6856
+ ctx.t = (key, params, fallback) => translate(msgs, key, params, fallback);
6856
6857
  globalThis.__LOCALE_DATA__ = msgs;
6857
6858
  }
6858
6859
  ctx.setPref = (name, value) => {
@@ -7659,7 +7660,7 @@ function createWsHandler(deps) {
7659
7660
  return wsToWorkerId.get(ws) || "";
7660
7661
  }
7661
7662
  return {
7662
- open(_ws, _ctx) {
7663
+ open(_ws, _ctx2) {
7663
7664
  },
7664
7665
  async message(ws, ctx, data) {
7665
7666
  let msg;
@@ -8315,6 +8316,7 @@ export {
8315
8316
  serve,
8316
8317
  serveStatic,
8317
8318
  setCookie,
8319
+ setCtx,
8318
8320
  smoothStream,
8319
8321
  streamObject,
8320
8322
  streamText,
package/dist/react.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { UseWebsocketOptions, UseWebsocketReturn } from './use-websocket.ts
3
3
  export { useAction } from './use-action.ts';
4
4
  export type { UseActionOptions, UseActionReturn } from './use-action.ts';
5
5
  export { Link, useNavigate, navigate, useNavigating } from './client-router.ts';
6
- export { TsxContext, useCtx } from './tsx-context.ts';
6
+ export { TsxContext, useCtx, setCtx } from './tsx-context.ts';
7
7
  export { Head } from './head.tsx';
8
8
  export { createStore, useData, useQueryState } from './client-state.ts';
9
9
  export type { StoreApi } from './client-state.ts';
package/dist/react.js CHANGED
@@ -316,26 +316,43 @@ async function prefetchPage(href) {
316
316
  }
317
317
 
318
318
  // tsx-context.ts
319
- import { createContext, useContext } from "react";
320
- var TsxContext = createContext({ params: {}, query: {} });
319
+ import { useSyncExternalStore, createContext } from "react";
320
+ var _ctx = { params: {}, query: {} };
321
+ var _listeners2 = /* @__PURE__ */ new Set();
322
+ function setCtx(value) {
323
+ _ctx = { ..._ctx, ...value };
324
+ _listeners2.forEach((fn) => fn());
325
+ }
326
+ function _buildT() {
327
+ const messages = typeof window !== "undefined" ? window.__LOCALE_DATA__ : globalThis.__LOCALE_DATA__;
328
+ if (!messages) return void 0;
329
+ return (key, params, fallback) => {
330
+ const msg = key.split(".").reduce((o, k) => o?.[k], messages);
331
+ if (msg === void 0 || msg === null) return fallback ?? key;
332
+ if (!params) return String(msg);
333
+ let result = String(msg);
334
+ for (const [k, v] of Object.entries(params)) result = result.replace(`{${k}}`, v);
335
+ return result;
336
+ };
337
+ }
321
338
  function useCtx() {
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;
339
+ useSyncExternalStore(
340
+ (cb) => {
341
+ _listeners2.add(cb);
342
+ return () => {
343
+ _listeners2.delete(cb);
333
344
  };
334
- }
335
- return wc;
336
- }
337
- return useContext(TsxContext);
345
+ },
346
+ () => _ctx,
347
+ () => _ctx
348
+ );
349
+ const data = typeof window !== "undefined" ? window.__WEIFUWU_CTX : null;
350
+ const t = data?.t ?? _ctx.t ?? _buildT();
351
+ const result = { ..._ctx, ...data };
352
+ if (t) result.t = t;
353
+ return result;
338
354
  }
355
+ var TsxContext = createContext({ params: {}, query: {} });
339
356
 
340
357
  // head.tsx
341
358
  import { createElement as createElement2 } from "react";
@@ -344,7 +361,7 @@ function Head({ children }) {
344
361
  }
345
362
 
346
363
  // client-state.ts
347
- import { useSyncExternalStore, useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
364
+ import { useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
348
365
  function createStore(initial) {
349
366
  let state = { ...initial };
350
367
  const listeners = /* @__PURE__ */ new Set();
@@ -360,7 +377,7 @@ function createStore(initial) {
360
377
  listeners.delete(listener);
361
378
  };
362
379
  };
363
- const useStore = ((selector) => useSyncExternalStore(
380
+ const useStore = ((selector) => useSyncExternalStore2(
364
381
  subscribe,
365
382
  () => selector ? selector(state) : state
366
383
  ));
@@ -451,7 +468,7 @@ function useQueryState(key, defaultValue = "") {
451
468
  const params = new URLSearchParams(window.location.search);
452
469
  return params.get(key) ?? defaultValue;
453
470
  }
454
- const value = useSyncExternalStore(
471
+ const value = useSyncExternalStore2(
455
472
  (cb) => {
456
473
  if (typeof window === "undefined") return () => {
457
474
  };
@@ -481,6 +498,7 @@ export {
481
498
  TsxContext,
482
499
  createStore,
483
500
  navigate,
501
+ setCtx,
484
502
  useAction,
485
503
  useCtx,
486
504
  useData,
@@ -1,4 +1,4 @@
1
- export declare const TsxContext: import("react").Context<{
1
+ export interface CtxValue {
2
2
  params: Record<string, string>;
3
3
  query: Record<string, string>;
4
4
  user?: unknown;
@@ -6,7 +6,9 @@ export declare const TsxContext: import("react").Context<{
6
6
  prefs?: Record<string, string>;
7
7
  locale?: string;
8
8
  theme?: string;
9
- t?: (key: string, params?: Record<string, string>) => string;
9
+ t?: (key: string, params?: Record<string, string>, fallback?: string) => string;
10
10
  env?: Record<string, string>;
11
- }>;
12
- export declare function useCtx(): any;
11
+ }
12
+ export declare function setCtx(value: Partial<CtxValue>): void;
13
+ export declare function useCtx(): CtxValue;
14
+ export declare const TsxContext: import("react").Context<CtxValue>;
@@ -1,6 +1,6 @@
1
1
  import { Router } from './router.ts';
2
- import { TsxContext, useCtx } from './tsx-context.ts';
3
- export { TsxContext, useCtx };
2
+ import { TsxContext, useCtx, setCtx } from './tsx-context.ts';
3
+ export { TsxContext, useCtx, setCtx };
4
4
  export interface TsxOptions {
5
5
  dir: string;
6
6
  }
package/dist/tsx.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { TsxContext, useCtx } from './tsx-instance.ts';
1
+ import { TsxContext, useCtx, setCtx } from './tsx-instance.ts';
2
2
  import type { TsxOptions } from './tsx-instance.ts';
3
3
  import type { Router } from './router.ts';
4
- export { TsxContext, useCtx };
4
+ export { TsxContext, useCtx, setCtx };
5
5
  export type { TsxOptions };
6
6
  export declare function tsx(options: TsxOptions): Promise<Router>;
package/dist/types.d.ts CHANGED
@@ -5,7 +5,7 @@ export interface Context {
5
5
  parsed?: Record<string, unknown>;
6
6
  mountPath?: string;
7
7
  locale?: string;
8
- t?: (key: string, params?: Record<string, string>) => string;
8
+ t?: (key: string, params?: Record<string, string>, fallback?: string) => string;
9
9
  requestId?: string;
10
10
  prefs?: Record<string, string>;
11
11
  theme?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weifuwu",
3
- "version": "0.17.3",
3
+ "version": "0.17.4",
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",