@dr.pogodin/react-utils 1.25.5 → 1.26.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/babel.config.js +3 -1
- package/bin/build.js +25 -5
- package/build/development/client/getInj.js +9 -8
- package/build/development/client/getInj.js.map +1 -1
- package/build/development/client/index.js +6 -3
- package/build/development/client/index.js.map +1 -1
- package/build/development/client/init.js +4 -0
- package/build/development/client/init.js.map +1 -1
- package/build/development/index.js +168 -42
- package/build/development/index.js.map +1 -1
- package/build/development/server/Cache.js +13 -13
- package/build/development/server/Cache.js.map +1 -1
- package/build/development/server/index.js +16 -24
- package/build/development/server/index.js.map +1 -1
- package/build/development/server/renderer.js +56 -44
- package/build/development/server/renderer.js.map +1 -1
- package/build/development/server/server.js +9 -5
- package/build/development/server/server.js.map +1 -1
- package/build/development/server/utils/errors.js +12 -9
- package/build/development/server/utils/errors.js.map +1 -1
- package/build/development/server/utils/index.js +2 -2
- package/build/development/server/utils/index.js.map +1 -1
- package/build/development/shared/components/Button/index.js +8 -7
- package/build/development/shared/components/Button/index.js.map +1 -1
- package/build/development/shared/components/Checkbox/index.js +25 -28
- package/build/development/shared/components/Checkbox/index.js.map +1 -1
- package/build/development/shared/components/Dropdown/index.js +25 -19
- package/build/development/shared/components/Dropdown/index.js.map +1 -1
- package/build/development/shared/components/GenericLink/index.js +44 -37
- package/build/development/shared/components/GenericLink/index.js.map +1 -1
- package/build/development/shared/components/Input/index.js +8 -9
- package/build/development/shared/components/Input/index.js.map +1 -1
- package/build/development/shared/components/Link.js +10 -9
- package/build/development/shared/components/Link.js.map +1 -1
- package/build/development/shared/components/MetaTags.js +22 -18
- package/build/development/shared/components/MetaTags.js.map +1 -1
- package/build/development/shared/components/Modal/index.js +17 -18
- package/build/development/shared/components/Modal/index.js.map +1 -1
- package/build/development/shared/components/NavLink.js +10 -9
- package/build/development/shared/components/NavLink.js.map +1 -1
- package/build/development/shared/components/PageLayout/index.js +17 -20
- package/build/development/shared/components/PageLayout/index.js.map +1 -1
- package/build/development/shared/components/ScalableRect/index.js +27 -7
- package/build/development/shared/components/ScalableRect/index.js.map +1 -1
- package/build/development/shared/components/Throbber/index.js +14 -23
- package/build/development/shared/components/Throbber/index.js.map +1 -1
- package/build/development/shared/components/WithTooltip/Tooltip.js +20 -24
- package/build/development/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/development/shared/components/WithTooltip/index.js +11 -11
- package/build/development/shared/components/WithTooltip/index.js.map +1 -1
- package/build/development/shared/components/YouTubeVideo/index.js +16 -15
- package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
- package/build/development/shared/components/index.js +2 -2
- package/build/development/shared/components/index.js.map +1 -1
- package/build/development/shared/utils/config.js +1 -2
- package/build/development/shared/utils/config.js.map +1 -1
- package/build/development/shared/utils/globalState.js +15 -0
- package/build/development/shared/utils/globalState.js.map +1 -0
- package/build/development/shared/utils/index.js +13 -11
- package/build/development/shared/utils/index.js.map +1 -1
- package/build/development/shared/utils/isomorphy/buildInfo.js +7 -3
- package/build/development/shared/utils/isomorphy/buildInfo.js.map +1 -1
- package/build/development/shared/utils/isomorphy/environment-check.js +2 -4
- package/build/development/shared/utils/isomorphy/environment-check.js.map +1 -1
- package/build/development/shared/utils/isomorphy/index.js.map +1 -1
- package/build/development/shared/utils/jest/E2eSsrEnv.js +35 -28
- package/build/development/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/development/shared/utils/jest/global.js +17 -0
- package/build/development/shared/utils/jest/global.js.map +1 -0
- package/build/development/shared/utils/jest/index.js +18 -11
- package/build/development/shared/utils/jest/index.js.map +1 -1
- package/build/development/shared/utils/splitComponent.js +25 -34
- package/build/development/shared/utils/splitComponent.js.map +1 -1
- package/build/development/shared/utils/time.js +16 -13
- package/build/development/shared/utils/time.js.map +1 -1
- package/build/development/shared/utils/webpack.js +3 -3
- package/build/development/shared/utils/webpack.js.map +1 -1
- package/build/development/web.bundle.js +92 -82
- package/build/production/client/getInj.js +1 -1
- package/build/production/client/getInj.js.map +1 -1
- package/build/production/client/index.js +4 -4
- package/build/production/client/index.js.map +1 -1
- package/build/production/client/init.js +3 -1
- package/build/production/client/init.js.map +1 -1
- package/build/production/index.js +1 -1
- package/build/production/index.js.map +1 -1
- package/build/production/server/Cache.js +7 -8
- package/build/production/server/Cache.js.map +1 -1
- package/build/production/server/index.js +5 -4
- package/build/production/server/index.js.map +1 -1
- package/build/production/server/renderer.js +32 -30
- package/build/production/server/renderer.js.map +1 -1
- package/build/production/server/server.js +7 -5
- package/build/production/server/server.js.map +1 -1
- package/build/production/server/utils/errors.js +9 -10
- package/build/production/server/utils/errors.js.map +1 -1
- package/build/production/server/utils/index.js +1 -1
- package/build/production/server/utils/index.js.map +1 -1
- package/build/production/shared/components/Button/index.js +4 -4
- package/build/production/shared/components/Button/index.js.map +1 -1
- package/build/production/shared/components/Checkbox/index.js +12 -12
- package/build/production/shared/components/Checkbox/index.js.map +1 -1
- package/build/production/shared/components/Dropdown/index.js +11 -11
- package/build/production/shared/components/Dropdown/index.js.map +1 -1
- package/build/production/shared/components/GenericLink/index.js +25 -20
- package/build/production/shared/components/GenericLink/index.js.map +1 -1
- package/build/production/shared/components/Input/index.js +7 -7
- package/build/production/shared/components/Input/index.js.map +1 -1
- package/build/production/shared/components/Link.js +2 -2
- package/build/production/shared/components/Link.js.map +1 -1
- package/build/production/shared/components/MetaTags.js +10 -10
- package/build/production/shared/components/MetaTags.js.map +1 -1
- package/build/production/shared/components/Modal/index.js +2 -2
- package/build/production/shared/components/Modal/index.js.map +1 -1
- package/build/production/shared/components/NavLink.js +1 -1
- package/build/production/shared/components/NavLink.js.map +1 -1
- package/build/production/shared/components/PageLayout/index.js +2 -2
- package/build/production/shared/components/PageLayout/index.js.map +1 -1
- package/build/production/shared/components/ScalableRect/index.js +7 -3
- package/build/production/shared/components/ScalableRect/index.js.map +1 -1
- package/build/production/shared/components/Throbber/index.js +2 -2
- package/build/production/shared/components/Throbber/index.js.map +1 -1
- package/build/production/shared/components/WithTooltip/Tooltip.js +13 -13
- package/build/production/shared/components/WithTooltip/Tooltip.js.map +1 -1
- package/build/production/shared/components/WithTooltip/index.js +3 -3
- package/build/production/shared/components/WithTooltip/index.js.map +1 -1
- package/build/production/shared/components/YouTubeVideo/index.js +7 -7
- package/build/production/shared/components/YouTubeVideo/index.js.map +1 -1
- package/build/production/shared/components/index.js +1 -1
- package/build/production/shared/components/index.js.map +1 -1
- package/build/production/shared/utils/config.js +1 -1
- package/build/production/shared/utils/config.js.map +1 -1
- package/build/production/shared/utils/globalState.js +3 -0
- package/build/production/shared/utils/globalState.js.map +1 -0
- package/build/production/shared/utils/index.js +3 -3
- package/build/production/shared/utils/index.js.map +1 -1
- package/build/production/shared/utils/isomorphy/buildInfo.js +7 -4
- package/build/production/shared/utils/isomorphy/buildInfo.js.map +1 -1
- package/build/production/shared/utils/isomorphy/environment-check.js +2 -2
- package/build/production/shared/utils/isomorphy/environment-check.js.map +1 -1
- package/build/production/shared/utils/isomorphy/index.js.map +1 -1
- package/build/production/shared/utils/jest/E2eSsrEnv.js +9 -9
- package/build/production/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/production/shared/utils/jest/global.js +2 -0
- package/build/production/shared/utils/jest/global.js.map +1 -0
- package/build/production/shared/utils/jest/index.js +6 -6
- package/build/production/shared/utils/jest/index.js.map +1 -1
- package/build/production/shared/utils/splitComponent.js +16 -16
- package/build/production/shared/utils/splitComponent.js.map +1 -1
- package/build/production/shared/utils/time.js +12 -8
- package/build/production/shared/utils/time.js.map +1 -1
- package/build/production/shared/utils/webpack.js +3 -3
- package/build/production/shared/utils/webpack.js.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/client/getInj.d.ts +3 -0
- package/build/types-code/client/index.d.ts +11 -0
- package/build/types-code/client/init.d.ts +9 -0
- package/build/types-code/index.d.ts +10 -0
- package/build/types-code/server/Cache.d.ts +37 -0
- package/build/types-code/server/index.d.ts +145 -0
- package/build/types-code/server/renderer.d.ts +106 -0
- package/build/types-code/server/server.d.ts +41 -0
- package/build/types-code/server/utils/errors.d.ts +104 -0
- package/build/types-code/server/utils/index.d.ts +1 -0
- package/build/types-code/shared/components/Button/index.d.ts +27 -0
- package/build/types-code/shared/components/Checkbox/index.d.ts +21 -0
- package/build/types-code/shared/components/Dropdown/index.d.ts +23 -0
- package/build/types-code/shared/components/GenericLink/index.d.ts +61 -0
- package/build/types-code/shared/components/Input/index.d.ts +11 -0
- package/build/types-code/shared/components/Link.d.ts +12 -0
- package/build/types-code/shared/components/MetaTags.d.ts +68 -0
- package/build/types-code/shared/components/Modal/index.d.ts +26 -0
- package/build/types-code/shared/components/NavLink.d.ts +5 -0
- package/build/types-code/shared/components/PageLayout/index.d.ts +16 -0
- package/build/types-code/shared/components/ScalableRect/index.d.ts +19 -0
- package/build/types-code/shared/components/Throbber/index.d.ts +9 -0
- package/build/types-code/shared/components/WithTooltip/Tooltip.d.ts +23 -0
- package/build/types-code/shared/components/WithTooltip/index.d.ts +17 -0
- package/build/types-code/shared/components/YouTubeVideo/index.d.ts +13 -0
- package/build/types-code/shared/components/index.d.ts +16 -0
- package/build/types-code/shared/utils/config.d.ts +2 -0
- package/build/types-code/shared/utils/globalState.d.ts +20 -0
- package/build/types-code/shared/utils/index.d.ts +52 -0
- package/build/types-code/shared/utils/isomorphy/buildInfo.d.ts +23 -0
- package/build/types-code/shared/utils/isomorphy/environment-check.d.ts +11 -0
- package/build/types-code/shared/utils/isomorphy/index.d.ts +20 -0
- package/build/types-code/shared/utils/jest/E2eSsrEnv.d.ts +31 -0
- package/build/types-code/shared/utils/jest/global.d.ts +12 -0
- package/build/types-code/shared/utils/jest/index.d.ts +85 -0
- package/build/types-code/shared/utils/splitComponent.d.ts +41 -0
- package/build/types-code/shared/utils/time.d.ts +62 -0
- package/build/types-code/shared/utils/webpack.d.ts +18 -0
- package/build/types-scss/__tests__/js/config/publicPath support/__assets__/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/config/stylename-generation/__assets__/MockPackageA/TestComponent/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/config/stylename-generation/__assets__/MockPackageB/TestComponent/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/config/stylename-generation/__assets__/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/shared/components/NavLink/styles.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/shared/utils/splitComponent/__assets__/SampleScene/ComponentA/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/shared/utils/splitComponent/__assets__/SampleScene/ComponentB/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/shared/utils/splitComponent/__assets__/SampleScene/ComponentC/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/js/shared/utils/splitComponent/__assets__/SampleScene/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/config/publicPath support/__assets__/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/config/stylename-generation/__assets__/MockPackageA/TestComponent/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/config/stylename-generation/__assets__/MockPackageB/TestComponent/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/config/stylename-generation/__assets__/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/shared/components/NavLink/styles.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/shared/utils/splitComponent/__assets__/SampleScene/ComponentA/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/shared/utils/splitComponent/__assets__/SampleScene/ComponentB/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/shared/utils/splitComponent/__assets__/SampleScene/ComponentC/style.scss.d.ts +1 -0
- package/build/types-scss/__tests__/ts/shared/utils/splitComponent/__assets__/SampleScene/style.scss.d.ts +1 -0
- package/build/types-scss/src/shared/components/Button/style.scss.d.ts +6 -0
- package/build/types-scss/src/shared/components/Checkbox/theme.scss.d.ts +6 -0
- package/build/types-scss/src/shared/components/Dropdown/theme.scss.d.ts +9 -0
- package/build/types-scss/src/shared/components/GenericLink/style.scss.d.ts +1 -0
- package/build/types-scss/src/shared/components/Input/theme.scss.d.ts +6 -0
- package/build/types-scss/src/shared/components/Modal/base-theme.scss.d.ts +5 -0
- package/build/types-scss/src/shared/components/PageLayout/base-theme.scss.d.ts +6 -0
- package/build/types-scss/src/shared/components/ScalableRect/style.scss.d.ts +2 -0
- package/build/types-scss/src/shared/components/Throbber/theme.scss.d.ts +6 -0
- package/build/types-scss/src/shared/components/WithTooltip/default-theme.scss.d.ts +7 -0
- package/build/types-scss/src/shared/components/YouTubeVideo/base.scss.d.ts +5 -0
- package/build/types-scss/src/shared/components/YouTubeVideo/throbber.scss.d.ts +4 -0
- package/config/eslint/jest.json +3 -2
- package/config/eslint/typescript.js +34 -0
- package/config/jest/default.js +3 -3
- package/package.json +75 -33
- package/src/client/getInj.ts +43 -0
- package/src/client/index.tsx +40 -0
- package/src/client/init.ts +47 -0
- package/src/index.ts +58 -0
- package/src/server/Cache.ts +68 -0
- package/src/server/index.ts +230 -0
- package/src/server/renderer.tsx +604 -0
- package/src/server/server.ts +309 -0
- package/src/server/utils/errors.ts +135 -0
- package/src/server/utils/index.ts +3 -0
- package/src/shared/components/Button/index.tsx +146 -0
- package/src/shared/components/Button/style.scss +53 -0
- package/src/shared/components/Checkbox/index.tsx +71 -0
- package/src/shared/components/Checkbox/theme.scss +43 -0
- package/src/shared/components/Dropdown/index.tsx +144 -0
- package/src/shared/components/Dropdown/theme.scss +63 -0
- package/src/shared/components/GenericLink/index.tsx +157 -0
- package/src/shared/components/GenericLink/style.scss +3 -0
- package/src/shared/components/Input/index.tsx +59 -0
- package/src/shared/components/Input/theme.scss +27 -0
- package/src/shared/components/Link.tsx +21 -0
- package/src/shared/components/MetaTags.tsx +170 -0
- package/src/shared/components/Modal/base-theme.scss +38 -0
- package/src/shared/components/Modal/index.tsx +144 -0
- package/src/shared/components/Modal/styles.scss +5 -0
- package/src/shared/components/NavLink.tsx +13 -0
- package/src/shared/components/PageLayout/base-theme.scss +30 -0
- package/src/shared/components/PageLayout/index.tsx +76 -0
- package/src/shared/components/ScalableRect/index.tsx +84 -0
- package/src/shared/components/ScalableRect/style.scss +10 -0
- package/src/shared/components/Throbber/index.tsx +43 -0
- package/src/shared/components/Throbber/theme.scss +26 -0
- package/src/shared/components/WithTooltip/Tooltip.tsx +353 -0
- package/src/shared/components/WithTooltip/default-theme.scss +36 -0
- package/src/shared/components/WithTooltip/index.tsx +204 -0
- package/src/shared/components/YouTubeVideo/base.scss +13 -0
- package/src/shared/components/YouTubeVideo/index.tsx +96 -0
- package/src/shared/components/YouTubeVideo/throbber.scss +11 -0
- package/src/shared/components/index.ts +17 -0
- package/src/shared/utils/config.ts +21 -0
- package/src/shared/utils/globalState.ts +29 -0
- package/src/shared/utils/index.ts +105 -0
- package/src/shared/utils/isomorphy/buildInfo.ts +54 -0
- package/src/shared/utils/isomorphy/environment-check.ts +18 -0
- package/src/shared/utils/isomorphy/index.ts +38 -0
- package/src/shared/utils/jest/E2eSsrEnv.ts +250 -0
- package/src/shared/utils/jest/global.ts +19 -0
- package/src/shared/utils/jest/index.tsx +157 -0
- package/src/shared/utils/splitComponent.tsx +255 -0
- package/src/shared/utils/time.ts +118 -0
- package/src/shared/utils/webpack.ts +45 -0
- package/src/styles/_global/reset.css +52 -0
- package/src/styles/global.scss +11 -0
- package/tsconfig.configs.json +18 -0
- package/tsconfig.json +27 -0
- package/tsconfig.types.json +53 -0
- package/typed-scss-modules.config.ts +9 -0
- package/types.d.ts +37 -0
- package/{webpack.config.js → webpack.config.ts} +7 -3
- package/config/babel/node-ssr.js +0 -85
- package/config/babel/webpack.js +0 -122
- package/config/webpack/app-base.js +0 -330
- package/config/webpack/app-development.js +0 -80
- package/config/webpack/app-production.js +0 -60
- package/config/webpack/lib-base.js +0 -155
- package/config/webpack/lib-development.js +0 -45
- package/config/webpack/lib-production.js +0 -44
|
@@ -4,10 +4,13 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
exports.default = launchServer;
|
|
8
|
+
Object.defineProperty(exports, "errors", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () {
|
|
11
|
+
return _utils.errors;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
11
14
|
Object.defineProperty(exports, "getDefaultCspSettings", {
|
|
12
15
|
enumerable: true,
|
|
13
16
|
get: function () {
|
|
@@ -19,29 +22,18 @@ var _http = _interopRequireDefault(require("http"));
|
|
|
19
22
|
var _https = _interopRequireDefault(require("https"));
|
|
20
23
|
var _lodash = require("lodash");
|
|
21
24
|
require("raf/polyfill");
|
|
25
|
+
require("webpack");
|
|
22
26
|
var _server = _interopRequireWildcard(require("./server"));
|
|
23
27
|
var _renderer = require("./renderer");
|
|
24
28
|
var _utils = require("./utils");
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
28
|
-
if (key in exports && exports[key] === _utils[key]) return;
|
|
29
|
-
Object.defineProperty(exports, key, {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
get: function () {
|
|
32
|
-
return _utils[key];
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
37
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
30
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
38
31
|
/* Polyfill required by ReactJS. */
|
|
39
32
|
|
|
40
33
|
/**
|
|
41
34
|
* Normalizes a port into a number, string, or false.
|
|
42
35
|
* TODO: Drop this function?
|
|
43
|
-
* @
|
|
44
|
-
* @param {String} value Port name or number.
|
|
36
|
+
* @param value Port name or number.
|
|
45
37
|
* @return Port number (Number), name (String), or false.
|
|
46
38
|
*/
|
|
47
39
|
function normalizePort(value) {
|
|
@@ -50,7 +42,6 @@ function normalizePort(value) {
|
|
|
50
42
|
if (!(0, _lodash.isNumber)(port)) return value; /* named pipe */
|
|
51
43
|
return false;
|
|
52
44
|
}
|
|
53
|
-
|
|
54
45
|
/**
|
|
55
46
|
* Creates and launches web-server for ReactJS application. Allows zero
|
|
56
47
|
* or detailed configuration, supports server-side rendering,
|
|
@@ -170,13 +161,16 @@ function normalizePort(value) {
|
|
|
170
161
|
* @return {Promise<{ expressServer: object, httpServer: object }>} Resolves to
|
|
171
162
|
* an object with created Express and HTTP servers.
|
|
172
163
|
*/
|
|
173
|
-
async function
|
|
164
|
+
async function launchServer(webpackConfig, options) {
|
|
174
165
|
/* Options normalization. */
|
|
175
166
|
const ops = options ? (0, _lodash.cloneDeep)(options) : {};
|
|
176
167
|
ops.port = normalizePort(ops.port || process.env.PORT || 3000);
|
|
177
168
|
(0, _lodash.defaults)(ops, {
|
|
178
169
|
httpsRedirect: true
|
|
179
170
|
});
|
|
171
|
+
|
|
172
|
+
// TODO: Need a separate type for normalized options, which guarantees
|
|
173
|
+
// the logger is set!
|
|
180
174
|
if (ops.logger === undefined) {
|
|
181
175
|
ops.logger = (0, _renderer.newDefaultLogger)({
|
|
182
176
|
defaultLogLevel: ops.defaultLoggerLogLevel
|
|
@@ -223,7 +217,5 @@ async function launch(webpackConfig, options) {
|
|
|
223
217
|
httpServer
|
|
224
218
|
};
|
|
225
219
|
}
|
|
226
|
-
|
|
227
|
-
var _default = launch;
|
|
228
|
-
exports.default = _default;
|
|
220
|
+
launchServer.SCRIPT_LOCATIONS = _renderer.SCRIPT_LOCATIONS;
|
|
229
221
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["require","_http","_interopRequireDefault","_https","_lodash","_server","_interopRequireWildcard","_renderer","_utils","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","newObj","hasPropertyDescriptor","getOwnPropertyDescriptor","desc","set","normalizePort","value","port","toNumber","isFinite","isNumber","launch","webpackConfig","options","ops","cloneDeep","process","env","PORT","defaults","httpsRedirect","logger","undefined","newDefaultLogger","defaultLogLevel","defaultLoggerLogLevel","expressServer","serverFactory","httpServer","https","createServer","cert","http","on","error","syscall","bind","isString","code","exit","addr","address","info","NODE_ENV","listen","SCRIPT_LOCATIONS","_default"],"sources":["../../../src/server/index.js"],"sourcesContent":["import 'source-map-support/register';\n\nimport http from 'http';\nimport https from 'https';\n\nimport {\n cloneDeep,\n defaults,\n isFinite,\n isNumber,\n isString,\n toNumber,\n} from 'lodash';\n\n/* Polyfill required by ReactJS. */\nimport 'raf/polyfill';\n\nimport serverFactory from './server';\nimport { SCRIPT_LOCATIONS, newDefaultLogger } from './renderer';\n\nexport { getDefaultCspSettings } from './server';\nexport * from './utils';\n\n/**\n * Normalizes a port into a number, string, or false.\n * TODO: Drop this function?\n * @ignore\n * @param {String} value Port name or number.\n * @return Port number (Number), name (String), or false.\n */\nfunction normalizePort(value) {\n const port = toNumber(value);\n if (isFinite(port)) return port; /* port number */\n if (!isNumber(port)) return value; /* named pipe */\n return false;\n}\n\n/**\n * Creates and launches web-server for ReactJS application. Allows zero\n * or detailed configuration, supports server-side rendering,\n * and development tools, including Hot Module Reloading (HMR).\n *\n * NOTE: Many of options defined below are passed down to the server and\n * renderer factories, and their declared default values are set in those\n * factories, rather than here.\n *\n * @param {object} webpackConfig Webpack configuration used to build\n * the frontend bundle. In production mode the server will read out of it\n * `context`, `publicPath`, and a few other parameters, necessary to locate\n * and serve the app bundle. In development mode the server will use entire\n * provided config to build the app bundle in memory, and further watch and\n * update it via HMR.\n * @param {object} [options] Additional parameters.\n * @param {Component} [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param {function} [options.beforeExpressJsError] Asynchronous callback\n * (`(server) => Promise<boolean>`) to be executed just before the default error\n * handler is added to ExpressJS server. If the callback is provided and its\n * result resolves to a truthy value, `react-utils` won't attach the default\n * error handler.\n * @param {function} [options.beforeExpressJsSetup] Asynchronous callback\n * (`(server) => Promise) to be executed right after ExpressJS server creation,\n * before any configuration is performed.\n * @param {BeforeRenderHook} [options.beforeRender] The hook to run just before\n * the server-side rendering. For each incoming request, it will be executed\n * just before the HTML markup is generated at the server. It allows to load\n * and provide the data necessary for server-side rendering, and also to inject\n * additional configuration and scripts into the generated HTML code.\n * @param {boolean} [options.noCsp] Set `true` to disable\n * Content-Security-Policy (CSP) headers altogether.\n * @param {function} [options.cspSettingsHook] A hook allowing\n * to customize [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n * settings for [helmet](https://github.com/helmetjs/helmet)'s\n * `contentSecurityPolicy` middleware on per-request basis.\n *\n * If provided it should be a with signature: \\\n * `(defaultSettings: object, req: object)` ⇒ `object` \\\n * which gets the default settings (also used without the hook),\n * and the incoming request object. The hook response will be passed\n * as options to the helmet `contentSecurityPolicy` middleware.\n *\n * Currently, the default settings is the following object in production\n * environment:\n * ```js\n * {\n * directives: {\n * defaultSrc: [\"'self'\"],\n * baseUri: [\"'self'\"],\n * blockAllMixedContent: [],\n * fontSrc: [\"'self'\", 'https:', 'data:'],\n * frameAncestors: [\"'self'\"],\n * frameSrc: [\"'self'\", 'https://*.youtube.com'],\n * imgSrc: [\"'self'\", 'data:'],\n * objectSrc: [\"'none'\"],\n * scriptSrc: [\"'self'\", \"'unsafe-eval'\", `'nonce-UNIQUE_NONCE_VALUE'`],\n * scriptSrcAttr: [\"'none'\"],\n * styleSrc: [\"'self'\", 'https:', \"'unsafe-inline'\"],\n * upgradeInsecureRequests: [] // Removed in dev mode.\n * }\n * }\n * ```\n * It matches the default value used by Helmet with a few updates:\n * - YouTube host is whitelisted in the `frameSrc` directive to ensure\n * the {@link YouTubeVideo} component works.\n * - An unique per-request nonce is added to `scriptSrc` directive to\n * whitelist auxiliary scripts injected by react-utils. The actual nonce\n * value can be fetched by host code via `.nonce` field of `req` argument\n * of `.beforeRender` hook.\n * - `upgradeInsecureRequests` directive is removed in development mode,\n * to simplify local testing with http requests.\n * @param {string} [options.defaultLoggerLogLevel='info'] Log level for\n * the default logger, which is created if no `logger` option provided.\n * @param {boolean} [options.devMode] Pass in `true` to start the server in\n * development mode.\n * @param {string} [options.favicon] Path to the favicon to use by the server.\n * By default no favicon is used.\n * @param {object} [options.https] If provided, HTTPS server will be started,\n * instead of HTTP otherwise. The object should provide SSL certificate and key\n * via two string fields: `cert`, and `key`.\n * @param {string} [options.https.cert] SSL Certificate.\n * @param {string} [options.https.key] SSL key.\n * @param {boolean} [options.httpsRedirect=true] Pass in `true` to enable\n * automatic redirection of all incoming HTTP requests to HTTPS.\n *\n * To smoothly use it at `localhost` you need to run the server in HTTPS mode,\n * and also properly create and install a self-signed SSL sertificate on your\n * system. This article is helpful:\n * [How to get HTTPS working on your local development environment in 5 minutes](https://medium.freecodecamp.org/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec)\n * @param {Logger} [options.logger] The logger to use at server side.\n * By default [`winston`](https://www.npmjs.com/package/winston) logger\n * with console transport is used. The logger you provide, or the default\n * `winston` logger otherwise, will be attached to the created ExpressJS server\n * object.\n * @param {function} [options.onExpressJsSetup] An async callback\n * (`(server) => Promise`) to be triggered when most of the server\n * configuration is completed, just before the server-side renderer,\n * and the default error handler are attached. You can use it to mount\n * custom API routes. The server-side logger can be accessed as `server.logger`.\n * @param {number|string} [options.port=3000] The port to start the server on.\n * @param {number} [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param {function} [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` – the cache key for the response;\n * - `maxage?: number` – the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @param {number} [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param {number} [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @return {Promise<{ expressServer: object, httpServer: object }>} Resolves to\n * an object with created Express and HTTP servers.\n */\nasync function launch(webpackConfig, options) {\n /* Options normalization. */\n const ops = options ? cloneDeep(options) : {};\n ops.port = normalizePort(ops.port || process.env.PORT || 3000);\n defaults(ops, { httpsRedirect: true });\n\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n /* Creates servers, resolves and sets the port. */\n const expressServer = await serverFactory(webpackConfig, ops);\n\n let httpServer;\n if (ops.https) {\n httpServer = https.createServer({\n cert: ops.https.cert,\n key: ops.https.key,\n }, expressServer);\n } else httpServer = http.createServer(expressServer);\n\n /* Sets error handler for HTTP(S) server. */\n httpServer.on('error', (error) => {\n if (error.syscall !== 'listen') throw error;\n const bind = isString(ops.port) ? `Pipe ${ops.port}` : `Port ${ops.port}`;\n\n /* Human-readable message for some specific listen errors. */\n switch (error.code) {\n case 'EACCES':\n ops.logger.error(`${bind} requires elevated privileges`);\n return process.exit(1);\n case 'EADDRINUSE':\n ops.logger.error(`${bind} is already in use`);\n return process.exit(1);\n default:\n throw error;\n }\n });\n\n /* Listening event handler for HTTP(S) server. */\n httpServer.on('listening', () => {\n const addr = httpServer.address();\n const bind = isString(addr) ? `pipe ${addr}` : `port ${addr.port}`;\n ops.logger.info(`Server listening on ${bind} in ${\n process.env.NODE_ENV} mode`);\n });\n\n httpServer.listen(ops.port);\n\n return {\n expressServer,\n httpServer,\n };\n}\n\nlaunch.SCRIPT_LOCATIONS = SCRIPT_LOCATIONS;\n\nexport default launch;\n"],"mappings":";;;;;;;;;;;;;;;;AAAAA,OAAA;AAEA,IAAAC,KAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,MAAA,GAAAD,sBAAA,CAAAF,OAAA;AAEA,IAAAI,OAAA,GAAAJ,OAAA;AAUAA,OAAA;AAEA,IAAAK,OAAA,GAAAC,uBAAA,CAAAN,OAAA;AACA,IAAAO,SAAA,GAAAP,OAAA;AAGA,IAAAQ,MAAA,GAAAR,OAAA;AAAAS,MAAA,CAAAC,IAAA,CAAAF,MAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,MAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,MAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAAwB,SAAAS,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAhB,wBAAAoB,GAAA,EAAAJ,WAAA,SAAAA,WAAA,IAAAI,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,oBAAAA,GAAA,wBAAAA,GAAA,4BAAAE,OAAA,EAAAF,GAAA,UAAAG,KAAA,GAAAR,wBAAA,CAAAC,WAAA,OAAAO,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAJ,GAAA,YAAAG,KAAA,CAAAT,GAAA,CAAAM,GAAA,SAAAK,MAAA,WAAAC,qBAAA,GAAAvB,MAAA,CAAAS,cAAA,IAAAT,MAAA,CAAAwB,wBAAA,WAAArB,GAAA,IAAAc,GAAA,QAAAd,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAW,GAAA,EAAAd,GAAA,SAAAsB,IAAA,GAAAF,qBAAA,GAAAvB,MAAA,CAAAwB,wBAAA,CAAAP,GAAA,EAAAd,GAAA,cAAAsB,IAAA,KAAAA,IAAA,CAAAd,GAAA,IAAAc,IAAA,CAAAC,GAAA,KAAA1B,MAAA,CAAAS,cAAA,CAAAa,MAAA,EAAAnB,GAAA,EAAAsB,IAAA,YAAAH,MAAA,CAAAnB,GAAA,IAAAc,GAAA,CAAAd,GAAA,SAAAmB,MAAA,CAAAH,OAAA,GAAAF,GAAA,MAAAG,KAAA,IAAAA,KAAA,CAAAM,GAAA,CAAAT,GAAA,EAAAK,MAAA,YAAAA,MAAA;AAPxB;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASK,aAAaA,CAACC,KAAK,EAAE;EAC5B,MAAMC,IAAI,GAAG,IAAAC,gBAAQ,EAACF,KAAK,CAAC;EAC5B,IAAI,IAAAG,gBAAQ,EAACF,IAAI,CAAC,EAAE,OAAOA,IAAI,CAAC,CAAC;EACjC,IAAI,CAAC,IAAAG,gBAAQ,EAACH,IAAI,CAAC,EAAE,OAAOD,KAAK,CAAC,CAAC;EACnC,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeK,MAAMA,CAACC,aAAa,EAAEC,OAAO,EAAE;EAC5C;EACA,MAAMC,GAAG,GAAGD,OAAO,GAAG,IAAAE,iBAAS,EAACF,OAAO,CAAC,GAAG,CAAC,CAAC;EAC7CC,GAAG,CAACP,IAAI,GAAGF,aAAa,CAACS,GAAG,CAACP,IAAI,IAAIS,OAAO,CAACC,GAAG,CAACC,IAAI,IAAI,IAAI,CAAC;EAC9D,IAAAC,gBAAQ,EAACL,GAAG,EAAE;IAAEM,aAAa,EAAE;EAAK,CAAC,CAAC;EAEtC,IAAIN,GAAG,CAACO,MAAM,KAAKC,SAAS,EAAE;IAC5BR,GAAG,CAACO,MAAM,GAAG,IAAAE,0BAAgB,EAAC;MAC5BC,eAAe,EAAEV,GAAG,CAACW;IACvB,CAAC,CAAC;EACJ;;EAEA;EACA,MAAMC,aAAa,GAAG,MAAM,IAAAC,eAAa,EAACf,aAAa,EAAEE,GAAG,CAAC;EAE7D,IAAIc,UAAU;EACd,IAAId,GAAG,CAACe,KAAK,EAAE;IACbD,UAAU,GAAGC,cAAK,CAACC,YAAY,CAAC;MAC9BC,IAAI,EAAEjB,GAAG,CAACe,KAAK,CAACE,IAAI;MACpBlD,GAAG,EAAEiC,GAAG,CAACe,KAAK,CAAChD;IACjB,CAAC,EAAE6C,aAAa,CAAC;EACnB,CAAC,MAAME,UAAU,GAAGI,aAAI,CAACF,YAAY,CAACJ,aAAa,CAAC;;EAEpD;EACAE,UAAU,CAACK,EAAE,CAAC,OAAO,EAAGC,KAAK,IAAK;IAChC,IAAIA,KAAK,CAACC,OAAO,KAAK,QAAQ,EAAE,MAAMD,KAAK;IAC3C,MAAME,IAAI,GAAG,IAAAC,gBAAQ,EAACvB,GAAG,CAACP,IAAI,CAAC,GAAI,QAAOO,GAAG,CAACP,IAAK,EAAC,GAAI,QAAOO,GAAG,CAACP,IAAK,EAAC;;IAEzE;IACA,QAAQ2B,KAAK,CAACI,IAAI;MAChB,KAAK,QAAQ;QACXxB,GAAG,CAACO,MAAM,CAACa,KAAK,CAAE,GAAEE,IAAK,+BAA8B,CAAC;QACxD,OAAOpB,OAAO,CAACuB,IAAI,CAAC,CAAC,CAAC;MACxB,KAAK,YAAY;QACfzB,GAAG,CAACO,MAAM,CAACa,KAAK,CAAE,GAAEE,IAAK,oBAAmB,CAAC;QAC7C,OAAOpB,OAAO,CAACuB,IAAI,CAAC,CAAC,CAAC;MACxB;QACE,MAAML,KAAK;IACf;EACF,CAAC,CAAC;;EAEF;EACAN,UAAU,CAACK,EAAE,CAAC,WAAW,EAAE,MAAM;IAC/B,MAAMO,IAAI,GAAGZ,UAAU,CAACa,OAAO,CAAC,CAAC;IACjC,MAAML,IAAI,GAAG,IAAAC,gBAAQ,EAACG,IAAI,CAAC,GAAI,QAAOA,IAAK,EAAC,GAAI,QAAOA,IAAI,CAACjC,IAAK,EAAC;IAClEO,GAAG,CAACO,MAAM,CAACqB,IAAI,CAAE,uBAAsBN,IAAK,OAC1CpB,OAAO,CAACC,GAAG,CAAC0B,QAAS,OAAM,CAAC;EAChC,CAAC,CAAC;EAEFf,UAAU,CAACgB,MAAM,CAAC9B,GAAG,CAACP,IAAI,CAAC;EAE3B,OAAO;IACLmB,aAAa;IACbE;EACF,CAAC;AACH;AAEAjB,MAAM,CAACkC,gBAAgB,GAAGA,0BAAgB;AAAC,IAAAC,QAAA,GAE5BnC,MAAM;AAAAzB,OAAA,CAAAW,OAAA,GAAAiD,QAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["require","_http","_interopRequireDefault","_https","_lodash","_server","_interopRequireWildcard","_renderer","_utils","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","normalizePort","value","port","toNumber","isFinite","isNumber","launchServer","webpackConfig","options","ops","cloneDeep","process","env","PORT","defaults","httpsRedirect","logger","undefined","newDefaultLogger","defaultLogLevel","defaultLoggerLogLevel","expressServer","serverFactory","httpServer","https","createServer","cert","key","http","on","error","syscall","bind","isString","code","exit","addr","address","info","NODE_ENV","listen","SCRIPT_LOCATIONS"],"sources":["../../../src/server/index.ts"],"sourcesContent":["import 'source-map-support/register';\n\nimport http from 'http';\nimport https from 'https';\n\nimport {\n cloneDeep,\n defaults,\n isFinite,\n isNumber,\n isString,\n toNumber,\n} from 'lodash';\n\n/* Polyfill required by ReactJS. */\nimport 'raf/polyfill';\n\nimport { type Configuration } from 'webpack';\n\nimport serverFactory, { type OptionsT as ServerOptionsT } from './server';\nimport { SCRIPT_LOCATIONS, newDefaultLogger } from './renderer';\n\nexport {\n getDefaultCspSettings,\n} from './server';\n\nexport { errors } from './utils';\n\n/**\n * Normalizes a port into a number, string, or false.\n * TODO: Drop this function?\n * @param value Port name or number.\n * @return Port number (Number), name (String), or false.\n */\nfunction normalizePort(value: number | string) {\n const port = toNumber(value);\n if (isFinite(port)) return port; /* port number */\n if (!isNumber(port)) return value; /* named pipe */\n return false;\n}\n\ntype OptionsT = ServerOptionsT & {\n https?: {\n cert: string;\n key: string;\n },\n\n // TODO: Should we limit it to number | string, and throw if it is different value?\n port?: false | number | string;\n};\n\n/**\n * Creates and launches web-server for ReactJS application. Allows zero\n * or detailed configuration, supports server-side rendering,\n * and development tools, including Hot Module Reloading (HMR).\n *\n * NOTE: Many of options defined below are passed down to the server and\n * renderer factories, and their declared default values are set in those\n * factories, rather than here.\n *\n * @param {object} webpackConfig Webpack configuration used to build\n * the frontend bundle. In production mode the server will read out of it\n * `context`, `publicPath`, and a few other parameters, necessary to locate\n * and serve the app bundle. In development mode the server will use entire\n * provided config to build the app bundle in memory, and further watch and\n * update it via HMR.\n * @param {object} [options] Additional parameters.\n * @param {Component} [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param {function} [options.beforeExpressJsError] Asynchronous callback\n * (`(server) => Promise<boolean>`) to be executed just before the default error\n * handler is added to ExpressJS server. If the callback is provided and its\n * result resolves to a truthy value, `react-utils` won't attach the default\n * error handler.\n * @param {function} [options.beforeExpressJsSetup] Asynchronous callback\n * (`(server) => Promise) to be executed right after ExpressJS server creation,\n * before any configuration is performed.\n * @param {BeforeRenderHook} [options.beforeRender] The hook to run just before\n * the server-side rendering. For each incoming request, it will be executed\n * just before the HTML markup is generated at the server. It allows to load\n * and provide the data necessary for server-side rendering, and also to inject\n * additional configuration and scripts into the generated HTML code.\n * @param {boolean} [options.noCsp] Set `true` to disable\n * Content-Security-Policy (CSP) headers altogether.\n * @param {function} [options.cspSettingsHook] A hook allowing\n * to customize [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n * settings for [helmet](https://github.com/helmetjs/helmet)'s\n * `contentSecurityPolicy` middleware on per-request basis.\n *\n * If provided it should be a with signature: \\\n * `(defaultSettings: object, req: object)` ⇒ `object` \\\n * which gets the default settings (also used without the hook),\n * and the incoming request object. The hook response will be passed\n * as options to the helmet `contentSecurityPolicy` middleware.\n *\n * Currently, the default settings is the following object in production\n * environment:\n * ```js\n * {\n * directives: {\n * defaultSrc: [\"'self'\"],\n * baseUri: [\"'self'\"],\n * blockAllMixedContent: [],\n * fontSrc: [\"'self'\", 'https:', 'data:'],\n * frameAncestors: [\"'self'\"],\n * frameSrc: [\"'self'\", 'https://*.youtube.com'],\n * imgSrc: [\"'self'\", 'data:'],\n * objectSrc: [\"'none'\"],\n * scriptSrc: [\"'self'\", \"'unsafe-eval'\", `'nonce-UNIQUE_NONCE_VALUE'`],\n * scriptSrcAttr: [\"'none'\"],\n * styleSrc: [\"'self'\", 'https:', \"'unsafe-inline'\"],\n * upgradeInsecureRequests: [] // Removed in dev mode.\n * }\n * }\n * ```\n * It matches the default value used by Helmet with a few updates:\n * - YouTube host is whitelisted in the `frameSrc` directive to ensure\n * the {@link YouTubeVideo} component works.\n * - An unique per-request nonce is added to `scriptSrc` directive to\n * whitelist auxiliary scripts injected by react-utils. The actual nonce\n * value can be fetched by host code via `.nonce` field of `req` argument\n * of `.beforeRender` hook.\n * - `upgradeInsecureRequests` directive is removed in development mode,\n * to simplify local testing with http requests.\n * @param {string} [options.defaultLoggerLogLevel='info'] Log level for\n * the default logger, which is created if no `logger` option provided.\n * @param {boolean} [options.devMode] Pass in `true` to start the server in\n * development mode.\n * @param {string} [options.favicon] Path to the favicon to use by the server.\n * By default no favicon is used.\n * @param {object} [options.https] If provided, HTTPS server will be started,\n * instead of HTTP otherwise. The object should provide SSL certificate and key\n * via two string fields: `cert`, and `key`.\n * @param {string} [options.https.cert] SSL Certificate.\n * @param {string} [options.https.key] SSL key.\n * @param {boolean} [options.httpsRedirect=true] Pass in `true` to enable\n * automatic redirection of all incoming HTTP requests to HTTPS.\n *\n * To smoothly use it at `localhost` you need to run the server in HTTPS mode,\n * and also properly create and install a self-signed SSL sertificate on your\n * system. This article is helpful:\n * [How to get HTTPS working on your local development environment in 5 minutes](https://medium.freecodecamp.org/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec)\n * @param {Logger} [options.logger] The logger to use at server side.\n * By default [`winston`](https://www.npmjs.com/package/winston) logger\n * with console transport is used. The logger you provide, or the default\n * `winston` logger otherwise, will be attached to the created ExpressJS server\n * object.\n * @param {function} [options.onExpressJsSetup] An async callback\n * (`(server) => Promise`) to be triggered when most of the server\n * configuration is completed, just before the server-side renderer,\n * and the default error handler are attached. You can use it to mount\n * custom API routes. The server-side logger can be accessed as `server.logger`.\n * @param {number|string} [options.port=3000] The port to start the server on.\n * @param {number} [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param {function} [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` – the cache key for the response;\n * - `maxage?: number` – the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @param {number} [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param {number} [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @return {Promise<{ expressServer: object, httpServer: object }>} Resolves to\n * an object with created Express and HTTP servers.\n */\nexport default async function launchServer(webpackConfig: Configuration, options: OptionsT) {\n /* Options normalization. */\n const ops = options ? cloneDeep(options) : {};\n ops.port = normalizePort(ops.port || process.env.PORT || 3000);\n defaults(ops, { httpsRedirect: true });\n\n // TODO: Need a separate type for normalized options, which guarantees\n // the logger is set!\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n /* Creates servers, resolves and sets the port. */\n const expressServer = await serverFactory(webpackConfig, ops);\n\n let httpServer: http.Server;\n if (ops.https) {\n httpServer = https.createServer({\n cert: ops.https.cert,\n key: ops.https.key,\n }, expressServer);\n } else httpServer = http.createServer(expressServer);\n\n /* Sets error handler for HTTP(S) server. */\n httpServer.on('error', (error: Error) => {\n if ((error as any).syscall !== 'listen') throw error;\n const bind = isString(ops.port) ? `Pipe ${ops.port}` : `Port ${ops.port}`;\n\n /* Human-readable message for some specific listen errors. */\n switch ((error as any).code) {\n case 'EACCES':\n ops.logger!.error(`${bind} requires elevated privileges`);\n return process.exit(1);\n case 'EADDRINUSE':\n ops.logger!.error(`${bind} is already in use`);\n return process.exit(1);\n default:\n throw error;\n }\n });\n\n /* Listening event handler for HTTP(S) server. */\n httpServer.on('listening', () => {\n const addr = httpServer.address()!;\n const bind = isString(addr) ? `pipe ${addr}` : `port ${addr.port}`;\n ops.logger!.info(`Server listening on ${bind} in ${\n process.env.NODE_ENV} mode`);\n });\n\n httpServer.listen(ops.port);\n\n return {\n expressServer,\n httpServer,\n };\n}\n\nlaunchServer.SCRIPT_LOCATIONS = SCRIPT_LOCATIONS;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAAA,OAAA;AAEA,IAAAC,KAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,MAAA,GAAAD,sBAAA,CAAAF,OAAA;AAEA,IAAAI,OAAA,GAAAJ,OAAA;AAUAA,OAAA;AAEAA,OAAA;AAEA,IAAAK,OAAA,GAAAC,uBAAA,CAAAN,OAAA;AACA,IAAAO,SAAA,GAAAP,OAAA;AAMA,IAAAQ,MAAA,GAAAR,OAAA;AAAiC,SAAAS,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAJ,wBAAAI,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAK,OAAA,EAAAL,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAG,GAAA,CAAAN,CAAA,UAAAG,CAAA,CAAAI,GAAA,CAAAP,CAAA,OAAAQ,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,CAAA,IAAAd,CAAA,oBAAAc,CAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAc,CAAA,SAAAI,CAAA,GAAAR,CAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAb,CAAA,EAAAc,CAAA,UAAAI,CAAA,KAAAA,CAAA,CAAAX,GAAA,IAAAW,CAAA,CAAAC,GAAA,IAAAR,MAAA,CAAAC,cAAA,CAAAJ,CAAA,EAAAM,CAAA,EAAAI,CAAA,IAAAV,CAAA,CAAAM,CAAA,IAAAd,CAAA,CAAAc,CAAA,YAAAN,CAAA,CAAAH,OAAA,GAAAL,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAgB,GAAA,CAAAnB,CAAA,EAAAQ,CAAA,GAAAA,CAAA;AAZjC;;AAcA;AACA;AACA;AACA;AACA;AACA;AACA,SAASY,aAAaA,CAACC,KAAsB,EAAE;EAC7C,MAAMC,IAAI,GAAG,IAAAC,gBAAQ,EAACF,KAAK,CAAC;EAC5B,IAAI,IAAAG,gBAAQ,EAACF,IAAI,CAAC,EAAE,OAAOA,IAAI,CAAC,CAAC;EACjC,IAAI,CAAC,IAAAG,gBAAQ,EAACH,IAAI,CAAC,EAAE,OAAOD,KAAK,CAAC,CAAC;EACnC,OAAO,KAAK;AACd;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,eAAeK,YAAYA,CAACC,aAA4B,EAAEC,OAAiB,EAAE;EAC1F;EACA,MAAMC,GAAG,GAAGD,OAAO,GAAG,IAAAE,iBAAS,EAACF,OAAO,CAAC,GAAG,CAAC,CAAC;EAC7CC,GAAG,CAACP,IAAI,GAAGF,aAAa,CAACS,GAAG,CAACP,IAAI,IAAIS,OAAO,CAACC,GAAG,CAACC,IAAI,IAAI,IAAI,CAAC;EAC9D,IAAAC,gBAAQ,EAACL,GAAG,EAAE;IAAEM,aAAa,EAAE;EAAK,CAAC,CAAC;;EAEtC;EACA;EACA,IAAIN,GAAG,CAACO,MAAM,KAAKC,SAAS,EAAE;IAC5BR,GAAG,CAACO,MAAM,GAAG,IAAAE,0BAAgB,EAAC;MAC5BC,eAAe,EAAEV,GAAG,CAACW;IACvB,CAAC,CAAC;EACJ;;EAEA;EACA,MAAMC,aAAa,GAAG,MAAM,IAAAC,eAAa,EAACf,aAAa,EAAEE,GAAG,CAAC;EAE7D,IAAIc,UAAuB;EAC3B,IAAId,GAAG,CAACe,KAAK,EAAE;IACbD,UAAU,GAAGC,cAAK,CAACC,YAAY,CAAC;MAC9BC,IAAI,EAAEjB,GAAG,CAACe,KAAK,CAACE,IAAI;MACpBC,GAAG,EAAElB,GAAG,CAACe,KAAK,CAACG;IACjB,CAAC,EAAEN,aAAa,CAAC;EACnB,CAAC,MAAME,UAAU,GAAGK,aAAI,CAACH,YAAY,CAACJ,aAAa,CAAC;;EAEpD;EACAE,UAAU,CAACM,EAAE,CAAC,OAAO,EAAGC,KAAY,IAAK;IACvC,IAAKA,KAAK,CAASC,OAAO,KAAK,QAAQ,EAAE,MAAMD,KAAK;IACpD,MAAME,IAAI,GAAG,IAAAC,gBAAQ,EAACxB,GAAG,CAACP,IAAI,CAAC,GAAI,QAAOO,GAAG,CAACP,IAAK,EAAC,GAAI,QAAOO,GAAG,CAACP,IAAK,EAAC;;IAEzE;IACA,QAAS4B,KAAK,CAASI,IAAI;MACzB,KAAK,QAAQ;QACXzB,GAAG,CAACO,MAAM,CAAEc,KAAK,CAAE,GAAEE,IAAK,+BAA8B,CAAC;QACzD,OAAOrB,OAAO,CAACwB,IAAI,CAAC,CAAC,CAAC;MACxB,KAAK,YAAY;QACf1B,GAAG,CAACO,MAAM,CAAEc,KAAK,CAAE,GAAEE,IAAK,oBAAmB,CAAC;QAC9C,OAAOrB,OAAO,CAACwB,IAAI,CAAC,CAAC,CAAC;MACxB;QACE,MAAML,KAAK;IACf;EACF,CAAC,CAAC;;EAEF;EACAP,UAAU,CAACM,EAAE,CAAC,WAAW,EAAE,MAAM;IAC/B,MAAMO,IAAI,GAAGb,UAAU,CAACc,OAAO,CAAC,CAAE;IAClC,MAAML,IAAI,GAAG,IAAAC,gBAAQ,EAACG,IAAI,CAAC,GAAI,QAAOA,IAAK,EAAC,GAAI,QAAOA,IAAI,CAAClC,IAAK,EAAC;IAClEO,GAAG,CAACO,MAAM,CAAEsB,IAAI,CAAE,uBAAsBN,IAAK,OAC3CrB,OAAO,CAACC,GAAG,CAAC2B,QAAS,OAAM,CAAC;EAChC,CAAC,CAAC;EAEFhB,UAAU,CAACiB,MAAM,CAAC/B,GAAG,CAACP,IAAI,CAAC;EAE3B,OAAO;IACLmB,aAAa;IACbE;EACF,CAAC;AACH;AAEAjB,YAAY,CAACmC,gBAAgB,GAAGA,0BAAgB"}
|
|
@@ -10,6 +10,8 @@ exports.isBrotliAcceptable = isBrotliAcceptable;
|
|
|
10
10
|
exports.newDefaultLogger = newDefaultLogger;
|
|
11
11
|
var _fs = _interopRequireDefault(require("fs"));
|
|
12
12
|
var _path = _interopRequireDefault(require("path"));
|
|
13
|
+
require("express");
|
|
14
|
+
require("react");
|
|
13
15
|
var _stream = require("stream");
|
|
14
16
|
var _zlib = require("zlib");
|
|
15
17
|
var _winston = _interopRequireDefault(require("winston"));
|
|
@@ -23,6 +25,8 @@ var _reactHelmet = require("react-helmet");
|
|
|
23
25
|
var _server2 = require("react-router-dom/server");
|
|
24
26
|
var _serializeJavascript = _interopRequireDefault(require("serialize-javascript"));
|
|
25
27
|
var _buildInfo = require("../shared/utils/isomorphy/buildInfo");
|
|
28
|
+
require("../shared/utils/globalState");
|
|
29
|
+
require("webpack");
|
|
26
30
|
var _Cache = _interopRequireDefault(require("./Cache"));
|
|
27
31
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
28
32
|
/**
|
|
@@ -30,26 +34,38 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
30
34
|
*/
|
|
31
35
|
|
|
32
36
|
const sanitizedConfig = (0, _lodash.omit)(_config.default, 'SECRET');
|
|
33
|
-
const SCRIPT_LOCATIONS = {
|
|
34
|
-
BODY_OPEN: 'BODY_OPEN',
|
|
35
|
-
DEFAULT: 'DEFAULT',
|
|
36
|
-
HEAD_OPEN: 'HEAD_OPEN'
|
|
37
|
-
};
|
|
38
37
|
|
|
38
|
+
// Note: These type definitions for logger are copied from Winston logger,
|
|
39
|
+
// then simplified to make it easier to fit an alternative logger into this
|
|
40
|
+
// interface.
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
42
|
+
let SCRIPT_LOCATIONS = exports.SCRIPT_LOCATIONS = /*#__PURE__*/function (SCRIPT_LOCATIONS) {
|
|
43
|
+
SCRIPT_LOCATIONS["BODY_OPEN"] = "BODY_OPEN";
|
|
44
|
+
SCRIPT_LOCATIONS["DEFAULT"] = "DEFAULT";
|
|
45
|
+
SCRIPT_LOCATIONS["HEAD_OPEN"] = "HEAD_OPEN";
|
|
46
|
+
return SCRIPT_LOCATIONS;
|
|
47
|
+
}({});
|
|
48
|
+
class ServerSsrContext extends _reactGlobalState.SsrContext {
|
|
49
|
+
chunks = [];
|
|
50
|
+
status = 200;
|
|
51
|
+
constructor(req, chunkGroups, initialState) {
|
|
52
|
+
super((0, _lodash.cloneDeep)(initialState) || {});
|
|
53
|
+
this.chunkGroups = chunkGroups;
|
|
54
|
+
this.req = req;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
39
57
|
/**
|
|
40
58
|
* Reads build-time information about the app. This information is generated
|
|
41
59
|
* by our standard Webpack config for apps, and it is written into
|
|
42
60
|
* ".build-info" file in the context folder specified in Webpack config.
|
|
43
61
|
* At the moment, that file contains build timestamp and a random 32-bit key,
|
|
44
62
|
* suitable for cryptographical use.
|
|
45
|
-
* @
|
|
46
|
-
* @
|
|
47
|
-
* @return {Object} Resolves to the build-time information.
|
|
63
|
+
* @param context Webpack context path used during the build.
|
|
64
|
+
* @return Resolves to the build-time information.
|
|
48
65
|
*/
|
|
49
|
-
exports.SCRIPT_LOCATIONS = SCRIPT_LOCATIONS;
|
|
50
66
|
function getBuildInfo(context) {
|
|
51
67
|
const url = _path.default.resolve(context, '.build-info');
|
|
52
|
-
return JSON.parse(_fs.default.readFileSync(url));
|
|
68
|
+
return JSON.parse(_fs.default.readFileSync(url, 'utf8'));
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
/**
|
|
@@ -57,15 +73,14 @@ function getBuildInfo(context) {
|
|
|
57
73
|
* by Webpack during the compilation.
|
|
58
74
|
* It will not work for development builds, where these stats should be captured
|
|
59
75
|
* via compilator callback.
|
|
60
|
-
* @
|
|
61
|
-
* @
|
|
62
|
-
* @return {object}
|
|
76
|
+
* @param buildDir
|
|
77
|
+
* @return
|
|
63
78
|
*/
|
|
64
79
|
function readChunkGroupsJson(buildDir) {
|
|
65
80
|
const url = _path.default.resolve(buildDir, '__chunk_groups__.json');
|
|
66
81
|
let res;
|
|
67
82
|
try {
|
|
68
|
-
res = JSON.parse(_fs.default.readFileSync(url));
|
|
83
|
+
res = JSON.parse(_fs.default.readFileSync(url, 'utf8'));
|
|
69
84
|
} catch (err) {
|
|
70
85
|
res = null;
|
|
71
86
|
}
|
|
@@ -74,10 +89,9 @@ function readChunkGroupsJson(buildDir) {
|
|
|
74
89
|
|
|
75
90
|
/**
|
|
76
91
|
* Prepares a new Cipher for data encryption.
|
|
77
|
-
* @
|
|
78
|
-
* @param {String} key Encryption key (32-bit random key is expected, see
|
|
92
|
+
* @param key Encryption key (32-bit random key is expected, see
|
|
79
93
|
* node-forge documentation, in case of doubts).
|
|
80
|
-
* @return
|
|
94
|
+
* @return Resolves to the object with two fields:
|
|
81
95
|
* 1. cipher - a new Cipher, ready for encryption;
|
|
82
96
|
* 2. iv - initial vector used by the cipher.
|
|
83
97
|
*/
|
|
@@ -184,29 +198,28 @@ function newDefaultLogger({
|
|
|
184
198
|
transports: [new transports.Console()]
|
|
185
199
|
});
|
|
186
200
|
}
|
|
187
|
-
|
|
188
201
|
/**
|
|
189
202
|
* Creates the middleware.
|
|
190
|
-
* @param
|
|
191
|
-
* @param
|
|
192
|
-
* @param
|
|
203
|
+
* @param webpackConfig
|
|
204
|
+
* @param options Additional options:
|
|
205
|
+
* @param [options.Application] The root ReactJS component of
|
|
193
206
|
* the app to use for the server-side rendering. When not provided
|
|
194
207
|
* the server-side rendering is disabled.
|
|
195
|
-
* @param
|
|
208
|
+
* @param [options.buildInfo] "Build info" object to use. If provided,
|
|
196
209
|
* it will be used, instead of trying to load from the filesystem the one
|
|
197
210
|
* generated by the Webpack build. It is intended for test environments,
|
|
198
211
|
* where passing this stuff via file system is no bueno.
|
|
199
|
-
* @param
|
|
212
|
+
* @param [options.favicon] `true` will include favicon
|
|
200
213
|
* link into the rendered HTML templates.
|
|
201
|
-
* @param
|
|
214
|
+
* @param [options.noCsp] `true` means that no
|
|
202
215
|
* Content-Security-Policy (CSP) is used by server, thus the renderer
|
|
203
216
|
* may cut a few corners.
|
|
204
|
-
* @param
|
|
205
|
-
* @param
|
|
217
|
+
* @param [options.maxSsrRounds=10] Maximum number of SSR rounds.
|
|
218
|
+
* @param [options.ssrTimeout=1000] SSR timeout in milliseconds,
|
|
206
219
|
* defaults to 1 second.
|
|
207
|
-
* @param
|
|
220
|
+
* @param [options.staticCacheSize=1.e7] The maximum
|
|
208
221
|
* static cache size in bytes. Defaults to ~10 MB.
|
|
209
|
-
* @param
|
|
222
|
+
* @param [options.staticCacheController] When given, it activates,
|
|
210
223
|
* and controls the static caching of generated HTML markup. When this function
|
|
211
224
|
* is provided, on each incoming request it is triggered with the request
|
|
212
225
|
* passed in as the argument. To attempt to serve the response from the cache
|
|
@@ -214,7 +227,7 @@ function newDefaultLogger({
|
|
|
214
227
|
* - `key: string` – the cache key for the response;
|
|
215
228
|
* - `maxage?: number` – the maximum age of cached result in ms.
|
|
216
229
|
* If undefined - infinite age is assumed.
|
|
217
|
-
* @return
|
|
230
|
+
* @return Created middleware.
|
|
218
231
|
*/
|
|
219
232
|
function factory(webpackConfig, options) {
|
|
220
233
|
const ops = (0, _lodash.defaults)((0, _lodash.clone)(options), {
|
|
@@ -312,17 +325,16 @@ function factory(webpackConfig, options) {
|
|
|
312
325
|
} else if (CHUNK_GROUPS) chunkGroups = CHUNK_GROUPS;else chunkGroups = {};
|
|
313
326
|
|
|
314
327
|
/* Optional server-side rendering. */
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
state: (0, _lodash.cloneDeep)(initialState || {}),
|
|
319
|
-
// Array of chunk names encountered during the rendering.
|
|
320
|
-
chunks: [],
|
|
321
|
-
chunkGroups
|
|
322
|
-
};
|
|
328
|
+
const App = ops.Application;
|
|
329
|
+
let appHtmlMarkup = '';
|
|
330
|
+
const ssrContext = new ServerSsrContext(req, chunkGroups, initialState);
|
|
323
331
|
let stream;
|
|
324
332
|
if (App) {
|
|
325
333
|
const ssrStart = Date.now();
|
|
334
|
+
|
|
335
|
+
// TODO: Somehow, without it TS does not realise that
|
|
336
|
+
// App has been checked to exist.
|
|
337
|
+
const App2 = App;
|
|
326
338
|
const renderPass = async () => {
|
|
327
339
|
ssrContext.chunks = [];
|
|
328
340
|
return new Promise((resolve, reject) => {
|
|
@@ -331,7 +343,7 @@ function factory(webpackConfig, options) {
|
|
|
331
343
|
ssrContext: ssrContext,
|
|
332
344
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_server2.StaticRouter, {
|
|
333
345
|
location: req.url,
|
|
334
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
346
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(App2, {})
|
|
335
347
|
})
|
|
336
348
|
}), {
|
|
337
349
|
onAllReady: () => resolve(pipeableStream),
|
|
@@ -362,10 +374,9 @@ function factory(webpackConfig, options) {
|
|
|
362
374
|
logMsg = bailed ? `SSR timed out after ${ops.ssrTimeout} second(s)` : `SSR bailed out after ${ops.maxSsrRounds} round(s)`;
|
|
363
375
|
} else logMsg = `SSR completed in ${ssrRound + 1} round(s)`;
|
|
364
376
|
ops.logger.log(ssrContext.dirty ? 'warn' : 'info', logMsg);
|
|
365
|
-
App = '';
|
|
366
377
|
stream.pipe(new _stream.Writable({
|
|
367
378
|
write: (chunk, _, done) => {
|
|
368
|
-
|
|
379
|
+
appHtmlMarkup += chunk.toString();
|
|
369
380
|
done();
|
|
370
381
|
}
|
|
371
382
|
}));
|
|
@@ -438,7 +449,7 @@ function factory(webpackConfig, options) {
|
|
|
438
449
|
</head>
|
|
439
450
|
<body>
|
|
440
451
|
${grouppedExtraScripts[SCRIPT_LOCATIONS.BODY_OPEN]}
|
|
441
|
-
<div id="react-view">${
|
|
452
|
+
<div id="react-view">${appHtmlMarkup}</div>
|
|
442
453
|
${scriptChunkString}
|
|
443
454
|
${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}
|
|
444
455
|
</body>
|
|
@@ -450,12 +461,13 @@ function factory(webpackConfig, options) {
|
|
|
450
461
|
// but it greately simplifies testing, and error reporting.
|
|
451
462
|
await new Promise((done, failed) => {
|
|
452
463
|
(0, _zlib.brotliCompress)(html, (error, buffer) => {
|
|
464
|
+
const b = buffer;
|
|
453
465
|
if (error) failed(error);else {
|
|
454
|
-
|
|
466
|
+
b.nonce = req.nonce; // eslint-disable-line no-param-reassign
|
|
455
467
|
cache.add({
|
|
456
|
-
buffer,
|
|
468
|
+
buffer: b,
|
|
457
469
|
status
|
|
458
|
-
}, cacheRef.key);
|
|
470
|
+
}, cacheRef.key, buffer.length);
|
|
459
471
|
done();
|
|
460
472
|
}
|
|
461
473
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.js","names":["_fs","_interopRequireDefault","require","_path","_stream","_zlib","_winston","_reactGlobalState","_jsUtils","_lodash","_config","_nodeForge","_server","_reactHelmet","_server2","_serializeJavascript","_buildInfo","_Cache","_jsxRuntime","sanitizedConfig","omit","config","SCRIPT_LOCATIONS","BODY_OPEN","DEFAULT","HEAD_OPEN","exports","getBuildInfo","context","url","path","resolve","JSON","parse","fs","readFileSync","readChunkGroupsJson","buildDir","res","err","prepareCipher","key","Promise","reject","forge","random","getBytes","iv","cipher","createCipher","start","isBrotliAcceptable","req","acceptable","get","ops","split","i","length","type","priority","trim","parseFloat","groupExtraScripts","scripts","script","isString","code","location","undefined","Error","newDefaultLogger","defaultLogLevel","format","transports","winston","createLogger","level","combine","splat","timestamp","colorize","printf","message","stack","rest","Object","keys","stringify","Console","factory","webpackConfig","options","defaults","clone","beforeRender","maxSsrRounds","ssrTimeout","staticCacheSize","logger","defaultLoggerLogLevel","buildInfo","setBuildInfo","publicPath","outputPath","output","manifestLink","existsSync","cache","staticCacheController","Cache","CHUNK_GROUPS","next","set","cookie","csrfToken","cacheRef","data","buffer","status","noCsp","send","done","failed","brotliDecompress","error","html","h","toString","regex","RegExp","nonce","replace","configToInject","extraScripts","initialState","all","helmet","chunkGroups","webpackStats","locals","mapValues","toJson","namedChunkGroups","item","assets","map","name","App","Application","ssrContext","state","cloneDeep","chunks","stream","ssrStart","Date","now","renderPass","pipeableStream","renderToPipeableStream","jsx","GlobalStateProvider","children","StaticRouter","onAllReady","onError","ssrRound","bailed","dirty","timeout","race","allSettled","pending","timer","then","logMsg","log","pipe","Writable","write","chunk","_","Helmet","renderStatic","payload","serializeJs","CONFIG","ISTATE","ignoreFunction","unsafe","update","util","createBuffer","finish","INJ","encode64","chunkSet","Set","forEach","asset","add","styleChunkString","scriptChunkString","endsWith","grouppedExtraScripts","faviconLink","favicon","title","meta","brotliCompress"],"sources":["../../../src/server/renderer.jsx"],"sourcesContent":["/**\n * ExpressJS middleware for server-side rendering of a ReactJS app.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { Writable } from 'stream';\nimport { brotliCompress, brotliDecompress } from 'zlib';\nimport winston from 'winston';\n\nimport { GlobalStateProvider } from '@dr.pogodin/react-global-state';\nimport { timer } from '@dr.pogodin/js-utils';\n\nimport {\n clone,\n cloneDeep,\n defaults,\n isString,\n get,\n mapValues,\n omit,\n} from 'lodash';\n\nimport config from 'config';\nimport forge from 'node-forge';\n\nimport { renderToPipeableStream } from 'react-dom/server';\nimport { Helmet } from 'react-helmet';\nimport { StaticRouter } from 'react-router-dom/server';\nimport serializeJs from 'serialize-javascript';\nimport { setBuildInfo } from 'utils/isomorphy/buildInfo';\n\nimport Cache from './Cache';\n\nconst sanitizedConfig = omit(config, 'SECRET');\n\nexport const SCRIPT_LOCATIONS = {\n BODY_OPEN: 'BODY_OPEN',\n DEFAULT: 'DEFAULT',\n HEAD_OPEN: 'HEAD_OPEN',\n};\n\n/**\n * Reads build-time information about the app. This information is generated\n * by our standard Webpack config for apps, and it is written into\n * \".build-info\" file in the context folder specified in Webpack config.\n * At the moment, that file contains build timestamp and a random 32-bit key,\n * suitable for cryptographical use.\n * @ignore\n * @param {String} context Webpack context path used during the build.\n * @return {Object} Resolves to the build-time information.\n */\nfunction getBuildInfo(context) {\n const url = path.resolve(context, '.build-info');\n return JSON.parse(fs.readFileSync(url));\n}\n\n/**\n * Attempts to read from disk the named chunk groups mapping generated\n * by Webpack during the compilation.\n * It will not work for development builds, where these stats should be captured\n * via compilator callback.\n * @ignore\n * @param {string} buildDir\n * @return {object}\n */\nfunction readChunkGroupsJson(buildDir) {\n const url = path.resolve(buildDir, '__chunk_groups__.json');\n let res;\n try {\n res = JSON.parse(fs.readFileSync(url));\n } catch (err) {\n res = null;\n }\n return res;\n}\n\n/**\n * Prepares a new Cipher for data encryption.\n * @ignore\n * @param {String} key Encryption key (32-bit random key is expected, see\n * node-forge documentation, in case of doubts).\n * @return {Promise} Resolves to the object with two fields:\n * 1. cipher - a new Cipher, ready for encryption;\n * 2. iv - initial vector used by the cipher.\n */\nfunction prepareCipher(key) {\n return new Promise((resolve, reject) => {\n forge.random.getBytes(32, (err, iv) => {\n if (err) reject(err);\n else {\n const cipher = forge.cipher.createCipher('AES-CBC', key);\n cipher.start({ iv });\n resolve({ cipher, iv });\n }\n });\n });\n}\n\n/**\n * Given an incoming HTTP requests, it deduces whether Brotli-encoded responses\n * are acceptable to the caller.\n * @param {object} req\n * @return {boolean}\n * @ignore\n */\nexport function isBrotliAcceptable(req) {\n const acceptable = req.get('accept-encoding');\n if (acceptable) {\n const ops = acceptable.split(',');\n for (let i = 0; i < ops.length; ++i) {\n const [type, priority] = ops[i].trim().split(';q=');\n if ((type === '*' || type === 'br')\n && (!priority || parseFloat(priority) > 0)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Given an array of extra script strings / objects, it returns an object with\n * arrays of scripts to inject in different HTML template locations. During\n * the script groupping it also filters out any empty scripts.\n * @param {({\n * code: string;\n * location: string;\n * }|string)[]} [scripts=[]]\n * @return {{\n * BODY_OPEN: string[];\n * DEFAULT: string[];\n * HEAD_OPEN: string[];\n * }}\n */\nfunction groupExtraScripts(scripts = []) {\n const res = {\n [SCRIPT_LOCATIONS.BODY_OPEN]: '',\n [SCRIPT_LOCATIONS.DEFAULT]: '',\n [SCRIPT_LOCATIONS.HEAD_OPEN]: '',\n };\n for (let i = 0; i < scripts.length; ++i) {\n const script = scripts[i];\n if (isString(script)) {\n if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;\n } else if (script.code) {\n if (res[script.location] !== undefined) {\n res[script.location] += script.code;\n } else throw Error(`Invalid location \"${script.location}\"`);\n }\n }\n return res;\n}\n\n/**\n * Creates a new default (Winston) logger.\n * @param {object} [options={}]\n * @param {string} [options.defaultLogLevel='info']\n * @return {object}\n */\nexport function newDefaultLogger({\n defaultLogLevel = 'info',\n} = {}) {\n const { format, transports } = winston;\n return winston.createLogger({\n level: defaultLogLevel,\n format: format.combine(\n format.splat(),\n format.timestamp(),\n format.colorize(),\n format.printf(\n ({\n level,\n message,\n timestamp,\n stack,\n ...rest\n }) => {\n let res = `${level}\\t(at ${timestamp}):\\t${message}`;\n if (Object.keys(rest).length) {\n res += `\\n${JSON.stringify(rest, null, 2)}`;\n }\n if (stack) res += `\\n${stack}`;\n return res;\n },\n ),\n ),\n transports: [new transports.Console()],\n });\n}\n\n/**\n * Creates the middleware.\n * @param {object} webpackConfig\n * @param {object} options Additional options:\n * @param {Component} [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param {object} [options.buildInfo] \"Build info\" object to use. If provided,\n * it will be used, instead of trying to load from the filesystem the one\n * generated by the Webpack build. It is intended for test environments,\n * where passing this stuff via file system is no bueno.\n * @param {boolean} [options.favicon] `true` will include favicon\n * link into the rendered HTML templates.\n * @param {boolean} [options.noCsp] `true` means that no\n * Content-Security-Policy (CSP) is used by server, thus the renderer\n * may cut a few corners.\n * @param {number} [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param {number} [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @param {number} [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param {function} [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` – the cache key for the response;\n * - `maxage?: number` – the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @return {function} Created middleware.\n */\nexport default function factory(webpackConfig, options) {\n const ops = defaults(clone(options), {\n beforeRender: () => Promise.resolve({}),\n maxSsrRounds: 10,\n ssrTimeout: 1000,\n staticCacheSize: 1.e7,\n });\n\n // Note: in normal use the default logger is created and set in the root\n // server function, and this initialization is for testing uses, where\n // renderer is imported directly.\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n const buildInfo = ops.buildInfo || getBuildInfo(webpackConfig.context);\n setBuildInfo(buildInfo);\n\n // publicPath from webpack.output has a trailing slash at the end.\n const { publicPath, path: outputPath } = webpackConfig.output;\n\n const manifestLink = fs.existsSync(`${outputPath}/manifest.json`)\n ? `<link rel=\"manifest\" href=\"${publicPath}manifest.json\">` : '';\n\n const cache = ops.staticCacheController\n ? new Cache(ops.staticCacheSize) : null;\n\n const CHUNK_GROUPS = readChunkGroupsJson(outputPath);\n\n return async (req, res, next) => {\n try {\n // Ensures any caches always revalidate HTML markup before reuse.\n res.set('Cache-Control', 'no-cache');\n\n res.cookie('csrfToken', req.csrfToken());\n\n let cacheRef;\n if (cache) {\n cacheRef = ops.staticCacheController(req);\n if (cacheRef) {\n const data = cache.get(cacheRef);\n if (data !== null) {\n const { buffer, status } = data;\n if (ops.noCsp && isBrotliAcceptable(req)) {\n res.set('Content-Type', 'text/html');\n res.set('Content-Encoding', 'br');\n if (status !== 200) res.status(status);\n res.send(buffer);\n } else {\n await new Promise((done, failed) => {\n brotliDecompress(buffer, (error, html) => {\n if (error) failed(error);\n else {\n let h = html.toString();\n if (!ops.noCsp) {\n // TODO: Starting from Node v15 we'll be able to use string's\n // .replaceAll() method instead relying on reg. expression for\n // global matching.\n const regex = new RegExp(buffer.nonce, 'g');\n h = h.replace(regex, req.nonce);\n }\n if (status !== 200) res.status(status);\n res.send(h);\n done();\n }\n });\n });\n }\n return;\n }\n }\n }\n\n const [{\n configToInject,\n extraScripts,\n initialState,\n }, {\n cipher,\n iv,\n }] = await Promise.all([\n ops.beforeRender(req, sanitizedConfig),\n prepareCipher(buildInfo.key),\n ]);\n\n let helmet;\n\n // Gets the mapping between code chunk names and their asset files.\n // These data come from the Webpack compilation, either from the stats\n // attached to the request (in dev mode), or from a file output during\n // the build (in prod mode).\n let chunkGroups;\n const webpackStats = get(res.locals, 'webpack.devMiddleware.stats');\n if (webpackStats) {\n chunkGroups = mapValues(\n webpackStats.toJson({\n all: false,\n chunkGroups: true,\n }).namedChunkGroups,\n (item) => item.assets.map(({ name }) => name),\n );\n } else if (CHUNK_GROUPS) chunkGroups = CHUNK_GROUPS;\n else chunkGroups = {};\n\n /* Optional server-side rendering. */\n let App = ops.Application;\n const ssrContext = {\n req,\n state: cloneDeep(initialState || {}),\n\n // Array of chunk names encountered during the rendering.\n chunks: [],\n\n chunkGroups,\n };\n let stream;\n if (App) {\n const ssrStart = Date.now();\n\n const renderPass = async () => {\n ssrContext.chunks = [];\n return new Promise((resolve, reject) => {\n const pipeableStream = renderToPipeableStream(\n <GlobalStateProvider\n initialState={ssrContext.state}\n ssrContext={ssrContext}\n >\n <StaticRouter location={req.url}>\n <App />\n </StaticRouter>\n </GlobalStateProvider>,\n {\n onAllReady: () => resolve(pipeableStream),\n onError: reject,\n },\n );\n });\n };\n\n let ssrRound = 0;\n let bailed = false;\n for (; ssrRound < ops.maxSsrRounds; ++ssrRound) {\n stream = await renderPass(); // eslint-disable-line no-await-in-loop\n\n if (!ssrContext.dirty) break;\n\n /* eslint-disable no-await-in-loop */\n const timeout = ops.ssrTimeout + ssrStart - Date.now();\n bailed = timeout <= 0 || !await Promise.race([\n Promise.allSettled(ssrContext.pending),\n timer(timeout).then(() => false),\n ]);\n if (bailed) break;\n /* eslint-enable no-await-in-loop */\n }\n\n let logMsg;\n if (ssrContext.dirty) {\n // NOTE: In the case of incomplete SSR one more round is necessary\n // to ensure the correct hydration when some pending promises have\n // resolved and placed their data into the initial global state.\n stream = await renderPass();\n\n logMsg = bailed ? `SSR timed out after ${ops.ssrTimeout} second(s)`\n : `SSR bailed out after ${ops.maxSsrRounds} round(s)`;\n } else logMsg = `SSR completed in ${ssrRound + 1} round(s)`;\n\n ops.logger.log(ssrContext.dirty ? 'warn' : 'info', logMsg);\n\n App = '';\n stream.pipe(new Writable({\n write: (chunk, _, done) => {\n App += chunk.toString();\n done();\n },\n }));\n\n /* This takes care about server-side rendering of page title and meta tags\n * (still demands injection into HTML template, which happens below). */\n helmet = Helmet.renderStatic();\n }\n\n /* Encrypts data to be injected into HTML.\n * Keep in mind, that this encryption is no way secure: as the JS bundle\n * contains decryption key and is able to decode it at the client side.\n * Hovewer, for a number of reasons, encryption of injected data is still\n * better than injection of a plain text. */\n const payload = serializeJs({\n CHUNK_GROUPS: chunkGroups,\n CONFIG: configToInject || sanitizedConfig,\n ISTATE: ssrContext.state,\n }, {\n ignoreFunction: true,\n unsafe: true,\n });\n cipher.update(forge.util.createBuffer(payload, 'utf8'));\n cipher.finish();\n const INJ = forge.util.encode64(`${iv}${cipher.output.data}`);\n\n const chunkSet = new Set();\n\n // TODO: \"main\" chunk has to be added explicitly,\n // because unlike all other chunks they are not managed by <CodeSplit>\n // component, thus they are not added to the ssrContext.chunks\n // automatically. Actually, names of these entry chunks should be\n // read from Wepback config, as the end user may customize them,\n // remove or add other entry points, but it requires additional\n // efforts to figure out how to automatically order them right,\n // thus for now this handles the default config.\n [\n 'main',\n ...ssrContext.chunks,\n ].forEach((chunk) => {\n const assets = chunkGroups[chunk];\n if (assets) assets.forEach((asset) => chunkSet.add(asset));\n });\n\n let styleChunkString = '';\n let scriptChunkString = '';\n chunkSet.forEach((chunk) => {\n if (chunk.endsWith('.css')) {\n styleChunkString += `<link href=\"${publicPath}${chunk}\" rel=\"stylesheet\">`;\n } else if (\n chunk.endsWith('.js')\n // In dev mode HMR adds JS updates into asset arrays,\n // and they (updates) should be ignored.\n && !chunk.endsWith('.hot-update.js')\n ) {\n scriptChunkString += `<script src=\"${publicPath}${chunk}\" type=\"application/javascript\"></script>`;\n }\n });\n\n const grouppedExtraScripts = groupExtraScripts(extraScripts);\n\n const faviconLink = ops.favicon ? (\n '<link rel=\"shortcut icon\" href=\"/favicon.ico\">'\n ) : '';\n\n const html = `<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.HEAD_OPEN]}\n ${helmet ? helmet.title.toString() : ''}\n ${helmet ? helmet.meta.toString() : ''}\n <meta name=\"theme-color\" content=\"#FFFFFF\">\n ${manifestLink}\n ${styleChunkString}\n ${faviconLink}\n <meta charset=\"utf-8\">\n <meta\n content=\"width=device-width,initial-scale=1.0\"\n name=\"viewport\"\n >\n <meta itemprop=\"drpruinj\" content=\"${INJ}\">\n </head>\n <body>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.BODY_OPEN]}\n <div id=\"react-view\">${App || ''}</div>\n ${scriptChunkString}\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}\n </body>\n </html>`;\n\n const status = ssrContext.status || 200;\n if (status !== 200) res.status(status);\n\n if (cacheRef && status < 500) {\n // Note: waiting for the caching to complete is not strictly necessary,\n // but it greately simplifies testing, and error reporting.\n await new Promise((done, failed) => {\n brotliCompress(html, (error, buffer) => {\n if (error) failed(error);\n else {\n buffer.nonce = req.nonce; // eslint-disable-line no-param-reassign\n cache.add({ buffer, status }, cacheRef.key);\n done();\n }\n });\n });\n }\n\n // Note: as caching code above may throw in some cases, sending response\n // before it completes will likely hide the error, making it difficult\n // to debug. Thus, at least for now, lets send response after it.\n res.send(html);\n } catch (error) {\n next(error);\n }\n };\n}\n"],"mappings":";;;;;;;;;;AAIA,IAAAA,GAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,KAAA,GAAAF,sBAAA,CAAAC,OAAA;AAEA,IAAAE,OAAA,GAAAF,OAAA;AACA,IAAAG,KAAA,GAAAH,OAAA;AACA,IAAAI,QAAA,GAAAL,sBAAA,CAAAC,OAAA;AAEA,IAAAK,iBAAA,GAAAL,OAAA;AACA,IAAAM,QAAA,GAAAN,OAAA;AAEA,IAAAO,OAAA,GAAAP,OAAA;AAUA,IAAAQ,OAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,UAAA,GAAAV,sBAAA,CAAAC,OAAA;AAEA,IAAAU,OAAA,GAAAV,OAAA;AACA,IAAAW,YAAA,GAAAX,OAAA;AACA,IAAAY,QAAA,GAAAZ,OAAA;AACA,IAAAa,oBAAA,GAAAd,sBAAA,CAAAC,OAAA;AACA,IAAAc,UAAA,GAAAd,OAAA;AAEA,IAAAe,MAAA,GAAAhB,sBAAA,CAAAC,OAAA;AAA4B,IAAAgB,WAAA,GAAAhB,OAAA;AAjC5B;AACA;AACA;;AAiCA,MAAMiB,eAAe,GAAG,IAAAC,YAAI,EAACC,eAAM,EAAE,QAAQ,CAAC;AAEvC,MAAMC,gBAAgB,GAAG;EAC9BC,SAAS,EAAE,WAAW;EACtBC,OAAO,EAAE,SAAS;EAClBC,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATAC,OAAA,CAAAJ,gBAAA,GAAAA,gBAAA;AAUA,SAASK,YAAYA,CAACC,OAAO,EAAE;EAC7B,MAAMC,GAAG,GAAGC,aAAI,CAACC,OAAO,CAACH,OAAO,EAAE,aAAa,CAAC;EAChD,OAAOI,IAAI,CAACC,KAAK,CAACC,WAAE,CAACC,YAAY,CAACN,GAAG,CAAC,CAAC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASO,mBAAmBA,CAACC,QAAQ,EAAE;EACrC,MAAMR,GAAG,GAAGC,aAAI,CAACC,OAAO,CAACM,QAAQ,EAAE,uBAAuB,CAAC;EAC3D,IAAIC,GAAG;EACP,IAAI;IACFA,GAAG,GAAGN,IAAI,CAACC,KAAK,CAACC,WAAE,CAACC,YAAY,CAACN,GAAG,CAAC,CAAC;EACxC,CAAC,CAAC,OAAOU,GAAG,EAAE;IACZD,GAAG,GAAG,IAAI;EACZ;EACA,OAAOA,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASE,aAAaA,CAACC,GAAG,EAAE;EAC1B,OAAO,IAAIC,OAAO,CAAC,CAACX,OAAO,EAAEY,MAAM,KAAK;IACtCC,kBAAK,CAACC,MAAM,CAACC,QAAQ,CAAC,EAAE,EAAE,CAACP,GAAG,EAAEQ,EAAE,KAAK;MACrC,IAAIR,GAAG,EAAEI,MAAM,CAACJ,GAAG,CAAC,CAAC,KAChB;QACH,MAAMS,MAAM,GAAGJ,kBAAK,CAACI,MAAM,CAACC,YAAY,CAAC,SAAS,EAAER,GAAG,CAAC;QACxDO,MAAM,CAACE,KAAK,CAAC;UAAEH;QAAG,CAAC,CAAC;QACpBhB,OAAO,CAAC;UAAEiB,MAAM;UAAED;QAAG,CAAC,CAAC;MACzB;IACF,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASI,kBAAkBA,CAACC,GAAG,EAAE;EACtC,MAAMC,UAAU,GAAGD,GAAG,CAACE,GAAG,CAAC,iBAAiB,CAAC;EAC7C,IAAID,UAAU,EAAE;IACd,MAAME,GAAG,GAAGF,UAAU,CAACG,KAAK,CAAC,GAAG,CAAC;IACjC,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGF,GAAG,CAACG,MAAM,EAAE,EAAED,CAAC,EAAE;MACnC,MAAM,CAACE,IAAI,EAAEC,QAAQ,CAAC,GAAGL,GAAG,CAACE,CAAC,CAAC,CAACI,IAAI,CAAC,CAAC,CAACL,KAAK,CAAC,KAAK,CAAC;MACnD,IAAI,CAACG,IAAI,KAAK,GAAG,IAAIA,IAAI,KAAK,IAAI,MAC9B,CAACC,QAAQ,IAAIE,UAAU,CAACF,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE;QAC1C,OAAO,IAAI;MACb;IACF;EACF;EACA,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASG,iBAAiBA,CAACC,OAAO,GAAG,EAAE,EAAE;EACvC,MAAM1B,GAAG,GAAG;IACV,CAAChB,gBAAgB,CAACC,SAAS,GAAG,EAAE;IAChC,CAACD,gBAAgB,CAACE,OAAO,GAAG,EAAE;IAC9B,CAACF,gBAAgB,CAACG,SAAS,GAAG;EAChC,CAAC;EACD,KAAK,IAAIgC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGO,OAAO,CAACN,MAAM,EAAE,EAAED,CAAC,EAAE;IACvC,MAAMQ,MAAM,GAAGD,OAAO,CAACP,CAAC,CAAC;IACzB,IAAI,IAAAS,gBAAQ,EAACD,MAAM,CAAC,EAAE;MACpB,IAAIA,MAAM,EAAE3B,GAAG,CAAChB,gBAAgB,CAACE,OAAO,CAAC,IAAIyC,MAAM;IACrD,CAAC,MAAM,IAAIA,MAAM,CAACE,IAAI,EAAE;MACtB,IAAI7B,GAAG,CAAC2B,MAAM,CAACG,QAAQ,CAAC,KAAKC,SAAS,EAAE;QACtC/B,GAAG,CAAC2B,MAAM,CAACG,QAAQ,CAAC,IAAIH,MAAM,CAACE,IAAI;MACrC,CAAC,MAAM,MAAMG,KAAK,CAAE,qBAAoBL,MAAM,CAACG,QAAS,GAAE,CAAC;IAC7D;EACF;EACA,OAAO9B,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,SAASiC,gBAAgBA,CAAC;EAC/BC,eAAe,GAAG;AACpB,CAAC,GAAG,CAAC,CAAC,EAAE;EACN,MAAM;IAAEC,MAAM;IAAEC;EAAW,CAAC,GAAGC,gBAAO;EACtC,OAAOA,gBAAO,CAACC,YAAY,CAAC;IAC1BC,KAAK,EAAEL,eAAe;IACtBC,MAAM,EAAEA,MAAM,CAACK,OAAO,CACpBL,MAAM,CAACM,KAAK,CAAC,CAAC,EACdN,MAAM,CAACO,SAAS,CAAC,CAAC,EAClBP,MAAM,CAACQ,QAAQ,CAAC,CAAC,EACjBR,MAAM,CAACS,MAAM,CACX,CAAC;MACCL,KAAK;MACLM,OAAO;MACPH,SAAS;MACTI,KAAK;MACL,GAAGC;IACL,CAAC,KAAK;MACJ,IAAI/C,GAAG,GAAI,GAAEuC,KAAM,SAAQG,SAAU,OAAMG,OAAQ,EAAC;MACpD,IAAIG,MAAM,CAACC,IAAI,CAACF,IAAI,CAAC,CAAC3B,MAAM,EAAE;QAC5BpB,GAAG,IAAK,KAAIN,IAAI,CAACwD,SAAS,CAACH,IAAI,EAAE,IAAI,EAAE,CAAC,CAAE,EAAC;MAC7C;MACA,IAAID,KAAK,EAAE9C,GAAG,IAAK,KAAI8C,KAAM,EAAC;MAC9B,OAAO9C,GAAG;IACZ,CACF,CACF,CAAC;IACDoC,UAAU,EAAE,CAAC,IAAIA,UAAU,CAACe,OAAO,CAAC,CAAC;EACvC,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASC,OAAOA,CAACC,aAAa,EAAEC,OAAO,EAAE;EACtD,MAAMrC,GAAG,GAAG,IAAAsC,gBAAQ,EAAC,IAAAC,aAAK,EAACF,OAAO,CAAC,EAAE;IACnCG,YAAY,EAAEA,CAAA,KAAMrD,OAAO,CAACX,OAAO,CAAC,CAAC,CAAC,CAAC;IACvCiE,YAAY,EAAE,EAAE;IAChBC,UAAU,EAAE,IAAI;IAChBC,eAAe,EAAE;EACnB,CAAC,CAAC;;EAEF;EACA;EACA;EACA,IAAI3C,GAAG,CAAC4C,MAAM,KAAK9B,SAAS,EAAE;IAC5Bd,GAAG,CAAC4C,MAAM,GAAG5B,gBAAgB,CAAC;MAC5BC,eAAe,EAAEjB,GAAG,CAAC6C;IACvB,CAAC,CAAC;EACJ;EAEA,MAAMC,SAAS,GAAG9C,GAAG,CAAC8C,SAAS,IAAI1E,YAAY,CAACgE,aAAa,CAAC/D,OAAO,CAAC;EACtE,IAAA0E,uBAAY,EAACD,SAAS,CAAC;;EAEvB;EACA,MAAM;IAAEE,UAAU;IAAEzE,IAAI,EAAE0E;EAAW,CAAC,GAAGb,aAAa,CAACc,MAAM;EAE7D,MAAMC,YAAY,GAAGxE,WAAE,CAACyE,UAAU,CAAE,GAAEH,UAAW,gBAAe,CAAC,GAC5D,8BAA6BD,UAAW,iBAAgB,GAAG,EAAE;EAElE,MAAMK,KAAK,GAAGrD,GAAG,CAACsD,qBAAqB,GACnC,IAAIC,cAAK,CAACvD,GAAG,CAAC2C,eAAe,CAAC,GAAG,IAAI;EAEzC,MAAMa,YAAY,GAAG3E,mBAAmB,CAACoE,UAAU,CAAC;EAEpD,OAAO,OAAOpD,GAAG,EAAEd,GAAG,EAAE0E,IAAI,KAAK;IAC/B,IAAI;MACF;MACA1E,GAAG,CAAC2E,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC;MAEpC3E,GAAG,CAAC4E,MAAM,CAAC,WAAW,EAAE9D,GAAG,CAAC+D,SAAS,CAAC,CAAC,CAAC;MAExC,IAAIC,QAAQ;MACZ,IAAIR,KAAK,EAAE;QACTQ,QAAQ,GAAG7D,GAAG,CAACsD,qBAAqB,CAACzD,GAAG,CAAC;QACzC,IAAIgE,QAAQ,EAAE;UACZ,MAAMC,IAAI,GAAGT,KAAK,CAACtD,GAAG,CAAC8D,QAAQ,CAAC;UAChC,IAAIC,IAAI,KAAK,IAAI,EAAE;YACjB,MAAM;cAAEC,MAAM;cAAEC;YAAO,CAAC,GAAGF,IAAI;YAC/B,IAAI9D,GAAG,CAACiE,KAAK,IAAIrE,kBAAkB,CAACC,GAAG,CAAC,EAAE;cACxCd,GAAG,CAAC2E,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;cACpC3E,GAAG,CAAC2E,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC;cACjC,IAAIM,MAAM,KAAK,GAAG,EAAEjF,GAAG,CAACiF,MAAM,CAACA,MAAM,CAAC;cACtCjF,GAAG,CAACmF,IAAI,CAACH,MAAM,CAAC;YAClB,CAAC,MAAM;cACL,MAAM,IAAI5E,OAAO,CAAC,CAACgF,IAAI,EAAEC,MAAM,KAAK;gBAClC,IAAAC,sBAAgB,EAACN,MAAM,EAAE,CAACO,KAAK,EAAEC,IAAI,KAAK;kBACxC,IAAID,KAAK,EAAEF,MAAM,CAACE,KAAK,CAAC,CAAC,KACpB;oBACH,IAAIE,CAAC,GAAGD,IAAI,CAACE,QAAQ,CAAC,CAAC;oBACvB,IAAI,CAACzE,GAAG,CAACiE,KAAK,EAAE;sBACd;sBACA;sBACA;sBACA,MAAMS,KAAK,GAAG,IAAIC,MAAM,CAACZ,MAAM,CAACa,KAAK,EAAE,GAAG,CAAC;sBAC3CJ,CAAC,GAAGA,CAAC,CAACK,OAAO,CAACH,KAAK,EAAE7E,GAAG,CAAC+E,KAAK,CAAC;oBACjC;oBACA,IAAIZ,MAAM,KAAK,GAAG,EAAEjF,GAAG,CAACiF,MAAM,CAACA,MAAM,CAAC;oBACtCjF,GAAG,CAACmF,IAAI,CAACM,CAAC,CAAC;oBACXL,IAAI,CAAC,CAAC;kBACR;gBACF,CAAC,CAAC;cACJ,CAAC,CAAC;YACJ;YACA;UACF;QACF;MACF;MAEA,MAAM,CAAC;QACLW,cAAc;QACdC,YAAY;QACZC;MACF,CAAC,EAAE;QACDvF,MAAM;QACND;MACF,CAAC,CAAC,GAAG,MAAML,OAAO,CAAC8F,GAAG,CAAC,CACrBjF,GAAG,CAACwC,YAAY,CAAC3C,GAAG,EAAEjC,eAAe,CAAC,EACtCqB,aAAa,CAAC6D,SAAS,CAAC5D,GAAG,CAAC,CAC7B,CAAC;MAEF,IAAIgG,MAAM;;MAEV;MACA;MACA;MACA;MACA,IAAIC,WAAW;MACf,MAAMC,YAAY,GAAG,IAAArF,WAAG,EAAChB,GAAG,CAACsG,MAAM,EAAE,6BAA6B,CAAC;MACnE,IAAID,YAAY,EAAE;QAChBD,WAAW,GAAG,IAAAG,iBAAS,EACrBF,YAAY,CAACG,MAAM,CAAC;UAClBN,GAAG,EAAE,KAAK;UACVE,WAAW,EAAE;QACf,CAAC,CAAC,CAACK,gBAAgB,EAClBC,IAAI,IAAKA,IAAI,CAACC,MAAM,CAACC,GAAG,CAAC,CAAC;UAAEC;QAAK,CAAC,KAAKA,IAAI,CAC9C,CAAC;MACH,CAAC,MAAM,IAAIpC,YAAY,EAAE2B,WAAW,GAAG3B,YAAY,CAAC,KAC/C2B,WAAW,GAAG,CAAC,CAAC;;MAErB;MACA,IAAIU,GAAG,GAAG7F,GAAG,CAAC8F,WAAW;MACzB,MAAMC,UAAU,GAAG;QACjBlG,GAAG;QACHmG,KAAK,EAAE,IAAAC,iBAAS,EAACjB,YAAY,IAAI,CAAC,CAAC,CAAC;QAEpC;QACAkB,MAAM,EAAE,EAAE;QAEVf;MACF,CAAC;MACD,IAAIgB,MAAM;MACV,IAAIN,GAAG,EAAE;QACP,MAAMO,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;QAE3B,MAAMC,UAAU,GAAG,MAAAA,CAAA,KAAY;UAC7BR,UAAU,CAACG,MAAM,GAAG,EAAE;UACtB,OAAO,IAAI/G,OAAO,CAAC,CAACX,OAAO,EAAEY,MAAM,KAAK;YACtC,MAAMoH,cAAc,GAAG,IAAAC,8BAAsB,gBAC3C,IAAA9I,WAAA,CAAA+I,GAAA,EAAC1J,iBAAA,CAAA2J,mBAAmB;cAClB3B,YAAY,EAAEe,UAAU,CAACC,KAAM;cAC/BD,UAAU,EAAEA,UAAW;cAAAa,QAAA,eAEvB,IAAAjJ,WAAA,CAAA+I,GAAA,EAACnJ,QAAA,CAAAsJ,YAAY;gBAAChG,QAAQ,EAAEhB,GAAG,CAACvB,GAAI;gBAAAsI,QAAA,eAC9B,IAAAjJ,WAAA,CAAA+I,GAAA,EAACb,GAAG,IAAE;cAAC,CACK;YAAC,CACI,CAAC,EACtB;cACEiB,UAAU,EAAEA,CAAA,KAAMtI,OAAO,CAACgI,cAAc,CAAC;cACzCO,OAAO,EAAE3H;YACX,CACF,CAAC;UACH,CAAC,CAAC;QACJ,CAAC;QAED,IAAI4H,QAAQ,GAAG,CAAC;QAChB,IAAIC,MAAM,GAAG,KAAK;QAClB,OAAOD,QAAQ,GAAGhH,GAAG,CAACyC,YAAY,EAAE,EAAEuE,QAAQ,EAAE;UAC9Cb,MAAM,GAAG,MAAMI,UAAU,CAAC,CAAC,CAAC,CAAC;;UAE7B,IAAI,CAACR,UAAU,CAACmB,KAAK,EAAE;;UAEvB;UACA,MAAMC,OAAO,GAAGnH,GAAG,CAAC0C,UAAU,GAAG0D,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;UACtDW,MAAM,GAAGE,OAAO,IAAI,CAAC,IAAI,EAAC,MAAMhI,OAAO,CAACiI,IAAI,CAAC,CAC3CjI,OAAO,CAACkI,UAAU,CAACtB,UAAU,CAACuB,OAAO,CAAC,EACtC,IAAAC,cAAK,EAACJ,OAAO,CAAC,CAACK,IAAI,CAAC,MAAM,KAAK,CAAC,CACjC,CAAC;UACF,IAAIP,MAAM,EAAE;UACZ;QACF;;QAEA,IAAIQ,MAAM;QACV,IAAI1B,UAAU,CAACmB,KAAK,EAAE;UACpB;UACA;UACA;UACAf,MAAM,GAAG,MAAMI,UAAU,CAAC,CAAC;UAE3BkB,MAAM,GAAGR,MAAM,GAAI,uBAAsBjH,GAAG,CAAC0C,UAAW,YAAW,GAC9D,wBAAuB1C,GAAG,CAACyC,YAAa,WAAU;QACzD,CAAC,MAAMgF,MAAM,GAAI,oBAAmBT,QAAQ,GAAG,CAAE,WAAU;QAE3DhH,GAAG,CAAC4C,MAAM,CAAC8E,GAAG,CAAC3B,UAAU,CAACmB,KAAK,GAAG,MAAM,GAAG,MAAM,EAAEO,MAAM,CAAC;QAE1D5B,GAAG,GAAG,EAAE;QACRM,MAAM,CAACwB,IAAI,CAAC,IAAIC,gBAAQ,CAAC;UACvBC,KAAK,EAAEA,CAACC,KAAK,EAAEC,CAAC,EAAE5D,IAAI,KAAK;YACzB0B,GAAG,IAAIiC,KAAK,CAACrD,QAAQ,CAAC,CAAC;YACvBN,IAAI,CAAC,CAAC;UACR;QACF,CAAC,CAAC,CAAC;;QAEH;AACR;QACQe,MAAM,GAAG8C,mBAAM,CAACC,YAAY,CAAC,CAAC;MAChC;;MAEA;AACN;AACA;AACA;AACA;MACM,MAAMC,OAAO,GAAG,IAAAC,4BAAW,EAAC;QAC1B3E,YAAY,EAAE2B,WAAW;QACzBiD,MAAM,EAAEtD,cAAc,IAAIlH,eAAe;QACzCyK,MAAM,EAAEtC,UAAU,CAACC;MACrB,CAAC,EAAE;QACDsC,cAAc,EAAE,IAAI;QACpBC,MAAM,EAAE;MACV,CAAC,CAAC;MACF9I,MAAM,CAAC+I,MAAM,CAACnJ,kBAAK,CAACoJ,IAAI,CAACC,YAAY,CAACR,OAAO,EAAE,MAAM,CAAC,CAAC;MACvDzI,MAAM,CAACkJ,MAAM,CAAC,CAAC;MACf,MAAMC,GAAG,GAAGvJ,kBAAK,CAACoJ,IAAI,CAACI,QAAQ,CAAE,GAAErJ,EAAG,GAAEC,MAAM,CAACyD,MAAM,CAACY,IAAK,EAAC,CAAC;MAE7D,MAAMgF,QAAQ,GAAG,IAAIC,GAAG,CAAC,CAAC;;MAE1B;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,CACE,MAAM,EACN,GAAGhD,UAAU,CAACG,MAAM,CACrB,CAAC8C,OAAO,CAAElB,KAAK,IAAK;QACnB,MAAMpC,MAAM,GAAGP,WAAW,CAAC2C,KAAK,CAAC;QACjC,IAAIpC,MAAM,EAAEA,MAAM,CAACsD,OAAO,CAAEC,KAAK,IAAKH,QAAQ,CAACI,GAAG,CAACD,KAAK,CAAC,CAAC;MAC5D,CAAC,CAAC;MAEF,IAAIE,gBAAgB,GAAG,EAAE;MACzB,IAAIC,iBAAiB,GAAG,EAAE;MAC1BN,QAAQ,CAACE,OAAO,CAAElB,KAAK,IAAK;QAC1B,IAAIA,KAAK,CAACuB,QAAQ,CAAC,MAAM,CAAC,EAAE;UAC1BF,gBAAgB,IAAK,eAAcnG,UAAW,GAAE8E,KAAM,qBAAoB;QAC5E,CAAC,MAAM,IACLA,KAAK,CAACuB,QAAQ,CAAC,KAAK;QAClB;QACA;QAAA,GACG,CAACvB,KAAK,CAACuB,QAAQ,CAAC,gBAAgB,CAAC,EACtC;UACAD,iBAAiB,IAAK,gBAAepG,UAAW,GAAE8E,KAAM,2CAA0C;QACpG;MACF,CAAC,CAAC;MAEF,MAAMwB,oBAAoB,GAAG9I,iBAAiB,CAACuE,YAAY,CAAC;MAE5D,MAAMwE,WAAW,GAAGvJ,GAAG,CAACwJ,OAAO,GAC7B,gDAAgD,GAC9C,EAAE;MAEN,MAAMjF,IAAI,GAAI;AACpB;AACA;AACA,cAAc+E,oBAAoB,CAACvL,gBAAgB,CAACG,SAAS,CAAE;AAC/D,cAAcgH,MAAM,GAAGA,MAAM,CAACuE,KAAK,CAAChF,QAAQ,CAAC,CAAC,GAAG,EAAG;AACpD,cAAcS,MAAM,GAAGA,MAAM,CAACwE,IAAI,CAACjF,QAAQ,CAAC,CAAC,GAAG,EAAG;AACnD;AACA,cAActB,YAAa;AAC3B,cAAcgG,gBAAiB;AAC/B,cAAcI,WAAY;AAC1B;AACA;AACA;AACA;AACA;AACA,iDAAiDX,GAAI;AACrD;AACA;AACA,cAAcU,oBAAoB,CAACvL,gBAAgB,CAACC,SAAS,CAAE;AAC/D,mCAAmC6H,GAAG,IAAI,EAAG;AAC7C,cAAcuD,iBAAkB;AAChC,cAAcE,oBAAoB,CAACvL,gBAAgB,CAACE,OAAO,CAAE;AAC7D;AACA,gBAAgB;MAEV,MAAM+F,MAAM,GAAG+B,UAAU,CAAC/B,MAAM,IAAI,GAAG;MACvC,IAAIA,MAAM,KAAK,GAAG,EAAEjF,GAAG,CAACiF,MAAM,CAACA,MAAM,CAAC;MAEtC,IAAIH,QAAQ,IAAIG,MAAM,GAAG,GAAG,EAAE;QAC5B;QACA;QACA,MAAM,IAAI7E,OAAO,CAAC,CAACgF,IAAI,EAAEC,MAAM,KAAK;UAClC,IAAAuF,oBAAc,EAACpF,IAAI,EAAE,CAACD,KAAK,EAAEP,MAAM,KAAK;YACtC,IAAIO,KAAK,EAAEF,MAAM,CAACE,KAAK,CAAC,CAAC,KACpB;cACHP,MAAM,CAACa,KAAK,GAAG/E,GAAG,CAAC+E,KAAK,CAAC,CAAC;cAC1BvB,KAAK,CAAC6F,GAAG,CAAC;gBAAEnF,MAAM;gBAAEC;cAAO,CAAC,EAAEH,QAAQ,CAAC3E,GAAG,CAAC;cAC3CiF,IAAI,CAAC,CAAC;YACR;UACF,CAAC,CAAC;QACJ,CAAC,CAAC;MACJ;;MAEA;MACA;MACA;MACApF,GAAG,CAACmF,IAAI,CAACK,IAAI,CAAC;IAChB,CAAC,CAAC,OAAOD,KAAK,EAAE;MACdb,IAAI,CAACa,KAAK,CAAC;IACb;EACF,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"renderer.js","names":["_fs","_interopRequireDefault","require","_path","_stream","_zlib","_winston","_reactGlobalState","_jsUtils","_lodash","_config","_nodeForge","_server","_reactHelmet","_server2","_serializeJavascript","_buildInfo","_Cache","_jsxRuntime","sanitizedConfig","omit","config","SCRIPT_LOCATIONS","exports","ServerSsrContext","SsrContext","chunks","status","constructor","req","chunkGroups","initialState","cloneDeep","getBuildInfo","context","url","path","resolve","JSON","parse","fs","readFileSync","readChunkGroupsJson","buildDir","res","err","prepareCipher","key","Promise","reject","forge","random","getBytes","iv","cipher","createCipher","start","isBrotliAcceptable","acceptable","get","ops","split","i","length","type","priority","trim","parseFloat","groupExtraScripts","scripts","BODY_OPEN","DEFAULT","HEAD_OPEN","script","isString","code","location","undefined","Error","newDefaultLogger","defaultLogLevel","format","transports","winston","createLogger","level","combine","splat","timestamp","colorize","printf","message","stack","rest","Object","keys","stringify","Console","factory","webpackConfig","options","defaults","clone","beforeRender","maxSsrRounds","ssrTimeout","staticCacheSize","logger","defaultLoggerLogLevel","buildInfo","setBuildInfo","publicPath","outputPath","output","manifestLink","existsSync","cache","staticCacheController","Cache","CHUNK_GROUPS","next","set","cookie","csrfToken","cacheRef","data","buffer","noCsp","send","done","failed","brotliDecompress","error","html","h","toString","regex","RegExp","nonce","replace","configToInject","extraScripts","all","helmet","webpackStats","locals","mapValues","toJson","namedChunkGroups","item","assets","map","name","App","Application","appHtmlMarkup","ssrContext","stream","ssrStart","Date","now","App2","renderPass","pipeableStream","renderToPipeableStream","jsx","GlobalStateProvider","state","children","StaticRouter","onAllReady","onError","ssrRound","bailed","dirty","timeout","race","allSettled","pending","timer","then","logMsg","log","pipe","Writable","write","chunk","_","Helmet","renderStatic","payload","serializeJs","CONFIG","ISTATE","ignoreFunction","unsafe","update","util","createBuffer","finish","INJ","encode64","chunkSet","Set","forEach","asset","add","styleChunkString","scriptChunkString","endsWith","grouppedExtraScripts","faviconLink","favicon","title","meta","brotliCompress","b"],"sources":["../../../src/server/renderer.tsx"],"sourcesContent":["/**\n * ExpressJS middleware for server-side rendering of a ReactJS app.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { type Request, type RequestHandler } from 'express';\nimport { type ComponentType } from 'react';\nimport { Writable } from 'stream';\nimport { brotliCompress, brotliDecompress } from 'zlib';\nimport winston from 'winston';\n\nimport { GlobalStateProvider, SsrContext } from '@dr.pogodin/react-global-state';\nimport { timer } from '@dr.pogodin/js-utils';\n\nimport {\n clone,\n cloneDeep,\n defaults,\n isString,\n get,\n mapValues,\n omit,\n} from 'lodash';\n\nimport config from 'config';\nimport forge from 'node-forge';\n\nimport { type PipeableStream, renderToPipeableStream } from 'react-dom/server';\nimport { Helmet } from 'react-helmet';\nimport { StaticRouter } from 'react-router-dom/server';\nimport serializeJs from 'serialize-javascript';\nimport { type BuildInfoT, setBuildInfo } from 'utils/isomorphy/buildInfo';\n\nimport { type ChunkGroupsT, type SsrContextT } from 'utils/globalState';\n\nimport { type Configuration } from 'webpack';\n\nimport Cache from './Cache';\n\nconst sanitizedConfig = omit(config, 'SECRET');\n\n// Note: These type definitions for logger are copied from Winston logger,\n// then simplified to make it easier to fit an alternative logger into this\n// interface.\ninterface LogMethodI {\n (level: string, message: string, ...meta: any[]): void;\n}\ninterface LeveledLogMethodI {\n (message: string, ...meta: any[]): void;\n}\n\nexport interface LoggerI {\n debug: LeveledLogMethodI;\n error: LeveledLogMethodI;\n info: LeveledLogMethodI;\n log: LogMethodI;\n warn: LeveledLogMethodI;\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport enum SCRIPT_LOCATIONS {\n BODY_OPEN = 'BODY_OPEN',\n DEFAULT = 'DEFAULT',\n HEAD_OPEN = 'HEAD_OPEN',\n}\n\nclass ServerSsrContext<StateT>\n extends SsrContext<StateT>\n implements SsrContextT<StateT> {\n chunkGroups: ChunkGroupsT;\n\n chunks: string[] = [];\n\n req: Request;\n\n status: number = 200;\n\n constructor(\n req: Request,\n chunkGroups: ChunkGroupsT,\n initialState?: StateT,\n ) {\n super(cloneDeep(initialState) || ({} as StateT));\n this.chunkGroups = chunkGroups;\n this.req = req;\n }\n}\n\ntype ScriptT = {\n code: string;\n location: SCRIPT_LOCATIONS;\n};\n\n/**\n * Reads build-time information about the app. This information is generated\n * by our standard Webpack config for apps, and it is written into\n * \".build-info\" file in the context folder specified in Webpack config.\n * At the moment, that file contains build timestamp and a random 32-bit key,\n * suitable for cryptographical use.\n * @param context Webpack context path used during the build.\n * @return Resolves to the build-time information.\n */\nfunction getBuildInfo(context: string) {\n const url = path.resolve(context, '.build-info');\n return JSON.parse(fs.readFileSync(url, 'utf8'));\n}\n\n/**\n * Attempts to read from disk the named chunk groups mapping generated\n * by Webpack during the compilation.\n * It will not work for development builds, where these stats should be captured\n * via compilator callback.\n * @param buildDir\n * @return\n */\nfunction readChunkGroupsJson(buildDir: string) {\n const url = path.resolve(buildDir, '__chunk_groups__.json');\n let res;\n try {\n res = JSON.parse(fs.readFileSync(url, 'utf8'));\n } catch (err) {\n res = null;\n }\n return res;\n}\n\n/**\n * Prepares a new Cipher for data encryption.\n * @param key Encryption key (32-bit random key is expected, see\n * node-forge documentation, in case of doubts).\n * @return Resolves to the object with two fields:\n * 1. cipher - a new Cipher, ready for encryption;\n * 2. iv - initial vector used by the cipher.\n */\nfunction prepareCipher(key: string) {\n return new Promise((resolve, reject) => {\n forge.random.getBytes(32, (err, iv) => {\n if (err) reject(err);\n else {\n const cipher = forge.cipher.createCipher('AES-CBC', key);\n cipher.start({ iv });\n resolve({ cipher, iv });\n }\n });\n });\n}\n\n/**\n * Given an incoming HTTP requests, it deduces whether Brotli-encoded responses\n * are acceptable to the caller.\n * @param {object} req\n * @return {boolean}\n * @ignore\n */\nexport function isBrotliAcceptable(req: Request) {\n const acceptable = req.get('accept-encoding');\n if (acceptable) {\n const ops = acceptable.split(',');\n for (let i = 0; i < ops.length; ++i) {\n const [type, priority] = ops[i].trim().split(';q=');\n if ((type === '*' || type === 'br')\n && (!priority || parseFloat(priority) > 0)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Given an array of extra script strings / objects, it returns an object with\n * arrays of scripts to inject in different HTML template locations. During\n * the script groupping it also filters out any empty scripts.\n * @param {({\n * code: string;\n * location: string;\n * }|string)[]} [scripts=[]]\n * @return {{\n * BODY_OPEN: string[];\n * DEFAULT: string[];\n * HEAD_OPEN: string[];\n * }}\n */\nfunction groupExtraScripts(scripts: Array<string | ScriptT> = []) {\n const res = {\n [SCRIPT_LOCATIONS.BODY_OPEN]: '',\n [SCRIPT_LOCATIONS.DEFAULT]: '',\n [SCRIPT_LOCATIONS.HEAD_OPEN]: '',\n };\n for (let i = 0; i < scripts.length; ++i) {\n const script = scripts[i];\n if (isString(script)) {\n if (script) res[SCRIPT_LOCATIONS.DEFAULT] += script;\n } else if (script.code) {\n if (res[script.location] !== undefined) {\n res[script.location] += script.code;\n } else throw Error(`Invalid location \"${script.location}\"`);\n }\n }\n return res;\n}\n\n/**\n * Creates a new default (Winston) logger.\n * @param {object} [options={}]\n * @param {string} [options.defaultLogLevel='info']\n * @return {object}\n */\nexport function newDefaultLogger({\n defaultLogLevel = 'info',\n} = {}) {\n const { format, transports } = winston;\n return winston.createLogger({\n level: defaultLogLevel,\n format: format.combine(\n format.splat(),\n format.timestamp(),\n format.colorize(),\n format.printf(\n ({\n level,\n message,\n timestamp,\n stack,\n ...rest\n }) => {\n let res = `${level}\\t(at ${timestamp}):\\t${message}`;\n if (Object.keys(rest).length) {\n res += `\\n${JSON.stringify(rest, null, 2)}`;\n }\n if (stack) res += `\\n${stack}`;\n return res;\n },\n ),\n ),\n transports: [new transports.Console()],\n });\n}\n\ntype ConfigT = {\n [key: string]: ConfigT | string;\n};\n\ntype BeforeRenderResT = {\n configToInject?: ConfigT;\n extraScripts?: Array<ScriptT | string>;\n initialState?: any;\n};\n\ntype BeforeRenderT =\n(req: Request, config: ConfigT) => BeforeRenderResT | Promise<BeforeRenderResT>;\n\ntype CacheRefT = {\n key: string;\n maxage?: number;\n};\n\nexport type OptionsT = {\n Application?: ComponentType;\n beforeRender?: BeforeRenderT;\n buildInfo?: BuildInfoT;\n defaultLoggerLogLevel?: string;\n favicon?: string;\n logger?: LoggerI;\n maxSsrRounds?: number;\n noCsp?: boolean;\n staticCacheSize?: number;\n ssrTimeout?: number;\n staticCacheController?: (req: Request) => CacheRefT;\n};\n\n/**\n * Creates the middleware.\n * @param webpackConfig\n * @param options Additional options:\n * @param [options.Application] The root ReactJS component of\n * the app to use for the server-side rendering. When not provided\n * the server-side rendering is disabled.\n * @param [options.buildInfo] \"Build info\" object to use. If provided,\n * it will be used, instead of trying to load from the filesystem the one\n * generated by the Webpack build. It is intended for test environments,\n * where passing this stuff via file system is no bueno.\n * @param [options.favicon] `true` will include favicon\n * link into the rendered HTML templates.\n * @param [options.noCsp] `true` means that no\n * Content-Security-Policy (CSP) is used by server, thus the renderer\n * may cut a few corners.\n * @param [options.maxSsrRounds=10] Maximum number of SSR rounds.\n * @param [options.ssrTimeout=1000] SSR timeout in milliseconds,\n * defaults to 1 second.\n * @param [options.staticCacheSize=1.e7] The maximum\n * static cache size in bytes. Defaults to ~10 MB.\n * @param [options.staticCacheController] When given, it activates,\n * and controls the static caching of generated HTML markup. When this function\n * is provided, on each incoming request it is triggered with the request\n * passed in as the argument. To attempt to serve the response from the cache\n * it should return the object with the following fields:\n * - `key: string` – the cache key for the response;\n * - `maxage?: number` – the maximum age of cached result in ms.\n * If undefined - infinite age is assumed.\n * @return Created middleware.\n */\nexport default function factory(\n webpackConfig: Configuration,\n options: OptionsT,\n): RequestHandler {\n const ops: OptionsT = defaults(clone(options), {\n beforeRender: () => Promise.resolve({}),\n maxSsrRounds: 10,\n ssrTimeout: 1000,\n staticCacheSize: 1.e7,\n });\n\n // Note: in normal use the default logger is created and set in the root\n // server function, and this initialization is for testing uses, where\n // renderer is imported directly.\n if (ops.logger === undefined) {\n ops.logger = newDefaultLogger({\n defaultLogLevel: ops.defaultLoggerLogLevel,\n });\n }\n\n const buildInfo = ops.buildInfo || getBuildInfo(webpackConfig.context!);\n setBuildInfo(buildInfo);\n\n // publicPath from webpack.output has a trailing slash at the end.\n const { publicPath, path: outputPath } = webpackConfig.output!;\n\n const manifestLink = fs.existsSync(`${outputPath}/manifest.json`)\n ? `<link rel=\"manifest\" href=\"${publicPath}manifest.json\">` : '';\n\n interface BufferWithNonce extends Buffer {\n nonce: string;\n }\n\n const cache = ops.staticCacheController\n ? new Cache<{\n buffer: BufferWithNonce;\n status: number;\n }>(ops.staticCacheSize!)\n : null;\n\n const CHUNK_GROUPS = readChunkGroupsJson(outputPath!);\n\n return async (req, res, next) => {\n try {\n // Ensures any caches always revalidate HTML markup before reuse.\n res.set('Cache-Control', 'no-cache');\n\n res.cookie('csrfToken', req.csrfToken());\n\n let cacheRef: CacheRefT | undefined;\n if (cache) {\n cacheRef = ops.staticCacheController!(req);\n if (cacheRef) {\n const data = cache.get(cacheRef);\n if (data !== null) {\n const { buffer, status } = data;\n if (ops.noCsp && isBrotliAcceptable(req)) {\n res.set('Content-Type', 'text/html');\n res.set('Content-Encoding', 'br');\n if (status !== 200) res.status(status);\n res.send(buffer);\n } else {\n await new Promise<void>((done, failed) => {\n brotliDecompress(buffer, (error, html) => {\n if (error) failed(error);\n else {\n let h = html.toString();\n if (!ops.noCsp) {\n // TODO: Starting from Node v15 we'll be able to use string's\n // .replaceAll() method instead relying on reg. expression for\n // global matching.\n const regex = new RegExp(buffer.nonce, 'g');\n h = h.replace(regex, (req as any).nonce);\n }\n if (status !== 200) res.status(status);\n res.send(h);\n done();\n }\n });\n });\n }\n return;\n }\n }\n }\n\n const [{\n configToInject,\n extraScripts,\n initialState,\n }, {\n cipher,\n iv,\n }] = await Promise.all([\n ops.beforeRender!(req, sanitizedConfig as any),\n prepareCipher(buildInfo.key) as Promise<any>,\n ]);\n\n let helmet;\n\n // Gets the mapping between code chunk names and their asset files.\n // These data come from the Webpack compilation, either from the stats\n // attached to the request (in dev mode), or from a file output during\n // the build (in prod mode).\n let chunkGroups: ChunkGroupsT;\n const webpackStats = get(res.locals, 'webpack.devMiddleware.stats');\n if (webpackStats) {\n chunkGroups = mapValues(\n webpackStats.toJson({\n all: false,\n chunkGroups: true,\n }).namedChunkGroups,\n (item) => item.assets.map(({ name }: { name: string }) => name),\n );\n } else if (CHUNK_GROUPS) chunkGroups = CHUNK_GROUPS;\n else chunkGroups = {};\n\n /* Optional server-side rendering. */\n const App = ops.Application;\n let appHtmlMarkup: string = '';\n const ssrContext = new ServerSsrContext(req, chunkGroups, initialState);\n let stream: PipeableStream;\n if (App) {\n const ssrStart = Date.now();\n\n // TODO: Somehow, without it TS does not realise that\n // App has been checked to exist.\n const App2 = App;\n\n const renderPass = async () => {\n ssrContext.chunks = [];\n return new Promise<PipeableStream>((resolve, reject) => {\n const pipeableStream = renderToPipeableStream(\n <GlobalStateProvider\n initialState={ssrContext.state}\n ssrContext={ssrContext}\n >\n <StaticRouter location={req.url}>\n <App2 />\n </StaticRouter>\n </GlobalStateProvider>,\n {\n onAllReady: () => resolve(pipeableStream),\n onError: reject,\n },\n );\n });\n };\n\n let ssrRound = 0;\n let bailed = false;\n for (; ssrRound < ops.maxSsrRounds!; ++ssrRound) {\n stream = await renderPass(); // eslint-disable-line no-await-in-loop\n\n if (!ssrContext.dirty) break;\n\n /* eslint-disable no-await-in-loop */\n const timeout = ops.ssrTimeout! + ssrStart - Date.now();\n bailed = timeout <= 0 || !await Promise.race([\n Promise.allSettled(ssrContext.pending),\n timer(timeout).then(() => false),\n ]);\n if (bailed) break;\n /* eslint-enable no-await-in-loop */\n }\n\n let logMsg;\n if (ssrContext.dirty) {\n // NOTE: In the case of incomplete SSR one more round is necessary\n // to ensure the correct hydration when some pending promises have\n // resolved and placed their data into the initial global state.\n stream = await renderPass();\n\n logMsg = bailed ? `SSR timed out after ${ops.ssrTimeout} second(s)`\n : `SSR bailed out after ${ops.maxSsrRounds} round(s)`;\n } else logMsg = `SSR completed in ${ssrRound + 1} round(s)`;\n\n ops.logger!.log(ssrContext.dirty ? 'warn' : 'info', logMsg);\n\n stream!.pipe(new Writable({\n write: (chunk, _, done) => {\n appHtmlMarkup += chunk.toString();\n done();\n },\n }));\n\n /* This takes care about server-side rendering of page title and meta tags\n * (still demands injection into HTML template, which happens below). */\n helmet = Helmet.renderStatic();\n }\n\n /* Encrypts data to be injected into HTML.\n * Keep in mind, that this encryption is no way secure: as the JS bundle\n * contains decryption key and is able to decode it at the client side.\n * Hovewer, for a number of reasons, encryption of injected data is still\n * better than injection of a plain text. */\n const payload = serializeJs({\n CHUNK_GROUPS: chunkGroups,\n CONFIG: configToInject || sanitizedConfig,\n ISTATE: ssrContext.state,\n }, {\n ignoreFunction: true,\n unsafe: true,\n });\n cipher.update(forge.util.createBuffer(payload, 'utf8'));\n cipher.finish();\n const INJ = forge.util.encode64(`${iv}${cipher.output.data}`);\n\n const chunkSet = new Set<string>();\n\n // TODO: \"main\" chunk has to be added explicitly,\n // because unlike all other chunks they are not managed by <CodeSplit>\n // component, thus they are not added to the ssrContext.chunks\n // automatically. Actually, names of these entry chunks should be\n // read from Wepback config, as the end user may customize them,\n // remove or add other entry points, but it requires additional\n // efforts to figure out how to automatically order them right,\n // thus for now this handles the default config.\n [\n 'main',\n ...ssrContext.chunks,\n ].forEach((chunk) => {\n const assets = chunkGroups[chunk];\n if (assets) assets.forEach((asset) => chunkSet.add(asset));\n });\n\n let styleChunkString = '';\n let scriptChunkString = '';\n chunkSet.forEach((chunk) => {\n if (chunk.endsWith('.css')) {\n styleChunkString += `<link href=\"${publicPath}${chunk}\" rel=\"stylesheet\">`;\n } else if (\n chunk.endsWith('.js')\n // In dev mode HMR adds JS updates into asset arrays,\n // and they (updates) should be ignored.\n && !chunk.endsWith('.hot-update.js')\n ) {\n scriptChunkString += `<script src=\"${publicPath}${chunk}\" type=\"application/javascript\"></script>`;\n }\n });\n\n const grouppedExtraScripts = groupExtraScripts(extraScripts);\n\n const faviconLink = ops.favicon ? (\n '<link rel=\"shortcut icon\" href=\"/favicon.ico\">'\n ) : '';\n\n const html = `<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.HEAD_OPEN]}\n ${helmet ? helmet.title.toString() : ''}\n ${helmet ? helmet.meta.toString() : ''}\n <meta name=\"theme-color\" content=\"#FFFFFF\">\n ${manifestLink}\n ${styleChunkString}\n ${faviconLink}\n <meta charset=\"utf-8\">\n <meta\n content=\"width=device-width,initial-scale=1.0\"\n name=\"viewport\"\n >\n <meta itemprop=\"drpruinj\" content=\"${INJ}\">\n </head>\n <body>\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.BODY_OPEN]}\n <div id=\"react-view\">${appHtmlMarkup}</div>\n ${scriptChunkString}\n ${grouppedExtraScripts[SCRIPT_LOCATIONS.DEFAULT]}\n </body>\n </html>`;\n\n const status = ssrContext.status || 200;\n if (status !== 200) res.status(status);\n\n if (cacheRef && status < 500) {\n // Note: waiting for the caching to complete is not strictly necessary,\n // but it greately simplifies testing, and error reporting.\n await new Promise<void>((done, failed) => {\n brotliCompress(html, (error, buffer) => {\n const b = buffer as BufferWithNonce;\n if (error) failed(error);\n else {\n b.nonce = (req as any).nonce; // eslint-disable-line no-param-reassign\n cache!.add({ buffer: b, status }, cacheRef!.key, buffer.length);\n done();\n }\n });\n });\n }\n\n // Note: as caching code above may throw in some cases, sending response\n // before it completes will likely hide the error, making it difficult\n // to debug. Thus, at least for now, lets send response after it.\n res.send(html);\n } catch (error) {\n next(error);\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -18,6 +18,7 @@ var _helmet = _interopRequireDefault(require("helmet"));
|
|
|
18
18
|
var _morgan = _interopRequireDefault(require("morgan"));
|
|
19
19
|
var _requestIp = _interopRequireDefault(require("request-ip"));
|
|
20
20
|
var _uuid = require("uuid");
|
|
21
|
+
require("webpack");
|
|
21
22
|
var _renderer = _interopRequireDefault(require("./renderer"));
|
|
22
23
|
var _errors = require("./utils/errors");
|
|
23
24
|
/**
|
|
@@ -75,7 +76,7 @@ async function factory(webpackConfig, options) {
|
|
|
75
76
|
if (options.beforeExpressJsSetup) {
|
|
76
77
|
await options.beforeExpressJsSetup(server);
|
|
77
78
|
}
|
|
78
|
-
server.logger = options.logger;
|
|
79
|
+
if (options.logger) server.logger = options.logger;
|
|
79
80
|
if (options.httpsRedirect) {
|
|
80
81
|
server.use((req, res, next) => {
|
|
81
82
|
const schema = req.headers['x-forwarded-proto'];
|
|
@@ -96,16 +97,17 @@ async function factory(webpackConfig, options) {
|
|
|
96
97
|
}));
|
|
97
98
|
if (!options.noCsp) {
|
|
98
99
|
server.use((req, res, next) => {
|
|
99
|
-
|
|
100
|
+
const req2 = req;
|
|
101
|
+
req2.nonce = (0, _uuid.v4)();
|
|
100
102
|
|
|
101
103
|
// TODO: This is deprecated, but it is kept for now for backward
|
|
102
104
|
// compatibility. Should be removed sometime later.
|
|
103
|
-
|
|
105
|
+
req2.cspNonce = req2.nonce;
|
|
104
106
|
|
|
105
107
|
// The deep clone is necessary here to ensure that default value can't be
|
|
106
108
|
// mutated during request processing.
|
|
107
109
|
let cspSettings = (0, _lodash.cloneDeep)(defaultCspSettings);
|
|
108
|
-
cspSettings.directives['script-src'].push(`'nonce-${
|
|
110
|
+
(cspSettings.directives?.['script-src']).push(`'nonce-${req2.nonce}'`);
|
|
109
111
|
if (options.cspSettingsHook) {
|
|
110
112
|
cspSettings = options.cspSettingsHook(cspSettings, req);
|
|
111
113
|
}
|
|
@@ -131,6 +133,8 @@ async function factory(webpackConfig, options) {
|
|
|
131
133
|
const FORMAT = ':ip > :status :method :url :response-time ms :res[content-length] :referrer :user-agent';
|
|
132
134
|
server.use((0, _morgan.default)(FORMAT, {
|
|
133
135
|
stream: {
|
|
136
|
+
// TODO: This implies the logger is always set. Is it on a higher level?
|
|
137
|
+
// then mark it as always present.
|
|
134
138
|
write: options.logger.info.bind(options.logger)
|
|
135
139
|
}
|
|
136
140
|
}));
|
|
@@ -139,7 +143,7 @@ async function factory(webpackConfig, options) {
|
|
|
139
143
|
// to be served from the root, to have all web app pages in its scope.
|
|
140
144
|
// Thus, this setup to serve it. Probably, need some more configuration
|
|
141
145
|
// for special cases, but this will do for now.
|
|
142
|
-
server.get('/__service-worker.js', _express.default.static(webpackConfig.output
|
|
146
|
+
server.get('/__service-worker.js', _express.default.static(webpackConfig.output?.path || '', {
|
|
143
147
|
setHeaders: res => res.set('Cache-Control', 'no-cache')
|
|
144
148
|
}));
|
|
145
149
|
|