@nifrajs/web-react 2.11.0 → 2.12.1

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/client.d.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  import type { MountRouterOptions, RenderProps } from "@nifrajs/web";
2
2
  export { errorBoundary } from "./error.js";
3
3
  /** Hydrate a server-rendered React layout `chain` (with the loader `props`) inside `container`. */
4
- export declare function hydrate(chain: readonly unknown[], props: RenderProps, container: unknown): void;
4
+ export interface HydrationAssuranceOptions {
5
+ readonly onRecoverableError?: (error: unknown, info?: unknown) => void;
6
+ }
7
+ export declare function hydrate(chain: readonly unknown[], props: RenderProps, container: unknown, options?: HydrationAssuranceOptions): void;
8
+ /** Testing hook used by verification runners to observe React's recoverable errors and identity. */
9
+ export declare const hydrationAssuranceHook: Readonly<{
10
+ framework: "react";
11
+ runtimeIdentity: () => object;
12
+ }>;
5
13
  /**
6
14
  * Hydrate a stateful React Router. `useSyncExternalStore` subscribes to the agnostic store and
7
15
  * re-renders the matched layout chain on each store change - so client navigations swap routes
@@ -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;AAiBnE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,mGAAmG;AACnG,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAyB7D"}
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;AAkBnE,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,CA8B7D"}
package/dist/client.js CHANGED
@@ -7,6 +7,7 @@ import { searchOfChain } from "@nifrajs/web/client";
7
7
  * `useSyncExternalStore`) and re-renders the matched chain on every client navigation (no full
8
8
  * reload). Kept in its own entry so server code stays out of the client bundle.
9
9
  */
10
+ import * as React from "react";
10
11
  import { createElement, useSyncExternalStore } from "react";
11
12
  import { hydrateRoot } from "react-dom/client";
12
13
  import { compose } from "./compose.js";
@@ -14,10 +15,27 @@ import { setMountedRouter } from "./fetcher.js";
14
15
  // The `_error` boundary chain element - defined in its own (react-dom-free) module, re-exported here so
15
16
  // nifra's client codegen resolves it from `@nifrajs/web-react/client` alongside `mountRouter`.
16
17
  export { errorBoundary } from "./error.js";
17
- /** Hydrate a server-rendered React layout `chain` (with the loader `props`) inside `container`. */
18
- export function hydrate(chain, props, container) {
19
- hydrateRoot(container, compose(chain, props));
18
+ function assuranceError() {
19
+ const value = globalThis[Symbol.for("nifra.hydration.assurance")];
20
+ if (typeof value !== "object" || value === null)
21
+ return undefined;
22
+ const callback = value.onRecoverableError;
23
+ return typeof callback === "function"
24
+ ? callback
25
+ : undefined;
20
26
  }
27
+ export function hydrate(chain, props, container, options) {
28
+ const onRecoverableError = options?.onRecoverableError ?? assuranceError();
29
+ if (onRecoverableError === undefined)
30
+ hydrateRoot(container, compose(chain, props));
31
+ else
32
+ hydrateRoot(container, compose(chain, props), { onRecoverableError });
33
+ }
34
+ /** Testing hook used by verification runners to observe React's recoverable errors and identity. */
35
+ export const hydrationAssuranceHook = Object.freeze({
36
+ framework: "react",
37
+ runtimeIdentity: () => React,
38
+ });
21
39
  /**
22
40
  * Hydrate a stateful React Router. `useSyncExternalStore` subscribes to the agnostic store and
23
41
  * re-renders the matched layout chain on each store change - so client navigations swap routes
@@ -48,6 +66,7 @@ export function mountRouter(options) {
48
66
  ...(state.submission ? { submission: state.submission } : {}),
49
67
  });
50
68
  };
51
- hydrateRoot(container, createElement(Router));
69
+ const onRecoverableError = assuranceError();
70
+ hydrateRoot(container, createElement(Router), ...(onRecoverableError === undefined ? [] : [{ onRecoverableError }]));
52
71
  }
53
72
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,mGAAmG;AACnG,gGAAgG;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD;;;;;GAKG;AACH,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;AAE/C,wGAAwG;AACxG,+FAA+F;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,mGAAmG;AACnG,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,KAAkB,EAAE,SAAkB;IACvF,WAAW,CAAC,SAAoB,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC5D,gBAAgB,CAAC,MAAM,CAAC,CAAA,CAAC,+DAA+D;IACxF,MAAM,MAAM,GAAsB,GAAG,EAAE;QACrC,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACtF,qGAAqG;QACrG,sGAAsG;QACtG,oCAAoC;QACpC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,+FAA+F;YAC/F,iGAAiG;YACjG,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,aAAa,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC;YACtE,2EAA2E;YAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,WAAW,CAAC,SAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;AAC1D,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@nifrajs/web-react",
3
- "version": "2.11.0",
3
+ "version": "2.12.1",
4
4
  "description": "React render adapter for @nifrajs/web - SSR + hydration (Bun-native JSX, no Babel).",
5
5
  "keywords": [
6
6
  "bun",
7
7
  "typescript",
8
8
  "nifra",
9
- "web-framework",
10
- "full-stack",
11
- "edge",
12
- "ssr"
9
+ "react",
10
+ "ssr",
11
+ "hydration",
12
+ "streaming-ssr",
13
+ "render-adapter",
14
+ "full-stack"
13
15
  ],
14
16
  "type": "module",
15
17
  "main": "./dist/index.js",
@@ -85,10 +87,10 @@
85
87
  "access": "public"
86
88
  },
87
89
  "dependencies": {
88
- "@nifrajs/core": "2.11.0",
89
- "@nifrajs/i18n": "2.11.0",
90
- "@nifrajs/image": "2.11.0",
91
- "@nifrajs/web": "2.11.0"
90
+ "@nifrajs/core": "2.12.1",
91
+ "@nifrajs/i18n": "2.12.1",
92
+ "@nifrajs/image": "2.12.1",
93
+ "@nifrajs/web": "2.12.1"
92
94
  },
93
95
  "peerDependencies": {
94
96
  "react": "^19.0.0",
package/src/client.ts CHANGED
@@ -8,6 +8,7 @@ import { searchOfChain } from "@nifrajs/web/client"
8
8
  * `useSyncExternalStore`) and re-renders the matched chain on every client navigation (no full
9
9
  * reload). Kept in its own entry so server code stays out of the client bundle.
10
10
  */
11
+ import * as React from "react"
11
12
  import { createElement, type FunctionComponent, useSyncExternalStore } from "react"
12
13
  import { hydrateRoot } from "react-dom/client"
13
14
  import { compose } from "./compose.ts"
@@ -18,10 +19,38 @@ import { setMountedRouter } from "./fetcher.ts"
18
19
  export { errorBoundary } from "./error.ts"
19
20
 
20
21
  /** Hydrate a server-rendered React layout `chain` (with the loader `props`) inside `container`. */
21
- export function hydrate(chain: readonly unknown[], props: RenderProps, container: unknown): void {
22
- hydrateRoot(container as Element, compose(chain, props))
22
+ export interface HydrationAssuranceOptions {
23
+ readonly onRecoverableError?: (error: unknown, info?: unknown) => void
23
24
  }
24
25
 
26
+ function assuranceError(): HydrationAssuranceOptions["onRecoverableError"] {
27
+ const value = (globalThis as unknown as Record<PropertyKey, unknown>)[
28
+ Symbol.for("nifra.hydration.assurance")
29
+ ]
30
+ if (typeof value !== "object" || value === null) return undefined
31
+ const callback = (value as { onRecoverableError?: unknown }).onRecoverableError
32
+ return typeof callback === "function"
33
+ ? (callback as HydrationAssuranceOptions["onRecoverableError"])
34
+ : undefined
35
+ }
36
+
37
+ export function hydrate(
38
+ chain: readonly unknown[],
39
+ props: RenderProps,
40
+ container: unknown,
41
+ options?: HydrationAssuranceOptions,
42
+ ): void {
43
+ const onRecoverableError = options?.onRecoverableError ?? assuranceError()
44
+ if (onRecoverableError === undefined) hydrateRoot(container as Element, compose(chain, props))
45
+ else hydrateRoot(container as Element, compose(chain, props), { onRecoverableError })
46
+ }
47
+
48
+ /** Testing hook used by verification runners to observe React's recoverable errors and identity. */
49
+ export const hydrationAssuranceHook = Object.freeze({
50
+ framework: "react" as const,
51
+ runtimeIdentity: (): object => React,
52
+ })
53
+
25
54
  /**
26
55
  * Hydrate a stateful React Router. `useSyncExternalStore` subscribes to the agnostic store and
27
56
  * re-renders the matched layout chain on each store change - so client navigations swap routes
@@ -52,5 +81,10 @@ export function mountRouter(options: MountRouterOptions): void {
52
81
  ...(state.submission ? { submission: state.submission } : {}),
53
82
  })
54
83
  }
55
- hydrateRoot(container as Element, createElement(Router))
84
+ const onRecoverableError = assuranceError()
85
+ hydrateRoot(
86
+ container as Element,
87
+ createElement(Router),
88
+ ...(onRecoverableError === undefined ? [] : [{ onRecoverableError }]),
89
+ )
56
90
  }