@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/CHANGELOG.md +1284 -0
- package/dist/i18n.d.ts +12 -3
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +33 -7
- package/dist/i18n.js.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -2
- package/dist/plugin.js.map +1 -1
- package/package.json +7 -6
- package/src/i18n.ts +37 -6
- package/src/index.ts +3 -3
- package/src/plugin.ts +7 -2
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).
|
|
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
|
-
|
|
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
|
/**
|
package/dist/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA
|
|
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).
|
|
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
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EACL,uBAAuB,EACvB,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,GACtC,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,cAAc,GAAG,uBAAuB,EAAE,CAAA;AAEhD,kFAAkF;AAClF,MAAM,WAAW,GAAG,GAAY,EAAE;IAChC,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAA;IAClF,OAAO,OAAO,KAAK,aAAa,IAAI,OAAO,KAAK,MAAM,CAAA;AACxD,CAAC,CAAA;AAED,wGAAwG;AACxG,SAAS,aAAa;IACpB,qGAAqG;IACrG,+CAA+C;IAC/C,gJAAgJ;IAChJ,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE;QACpC,OAAO,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE;KAChF,CAAU,CAAA;AACb,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
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
|
|
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.
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,oDAAoD;AACpD,OAAO,gBAAgB,MAAM,0BAA0B,CAAA;AACvD,OAAO,
|
|
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.
|
|
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.
|
|
125
|
-
"@nifrajs/i18n": "5.
|
|
126
|
-
"@nifrajs/image": "5.
|
|
127
|
-
"@nifrajs/web": "5.
|
|
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).
|
|
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
|
-
|
|
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
|
|
41
|
-
|
|
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 {
|
|
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
|
|
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.
|