@nestjs-ssr/react 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/init.js +5 -5
- package/dist/cli/init.mjs +5 -5
- package/dist/index.js +36 -32
- package/dist/index.mjs +6 -2
- package/dist/render/index.js +23 -20
- package/dist/render/index.mjs +5 -1
- package/dist/templates/entry-client.tsx +48 -25
- package/etc/react.api.md +250 -262
- package/package.json +1 -1
- package/src/templates/entry-client.tsx +48 -25
package/dist/cli/init.js
CHANGED
|
@@ -39,7 +39,7 @@ var main = citty.defineCommand({
|
|
|
39
39
|
default: "5173"
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
|
-
|
|
42
|
+
run({ args }) {
|
|
43
43
|
const cwd = process.cwd();
|
|
44
44
|
const viewsDir = args.views;
|
|
45
45
|
const vitePort = parseInt(args.port, 10) || 5173;
|
|
@@ -419,17 +419,17 @@ export default defineConfig({
|
|
|
419
419
|
packageJson.scripts["start:dev"] = 'concurrently --raw -n vite,nest -c cyan,green "pnpm:dev:vite" "pnpm:dev:nest"';
|
|
420
420
|
shouldUpdate = true;
|
|
421
421
|
}
|
|
422
|
-
const existingBuild = packageJson.scripts
|
|
422
|
+
const existingBuild = packageJson.scripts["build"];
|
|
423
423
|
const recommendedBuild = "nest build && pnpm build:client && pnpm build:server";
|
|
424
424
|
if (!existingBuild) {
|
|
425
|
-
packageJson.scripts
|
|
425
|
+
packageJson.scripts["build"] = recommendedBuild;
|
|
426
426
|
shouldUpdate = true;
|
|
427
427
|
consola.consola.success("Created build script");
|
|
428
428
|
} else if (existingBuild !== recommendedBuild) {
|
|
429
429
|
if (!existingBuild.includes("build:client") || !existingBuild.includes("build:server")) {
|
|
430
430
|
consola.consola.warn(`Found existing build script: "${existingBuild}"`);
|
|
431
431
|
consola.consola.info(`Updating to: ${recommendedBuild}`);
|
|
432
|
-
packageJson.scripts
|
|
432
|
+
packageJson.scripts["build"] = recommendedBuild;
|
|
433
433
|
shouldUpdate = true;
|
|
434
434
|
} else {
|
|
435
435
|
consola.consola.info("Build scripts already configured");
|
|
@@ -528,4 +528,4 @@ export default defineConfig({
|
|
|
528
528
|
consola.consola.log(" Terminal 2: pnpm dev:nest");
|
|
529
529
|
}
|
|
530
530
|
});
|
|
531
|
-
citty.runMain(main);
|
|
531
|
+
void citty.runMain(main);
|
package/dist/cli/init.mjs
CHANGED
|
@@ -36,7 +36,7 @@ var main = defineCommand({
|
|
|
36
36
|
default: "5173"
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
-
|
|
39
|
+
run({ args }) {
|
|
40
40
|
const cwd = process.cwd();
|
|
41
41
|
const viewsDir = args.views;
|
|
42
42
|
const vitePort = parseInt(args.port, 10) || 5173;
|
|
@@ -416,17 +416,17 @@ export default defineConfig({
|
|
|
416
416
|
packageJson.scripts["start:dev"] = 'concurrently --raw -n vite,nest -c cyan,green "pnpm:dev:vite" "pnpm:dev:nest"';
|
|
417
417
|
shouldUpdate = true;
|
|
418
418
|
}
|
|
419
|
-
const existingBuild = packageJson.scripts
|
|
419
|
+
const existingBuild = packageJson.scripts["build"];
|
|
420
420
|
const recommendedBuild = "nest build && pnpm build:client && pnpm build:server";
|
|
421
421
|
if (!existingBuild) {
|
|
422
|
-
packageJson.scripts
|
|
422
|
+
packageJson.scripts["build"] = recommendedBuild;
|
|
423
423
|
shouldUpdate = true;
|
|
424
424
|
consola.success("Created build script");
|
|
425
425
|
} else if (existingBuild !== recommendedBuild) {
|
|
426
426
|
if (!existingBuild.includes("build:client") || !existingBuild.includes("build:server")) {
|
|
427
427
|
consola.warn(`Found existing build script: "${existingBuild}"`);
|
|
428
428
|
consola.info(`Updating to: ${recommendedBuild}`);
|
|
429
|
-
packageJson.scripts
|
|
429
|
+
packageJson.scripts["build"] = recommendedBuild;
|
|
430
430
|
shouldUpdate = true;
|
|
431
431
|
} else {
|
|
432
432
|
consola.info("Build scripts already configured");
|
|
@@ -525,4 +525,4 @@ export default defineConfig({
|
|
|
525
525
|
consola.log(" Terminal 2: pnpm dev:nest");
|
|
526
526
|
}
|
|
527
527
|
});
|
|
528
|
-
runMain(main);
|
|
528
|
+
void runMain(main);
|
package/dist/index.js
CHANGED
|
@@ -7,13 +7,13 @@ var path = require('path');
|
|
|
7
7
|
var devalue = require('devalue');
|
|
8
8
|
var escapeHtml = require('escape-html');
|
|
9
9
|
var server = require('react-dom/server');
|
|
10
|
-
var
|
|
10
|
+
var React2 = require('react');
|
|
11
11
|
var operators = require('rxjs/operators');
|
|
12
12
|
|
|
13
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
14
|
|
|
15
15
|
var escapeHtml__default = /*#__PURE__*/_interopDefault(escapeHtml);
|
|
16
|
-
var
|
|
16
|
+
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
17
17
|
|
|
18
18
|
var __defProp = Object.defineProperty;
|
|
19
19
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -339,16 +339,18 @@ StringRenderer = _ts_decorate2([
|
|
|
339
339
|
typeof exports.TemplateParserService === "undefined" ? Object : exports.TemplateParserService
|
|
340
340
|
])
|
|
341
341
|
], StringRenderer);
|
|
342
|
+
|
|
343
|
+
// src/render/error-pages/error-page-development.tsx
|
|
342
344
|
function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
343
345
|
const stackLines = error.stack ? error.stack.split("\n").slice(1) : [];
|
|
344
|
-
return /* @__PURE__ */
|
|
346
|
+
return /* @__PURE__ */ React.createElement("html", {
|
|
345
347
|
lang: "en"
|
|
346
|
-
}, /* @__PURE__ */
|
|
348
|
+
}, /* @__PURE__ */ React.createElement("head", null, /* @__PURE__ */ React.createElement("meta", {
|
|
347
349
|
charSet: "UTF-8"
|
|
348
|
-
}), /* @__PURE__ */
|
|
350
|
+
}), /* @__PURE__ */ React.createElement("meta", {
|
|
349
351
|
name: "viewport",
|
|
350
352
|
content: "width=device-width, initial-scale=1.0"
|
|
351
|
-
}), /* @__PURE__ */
|
|
353
|
+
}), /* @__PURE__ */ React.createElement("title", null, `SSR Error - ${error.name}`), /* @__PURE__ */ React.createElement("style", {
|
|
352
354
|
dangerouslySetInnerHTML: {
|
|
353
355
|
__html: `
|
|
354
356
|
body {
|
|
@@ -399,28 +401,30 @@ function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
|
399
401
|
}
|
|
400
402
|
`
|
|
401
403
|
}
|
|
402
|
-
})), /* @__PURE__ */
|
|
404
|
+
})), /* @__PURE__ */ React.createElement("body", null, /* @__PURE__ */ React.createElement("div", {
|
|
403
405
|
className: "error-container"
|
|
404
|
-
}, /* @__PURE__ */
|
|
406
|
+
}, /* @__PURE__ */ React.createElement("h1", null, "Server-Side Rendering Error"), /* @__PURE__ */ React.createElement("div", {
|
|
405
407
|
className: "error-type"
|
|
406
|
-
}, error.name), /* @__PURE__ */
|
|
408
|
+
}, error.name), /* @__PURE__ */ React.createElement("div", {
|
|
407
409
|
className: "error-message"
|
|
408
|
-
}, error.message), /* @__PURE__ */
|
|
410
|
+
}, error.message), /* @__PURE__ */ React.createElement("h2", null, "Stack Trace"), /* @__PURE__ */ React.createElement("div", {
|
|
409
411
|
className: "stack-trace"
|
|
410
|
-
}, /* @__PURE__ */
|
|
412
|
+
}, /* @__PURE__ */ React.createElement("pre", null, stackLines.join("\n"))), /* @__PURE__ */ React.createElement("div", {
|
|
411
413
|
className: "meta"
|
|
412
|
-
}, /* @__PURE__ */
|
|
414
|
+
}, /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "View Path:"), " ", viewPath), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Error Phase:"), " ", phase === "shell" ? "Shell (before streaming started)" : "Streaming (during content delivery)"), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Environment:"), " Development")))));
|
|
413
415
|
}
|
|
414
416
|
__name(ErrorPageDevelopment, "ErrorPageDevelopment");
|
|
417
|
+
|
|
418
|
+
// src/render/error-pages/error-page-production.tsx
|
|
415
419
|
function ErrorPageProduction() {
|
|
416
|
-
return /* @__PURE__ */
|
|
420
|
+
return /* @__PURE__ */ React.createElement("html", {
|
|
417
421
|
lang: "en"
|
|
418
|
-
}, /* @__PURE__ */
|
|
422
|
+
}, /* @__PURE__ */ React.createElement("head", null, /* @__PURE__ */ React.createElement("meta", {
|
|
419
423
|
charSet: "UTF-8"
|
|
420
|
-
}), /* @__PURE__ */
|
|
424
|
+
}), /* @__PURE__ */ React.createElement("meta", {
|
|
421
425
|
name: "viewport",
|
|
422
426
|
content: "width=device-width, initial-scale=1.0"
|
|
423
|
-
}), /* @__PURE__ */
|
|
427
|
+
}), /* @__PURE__ */ React.createElement("title", null, "Error"), /* @__PURE__ */ React.createElement("style", {
|
|
424
428
|
dangerouslySetInnerHTML: {
|
|
425
429
|
__html: `
|
|
426
430
|
body {
|
|
@@ -447,9 +451,9 @@ function ErrorPageProduction() {
|
|
|
447
451
|
}
|
|
448
452
|
`
|
|
449
453
|
}
|
|
450
|
-
})), /* @__PURE__ */
|
|
454
|
+
})), /* @__PURE__ */ React.createElement("body", null, /* @__PURE__ */ React.createElement("div", {
|
|
451
455
|
className: "error-container"
|
|
452
|
-
}, /* @__PURE__ */
|
|
456
|
+
}, /* @__PURE__ */ React.createElement("h1", null, "500"), /* @__PURE__ */ React.createElement("p", null, "Internal Server Error"), /* @__PURE__ */ React.createElement("p", null, "Something went wrong while rendering this page."))));
|
|
453
457
|
}
|
|
454
458
|
__name(ErrorPageProduction, "ErrorPageProduction");
|
|
455
459
|
|
|
@@ -516,7 +520,7 @@ exports.StreamingErrorHandler = class _StreamingErrorHandler {
|
|
|
516
520
|
*/
|
|
517
521
|
renderDevelopmentErrorPage(error, viewPath, phase) {
|
|
518
522
|
const ErrorComponent = this.errorPageDevelopment || ErrorPageDevelopment;
|
|
519
|
-
const element =
|
|
523
|
+
const element = React2.createElement(ErrorComponent, {
|
|
520
524
|
error,
|
|
521
525
|
viewPath,
|
|
522
526
|
phase
|
|
@@ -528,7 +532,7 @@ exports.StreamingErrorHandler = class _StreamingErrorHandler {
|
|
|
528
532
|
*/
|
|
529
533
|
renderProductionErrorPage() {
|
|
530
534
|
const ErrorComponent = this.errorPageProduction || ErrorPageProduction;
|
|
531
|
-
const element =
|
|
535
|
+
const element = React2.createElement(ErrorComponent);
|
|
532
536
|
return "<!DOCTYPE html>\n" + server.renderToStaticMarkup(element);
|
|
533
537
|
}
|
|
534
538
|
/**
|
|
@@ -1703,7 +1707,7 @@ var CONTEXT_KEY = /* @__PURE__ */ Symbol.for("nestjs-ssr.PageContext");
|
|
|
1703
1707
|
var globalStore = globalThis;
|
|
1704
1708
|
function getOrCreateContext() {
|
|
1705
1709
|
if (!globalStore[CONTEXT_KEY]) {
|
|
1706
|
-
globalStore[CONTEXT_KEY] = /* @__PURE__ */
|
|
1710
|
+
globalStore[CONTEXT_KEY] = /* @__PURE__ */ React2.createContext(null);
|
|
1707
1711
|
}
|
|
1708
1712
|
return globalStore[CONTEXT_KEY];
|
|
1709
1713
|
}
|
|
@@ -1713,12 +1717,12 @@ function registerPageContextState(setter) {
|
|
|
1713
1717
|
}
|
|
1714
1718
|
__name(registerPageContextState, "registerPageContextState");
|
|
1715
1719
|
function PageContextProvider({ context: initialContext, children, isSegment = false }) {
|
|
1716
|
-
const [context, setContext] =
|
|
1717
|
-
|
|
1720
|
+
const [context, setContext] = React2.useState(initialContext);
|
|
1721
|
+
React2.useEffect(() => {
|
|
1718
1722
|
}, [
|
|
1719
1723
|
isSegment
|
|
1720
1724
|
]);
|
|
1721
|
-
return /* @__PURE__ */
|
|
1725
|
+
return /* @__PURE__ */ React2__default.default.createElement(PageContext.Provider, {
|
|
1722
1726
|
value: context
|
|
1723
1727
|
}, children);
|
|
1724
1728
|
}
|
|
@@ -1730,7 +1734,7 @@ function createSSRHooks() {
|
|
|
1730
1734
|
* Contains URL metadata, headers, and any custom properties you've added.
|
|
1731
1735
|
*/
|
|
1732
1736
|
usePageContext: /* @__PURE__ */ __name(() => {
|
|
1733
|
-
const context =
|
|
1737
|
+
const context = React2.useContext(PageContext);
|
|
1734
1738
|
if (!context) {
|
|
1735
1739
|
throw new Error("usePageContext must be used within PageContextProvider");
|
|
1736
1740
|
}
|
|
@@ -1747,7 +1751,7 @@ function createSSRHooks() {
|
|
|
1747
1751
|
* ```
|
|
1748
1752
|
*/
|
|
1749
1753
|
useParams: /* @__PURE__ */ __name(() => {
|
|
1750
|
-
const context =
|
|
1754
|
+
const context = React2.useContext(PageContext);
|
|
1751
1755
|
if (!context) {
|
|
1752
1756
|
throw new Error("useParams must be used within PageContextProvider");
|
|
1753
1757
|
}
|
|
@@ -1765,7 +1769,7 @@ function createSSRHooks() {
|
|
|
1765
1769
|
* ```
|
|
1766
1770
|
*/
|
|
1767
1771
|
useQuery: /* @__PURE__ */ __name(() => {
|
|
1768
|
-
const context =
|
|
1772
|
+
const context = React2.useContext(PageContext);
|
|
1769
1773
|
if (!context) {
|
|
1770
1774
|
throw new Error("useQuery must be used within PageContextProvider");
|
|
1771
1775
|
}
|
|
@@ -1785,7 +1789,7 @@ function createSSRHooks() {
|
|
|
1785
1789
|
* ```
|
|
1786
1790
|
*/
|
|
1787
1791
|
useRequest: /* @__PURE__ */ __name(() => {
|
|
1788
|
-
const context =
|
|
1792
|
+
const context = React2.useContext(PageContext);
|
|
1789
1793
|
if (!context) {
|
|
1790
1794
|
throw new Error("useRequest must be used within PageContextProvider");
|
|
1791
1795
|
}
|
|
@@ -1811,7 +1815,7 @@ function createSSRHooks() {
|
|
|
1811
1815
|
* ```
|
|
1812
1816
|
*/
|
|
1813
1817
|
useHeaders: /* @__PURE__ */ __name(() => {
|
|
1814
|
-
const context =
|
|
1818
|
+
const context = React2.useContext(PageContext);
|
|
1815
1819
|
if (!context) {
|
|
1816
1820
|
throw new Error("useHeaders must be used within PageContextProvider");
|
|
1817
1821
|
}
|
|
@@ -1846,7 +1850,7 @@ function createSSRHooks() {
|
|
|
1846
1850
|
* ```
|
|
1847
1851
|
*/
|
|
1848
1852
|
useHeader: /* @__PURE__ */ __name((name) => {
|
|
1849
|
-
const context =
|
|
1853
|
+
const context = React2.useContext(PageContext);
|
|
1850
1854
|
if (!context) {
|
|
1851
1855
|
throw new Error("useHeader must be used within PageContextProvider");
|
|
1852
1856
|
}
|
|
@@ -1872,7 +1876,7 @@ function createSSRHooks() {
|
|
|
1872
1876
|
* ```
|
|
1873
1877
|
*/
|
|
1874
1878
|
useCookies: /* @__PURE__ */ __name(() => {
|
|
1875
|
-
const context =
|
|
1879
|
+
const context = React2.useContext(PageContext);
|
|
1876
1880
|
if (!context) {
|
|
1877
1881
|
throw new Error("useCookies must be used within PageContextProvider");
|
|
1878
1882
|
}
|
|
@@ -1894,7 +1898,7 @@ function createSSRHooks() {
|
|
|
1894
1898
|
* ```
|
|
1895
1899
|
*/
|
|
1896
1900
|
useCookie: /* @__PURE__ */ __name((name) => {
|
|
1897
|
-
const context =
|
|
1901
|
+
const context = React2.useContext(PageContext);
|
|
1898
1902
|
if (!context) {
|
|
1899
1903
|
throw new Error("useCookie must be used within PageContextProvider");
|
|
1900
1904
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { join, relative } from 'path';
|
|
|
5
5
|
import { uneval } from 'devalue';
|
|
6
6
|
import escapeHtml from 'escape-html';
|
|
7
7
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
8
|
-
import
|
|
8
|
+
import React2, { createElement, createContext, useContext, useState, useEffect } from 'react';
|
|
9
9
|
import { switchMap } from 'rxjs/operators';
|
|
10
10
|
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
@@ -332,6 +332,8 @@ StringRenderer = _ts_decorate2([
|
|
|
332
332
|
typeof TemplateParserService === "undefined" ? Object : TemplateParserService
|
|
333
333
|
])
|
|
334
334
|
], StringRenderer);
|
|
335
|
+
|
|
336
|
+
// src/render/error-pages/error-page-development.tsx
|
|
335
337
|
function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
336
338
|
const stackLines = error.stack ? error.stack.split("\n").slice(1) : [];
|
|
337
339
|
return /* @__PURE__ */ React.createElement("html", {
|
|
@@ -405,6 +407,8 @@ function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
|
405
407
|
}, /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "View Path:"), " ", viewPath), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Error Phase:"), " ", phase === "shell" ? "Shell (before streaming started)" : "Streaming (during content delivery)"), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Environment:"), " Development")))));
|
|
406
408
|
}
|
|
407
409
|
__name(ErrorPageDevelopment, "ErrorPageDevelopment");
|
|
410
|
+
|
|
411
|
+
// src/render/error-pages/error-page-production.tsx
|
|
408
412
|
function ErrorPageProduction() {
|
|
409
413
|
return /* @__PURE__ */ React.createElement("html", {
|
|
410
414
|
lang: "en"
|
|
@@ -1711,7 +1715,7 @@ function PageContextProvider({ context: initialContext, children, isSegment = fa
|
|
|
1711
1715
|
}, [
|
|
1712
1716
|
isSegment
|
|
1713
1717
|
]);
|
|
1714
|
-
return /* @__PURE__ */
|
|
1718
|
+
return /* @__PURE__ */ React2.createElement(PageContext.Provider, {
|
|
1715
1719
|
value: context
|
|
1716
1720
|
}, children);
|
|
1717
1721
|
}
|
package/dist/render/index.js
CHANGED
|
@@ -7,13 +7,12 @@ var path = require('path');
|
|
|
7
7
|
var devalue = require('devalue');
|
|
8
8
|
var escapeHtml = require('escape-html');
|
|
9
9
|
var server = require('react-dom/server');
|
|
10
|
-
var
|
|
10
|
+
var react = require('react');
|
|
11
11
|
var operators = require('rxjs/operators');
|
|
12
12
|
|
|
13
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
14
|
|
|
15
15
|
var escapeHtml__default = /*#__PURE__*/_interopDefault(escapeHtml);
|
|
16
|
-
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
17
16
|
|
|
18
17
|
var __defProp = Object.defineProperty;
|
|
19
18
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -339,16 +338,18 @@ StringRenderer = _ts_decorate2([
|
|
|
339
338
|
typeof exports.TemplateParserService === "undefined" ? Object : exports.TemplateParserService
|
|
340
339
|
])
|
|
341
340
|
], StringRenderer);
|
|
341
|
+
|
|
342
|
+
// src/render/error-pages/error-page-development.tsx
|
|
342
343
|
function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
343
344
|
const stackLines = error.stack ? error.stack.split("\n").slice(1) : [];
|
|
344
|
-
return /* @__PURE__ */
|
|
345
|
+
return /* @__PURE__ */ React.createElement("html", {
|
|
345
346
|
lang: "en"
|
|
346
|
-
}, /* @__PURE__ */
|
|
347
|
+
}, /* @__PURE__ */ React.createElement("head", null, /* @__PURE__ */ React.createElement("meta", {
|
|
347
348
|
charSet: "UTF-8"
|
|
348
|
-
}), /* @__PURE__ */
|
|
349
|
+
}), /* @__PURE__ */ React.createElement("meta", {
|
|
349
350
|
name: "viewport",
|
|
350
351
|
content: "width=device-width, initial-scale=1.0"
|
|
351
|
-
}), /* @__PURE__ */
|
|
352
|
+
}), /* @__PURE__ */ React.createElement("title", null, `SSR Error - ${error.name}`), /* @__PURE__ */ React.createElement("style", {
|
|
352
353
|
dangerouslySetInnerHTML: {
|
|
353
354
|
__html: `
|
|
354
355
|
body {
|
|
@@ -399,28 +400,30 @@ function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
|
399
400
|
}
|
|
400
401
|
`
|
|
401
402
|
}
|
|
402
|
-
})), /* @__PURE__ */
|
|
403
|
+
})), /* @__PURE__ */ React.createElement("body", null, /* @__PURE__ */ React.createElement("div", {
|
|
403
404
|
className: "error-container"
|
|
404
|
-
}, /* @__PURE__ */
|
|
405
|
+
}, /* @__PURE__ */ React.createElement("h1", null, "Server-Side Rendering Error"), /* @__PURE__ */ React.createElement("div", {
|
|
405
406
|
className: "error-type"
|
|
406
|
-
}, error.name), /* @__PURE__ */
|
|
407
|
+
}, error.name), /* @__PURE__ */ React.createElement("div", {
|
|
407
408
|
className: "error-message"
|
|
408
|
-
}, error.message), /* @__PURE__ */
|
|
409
|
+
}, error.message), /* @__PURE__ */ React.createElement("h2", null, "Stack Trace"), /* @__PURE__ */ React.createElement("div", {
|
|
409
410
|
className: "stack-trace"
|
|
410
|
-
}, /* @__PURE__ */
|
|
411
|
+
}, /* @__PURE__ */ React.createElement("pre", null, stackLines.join("\n"))), /* @__PURE__ */ React.createElement("div", {
|
|
411
412
|
className: "meta"
|
|
412
|
-
}, /* @__PURE__ */
|
|
413
|
+
}, /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "View Path:"), " ", viewPath), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Error Phase:"), " ", phase === "shell" ? "Shell (before streaming started)" : "Streaming (during content delivery)"), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Environment:"), " Development")))));
|
|
413
414
|
}
|
|
414
415
|
__name(ErrorPageDevelopment, "ErrorPageDevelopment");
|
|
416
|
+
|
|
417
|
+
// src/render/error-pages/error-page-production.tsx
|
|
415
418
|
function ErrorPageProduction() {
|
|
416
|
-
return /* @__PURE__ */
|
|
419
|
+
return /* @__PURE__ */ React.createElement("html", {
|
|
417
420
|
lang: "en"
|
|
418
|
-
}, /* @__PURE__ */
|
|
421
|
+
}, /* @__PURE__ */ React.createElement("head", null, /* @__PURE__ */ React.createElement("meta", {
|
|
419
422
|
charSet: "UTF-8"
|
|
420
|
-
}), /* @__PURE__ */
|
|
423
|
+
}), /* @__PURE__ */ React.createElement("meta", {
|
|
421
424
|
name: "viewport",
|
|
422
425
|
content: "width=device-width, initial-scale=1.0"
|
|
423
|
-
}), /* @__PURE__ */
|
|
426
|
+
}), /* @__PURE__ */ React.createElement("title", null, "Error"), /* @__PURE__ */ React.createElement("style", {
|
|
424
427
|
dangerouslySetInnerHTML: {
|
|
425
428
|
__html: `
|
|
426
429
|
body {
|
|
@@ -447,9 +450,9 @@ function ErrorPageProduction() {
|
|
|
447
450
|
}
|
|
448
451
|
`
|
|
449
452
|
}
|
|
450
|
-
})), /* @__PURE__ */
|
|
453
|
+
})), /* @__PURE__ */ React.createElement("body", null, /* @__PURE__ */ React.createElement("div", {
|
|
451
454
|
className: "error-container"
|
|
452
|
-
}, /* @__PURE__ */
|
|
455
|
+
}, /* @__PURE__ */ React.createElement("h1", null, "500"), /* @__PURE__ */ React.createElement("p", null, "Internal Server Error"), /* @__PURE__ */ React.createElement("p", null, "Something went wrong while rendering this page."))));
|
|
453
456
|
}
|
|
454
457
|
__name(ErrorPageProduction, "ErrorPageProduction");
|
|
455
458
|
|
|
@@ -516,7 +519,7 @@ exports.StreamingErrorHandler = class _StreamingErrorHandler {
|
|
|
516
519
|
*/
|
|
517
520
|
renderDevelopmentErrorPage(error, viewPath, phase) {
|
|
518
521
|
const ErrorComponent = this.errorPageDevelopment || ErrorPageDevelopment;
|
|
519
|
-
const element =
|
|
522
|
+
const element = react.createElement(ErrorComponent, {
|
|
520
523
|
error,
|
|
521
524
|
viewPath,
|
|
522
525
|
phase
|
|
@@ -528,7 +531,7 @@ exports.StreamingErrorHandler = class _StreamingErrorHandler {
|
|
|
528
531
|
*/
|
|
529
532
|
renderProductionErrorPage() {
|
|
530
533
|
const ErrorComponent = this.errorPageProduction || ErrorPageProduction;
|
|
531
|
-
const element =
|
|
534
|
+
const element = react.createElement(ErrorComponent);
|
|
532
535
|
return "<!DOCTYPE html>\n" + server.renderToStaticMarkup(element);
|
|
533
536
|
}
|
|
534
537
|
/**
|
package/dist/render/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { join, relative } from 'path';
|
|
|
5
5
|
import { uneval } from 'devalue';
|
|
6
6
|
import escapeHtml from 'escape-html';
|
|
7
7
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
8
|
-
import
|
|
8
|
+
import { createElement } from 'react';
|
|
9
9
|
import { switchMap } from 'rxjs/operators';
|
|
10
10
|
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
@@ -332,6 +332,8 @@ StringRenderer = _ts_decorate2([
|
|
|
332
332
|
typeof TemplateParserService === "undefined" ? Object : TemplateParserService
|
|
333
333
|
])
|
|
334
334
|
], StringRenderer);
|
|
335
|
+
|
|
336
|
+
// src/render/error-pages/error-page-development.tsx
|
|
335
337
|
function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
336
338
|
const stackLines = error.stack ? error.stack.split("\n").slice(1) : [];
|
|
337
339
|
return /* @__PURE__ */ React.createElement("html", {
|
|
@@ -405,6 +407,8 @@ function ErrorPageDevelopment({ error, viewPath, phase }) {
|
|
|
405
407
|
}, /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "View Path:"), " ", viewPath), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Error Phase:"), " ", phase === "shell" ? "Shell (before streaming started)" : "Streaming (during content delivery)"), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Environment:"), " Development")))));
|
|
406
408
|
}
|
|
407
409
|
__name(ErrorPageDevelopment, "ErrorPageDevelopment");
|
|
410
|
+
|
|
411
|
+
// src/render/error-pages/error-page-production.tsx
|
|
408
412
|
function ErrorPageProduction() {
|
|
409
413
|
return /* @__PURE__ */ React.createElement("html", {
|
|
410
414
|
lang: "en"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="@nestjs-ssr/react/global" />
|
|
2
|
+
|
|
2
3
|
import React, { StrictMode } from 'react';
|
|
3
4
|
import { hydrateRoot } from 'react-dom/client';
|
|
4
5
|
import {
|
|
@@ -10,6 +11,15 @@ const componentName = window.__COMPONENT_NAME__;
|
|
|
10
11
|
const initialProps = window.__INITIAL_STATE__ || {};
|
|
11
12
|
const renderContext = window.__CONTEXT__ || {};
|
|
12
13
|
|
|
14
|
+
// Auto-discover root layout using Vite's glob import (must match server-side discovery)
|
|
15
|
+
// @ts-ignore - Vite-specific API
|
|
16
|
+
const layoutModules = import.meta.glob('@/views/layout.tsx', {
|
|
17
|
+
eager: true,
|
|
18
|
+
}) as Record<string, { default: React.ComponentType<any> }>;
|
|
19
|
+
|
|
20
|
+
const layoutPath = Object.keys(layoutModules)[0];
|
|
21
|
+
const RootLayout = layoutPath ? layoutModules[layoutPath].default : null;
|
|
22
|
+
|
|
13
23
|
// Auto-import all view components using Vite's glob feature
|
|
14
24
|
// Exclude entry-client.tsx and entry-server.tsx from the glob
|
|
15
25
|
// @ts-ignore - Vite-specific API
|
|
@@ -111,40 +121,53 @@ function hasLayout(
|
|
|
111
121
|
function composeWithLayout(
|
|
112
122
|
ViewComponent: React.ComponentType<any>,
|
|
113
123
|
props: any,
|
|
124
|
+
context?: any,
|
|
125
|
+
layouts: Array<{ layout: React.ComponentType<any>; props?: any }> = [],
|
|
114
126
|
): React.ReactElement {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
while (hasLayout(currentComponent)) {
|
|
130
|
-
layoutChain.push({
|
|
131
|
-
Layout: currentComponent.layout,
|
|
132
|
-
layoutProps: currentComponent.layoutProps || {},
|
|
133
|
-
});
|
|
134
|
-
currentComponent = currentComponent.layout;
|
|
127
|
+
// Start with the page component
|
|
128
|
+
let result = <ViewComponent {...props} />;
|
|
129
|
+
|
|
130
|
+
// If no layouts passed, check if component has its own layout chain
|
|
131
|
+
if (layouts.length === 0 && hasLayout(ViewComponent)) {
|
|
132
|
+
let currentComponent: any = ViewComponent;
|
|
133
|
+
while (hasLayout(currentComponent)) {
|
|
134
|
+
layouts.push({
|
|
135
|
+
layout: currentComponent.layout,
|
|
136
|
+
props: currentComponent.layoutProps || {},
|
|
137
|
+
});
|
|
138
|
+
currentComponent = currentComponent.layout;
|
|
139
|
+
}
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
// Wrap
|
|
138
|
-
|
|
139
|
-
for (const { Layout, layoutProps } of
|
|
140
|
-
|
|
142
|
+
// Wrap with each layout in the chain
|
|
143
|
+
// Must match server-side wrapping with data-layout and data-outlet attributes
|
|
144
|
+
for (const { layout: Layout, props: layoutProps } of layouts) {
|
|
145
|
+
const layoutName = Layout.displayName || Layout.name || 'Layout';
|
|
146
|
+
result = (
|
|
147
|
+
<div data-layout={layoutName}>
|
|
148
|
+
<Layout context={context} layoutProps={layoutProps}>
|
|
149
|
+
<div data-outlet={layoutName}>{result}</div>
|
|
150
|
+
</Layout>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
return result;
|
|
144
156
|
}
|
|
145
157
|
|
|
158
|
+
// Build layouts array - use RootLayout if it exists (matching server behavior)
|
|
159
|
+
const layouts: Array<{ layout: React.ComponentType<any>; props?: any }> = [];
|
|
160
|
+
if (RootLayout) {
|
|
161
|
+
layouts.push({ layout: RootLayout, props: {} });
|
|
162
|
+
}
|
|
163
|
+
|
|
146
164
|
// Compose the component with its layout (if any)
|
|
147
|
-
const composedElement = composeWithLayout(
|
|
165
|
+
const composedElement = composeWithLayout(
|
|
166
|
+
ViewComponent,
|
|
167
|
+
initialProps,
|
|
168
|
+
renderContext,
|
|
169
|
+
layouts,
|
|
170
|
+
);
|
|
148
171
|
|
|
149
172
|
// Wrap with providers to make context and navigation state available via hooks
|
|
150
173
|
const wrappedElement = (
|
package/etc/react.api.md
CHANGED
|
@@ -1,262 +1,250 @@
|
|
|
1
|
-
## API Report File for "@nestjs-ssr/react"
|
|
2
|
-
|
|
3
|
-
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// @public
|
|
77
|
-
export
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// @public
|
|
83
|
-
export interface
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// @public
|
|
212
|
-
export
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// @public
|
|
253
|
-
export function useParams(): Record<string, string>;
|
|
254
|
-
|
|
255
|
-
// @public
|
|
256
|
-
export function useQuery(): Record<string, string | string[]>;
|
|
257
|
-
|
|
258
|
-
// @public
|
|
259
|
-
export function useUserAgent(): string | undefined;
|
|
260
|
-
|
|
261
|
-
// (No @packageDocumentation comment for this package)
|
|
262
|
-
```
|
|
1
|
+
## API Report File for "@nestjs-ssr/react"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import { CallHandler } from '@nestjs/common';
|
|
8
|
+
import { ComponentType } from 'react';
|
|
9
|
+
import { DynamicModule } from '@nestjs/common';
|
|
10
|
+
import { ExecutionContext } from '@nestjs/common';
|
|
11
|
+
import { NestInterceptor } from '@nestjs/common';
|
|
12
|
+
import { Observable } from 'rxjs';
|
|
13
|
+
import { default as React_2 } from 'react';
|
|
14
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
15
|
+
import { ReactNode } from 'react';
|
|
16
|
+
import { Reflector } from '@nestjs/core';
|
|
17
|
+
import { Response as Response_2 } from 'express';
|
|
18
|
+
import { ViteDevServer } from 'vite';
|
|
19
|
+
|
|
20
|
+
// @public
|
|
21
|
+
export function createSSRHooks<T extends RenderContext = RenderContext>(): {
|
|
22
|
+
usePageContext: () => T;
|
|
23
|
+
useParams: () => Record<string, string>;
|
|
24
|
+
useQuery: () => Record<string, string | string[]>;
|
|
25
|
+
useRequest: () => T;
|
|
26
|
+
useHeaders: () => Record<string, string>;
|
|
27
|
+
useHeader: (name: string) => string | undefined;
|
|
28
|
+
useCookies: () => Record<string, string>;
|
|
29
|
+
useCookie: (name: string) => string | undefined;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Warning: (ae-forgotten-export) The symbol "ErrorPageDevelopmentProps" needs to be exported by the entry point index.d.ts
|
|
33
|
+
//
|
|
34
|
+
// @public
|
|
35
|
+
export function ErrorPageDevelopment({ error, viewPath, phase, }: ErrorPageDevelopmentProps): react_jsx_runtime.JSX.Element;
|
|
36
|
+
|
|
37
|
+
// @public
|
|
38
|
+
export function ErrorPageProduction(): react_jsx_runtime.JSX.Element;
|
|
39
|
+
|
|
40
|
+
// @public
|
|
41
|
+
export interface HeadData {
|
|
42
|
+
bodyAttributes?: Record<string, string>;
|
|
43
|
+
canonical?: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
htmlAttributes?: Record<string, string>;
|
|
46
|
+
jsonLd?: Array<Record<string, any>>;
|
|
47
|
+
keywords?: string;
|
|
48
|
+
links?: Array<{
|
|
49
|
+
rel: string;
|
|
50
|
+
href: string;
|
|
51
|
+
as?: string;
|
|
52
|
+
type?: string;
|
|
53
|
+
crossorigin?: string;
|
|
54
|
+
[key: string]: any;
|
|
55
|
+
}>;
|
|
56
|
+
meta?: Array<{
|
|
57
|
+
name?: string;
|
|
58
|
+
property?: string;
|
|
59
|
+
content: string;
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
}>;
|
|
62
|
+
ogDescription?: string;
|
|
63
|
+
ogImage?: string;
|
|
64
|
+
ogTitle?: string;
|
|
65
|
+
scripts?: Array<{
|
|
66
|
+
src?: string;
|
|
67
|
+
async?: boolean;
|
|
68
|
+
defer?: boolean;
|
|
69
|
+
type?: string;
|
|
70
|
+
innerHTML?: string;
|
|
71
|
+
[key: string]: any;
|
|
72
|
+
}>;
|
|
73
|
+
title?: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// @public
|
|
77
|
+
export function Layout(layout: LayoutComponent<any>, options?: LayoutDecoratorOptions): ClassDecorator;
|
|
78
|
+
|
|
79
|
+
// @public
|
|
80
|
+
export type LayoutComponent<TProps = {}> = ComponentType<LayoutProps<TProps>>;
|
|
81
|
+
|
|
82
|
+
// @public
|
|
83
|
+
export interface LayoutDecoratorOptions {
|
|
84
|
+
props?: Record<string, any>;
|
|
85
|
+
skipRoot?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// @public
|
|
89
|
+
export interface LayoutProps<TProps = {}> {
|
|
90
|
+
children: ReactNode;
|
|
91
|
+
context?: RenderContext;
|
|
92
|
+
head?: HeadData;
|
|
93
|
+
layoutProps?: TProps;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// @public
|
|
97
|
+
export interface PageComponentWithLayout<TPageProps = {}, TLayoutProps = {}> {
|
|
98
|
+
(props: TPageProps): ReactNode;
|
|
99
|
+
layout?: LayoutComponent<TLayoutProps>;
|
|
100
|
+
layoutProps?: TLayoutProps;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// @public
|
|
104
|
+
export function PageContextProvider({ context: initialContext, children, isSegment, }: {
|
|
105
|
+
context: RenderContext;
|
|
106
|
+
children: React_2.ReactNode;
|
|
107
|
+
isSegment?: boolean;
|
|
108
|
+
}): react_jsx_runtime.JSX.Element;
|
|
109
|
+
|
|
110
|
+
// @public
|
|
111
|
+
export type PageProps<TProps = {}> = TProps & {
|
|
112
|
+
head?: HeadData;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Warning: (ae-forgotten-export) The symbol "RenderReturnType" needs to be exported by the entry point index.d.ts
|
|
116
|
+
// Warning: (ae-forgotten-export) The symbol "ExtractComponentData" needs to be exported by the entry point index.d.ts
|
|
117
|
+
//
|
|
118
|
+
// @public
|
|
119
|
+
export function Render<T extends React_2.ComponentType<any>>(component: T, options?: RenderOptions): <TMethod extends (...args: any[]) => RenderReturnType<ExtractComponentData<T>> | Promise<RenderReturnType<ExtractComponentData<T>>>>(target: any, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<TMethod>) => TypedPropertyDescriptor<TMethod> | void;
|
|
120
|
+
|
|
121
|
+
// @public
|
|
122
|
+
export interface RenderConfig {
|
|
123
|
+
allowedCookies?: string[];
|
|
124
|
+
allowedHeaders?: string[];
|
|
125
|
+
defaultHead?: HeadData;
|
|
126
|
+
// Warning: (ae-forgotten-export) The symbol "ErrorPageDevelopmentProps$1" needs to be exported by the entry point index.d.ts
|
|
127
|
+
errorPageDevelopment?: ComponentType<ErrorPageDevelopmentProps$1>;
|
|
128
|
+
errorPageProduction?: ComponentType;
|
|
129
|
+
mode?: SSRMode;
|
|
130
|
+
template?: string;
|
|
131
|
+
timeout?: number;
|
|
132
|
+
// Warning: (ae-forgotten-export) The symbol "ViteConfig" needs to be exported by the entry point index.d.ts
|
|
133
|
+
vite?: ViteConfig;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// @public
|
|
137
|
+
export interface RenderContext {
|
|
138
|
+
// (undocumented)
|
|
139
|
+
method: string;
|
|
140
|
+
// (undocumented)
|
|
141
|
+
params: Record<string, string>;
|
|
142
|
+
// (undocumented)
|
|
143
|
+
path: string;
|
|
144
|
+
// (undocumented)
|
|
145
|
+
query: Record<string, string | string[]>;
|
|
146
|
+
// (undocumented)
|
|
147
|
+
url: string;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// @public (undocumented)
|
|
151
|
+
export class RenderInterceptor implements NestInterceptor {
|
|
152
|
+
constructor(reflector: Reflector, renderService: RenderService, allowedHeaders?: string[] | undefined, allowedCookies?: string[] | undefined);
|
|
153
|
+
// (undocumented)
|
|
154
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// @public (undocumented)
|
|
158
|
+
export class RenderModule {
|
|
159
|
+
static forRoot(config?: RenderConfig): DynamicModule;
|
|
160
|
+
static forRootAsync(options: {
|
|
161
|
+
imports?: any[];
|
|
162
|
+
inject?: any[];
|
|
163
|
+
useFactory: (...args: any[]) => Promise<RenderConfig> | RenderConfig;
|
|
164
|
+
}): DynamicModule;
|
|
165
|
+
// @deprecated (undocumented)
|
|
166
|
+
static register(config?: RenderConfig): DynamicModule;
|
|
167
|
+
// @deprecated (undocumented)
|
|
168
|
+
static registerAsync(options: {
|
|
169
|
+
imports?: any[];
|
|
170
|
+
inject?: any[];
|
|
171
|
+
useFactory: (...args: any[]) => Promise<RenderConfig> | RenderConfig;
|
|
172
|
+
}): DynamicModule;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// @public
|
|
176
|
+
export interface RenderOptions {
|
|
177
|
+
layout?: LayoutComponent<any> | false | null;
|
|
178
|
+
layoutProps?: Record<string, any>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// @public
|
|
182
|
+
export interface RenderResponse<T = any> {
|
|
183
|
+
head?: HeadData;
|
|
184
|
+
layoutProps?: Record<string, any>;
|
|
185
|
+
props: T;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// @public
|
|
189
|
+
export class RenderService {
|
|
190
|
+
// Warning: (ae-forgotten-export) The symbol "StringRenderer" needs to be exported by the entry point index.d.ts
|
|
191
|
+
// Warning: (ae-forgotten-export) The symbol "StreamRenderer" needs to be exported by the entry point index.d.ts
|
|
192
|
+
constructor(stringRenderer: StringRenderer, streamRenderer: StreamRenderer, ssrMode?: SSRMode, defaultHead?: HeadData | undefined, customTemplate?: string);
|
|
193
|
+
getRootLayout(): Promise<any | null>;
|
|
194
|
+
render(viewComponent: any, data?: any, res?: Response_2, head?: HeadData): Promise<string | void>;
|
|
195
|
+
// Warning: (ae-forgotten-export) The symbol "SegmentResponse" needs to be exported by the entry point index.d.ts
|
|
196
|
+
renderSegment(viewComponent: any, data: any, swapTarget: string, head?: HeadData): Promise<SegmentResponse>;
|
|
197
|
+
// (undocumented)
|
|
198
|
+
setViteServer(vite: ViteDevServer): void;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// @public
|
|
202
|
+
export type SSRMode = 'string' | 'stream';
|
|
203
|
+
|
|
204
|
+
// @public
|
|
205
|
+
export class StreamingErrorHandler {
|
|
206
|
+
constructor(errorPageDevelopment?: ComponentType<ErrorPageDevelopmentProps$1> | undefined, errorPageProduction?: ComponentType | undefined);
|
|
207
|
+
handleShellError(error: Error, res: Response_2, viewPath: string, isDevelopment: boolean): void;
|
|
208
|
+
handleStreamError(error: Error, viewPath: string): void;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// @public
|
|
212
|
+
export class TemplateParserService {
|
|
213
|
+
buildHeadTags(head?: HeadData): string;
|
|
214
|
+
buildInlineScripts(data: any, context: any, componentName: string, layouts?: Array<{
|
|
215
|
+
layout: any;
|
|
216
|
+
props?: any;
|
|
217
|
+
}>): string;
|
|
218
|
+
getClientScriptTag(isDevelopment: boolean, manifest?: any): string;
|
|
219
|
+
getStylesheetTags(isDevelopment: boolean, manifest?: any): string;
|
|
220
|
+
// Warning: (ae-forgotten-export) The symbol "TemplateParts" needs to be exported by the entry point index.d.ts
|
|
221
|
+
parseTemplate(html: string): TemplateParts;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// @public (undocumented)
|
|
225
|
+
export const useCookie: (name: string) => string | undefined;
|
|
226
|
+
|
|
227
|
+
// @public (undocumented)
|
|
228
|
+
export const useCookies: () => Record<string, string>;
|
|
229
|
+
|
|
230
|
+
// @public (undocumented)
|
|
231
|
+
export const useHeader: (name: string) => string | undefined;
|
|
232
|
+
|
|
233
|
+
// @public (undocumented)
|
|
234
|
+
export const useHeaders: () => Record<string, string>;
|
|
235
|
+
|
|
236
|
+
// @public (undocumented)
|
|
237
|
+
export const usePageContext: () => RenderContext;
|
|
238
|
+
|
|
239
|
+
// @public (undocumented)
|
|
240
|
+
export const useParams: () => Record<string, string>;
|
|
241
|
+
|
|
242
|
+
// @public (undocumented)
|
|
243
|
+
export const useQuery: () => Record<string, string | string[]>;
|
|
244
|
+
|
|
245
|
+
// @public (undocumented)
|
|
246
|
+
export const useRequest: () => RenderContext;
|
|
247
|
+
|
|
248
|
+
// (No @packageDocumentation comment for this package)
|
|
249
|
+
|
|
250
|
+
```
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="@nestjs-ssr/react/global" />
|
|
2
|
+
|
|
2
3
|
import React, { StrictMode } from 'react';
|
|
3
4
|
import { hydrateRoot } from 'react-dom/client';
|
|
4
5
|
import {
|
|
@@ -10,6 +11,15 @@ const componentName = window.__COMPONENT_NAME__;
|
|
|
10
11
|
const initialProps = window.__INITIAL_STATE__ || {};
|
|
11
12
|
const renderContext = window.__CONTEXT__ || {};
|
|
12
13
|
|
|
14
|
+
// Auto-discover root layout using Vite's glob import (must match server-side discovery)
|
|
15
|
+
// @ts-ignore - Vite-specific API
|
|
16
|
+
const layoutModules = import.meta.glob('@/views/layout.tsx', {
|
|
17
|
+
eager: true,
|
|
18
|
+
}) as Record<string, { default: React.ComponentType<any> }>;
|
|
19
|
+
|
|
20
|
+
const layoutPath = Object.keys(layoutModules)[0];
|
|
21
|
+
const RootLayout = layoutPath ? layoutModules[layoutPath].default : null;
|
|
22
|
+
|
|
13
23
|
// Auto-import all view components using Vite's glob feature
|
|
14
24
|
// Exclude entry-client.tsx and entry-server.tsx from the glob
|
|
15
25
|
// @ts-ignore - Vite-specific API
|
|
@@ -111,40 +121,53 @@ function hasLayout(
|
|
|
111
121
|
function composeWithLayout(
|
|
112
122
|
ViewComponent: React.ComponentType<any>,
|
|
113
123
|
props: any,
|
|
124
|
+
context?: any,
|
|
125
|
+
layouts: Array<{ layout: React.ComponentType<any>; props?: any }> = [],
|
|
114
126
|
): React.ReactElement {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
while (hasLayout(currentComponent)) {
|
|
130
|
-
layoutChain.push({
|
|
131
|
-
Layout: currentComponent.layout,
|
|
132
|
-
layoutProps: currentComponent.layoutProps || {},
|
|
133
|
-
});
|
|
134
|
-
currentComponent = currentComponent.layout;
|
|
127
|
+
// Start with the page component
|
|
128
|
+
let result = <ViewComponent {...props} />;
|
|
129
|
+
|
|
130
|
+
// If no layouts passed, check if component has its own layout chain
|
|
131
|
+
if (layouts.length === 0 && hasLayout(ViewComponent)) {
|
|
132
|
+
let currentComponent: any = ViewComponent;
|
|
133
|
+
while (hasLayout(currentComponent)) {
|
|
134
|
+
layouts.push({
|
|
135
|
+
layout: currentComponent.layout,
|
|
136
|
+
props: currentComponent.layoutProps || {},
|
|
137
|
+
});
|
|
138
|
+
currentComponent = currentComponent.layout;
|
|
139
|
+
}
|
|
135
140
|
}
|
|
136
141
|
|
|
137
|
-
// Wrap
|
|
138
|
-
|
|
139
|
-
for (const { Layout, layoutProps } of
|
|
140
|
-
|
|
142
|
+
// Wrap with each layout in the chain
|
|
143
|
+
// Must match server-side wrapping with data-layout and data-outlet attributes
|
|
144
|
+
for (const { layout: Layout, props: layoutProps } of layouts) {
|
|
145
|
+
const layoutName = Layout.displayName || Layout.name || 'Layout';
|
|
146
|
+
result = (
|
|
147
|
+
<div data-layout={layoutName}>
|
|
148
|
+
<Layout context={context} layoutProps={layoutProps}>
|
|
149
|
+
<div data-outlet={layoutName}>{result}</div>
|
|
150
|
+
</Layout>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
return result;
|
|
144
156
|
}
|
|
145
157
|
|
|
158
|
+
// Build layouts array - use RootLayout if it exists (matching server behavior)
|
|
159
|
+
const layouts: Array<{ layout: React.ComponentType<any>; props?: any }> = [];
|
|
160
|
+
if (RootLayout) {
|
|
161
|
+
layouts.push({ layout: RootLayout, props: {} });
|
|
162
|
+
}
|
|
163
|
+
|
|
146
164
|
// Compose the component with its layout (if any)
|
|
147
|
-
const composedElement = composeWithLayout(
|
|
165
|
+
const composedElement = composeWithLayout(
|
|
166
|
+
ViewComponent,
|
|
167
|
+
initialProps,
|
|
168
|
+
renderContext,
|
|
169
|
+
layouts,
|
|
170
|
+
);
|
|
148
171
|
|
|
149
172
|
// Wrap with providers to make context and navigation state available via hooks
|
|
150
173
|
const wrappedElement = (
|