@nifrajs/web-solid 5.1.0 → 5.3.0

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/i18n.d.ts CHANGED
@@ -3,12 +3,15 @@
3
3
  * `Formatter` (a `createMemo`, so switching locale rebuilds it) and provides it; `useT()` reads it.
4
4
  * Both `locale` + `messages` are serializable, so a loader returns them, the page renders with the
5
5
  * negotiated catalog on the server, and the client rebuilds the same formatter on hydrate (no
6
- * mismatch). Imports only `solid-js` + `@nifrajs/i18n`; no JSX (`createComponent`).
6
+ * mismatch). In an app that registers its locale routing (`i18n` in `backend/framework.ts`), `locale`
7
+ * defaults to the page's and `useLocale()` names it. No JSX (`createComponent`).
7
8
  */
8
9
  import { type Formatter, type FormatterOptions, type MessageKey, type RegisteredMessages, type Translation } from "@nifrajs/i18n";
9
- import { type JSX } from "solid-js";
10
+ import { type Accessor, type JSX } from "solid-js";
10
11
  export interface I18nProviderProps extends FormatterOptions {
11
- readonly locale: string;
12
+ /** The locale to format in. Default: the page's locale tag, in an app that registers its locale
13
+ * routing. */
14
+ readonly locale?: string;
12
15
  /** The catalog for `locale`, checked against the registered catalog type when one is declared. */
13
16
  readonly messages: Translation;
14
17
  readonly children?: JSX.Element;
@@ -20,6 +23,12 @@ export declare function I18nProvider(props: I18nProviderProps): JSX.Element;
20
23
  /** Read the current {@link Formatter} (`{ locale, t, get, n, d }`). Throws if no `<I18nProvider>` is above.
21
24
  * nifra switches locale by re-navigating, which re-runs the consuming component with the new catalog. */
22
25
  export declare function useT(): Formatter;
26
+ /**
27
+ * The page's locale key (`ur`, the URL segment), in an app that registers its locale routing (`i18n`
28
+ * in `backend/framework.ts`): from the request on the server, from the URL after each navigation.
29
+ * Without one, the nearest `<I18nProvider>`'s locale; with neither, reading it throws.
30
+ */
31
+ export declare function useLocale(): Accessor<string>;
23
32
  /** Tag handlers for {@link rich}, by tag name: each receives its tag's content as one node. */
24
33
  export type RichTags = Readonly<Record<string, (content: JSX.Element) => JSX.Element>>;
25
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,UAAU,CAAA;AAKjB,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CAChC;AAED;;sDAEsD;AACtD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAelE;AAED;yGACyG;AACzG,wBAAgB,IAAI,IAAI,SAAS,CAMhC;AAED,+FAA+F;AAC/F,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;AAStF;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,kBAAkB,EACxD,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,EAAE,QAAQ,EACf,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,GAAG,CAAC,OAAO,CAEb"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAA;AAGtB,OAAO,EACL,KAAK,QAAQ,EAIb,KAAK,GAAG,EAET,MAAM,UAAU,CAAA;AAMjB,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD;kBACc;IACd,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CAChC;AAED;;sDAEsD;AACtD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAsBlE;AAED;yGACyG;AACzG,wBAAgB,IAAI,IAAI,SAAS,CAMhC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,CAY5C;AAED,+FAA+F;AAC/F,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;AAStF;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,kBAAkB,EACxD,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,EAAE,QAAQ,EACf,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,GAAG,CAAC,OAAO,CAEb"}
package/dist/i18n.js CHANGED
@@ -3,23 +3,33 @@
3
3
  * `Formatter` (a `createMemo`, so switching locale rebuilds it) and provides it; `useT()` reads it.
4
4
  * Both `locale` + `messages` are serializable, so a loader returns them, the page renders with the
5
5
  * negotiated catalog on the server, and the client rebuilds the same formatter on hydrate (no
6
- * mismatch). Imports only `solid-js` + `@nifrajs/i18n`; no JSX (`createComponent`).
6
+ * mismatch). In an app that registers its locale routing (`i18n` in `backend/framework.ts`), `locale`
7
+ * defaults to the page's and `useLocale()` names it. No JSX (`createComponent`).
7
8
  */
8
9
  import { createFormatter, } from "@nifrajs/i18n";
9
10
  import { renderRich } from "@nifrajs/i18n/rich";
11
+ import { localeOfProps } from "@nifrajs/web/client";
10
12
  import { createComponent, createContext, createMemo, useContext, } from "solid-js";
11
13
  import { Dynamic } from "solid-js/web";
14
+ import { RenderPropsContext } from "./router.js";
12
15
  const I18nContext = createContext();
13
16
  /** Provide a {@link Formatter} (built from `locale` + `messages`, with the optional `fallback`,
14
17
  * `onMissing`, `timeZone` and `numberingSystem` of `createFormatter`) to the subtree. Memoized
15
18
  * on those props, so switching locale rebuilds it. */
16
19
  export function I18nProvider(props) {
17
- const formatter = createMemo(() => createFormatter(props.locale, props.messages, {
18
- fallback: props.fallback,
19
- onMissing: props.onMissing,
20
- timeZone: props.timeZone,
21
- numberingSystem: props.numberingSystem,
22
- }));
20
+ const renderProps = useContext(RenderPropsContext);
21
+ const formatter = createMemo(() => {
22
+ const locale = props.locale ?? localeOfProps(renderProps)?.lang;
23
+ if (locale === undefined) {
24
+ throw new Error("[nifra/web-solid] <I18nProvider> needs a `locale`, or an app that registers its locale routing (export `i18n` from backend/framework.ts)");
25
+ }
26
+ return createFormatter(locale, props.messages, {
27
+ fallback: props.fallback,
28
+ onMissing: props.onMissing,
29
+ timeZone: props.timeZone,
30
+ numberingSystem: props.numberingSystem,
31
+ });
32
+ });
23
33
  return createComponent(I18nContext.Provider, {
24
34
  value: formatter,
25
35
  get children() {
@@ -36,6 +46,22 @@ export function useT() {
36
46
  }
37
47
  return formatter();
38
48
  }
49
+ /**
50
+ * The page's locale key (`ur`, the URL segment), in an app that registers its locale routing (`i18n`
51
+ * in `backend/framework.ts`): from the request on the server, from the URL after each navigation.
52
+ * Without one, the nearest `<I18nProvider>`'s locale; with neither, reading it throws.
53
+ */
54
+ export function useLocale() {
55
+ const renderProps = useContext(RenderPropsContext);
56
+ const formatter = useContext(I18nContext);
57
+ return createMemo(() => {
58
+ const locale = localeOfProps(renderProps)?.key ?? formatter?.().locale;
59
+ if (locale === undefined) {
60
+ throw new Error("[nifra/web-solid] useLocale() needs an app that registers its locale routing (export `i18n` from backend/framework.ts), or an <I18nProvider> above it");
61
+ }
62
+ return locale;
63
+ });
64
+ }
39
65
  const join = (chunks) => chunks.length === 0 ? undefined : chunks.length === 1 ? chunks[0] : [...chunks];
40
66
  const SOLID_RICH = {
41
67
  join,
package/dist/i18n.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,eAAe,GAMhB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAsC,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAEL,eAAe,EACf,aAAa,EACb,UAAU,EAEV,UAAU,GACX,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,WAAW,GAAG,aAAa,EAAuB,CAAA;AASxD;;sDAEsD;AACtD,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAChC,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE;QAC5C,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,eAAe,EAAE,KAAK,CAAC,eAAe;KACvC,CAAC,CACH,CAAA;IACD,OAAO,eAAe,CAAC,WAAW,CAAC,QAAQ,EAAE;QAC3C,KAAK,EAAE,SAAS;QAChB,IAAI,QAAQ;YACV,OAAO,KAAK,CAAC,QAAQ,CAAA;QACvB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED;yGACyG;AACzG,MAAM,UAAU,IAAI;IAClB,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACzC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;IACnF,CAAC;IACD,OAAO,SAAS,EAAE,CAAA;AACpB,CAAC;AAKD,MAAM,IAAI,GAAG,CAAC,MAA+B,EAAe,EAAE,CAC5D,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAA;AACjF,MAAM,UAAU,GAA8B;IAC5C,IAAI;IACJ,SAAS,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;CAC/D,CAAA;AAED;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAClB,SAAuB,EACvB,GAAkB,EAClB,IAAe,EACf,IAAwC;IAExC,OAAO,UAAU,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;AAC3D,CAAC"}
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -19,17 +19,16 @@ function redactedError() {
19
19
  /**
20
20
  * Render `app` with every Error that Solid serializes for hydration replaced. An `<ErrorBoundary>` that
21
21
  * caught on the server, or a failed resource, otherwise ships the message and stack in an inline script.
22
- * Nested contexts copy this one, so they keep the wrapped `serialize`.
22
+ * Nested contexts copy this one, so they keep the wrapped `serialize`. NODE_ENV is read only when an
23
+ * Error is serialized: on Node every `process.env` read is a native call, and this runs every render.
23
24
  */
24
25
  function redactingErrors(app) {
25
- if (showsErrors())
26
- return app;
27
26
  return () => {
28
27
  // biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: Solid's server renderers set a context with serialize; the check below handles its absence.
29
28
  const context = sharedConfig.context;
30
29
  const serialize = context?.serialize;
31
30
  if (context !== undefined && serialize !== undefined) {
32
- context.serialize = (id, value) => serialize(id, value instanceof Error ? redactedError() : value);
31
+ context.serialize = (id, value) => serialize(id, value instanceof Error && !showsErrors() ? redactedError() : value);
33
32
  }
34
33
  return app();
35
34
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAGpC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CA0BjE"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAGpC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CA0BjE"}
package/dist/plugin.js CHANGED
@@ -6,7 +6,7 @@
6
6
  import { transformAsync } from "@babel/core";
7
7
  // @ts-expect-error - no type declarations published
8
8
  import presetTypeScript from "@babel/preset-typescript";
9
- import { devServerCompile, normalizeFilePath, rewriteSsrImports } from "@nifrajs/web/plugins/kit";
9
+ import { devServerCompile, normalizeFilePath, readSource, rewriteSsrImports, } from "@nifrajs/web/plugins/kit";
10
10
  // @ts-expect-error - no type declarations published
11
11
  import presetSolid from "babel-preset-solid";
12
12
  import solidRefreshBunHot, { SOLID_HOT_MODULE } from "./refresh-babel.js";
@@ -28,7 +28,7 @@ export function solidBunPlugin(generate) {
28
28
  // cache); strip it before reading the file off disk.
29
29
  build.onLoad({ filter: /\.tsx(\?|$)/ }, async (args) => {
30
30
  const path = normalizeFilePath(args.path);
31
- const source = await Bun.file(path).text();
31
+ const source = await readSource(build, path);
32
32
  const result = await transformAsync(source, {
33
33
  filename: path,
34
34
  // babel applies presets last→first: strip TS first, then Solid transforms JSX.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/web-solid",
3
- "version": "5.1.0",
3
+ "version": "5.3.0",
4
4
  "description": "Solid render adapter for @nifrajs/web - SSR + hydration, with the Solid Babel build plugin (@nifrajs/web-solid/plugin).",
5
5
  "keywords": [
6
6
  "bun",
@@ -108,7 +108,8 @@
108
108
  },
109
109
  "files": [
110
110
  "dist",
111
- "src"
111
+ "src",
112
+ "CHANGELOG.md"
112
113
  ],
113
114
  "sideEffects": false,
114
115
  "scripts": {
@@ -121,10 +122,10 @@
121
122
  "dependencies": {
122
123
  "@babel/core": "^7.26.0",
123
124
  "@babel/preset-typescript": "^7.26.0",
124
- "@nifrajs/core": "5.1.0",
125
- "@nifrajs/i18n": "5.1.0",
126
- "@nifrajs/image": "5.1.0",
127
- "@nifrajs/web": "5.1.0",
125
+ "@nifrajs/core": "5.3.0",
126
+ "@nifrajs/i18n": "5.3.0",
127
+ "@nifrajs/image": "5.3.0",
128
+ "@nifrajs/web": "5.3.0",
128
129
  "babel-preset-solid": "^1.9.3",
129
130
  "solid-refresh": "^0.7.8"
130
131
  },
package/src/i18n.ts CHANGED
@@ -3,7 +3,8 @@
3
3
  * `Formatter` (a `createMemo`, so switching locale rebuilds it) and provides it; `useT()` reads it.
4
4
  * Both `locale` + `messages` are serializable, so a loader returns them, the page renders with the
5
5
  * negotiated catalog on the server, and the client rebuilds the same formatter on hydrate (no
6
- * mismatch). Imports only `solid-js` + `@nifrajs/i18n`; no JSX (`createComponent`).
6
+ * mismatch). In an app that registers its locale routing (`i18n` in `backend/framework.ts`), `locale`
7
+ * defaults to the page's and `useLocale()` names it. No JSX (`createComponent`).
7
8
  */
8
9
  import {
9
10
  createFormatter,
@@ -14,6 +15,7 @@ import {
14
15
  type Translation,
15
16
  } from "@nifrajs/i18n"
16
17
  import { type RichChunks, type RichRenderer, renderRich } from "@nifrajs/i18n/rich"
18
+ import { localeOfProps } from "@nifrajs/web/client"
17
19
  import {
18
20
  type Accessor,
19
21
  createComponent,
@@ -23,11 +25,14 @@ import {
23
25
  useContext,
24
26
  } from "solid-js"
25
27
  import { Dynamic } from "solid-js/web"
28
+ import { RenderPropsContext } from "./router.ts"
26
29
 
27
30
  const I18nContext = createContext<Accessor<Formatter>>()
28
31
 
29
32
  export interface I18nProviderProps extends FormatterOptions {
30
- readonly locale: string
33
+ /** The locale to format in. Default: the page's locale tag, in an app that registers its locale
34
+ * routing. */
35
+ readonly locale?: string
31
36
  /** The catalog for `locale`, checked against the registered catalog type when one is declared. */
32
37
  readonly messages: Translation
33
38
  readonly children?: JSX.Element
@@ -37,14 +42,21 @@ export interface I18nProviderProps extends FormatterOptions {
37
42
  * `onMissing`, `timeZone` and `numberingSystem` of `createFormatter`) to the subtree. Memoized
38
43
  * on those props, so switching locale rebuilds it. */
39
44
  export function I18nProvider(props: I18nProviderProps): JSX.Element {
40
- const formatter = createMemo(() =>
41
- createFormatter(props.locale, props.messages, {
45
+ const renderProps = useContext(RenderPropsContext)
46
+ const formatter = createMemo(() => {
47
+ const locale = props.locale ?? localeOfProps(renderProps)?.lang
48
+ if (locale === undefined) {
49
+ throw new Error(
50
+ "[nifra/web-solid] <I18nProvider> needs a `locale`, or an app that registers its locale routing (export `i18n` from backend/framework.ts)",
51
+ )
52
+ }
53
+ return createFormatter(locale, props.messages, {
42
54
  fallback: props.fallback,
43
55
  onMissing: props.onMissing,
44
56
  timeZone: props.timeZone,
45
57
  numberingSystem: props.numberingSystem,
46
- }),
47
- )
58
+ })
59
+ })
48
60
  return createComponent(I18nContext.Provider, {
49
61
  value: formatter,
50
62
  get children() {
@@ -63,6 +75,25 @@ export function useT(): Formatter {
63
75
  return formatter()
64
76
  }
65
77
 
78
+ /**
79
+ * The page's locale key (`ur`, the URL segment), in an app that registers its locale routing (`i18n`
80
+ * in `backend/framework.ts`): from the request on the server, from the URL after each navigation.
81
+ * Without one, the nearest `<I18nProvider>`'s locale; with neither, reading it throws.
82
+ */
83
+ export function useLocale(): Accessor<string> {
84
+ const renderProps = useContext(RenderPropsContext)
85
+ const formatter = useContext(I18nContext)
86
+ return createMemo(() => {
87
+ const locale = localeOfProps(renderProps)?.key ?? formatter?.().locale
88
+ if (locale === undefined) {
89
+ throw new Error(
90
+ "[nifra/web-solid] useLocale() needs an app that registers its locale routing (export `i18n` from backend/framework.ts), or an <I18nProvider> above it",
91
+ )
92
+ }
93
+ return locale
94
+ })
95
+ }
96
+
66
97
  /** Tag handlers for {@link rich}, by tag name: each receives its tag's content as one node. */
67
98
  export type RichTags = Readonly<Record<string, (content: JSX.Element) => JSX.Element>>
68
99
 
package/src/index.ts CHANGED
@@ -34,10 +34,10 @@ function redactedError(): Error {
34
34
  /**
35
35
  * Render `app` with every Error that Solid serializes for hydration replaced. An `<ErrorBoundary>` that
36
36
  * caught on the server, or a failed resource, otherwise ships the message and stack in an inline script.
37
- * Nested contexts copy this one, so they keep the wrapped `serialize`.
37
+ * Nested contexts copy this one, so they keep the wrapped `serialize`. NODE_ENV is read only when an
38
+ * Error is serialized: on Node every `process.env` read is a native call, and this runs every render.
38
39
  */
39
40
  function redactingErrors<T>(app: () => T): () => T {
40
- if (showsErrors()) return app
41
41
  return () => {
42
42
  // biome-ignore lint/plugin/requireSafetyCommentForTypeAssertion: Solid's server renderers set a context with serialize; the check below handles its absence.
43
43
  const context = sharedConfig.context as
@@ -46,7 +46,7 @@ function redactingErrors<T>(app: () => T): () => T {
46
46
  const serialize = context?.serialize
47
47
  if (context !== undefined && serialize !== undefined) {
48
48
  context.serialize = (id, value) =>
49
- serialize(id, value instanceof Error ? redactedError() : value)
49
+ serialize(id, value instanceof Error && !showsErrors() ? redactedError() : value)
50
50
  }
51
51
  return app()
52
52
  }
package/src/plugin.ts CHANGED
@@ -6,7 +6,12 @@
6
6
  import { transformAsync } from "@babel/core"
7
7
  // @ts-expect-error - no type declarations published
8
8
  import presetTypeScript from "@babel/preset-typescript"
9
- import { devServerCompile, normalizeFilePath, rewriteSsrImports } from "@nifrajs/web/plugins/kit"
9
+ import {
10
+ devServerCompile,
11
+ normalizeFilePath,
12
+ readSource,
13
+ rewriteSsrImports,
14
+ } from "@nifrajs/web/plugins/kit"
10
15
  // @ts-expect-error - no type declarations published
11
16
  import presetSolid from "babel-preset-solid"
12
17
  import type { BunPlugin } from "bun"
@@ -31,7 +36,7 @@ export function solidBunPlugin(generate: "dom" | "ssr"): BunPlugin {
31
36
  // cache); strip it before reading the file off disk.
32
37
  build.onLoad({ filter: /\.tsx(\?|$)/ }, async (args) => {
33
38
  const path = normalizeFilePath(args.path)
34
- const source = await Bun.file(path).text()
39
+ const source = await readSource(build, path)
35
40
  const result = await transformAsync(source, {
36
41
  filename: path,
37
42
  // babel applies presets last→first: strip TS first, then Solid transforms JSX.