@nifrajs/web-react 3.5.0 → 4.0.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/auth.d.ts +32 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +85 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -24
- package/dist/client.js.map +1 -1
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +1 -0
- package/dist/compose.js.map +1 -1
- package/dist/i18n.d.ts +19 -6
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +27 -6
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/react-dom-server.d.ts +3 -1
- package/dist/react-dom-server.d.ts.map +1 -1
- package/dist/react-dom-server.js.map +1 -1
- package/dist/render-error.d.ts +4 -0
- package/dist/render-error.d.ts.map +1 -0
- package/dist/render-error.js +15 -0
- package/dist/render-error.js.map +1 -0
- package/dist/route-props.d.ts +4 -0
- package/dist/route-props.d.ts.map +1 -0
- package/dist/route-props.js +32 -0
- package/dist/route-props.js.map +1 -0
- package/dist/router.d.ts +23 -3
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +29 -2
- package/dist/router.js.map +1 -1
- package/package.json +14 -5
- package/src/auth.ts +128 -0
- package/src/client.ts +9 -24
- package/src/compose.ts +1 -0
- package/src/i18n.ts +49 -9
- package/src/index.ts +15 -3
- package/src/react-dom-server.ts +4 -1
- package/src/render-error.ts +18 -0
- package/src/route-props.ts +37 -0
- package/src/router.ts +42 -4
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web-react/auth` - React bindings for `@nifrajs/authjs`. `<AuthSessionProvider>`
|
|
3
|
+
* seeds the subtree with a session (from a loader on the server, refreshed in the browser) and
|
|
4
|
+
* `useAuthSession()` reads it; `signIn`/`signOut` delegate to the shared client. Imports only
|
|
5
|
+
* `react` + `@nifrajs/authjs/client`; no JSX (the package builds with plain `tsc`).
|
|
6
|
+
*/
|
|
7
|
+
import { type AuthClient, type Session, type SignInOptions, type SignOutOptions } from "@nifrajs/authjs/client";
|
|
8
|
+
import { type ReactNode } from "react";
|
|
9
|
+
export type { Session };
|
|
10
|
+
export type AuthStatus = "loading" | "authenticated" | "unauthenticated";
|
|
11
|
+
export interface AuthSession {
|
|
12
|
+
readonly status: AuthStatus;
|
|
13
|
+
readonly session: Session | null;
|
|
14
|
+
/** Re-read the session from the server (after an out-of-band change, for example). */
|
|
15
|
+
readonly refresh: () => Promise<void>;
|
|
16
|
+
readonly signIn: (providerId: string, options?: SignInOptions) => Promise<void>;
|
|
17
|
+
readonly signOut: (options?: SignOutOptions) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface AuthSessionProviderProps {
|
|
20
|
+
/** Shared client (base path, custom fetch). Default `createAuthClient()`. */
|
|
21
|
+
readonly client?: AuthClient;
|
|
22
|
+
/** SSR seed from a loader (`await getSession(request, config)`). `undefined` (default) fetches
|
|
23
|
+
* on mount instead - the subtree renders `loading` until it resolves. */
|
|
24
|
+
readonly initialSession?: Session | null;
|
|
25
|
+
readonly children?: ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/** Provide the Auth.js session to the subtree. Memoized on client + seed; refresh re-reads. A new
|
|
28
|
+
* `initialSession` (a loader re-run on navigation) replaces the session, as a remount would. */
|
|
29
|
+
export declare function AuthSessionProvider(props: AuthSessionProviderProps): ReactNode;
|
|
30
|
+
/** Read the Auth.js session (`{ status, session }`). Throws if no `<AuthSessionProvider>` is above. */
|
|
31
|
+
export declare function useAuthSession(): AuthSession;
|
|
32
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAGL,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AAEd,YAAY,EAAE,OAAO,EAAE,CAAA;AACvB,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,eAAe,GAAG,iBAAiB,CAAA;AAExE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAChC,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,QAAQ,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/E,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9D;AAID,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAA;IAC5B;6EACyE;IACzE,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAC9B;AAMD;gGACgG;AAChG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,SAAS,CAgE9E;AAED,uGAAuG;AACvG,wBAAgB,cAAc,IAAI,WAAW,CAQ5C"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web-react/auth` - React bindings for `@nifrajs/authjs`. `<AuthSessionProvider>`
|
|
3
|
+
* seeds the subtree with a session (from a loader on the server, refreshed in the browser) and
|
|
4
|
+
* `useAuthSession()` reads it; `signIn`/`signOut` delegate to the shared client. Imports only
|
|
5
|
+
* `react` + `@nifrajs/authjs/client`; no JSX (the package builds with plain `tsc`).
|
|
6
|
+
*/
|
|
7
|
+
import { createAuthClient, } from "@nifrajs/authjs/client";
|
|
8
|
+
import { createContext, createElement, useContext, useEffect, useMemo, useState, } from "react";
|
|
9
|
+
const AuthSessionContext = createContext(null);
|
|
10
|
+
function seededStatus(seed) {
|
|
11
|
+
return seed === undefined ? "loading" : seed === null ? "unauthenticated" : "authenticated";
|
|
12
|
+
}
|
|
13
|
+
/** Provide the Auth.js session to the subtree. Memoized on client + seed; refresh re-reads. A new
|
|
14
|
+
* `initialSession` (a loader re-run on navigation) replaces the session, as a remount would. */
|
|
15
|
+
export function AuthSessionProvider(props) {
|
|
16
|
+
const client = useMemo(() => props.client ?? createAuthClient(), [props.client]);
|
|
17
|
+
const [seed, setSeed] = useState(props.initialSession);
|
|
18
|
+
const [status, setStatus] = useState(seededStatus(props.initialSession));
|
|
19
|
+
const [session, setSession] = useState(props.initialSession ?? null);
|
|
20
|
+
if (seed !== props.initialSession) {
|
|
21
|
+
// A render-phase update: React re-runs this component before any child sees the old session.
|
|
22
|
+
setSeed(props.initialSession);
|
|
23
|
+
setStatus(seededStatus(props.initialSession));
|
|
24
|
+
setSession(props.initialSession ?? null);
|
|
25
|
+
}
|
|
26
|
+
const refresh = useMemo(() => {
|
|
27
|
+
return async () => {
|
|
28
|
+
try {
|
|
29
|
+
const next = await client.getSession();
|
|
30
|
+
setSession(next);
|
|
31
|
+
setStatus(next === null ? "unauthenticated" : "authenticated");
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// A failed session read must fail closed as anonymous; leaving "loading" can strand the
|
|
35
|
+
// subtree in an auth-pending state and make protected UI appear available by omission.
|
|
36
|
+
setSession(null);
|
|
37
|
+
setStatus("unauthenticated");
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}, [client]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
let live = true;
|
|
43
|
+
if (props.initialSession === undefined) {
|
|
44
|
+
void client.getSession().then((next) => {
|
|
45
|
+
if (!live)
|
|
46
|
+
return;
|
|
47
|
+
setSession(next);
|
|
48
|
+
setStatus(next === null ? "unauthenticated" : "authenticated");
|
|
49
|
+
}, () => {
|
|
50
|
+
// Treat an unavailable session endpoint as anonymous rather than keeping auth state
|
|
51
|
+
// pending indefinitely or exposing stale authenticated UI.
|
|
52
|
+
if (!live)
|
|
53
|
+
return;
|
|
54
|
+
setSession(null);
|
|
55
|
+
setStatus("unauthenticated");
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return () => {
|
|
59
|
+
live = false;
|
|
60
|
+
};
|
|
61
|
+
}, [client, props.initialSession]);
|
|
62
|
+
const value = useMemo(() => ({
|
|
63
|
+
status,
|
|
64
|
+
session,
|
|
65
|
+
refresh,
|
|
66
|
+
signIn: (providerId, options) => client.signIn(providerId, options),
|
|
67
|
+
signOut: async (options) => {
|
|
68
|
+
await client.signOut(options);
|
|
69
|
+
// The server ended the session: the subtree must not go on showing it, whether a redirect is
|
|
70
|
+
// pending or `redirect: false` keeps the page.
|
|
71
|
+
setSession(null);
|
|
72
|
+
setStatus("unauthenticated");
|
|
73
|
+
},
|
|
74
|
+
}), [status, session, refresh, client]);
|
|
75
|
+
return createElement(AuthSessionContext.Provider, { value }, props.children);
|
|
76
|
+
}
|
|
77
|
+
/** Read the Auth.js session (`{ status, session }`). Throws if no `<AuthSessionProvider>` is above. */
|
|
78
|
+
export function useAuthSession() {
|
|
79
|
+
const session = useContext(AuthSessionContext);
|
|
80
|
+
if (session === null) {
|
|
81
|
+
throw new Error("[nifra/web-react] useAuthSession() must be used within an <AuthSessionProvider>");
|
|
82
|
+
}
|
|
83
|
+
return session;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAgBnE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,mGAAmG;AACnG,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACvE;AAaD,wBAAgB,OAAO,CACrB,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,yBAAyB,GAClC,IAAI,CAIN;AAED,oGAAoG;AACpG,eAAO,MAAM,sBAAsB;;2BAEZ,MAAM;EAC3B,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAkB7D"}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// `/client`, not the root: the root's graph carries the server, and Vite's dev server evaluates it
|
|
2
|
-
// instead of tree-shaking it - which broke hydration before the browser ran a line of app code.
|
|
3
|
-
import { searchOfChain } from "@nifrajs/web/client";
|
|
4
1
|
/**
|
|
5
2
|
* @nifrajs/web-react/client - React client runtime. `hydrate` hydrates a single SSR'd route;
|
|
6
3
|
* `mountRouter` hydrates a stateful Router that subscribes to the agnostic store (via
|
|
@@ -12,6 +9,7 @@ import { createElement, useSyncExternalStore } from "react";
|
|
|
12
9
|
import { hydrateRoot } from "react-dom/client";
|
|
13
10
|
import { compose } from "./compose.js";
|
|
14
11
|
import { setMountedRouter } from "./fetcher.js";
|
|
12
|
+
import { routeProps } from "./route-props.js";
|
|
15
13
|
// The `_error` boundary chain element - defined in its own (react-dom-free) module, re-exported here so
|
|
16
14
|
// nifra's client codegen resolves it from `@nifrajs/web-react/client` alongside `mountRouter`.
|
|
17
15
|
export { errorBoundary } from "./error.js";
|
|
@@ -43,29 +41,16 @@ export const hydrationAssuranceHook = Object.freeze({
|
|
|
43
41
|
* SSR markup on hydration.
|
|
44
42
|
*/
|
|
45
43
|
export function mountRouter(options) {
|
|
46
|
-
const { router, routes, searchSchemas, container } = options;
|
|
44
|
+
const { router, routes, searchSchemas, matchChains, container } = options;
|
|
47
45
|
setMountedRouter(router); // expose it to useFetcher/useFetchers (same page, client-only)
|
|
46
|
+
// What the server rendered. React hydrates against THIS, whatever the store says by the time it gets
|
|
47
|
+
// to the component - hydration is scheduled, and a store that moved on first (a client loader that
|
|
48
|
+
// answered, a held `ssr = false` page released) would otherwise hydrate a tree the markup never had.
|
|
49
|
+
// React then re-renders with the live snapshot on its own.
|
|
50
|
+
const hydrated = router.snapshot();
|
|
48
51
|
const Router = () => {
|
|
49
|
-
const state = useSyncExternalStore(router.subscribe, router.snapshot,
|
|
50
|
-
|
|
51
|
-
// page, merged page-wins), the SAME `searchOfChain` the server ran, so `useSearch` reads an identical
|
|
52
|
-
// value and hydrates with no drift.
|
|
53
|
-
const q = state.path.indexOf("?");
|
|
54
|
-
const rawSearch = q === -1 ? "" : state.path.slice(q);
|
|
55
|
-
return compose(routes[state.routeId] ?? [], {
|
|
56
|
-
data: state.data,
|
|
57
|
-
actionData: state.actionData,
|
|
58
|
-
pending: state.pending,
|
|
59
|
-
...(state.pendingPath !== undefined ? { pendingPath: state.pendingPath } : {}),
|
|
60
|
-
// `params`/`path` feed the routing hooks (useParams/useLocation) via compose's RouterContext -
|
|
61
|
-
// sourced from router state here, matching the SSR render's request-derived values on hydration.
|
|
62
|
-
params: state.params,
|
|
63
|
-
path: state.path,
|
|
64
|
-
search: searchOfChain(searchSchemas?.[state.routeId] ?? [], rawSearch),
|
|
65
|
-
// The in-flight submission (for optimistic UI) - spread only when present.
|
|
66
|
-
...(state.submission ? { submission: state.submission } : {}),
|
|
67
|
-
...(state.boundaries !== undefined ? { boundaries: state.boundaries } : {}),
|
|
68
|
-
});
|
|
52
|
+
const state = useSyncExternalStore(router.subscribe, router.snapshot, () => hydrated);
|
|
53
|
+
return compose(routes[state.routeId] ?? [], routeProps(state, searchSchemas, matchChains));
|
|
69
54
|
};
|
|
70
55
|
const onRecoverableError = assuranceError();
|
|
71
56
|
hydrateRoot(container, createElement(Router), ...(onRecoverableError === undefined ? [] : [{ onRecoverableError }]));
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,aAAa,EAA0B,oBAAoB,EAAE,MAAM,OAAO,CAAA;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,wGAAwG;AACxG,+FAA+F;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO1C,SAAS,cAAc;IACrB,MAAM,KAAK,GAAI,UAAsD,CACnE,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CACxC,CAAA;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACjE,MAAM,QAAQ,GAAI,KAA0C,CAAC,kBAAkB,CAAA;IAC/E,OAAO,OAAO,QAAQ,KAAK,UAAU;QACnC,CAAC,CAAE,QAA4D;QAC/D,CAAC,CAAC,SAAS,CAAA;AACf,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,KAAyB,EACzB,KAAkB,EAClB,SAAkB,EAClB,OAAmC;IAEnC,MAAM,kBAAkB,GAAG,OAAO,EAAE,kBAAkB,IAAI,cAAc,EAAE,CAAA;IAC1E,IAAI,kBAAkB,KAAK,SAAS;QAAE,WAAW,CAAC,SAAoB,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;;QACzF,WAAW,CAAC,SAAoB,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAA;AACvF,CAAC;AAED,oGAAoG;AACpG,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC;IAClD,SAAS,EAAE,OAAgB;IAC3B,eAAe,EAAE,GAAW,EAAE,CAAC,KAAK;CACrC,CAAC,CAAA;AAEF;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IACzE,gBAAgB,CAAC,MAAM,CAAC,CAAA,CAAC,+DAA+D;IACxF,qGAAqG;IACrG,mGAAmG;IACnG,qGAAqG;IACrG,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAClC,MAAM,MAAM,GAAsB,GAAG,EAAE;QACrC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAA;QACrF,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAA;IAC5F,CAAC,CAAA;IACD,MAAM,kBAAkB,GAAG,cAAc,EAAE,CAAA;IAC3C,WAAW,CACT,SAAoB,EACpB,aAAa,CAAC,MAAM,CAAC,EACrB,GAAG,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CACtE,CAAA;AACH,CAAC"}
|
package/dist/compose.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAS7E;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAS7E;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,SAAS,CA+BhF"}
|
package/dist/compose.js
CHANGED
package/dist/compose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAA0C,MAAM,OAAO,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,oGAAoG;AACpG,MAAM,YAAY,GAAqC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAExE,oGAAoG;AACpG,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,IAAI,IAAI,GAAc,aAAa,CAAC,KAAK,CAAC,IAAI,CAAmC,EAAE,KAAK,CAAC,CAAA;IACzF,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,mFAAmF;QACnF,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,IAAI,GAAG,aAAa,CAClB,KAAK,CAAC,CAAC,CAAyC,EAChD;YACE,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;YACnC,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,EACD,IAAI,CACL,CAAA;IACH,CAAC;IACD,OAAO,aAAa,CAClB,aAAa,CAAC,QAAQ,EACtB;QACE,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY;YACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK;YAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAA0C,MAAM,OAAO,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,oGAAoG;AACpG,MAAM,YAAY,GAAqC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAExE,oGAAoG;AACpG,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAEzE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,IAAI,IAAI,GAAc,aAAa,CAAC,KAAK,CAAC,IAAI,CAAmC,EAAE,KAAK,CAAC,CAAA;IACzF,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,mFAAmF;QACnF,6FAA6F;QAC7F,mGAAmG;QACnG,kEAAkE;QAClE,IAAI,GAAG,aAAa,CAClB,KAAK,CAAC,CAAC,CAAyC,EAChD;YACE,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;YACnC,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,EACD,IAAI,CACL,CAAA;IACH,CAAC;IACD,OAAO,aAAa,CAClB,aAAa,CAAC,QAAQ,EACtB;QACE,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY;YACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK;YAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,WAAW,EAAE,KAAK;SACnB;KACF,EACD,IAAI,CACL,CAAA;AACH,CAAC"}
|
package/dist/i18n.d.ts
CHANGED
|
@@ -5,16 +5,29 @@
|
|
|
5
5
|
* and the client rebuilds the same formatter from the same props (no mismatch). Imports only `react` +
|
|
6
6
|
* `@nifrajs/i18n`; no JSX (the package builds with plain `tsc`).
|
|
7
7
|
*/
|
|
8
|
-
import { type Formatter, type
|
|
8
|
+
import { type Formatter, type FormatterOptions, type MessageKey, type RegisteredMessages, type Translation } from "@nifrajs/i18n";
|
|
9
9
|
import { type ReactNode } from "react";
|
|
10
|
-
export interface I18nProviderProps {
|
|
10
|
+
export interface I18nProviderProps extends FormatterOptions {
|
|
11
11
|
readonly locale: string;
|
|
12
|
-
|
|
12
|
+
/** The catalog for `locale`, checked against the registered catalog type when one is declared. */
|
|
13
|
+
readonly messages: Translation;
|
|
13
14
|
readonly children?: ReactNode;
|
|
14
15
|
}
|
|
15
|
-
/** Provide a {@link Formatter} (built from `locale` + `messages
|
|
16
|
-
* `
|
|
16
|
+
/** Provide a {@link Formatter} (built from `locale` + `messages`, with the optional `fallback`,
|
|
17
|
+
* `onMissing`, `timeZone` and `numberingSystem` of `createFormatter`) to the subtree. Memoized
|
|
18
|
+
* on those props, so switching locale rebuilds it and re-renders consumers; formatters are cached by
|
|
19
|
+
* catalog identity, so an inline `fallback={[en]}` still yields the same instance. */
|
|
17
20
|
export declare function I18nProvider(props: I18nProviderProps): ReactNode;
|
|
18
|
-
/** Read the current {@link Formatter} (`{ locale, t, n, d }`). Throws if no `<I18nProvider>` is above. */
|
|
21
|
+
/** Read the current {@link Formatter} (`{ locale, t, get, n, d }`). Throws if no `<I18nProvider>` is above. */
|
|
19
22
|
export declare function useT(): Formatter;
|
|
23
|
+
/** Tag handlers for {@link rich}, by tag name: each receives its tag's content as one node. */
|
|
24
|
+
export type RichTags = Readonly<Record<string, (content: ReactNode) => ReactNode>>;
|
|
25
|
+
/**
|
|
26
|
+
* The message at `key` with its tags rendered by `tags`, as React nodes - no HTML, no
|
|
27
|
+
* `dangerouslySetInnerHTML`. `"Read the <link>terms</link>"` with
|
|
28
|
+
* `{ link: (content) => <a href="/terms">{content}</a> }` renders the link around "terms"; a tag with
|
|
29
|
+
* no handler renders its content as text, `<br/>` is a `<br>`, and interpolated values are always
|
|
30
|
+
* text. See `@nifrajs/i18n/rich`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function rich<M extends object = RegisteredMessages>(formatter: Formatter<M>, key: MessageKey<M>, tags?: RichTags, vars?: Readonly<Record<string, unknown>>): ReactNode;
|
|
20
33
|
//# sourceMappingURL=i18n.d.ts.map
|
package/dist/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,
|
|
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,EAA0C,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAA;AAInG,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,SAAS,CAAA;CAC9B;AAED;;;sFAGsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAOhE;AAED,+GAA+G;AAC/G,wBAAgB,IAAI,IAAI,SAAS,CAMhC;AAED,+FAA+F;AAC/F,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAA;AAWlF;;;;;;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,SAAS,CAEX"}
|
package/dist/i18n.js
CHANGED
|
@@ -5,16 +5,20 @@
|
|
|
5
5
|
* and the client rebuilds the same formatter from the same props (no mismatch). Imports only `react` +
|
|
6
6
|
* `@nifrajs/i18n`; no JSX (the package builds with plain `tsc`).
|
|
7
7
|
*/
|
|
8
|
-
import { createFormatter } from "@nifrajs/i18n";
|
|
9
|
-
import {
|
|
8
|
+
import { createFormatter, } from "@nifrajs/i18n";
|
|
9
|
+
import { renderRich } from "@nifrajs/i18n/rich";
|
|
10
|
+
import { createContext, createElement, Fragment, useContext, useMemo } from "react";
|
|
10
11
|
const I18nContext = createContext(null);
|
|
11
|
-
/** Provide a {@link Formatter} (built from `locale` + `messages
|
|
12
|
-
* `
|
|
12
|
+
/** Provide a {@link Formatter} (built from `locale` + `messages`, with the optional `fallback`,
|
|
13
|
+
* `onMissing`, `timeZone` and `numberingSystem` of `createFormatter`) to the subtree. Memoized
|
|
14
|
+
* on those props, so switching locale rebuilds it and re-renders consumers; formatters are cached by
|
|
15
|
+
* catalog identity, so an inline `fallback={[en]}` still yields the same instance. */
|
|
13
16
|
export function I18nProvider(props) {
|
|
14
|
-
const
|
|
17
|
+
const { locale, messages, fallback, onMissing, timeZone, numberingSystem } = props;
|
|
18
|
+
const formatter = useMemo(() => createFormatter(locale, messages, { fallback, onMissing, timeZone, numberingSystem }), [locale, messages, fallback, onMissing, timeZone, numberingSystem]);
|
|
15
19
|
return createElement(I18nContext.Provider, { value: formatter }, props.children);
|
|
16
20
|
}
|
|
17
|
-
/** Read the current {@link Formatter} (`{ locale, t, n, d }`). Throws if no `<I18nProvider>` is above. */
|
|
21
|
+
/** Read the current {@link Formatter} (`{ locale, t, get, n, d }`). Throws if no `<I18nProvider>` is above. */
|
|
18
22
|
export function useT() {
|
|
19
23
|
const formatter = useContext(I18nContext);
|
|
20
24
|
if (formatter === null) {
|
|
@@ -22,4 +26,21 @@ export function useT() {
|
|
|
22
26
|
}
|
|
23
27
|
return formatter;
|
|
24
28
|
}
|
|
29
|
+
// Children passed as arguments, not an array, so React asks for no keys.
|
|
30
|
+
const join = (chunks) => chunks.length === 0
|
|
31
|
+
? null
|
|
32
|
+
: chunks.length === 1
|
|
33
|
+
? chunks[0]
|
|
34
|
+
: createElement(Fragment, null, ...chunks);
|
|
35
|
+
const REACT_RICH = { join, lineBreak: () => createElement("br") };
|
|
36
|
+
/**
|
|
37
|
+
* The message at `key` with its tags rendered by `tags`, as React nodes - no HTML, no
|
|
38
|
+
* `dangerouslySetInnerHTML`. `"Read the <link>terms</link>"` with
|
|
39
|
+
* `{ link: (content) => <a href="/terms">{content}</a> }` renders the link around "terms"; a tag with
|
|
40
|
+
* no handler renders its content as text, `<br/>` is a `<br>`, and interpolated values are always
|
|
41
|
+
* text. See `@nifrajs/i18n/rich`.
|
|
42
|
+
*/
|
|
43
|
+
export function rich(formatter, key, tags, vars) {
|
|
44
|
+
return renderRich(REACT_RICH, formatter, key, tags, vars);
|
|
45
|
+
}
|
|
25
46
|
//# sourceMappingURL=i18n.js.map
|
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,
|
|
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,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAkB,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAEnG,MAAM,WAAW,GAAG,aAAa,CAAmB,IAAI,CAAC,CAAA;AASzD;;;sFAGsF;AACtF,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,KAAK,CAAA;IAClF,MAAM,SAAS,GAAG,OAAO,CACvB,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,EAC3F,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CACnE,CAAA;IACD,OAAO,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AAClF,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,IAAI;IAClB,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IACzC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;IACnF,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAKD,yEAAyE;AACzE,MAAM,IAAI,GAAG,CAAC,MAA6B,EAAa,EAAE,CACxD,MAAM,CAAC,MAAM,KAAK,CAAC;IACjB,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QACnB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACX,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,CAAA;AAChD,MAAM,UAAU,GAA4B,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAA;AAE1F;;;;;;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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAUjD,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,aAoC1B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { compose } from "./compose.js";
|
|
7
7
|
import { reactDomServer } from "./react-dom-server.js";
|
|
8
|
+
import { explainRenderError } from "./render-error.js";
|
|
8
9
|
/** The React server render adapter - pass to @nifrajs/web's `renderPage`. */
|
|
9
10
|
export const reactAdapter = {
|
|
10
11
|
// Synchronous one-pass render for non-deferred pages (renderPage's buffered fast path). React's
|
|
@@ -17,14 +18,27 @@ export const reactAdapter = {
|
|
|
17
18
|
// renderPage awaits it.
|
|
18
19
|
async renderToString(chain, props) {
|
|
19
20
|
const { renderToString } = await reactDomServer();
|
|
20
|
-
|
|
21
|
+
try {
|
|
22
|
+
return renderToString(compose(chain, props));
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw explainRenderError(error);
|
|
26
|
+
}
|
|
21
27
|
},
|
|
22
|
-
async renderToStream(chain, props) {
|
|
28
|
+
async renderToStream(chain, props, options) {
|
|
23
29
|
// Resolves a Web `ReadableStream<Uint8Array>` once the shell is renderable; Suspense
|
|
24
30
|
// boundaries stream as they resolve. No `bootstrapModules` - nifra injects the client entry in
|
|
25
31
|
// the document tail. React's default `onError` logs to console.error (errors aren't swallowed).
|
|
32
|
+
// The nonce reaches the inline runtime React streams to reveal each resolved boundary.
|
|
26
33
|
const { renderToReadableStream } = await reactDomServer();
|
|
27
|
-
|
|
34
|
+
try {
|
|
35
|
+
return await (options?.nonce === undefined
|
|
36
|
+
? renderToReadableStream(compose(chain, props))
|
|
37
|
+
: renderToReadableStream(compose(chain, props), { nonce: options.nonce }));
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw explainRenderError(error);
|
|
41
|
+
}
|
|
28
42
|
},
|
|
29
43
|
// React reconciles against the existing DOM on hydrate, so no per-document bootstrap
|
|
30
44
|
// script is needed (contrast Solid's generateHydrationScript) - the seam allows both.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,gGAAgG;IAChG,kGAAkG;IAClG,oGAAoG;IACpG,mGAAmG;IACnG,EAAE;IACF,uGAAuG;IACvG,qGAAqG;IACrG,wBAAwB;IACxB,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK;QAC/B,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,cAAc,EAAE,CAAA;QACjD,OAAO,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,gGAAgG;IAChG,kGAAkG;IAClG,oGAAoG;IACpG,mGAAmG;IACnG,EAAE;IACF,uGAAuG;IACvG,qGAAqG;IACrG,wBAAwB;IACxB,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK;QAC/B,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,cAAc,EAAE,CAAA;QACjD,IAAI,CAAC;YACH,OAAO,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;QAC9C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IACD,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO;QACxC,qFAAqF;QACrF,+FAA+F;QAC/F,gGAAgG;QAChG,uFAAuF;QACvF,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,cAAc,EAAE,CAAA;QACzD,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS;gBACxC,CAAC,CAAC,sBAAsB,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC/C,CAAC,CAAC,sBAAsB,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QAC9E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IACD,qFAAqF;IACrF,sFAAsF;IACtF,aAAa;QACX,OAAO,EAAE,CAAA;IACX,CAAC;CACF,CAAA"}
|
|
@@ -27,7 +27,9 @@ import type { ReactNode } from "react";
|
|
|
27
27
|
* resolves to an absolute path string) stays strict - no `any` crosses the boundary. */
|
|
28
28
|
export interface ReactDomServer {
|
|
29
29
|
renderToString(node: ReactNode): string;
|
|
30
|
-
renderToReadableStream(node: ReactNode
|
|
30
|
+
renderToReadableStream(node: ReactNode, options?: {
|
|
31
|
+
readonly nonce?: string;
|
|
32
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* Get `react-dom/server` bound to the consumer app's React. Cached after the first call. Under the Bun
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-dom-server.d.ts","sourceRoot":"","sources":["../src/react-dom-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC;wFACwF;AACxF,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;IACvC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"react-dom-server.d.ts","sourceRoot":"","sources":["../src/react-dom-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC;wFACwF;AACxF,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;IACvC,sBAAsB,CACpB,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACpC,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAA;CACvC;AA6CD;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,CAIxD;AAED,6EAA6E;AAC7E,KAAK,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAE9D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,WAAW,EACpB,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAwB,GACnD,IAAI,CA0BN;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,WAAW,GAAG,SAA2B,GACjD,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAwB,GAAG,OAAO,CAGzE;AAED;;;;;;;;;;;;;;qEAcqE;AACrE,wBAAgB,aAAa,IAAI,WAAW,GAAG,SAAS,CAMvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-dom-server.js","sourceRoot":"","sources":["../src/react-dom-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"react-dom-server.js","sourceRoot":"","sources":["../src/react-dom-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Name the cause of a null-dispatcher crash. The app-root check in ./react-dom-server catches a
|
|
2
|
+
* renderer on the wrong copy; this covers a component that brings its own (a linked package's). */
|
|
3
|
+
export declare function explainRenderError(error: unknown): unknown;
|
|
4
|
+
//# sourceMappingURL=render-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-error.d.ts","sourceRoot":"","sources":["../src/render-error.ts"],"names":[],"mappings":"AAKA;mGACmG;AACnG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAU1D"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** A hook read a null dispatcher: the component's React is not the one the renderer set up. JSC and V8
|
|
2
|
+
* word the null dereference differently; the property read is always a hook. */
|
|
3
|
+
const NO_DISPATCHER = /ReactSharedInternals\.H\.|resolveDispatcher\(\)\.|Cannot read properties of null \(reading 'use[A-Za-z]*'\)/;
|
|
4
|
+
/** Name the cause of a null-dispatcher crash. The app-root check in ./react-dom-server catches a
|
|
5
|
+
* renderer on the wrong copy; this covers a component that brings its own (a linked package's). */
|
|
6
|
+
export function explainRenderError(error) {
|
|
7
|
+
if (!(error instanceof TypeError) || !NO_DISPATCHER.test(error.message))
|
|
8
|
+
return error;
|
|
9
|
+
return new Error("[nifra/web-react] a component called a React hook with no dispatcher, so two copies of React " +
|
|
10
|
+
"reached SSR: the one react-dom renders with, and another the component imports (often a linked " +
|
|
11
|
+
"package's own node_modules). Dedupe react to one physical copy: `nifra check` names the " +
|
|
12
|
+
"importer of each, and the package.json `nifra.singleCopy` declaration redirects them. " +
|
|
13
|
+
`See https://nifra.dev/docs/troubleshooting. (${error.message})`, { cause: error });
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=render-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-error.js","sourceRoot":"","sources":["../src/render-error.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,MAAM,aAAa,GACjB,6GAA6G,CAAA;AAE/G;mGACmG;AACnG,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,CAAC,CAAC,KAAK,YAAY,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACrF,OAAO,IAAI,KAAK,CACd,+FAA+F;QAC7F,iGAAiG;QACjG,0FAA0F;QAC1F,wFAAwF;QACxF,gDAAgD,KAAK,CAAC,OAAO,GAAG,EAClE,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MountRouterOptions, RenderProps, RouterState } from "@nifrajs/web";
|
|
2
|
+
/** The client half of the server's `RenderProps`, so the first render matches the SSR markup. */
|
|
3
|
+
export declare function routeProps(state: RouterState, searchSchemas: MountRouterOptions["searchSchemas"], matchChains?: MountRouterOptions["matchChains"]): RenderProps;
|
|
4
|
+
//# sourceMappingURL=route-props.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-props.d.ts","sourceRoot":"","sources":["../src/route-props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAKhF,iGAAiG;AACjG,wBAAgB,UAAU,CACxB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAClD,WAAW,CAAC,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAC9C,WAAW,CA0Bb"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// `/client`, not the root: the root's graph carries the server, and Vite's dev server evaluates it
|
|
2
|
+
// instead of tree-shaking it - which broke hydration before the browser ran a line of app code.
|
|
3
|
+
import { searchOfChain } from "@nifrajs/web/client";
|
|
4
|
+
/** The client half of the server's `RenderProps`, so the first render matches the SSR markup. */
|
|
5
|
+
export function routeProps(state, searchSchemas, matchChains) {
|
|
6
|
+
const matchChain = matchChains?.[state.routeId];
|
|
7
|
+
// Derive this route's typed `search` from the URL query + the route's schema CHAIN (layout schemas +
|
|
8
|
+
// page, merged page-wins), the SAME `searchOfChain` the server ran, so `useSearch` reads an identical
|
|
9
|
+
// value and hydrates with no drift.
|
|
10
|
+
const q = state.path.indexOf("?");
|
|
11
|
+
const rawSearch = q === -1 ? "" : state.path.slice(q);
|
|
12
|
+
return {
|
|
13
|
+
data: state.data,
|
|
14
|
+
// Each layout's own loader data. Without it a layout renders `data: null` on the client while the
|
|
15
|
+
// server rendered it with its data - a hydration mismatch on the first paint.
|
|
16
|
+
...(state.layoutData !== undefined ? { layoutData: state.layoutData } : {}),
|
|
17
|
+
actionData: state.actionData,
|
|
18
|
+
pending: state.pending,
|
|
19
|
+
...(state.pendingPath !== undefined ? { pendingPath: state.pendingPath } : {}),
|
|
20
|
+
// `params`/`path` feed the routing hooks (useParams/useLocation) via compose's RouterContext -
|
|
21
|
+
// sourced from router state here, matching the SSR render's request-derived values on hydration.
|
|
22
|
+
params: state.params,
|
|
23
|
+
path: state.path,
|
|
24
|
+
search: searchOfChain(searchSchemas?.[state.routeId] ?? [], rawSearch),
|
|
25
|
+
// The in-flight submission (for optimistic UI) - spread only when present.
|
|
26
|
+
...(state.submission ? { submission: state.submission } : {}),
|
|
27
|
+
...(state.boundaries !== undefined ? { boundaries: state.boundaries } : {}),
|
|
28
|
+
// The chain `useMatches` reports - the server passed the same one to the SSR render.
|
|
29
|
+
...(matchChain !== undefined ? { matchChain } : {}),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=route-props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-props.js","sourceRoot":"","sources":["../src/route-props.ts"],"names":[],"mappings":"AACA,mGAAmG;AACnG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,iGAAiG;AACjG,MAAM,UAAU,UAAU,CACxB,KAAkB,EAClB,aAAkD,EAClD,WAA+C;IAE/C,MAAM,UAAU,GAAG,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC/C,qGAAqG;IACrG,sGAAsG;IACtG,oCAAoC;IACpC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACrD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,kGAAkG;QAClG,8EAA8E;QAC9E,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,+FAA+F;QAC/F,iGAAiG;QACjG,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;QACtE,2EAA2E;QAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,qFAAqF;QACrF,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAA;AACH,CAAC"}
|
package/dist/router.d.ts
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* (the package builds with plain `tsc`), so everything is `createElement`.
|
|
12
12
|
*/
|
|
13
13
|
import type { InferOutput, StandardSchemaV1 } from "@nifrajs/core/server";
|
|
14
|
-
import type { Blocker, BlockerFunction, BlockerState, NavigateFunction, NavigateOptions } from "@nifrajs/web";
|
|
14
|
+
import type { Blocker, BlockerFunction, BlockerState, NavigateFunction, NavigateOptions, PrefetchMode, RenderProps, UIMatch } from "@nifrajs/web";
|
|
15
15
|
import { type AnchorHTMLAttributes, type CSSProperties, type ReactNode } from "react";
|
|
16
|
-
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction };
|
|
16
|
+
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction, PrefetchMode, UIMatch };
|
|
17
17
|
/** The current route the routing hooks read. Provided by `compose` on SSR + client mount alike. */
|
|
18
18
|
export interface RouterContextValue {
|
|
19
19
|
/** The matched route's decoded path params (`/users/:id` → `{ id: "7" }`). */
|
|
@@ -31,6 +31,8 @@ export interface RouterContextValue {
|
|
|
31
31
|
/** The `pathname + search` a navigation is transitioning TO while `pending` (`undefined` when idle or
|
|
32
32
|
* during a same-route revalidation). Powers {@link NavLink}'s per-link `isPending`. */
|
|
33
33
|
readonly pendingPath?: string | undefined;
|
|
34
|
+
/** The render's props, which {@link useMatches} derives the matches from. */
|
|
35
|
+
readonly renderProps?: RenderProps | undefined;
|
|
34
36
|
}
|
|
35
37
|
export declare const RouterContext: import("react").Context<RouterContextValue>;
|
|
36
38
|
/**
|
|
@@ -55,6 +57,20 @@ export declare function useParams<T extends Record<string, string | undefined> =
|
|
|
55
57
|
* ```
|
|
56
58
|
*/
|
|
57
59
|
export declare function useSearch<Schema extends StandardSchemaV1 | undefined = undefined>(): Schema extends StandardSchemaV1 ? InferOutput<Schema> : Record<string, unknown>;
|
|
60
|
+
/**
|
|
61
|
+
* The rendered chain, outermost layout first and the page last: each module's `id`, the URL
|
|
62
|
+
* `pathname` it wraps, its `params` and loader `data`, and its `handle` export. The same list on the
|
|
63
|
+
* server and in the browser, so a layout can render breadcrumbs or read a flag the page exports:
|
|
64
|
+
*
|
|
65
|
+
* ```tsx
|
|
66
|
+
* export const handle = { crumb: "Settings" } // in a page or a layout
|
|
67
|
+
* // in a layout above it:
|
|
68
|
+
* const crumbs = useMatches().flatMap((m) => (m.handle as { crumb?: string } | undefined)?.crumb ?? [])
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Empty outside a nifra route tree.
|
|
72
|
+
*/
|
|
73
|
+
export declare function useMatches(): readonly UIMatch[];
|
|
58
74
|
/** The parsed current location. `hash` is always `""` - the fragment is client-only and never reaches
|
|
59
75
|
* the router state / server, so exposing a live hash would hydration-mismatch; read `window.location.hash`
|
|
60
76
|
* directly (in an effect) if you truly need it. */
|
|
@@ -133,12 +149,16 @@ export type SetSearchParams = (next: SearchParamsInit | ((prev: URLSearchParams)
|
|
|
133
149
|
* navigates to the new query. Mirrors react-router's `useSearchParams` tuple.
|
|
134
150
|
*/
|
|
135
151
|
export declare function useSearchParams(): readonly [URLSearchParams, SetSearchParams];
|
|
136
|
-
/** {@link Link} props: every `<a>` attribute except `href` (set from `to`), plus `to
|
|
152
|
+
/** {@link Link} props: every `<a>` attribute except `href` (set from `to`), plus `to`, `replace` and
|
|
153
|
+
* `prefetch`. */
|
|
137
154
|
export interface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
138
155
|
/** Same-origin destination path (e.g. `/users/7?tab=posts`). Rendered as the `<a href>`. */
|
|
139
156
|
readonly to: string;
|
|
140
157
|
/** Replace the current history entry instead of pushing. */
|
|
141
158
|
readonly replace?: boolean;
|
|
159
|
+
/** When the link warms its route ahead of a click - rendered as `data-nifra-prefetch`. Unset, the
|
|
160
|
+
* nearest ancestor's `data-nifra-prefetch` decides, else `intent` (hover or focus). */
|
|
161
|
+
readonly prefetch?: PrefetchMode;
|
|
142
162
|
}
|
|
143
163
|
/**
|
|
144
164
|
* A client-navigating anchor. Renders a real `<a href={to}>` (so it's a working link before hydration
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|