@zengenti/contensis-react-base 4.0.0-beta.9 → 4.0.1-beta.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/README.md +14 -1
- package/cjs/{App-vZrUfVgQ.js → App-Bg1MzW4V.js} +593 -110
- package/cjs/App-Bg1MzW4V.js.map +1 -0
- package/cjs/{ChangePassword.container-ECjEXixF.js → ChangePassword.container-C4Du3Wb1.js} +57 -50
- package/cjs/ChangePassword.container-C4Du3Wb1.js.map +1 -0
- package/cjs/{SSRContext-DVj_QAC1.js → ContensisDeliveryApi-MfcvdfDR.js} +32 -74
- package/cjs/ContensisDeliveryApi-MfcvdfDR.js.map +1 -0
- package/cjs/CookieConstants-DfPiWCRZ.js +12 -0
- package/cjs/CookieConstants-DfPiWCRZ.js.map +1 -0
- package/{esm/CookieHelper.class-FTURFpz3.js → cjs/CookieHelper.class-Det3qfdU.js} +4 -6
- package/cjs/CookieHelper.class-Det3qfdU.js.map +1 -0
- package/cjs/{RouteLoader-D5Yg7EB5.js → RouteLoader-DJeM8cym.js} +17 -9
- package/cjs/RouteLoader-DJeM8cym.js.map +1 -0
- package/cjs/SSRContext-tMufQDHY.js +116 -0
- package/cjs/SSRContext-tMufQDHY.js.map +1 -0
- package/cjs/ToJs-BsWqWjdm.js +23 -0
- package/cjs/ToJs-BsWqWjdm.js.map +1 -0
- package/cjs/{VersionInfo-B_dKCubg.js → VersionInfo-zFPsvS8q.js} +3 -25
- package/cjs/VersionInfo-zFPsvS8q.js.map +1 -0
- package/cjs/client.js +63 -65
- package/cjs/client.js.map +1 -1
- package/cjs/contensis-react-base.js +208 -119
- package/cjs/contensis-react-base.js.map +1 -1
- package/cjs/i18n.js +75 -0
- package/cjs/i18n.js.map +1 -0
- package/cjs/{ToJs-C9jwV7YB.js → matchGroups-dqONU-vY.js} +2 -22
- package/cjs/matchGroups-dqONU-vY.js.map +1 -0
- package/cjs/redux.js +8 -6
- package/cjs/redux.js.map +1 -1
- package/cjs/routing.js +15 -7
- package/cjs/routing.js.map +1 -1
- package/cjs/{sagas-BVX4Ps1e.js → sagas-BCy9u6zA.js} +523 -375
- package/cjs/sagas-BCy9u6zA.js.map +1 -0
- package/cjs/search.js +54 -29
- package/cjs/search.js.map +1 -1
- package/cjs/{selectors-wCs5fHD4.js → selectors-BrxJ8-F8.js} +27 -6
- package/cjs/selectors-BrxJ8-F8.js.map +1 -0
- package/cjs/selectors-DAQR0uZa.js +18 -0
- package/cjs/selectors-DAQR0uZa.js.map +1 -0
- package/cjs/slice-5xJMH24n.js +69 -0
- package/cjs/slice-5xJMH24n.js.map +1 -0
- package/cjs/{store-D07FOXvM.js → store-B7SJs5Hf.js} +64 -5
- package/cjs/store-B7SJs5Hf.js.map +1 -0
- package/cjs/urls-DGZlAs0y.js +25 -0
- package/cjs/urls-DGZlAs0y.js.map +1 -0
- package/cjs/user.js +20 -17
- package/cjs/user.js.map +1 -1
- package/cjs/util-eOjxDjxF.js +148 -0
- package/cjs/util-eOjxDjxF.js.map +1 -0
- package/cjs/util.js +80 -22
- package/cjs/util.js.map +1 -1
- package/cjs/{version-CM-bJ62L.js → version-rFG9Y6_B.js} +2 -2
- package/cjs/{version-CM-bJ62L.js.map → version-rFG9Y6_B.js.map} +1 -1
- package/cjs/{version-B7XFkBhY.js → version-yjHMrfVz.js} +15 -16
- package/cjs/version-yjHMrfVz.js.map +1 -0
- package/esm/{App-DLZweVSp.js → App-Bplaqueq.js} +554 -72
- package/esm/App-Bplaqueq.js.map +1 -0
- package/esm/{ChangePassword.container-BgzIy8dA.js → ChangePassword.container-CUBtn82K.js} +19 -13
- package/esm/ChangePassword.container-CUBtn82K.js.map +1 -0
- package/esm/{SSRContext-BE8ElZ3X.js → ContensisDeliveryApi-LWYXevZ1.js} +30 -67
- package/esm/ContensisDeliveryApi-LWYXevZ1.js.map +1 -0
- package/esm/CookieConstants-DEmbwzYr.js +7 -0
- package/esm/CookieConstants-DEmbwzYr.js.map +1 -0
- package/{cjs/CookieHelper.class-C3Eqoze9.js → esm/CookieHelper.class-C6rTRl_1.js} +2 -14
- package/esm/CookieHelper.class-C6rTRl_1.js.map +1 -0
- package/esm/{RouteLoader-xeQBXywk.js → RouteLoader-CzrlySZf.js} +14 -6
- package/esm/RouteLoader-CzrlySZf.js.map +1 -0
- package/esm/SSRContext-Bxtg1KGv.js +106 -0
- package/esm/SSRContext-Bxtg1KGv.js.map +1 -0
- package/esm/ToJs-BnRRHk6f.js +17 -0
- package/esm/ToJs-BnRRHk6f.js.map +1 -0
- package/esm/{VersionInfo-Cno7K0OA.js → VersionInfo-By2ZCZOh.js} +4 -24
- package/esm/VersionInfo-By2ZCZOh.js.map +1 -0
- package/esm/client.js +63 -64
- package/esm/client.js.map +1 -1
- package/esm/contensis-react-base.js +201 -114
- package/esm/contensis-react-base.js.map +1 -1
- package/esm/i18n.js +64 -0
- package/esm/i18n.js.map +1 -0
- package/esm/{ToJs-CNzfvyxJ.js → matchGroups-_w8BwzCC.js} +3 -18
- package/esm/matchGroups-_w8BwzCC.js.map +1 -0
- package/esm/redux.js +11 -8
- package/esm/redux.js.map +1 -1
- package/esm/routing.js +14 -7
- package/esm/routing.js.map +1 -1
- package/esm/{sagas-JI51CS37.js → sagas-Fr9yRduO.js} +511 -362
- package/esm/sagas-Fr9yRduO.js.map +1 -0
- package/esm/search.js +73 -47
- package/esm/search.js.map +1 -1
- package/esm/{selectors-DO2ocdOp.js → selectors-8ROQrTd7.js} +25 -7
- package/esm/selectors-8ROQrTd7.js.map +1 -0
- package/esm/selectors-DcmvOeX2.js +10 -0
- package/esm/selectors-DcmvOeX2.js.map +1 -0
- package/esm/slice-C6JLQik8.js +63 -0
- package/esm/slice-C6JLQik8.js.map +1 -0
- package/esm/{store-3u0RzHZ0.js → store-B4IrBYHm.js} +64 -6
- package/esm/store-B4IrBYHm.js.map +1 -0
- package/esm/urls-tLxo_skx.js +22 -0
- package/esm/urls-tLxo_skx.js.map +1 -0
- package/esm/user.js +9 -6
- package/esm/user.js.map +1 -1
- package/esm/util-Bl2u6LpY.js +136 -0
- package/esm/util-Bl2u6LpY.js.map +1 -0
- package/esm/util.js +58 -14
- package/esm/util.js.map +1 -1
- package/esm/{version-wnf-TITV.js → version-BQAL8sQO.js} +2 -2
- package/esm/{version-wnf-TITV.js.map → version-BQAL8sQO.js.map} +1 -1
- package/esm/{version-BlsI7hX2.js → version-CA9Mdm3A.js} +16 -16
- package/esm/version-CA9Mdm3A.js.map +1 -0
- package/i18n/package.json +5 -0
- package/models/app/pages/VersionInfo/components/VersionInfo.d.ts +1 -1
- package/models/app/pages/VersionInfo/components/VersionInfo.styled.d.ts +1 -2
- package/models/i18n/index.d.ts +5 -0
- package/models/i18n/redux/sagas.d.ts +19 -0
- package/models/i18n/redux/selectors.d.ts +11 -0
- package/models/i18n/redux/slice.d.ts +198 -0
- package/models/i18n/routes.d.ts +8 -0
- package/models/i18n/useI18n.hook.d.ts +20 -0
- package/models/index.d.ts +1 -0
- package/models/models/AppState.d.ts +2 -0
- package/models/models/ContentTypeMapping.d.ts +6 -1
- package/models/models/EntryMapper.d.ts +2 -1
- package/models/models/Locales.d.ts +11 -0
- package/models/models/MatchedRoute.d.ts +5 -1
- package/models/models/RouteComponent.d.ts +0 -1
- package/models/models/RouteNode.d.ts +4 -2
- package/models/models/SSRContext.d.ts +4 -4
- package/models/models/StaticRoute.d.ts +12 -1
- package/models/models/WithEvents.d.ts +8 -0
- package/models/models/config/AppConfig.d.ts +2 -0
- package/models/models/config/I18n.d.ts +38 -0
- package/models/models/config/ServerConfig.d.ts +14 -0
- package/models/redux/index.d.ts +2 -1
- package/models/redux/sagas/index.d.ts +3 -1
- package/models/redux/sagas/injector.d.ts +13 -0
- package/models/redux/store/injectors/index.d.ts +26 -0
- package/models/redux/store/injectors/inject.d.ts +24 -0
- package/models/redux/store/injectors/util.d.ts +2 -0
- package/models/redux/store/store.d.ts +13 -4
- package/models/redux/util.d.ts +1 -1
- package/models/routing/components/RouteLoader.d.ts +3 -3
- package/models/routing/httpContext.d.ts +0 -1
- package/models/routing/index.d.ts +1 -0
- package/models/routing/redux/actions.d.ts +1 -1
- package/models/routing/redux/invokeSearch.d.ts +22 -0
- package/models/routing/redux/selectors.d.ts +47 -4
- package/models/routing/util/expressions.d.ts +1 -1
- package/models/routing/util/find-contenttype-mapping.d.ts +3 -1
- package/models/search/containers/withListing.d.ts +1 -1
- package/models/search/containers/withSearch.d.ts +1 -1
- package/models/search/models/Queries.d.ts +3 -5
- package/models/search/models/Search.d.ts +43 -13
- package/models/search/models/SearchActions.d.ts +61 -18
- package/models/search/models/SearchProps.d.ts +11 -10
- package/models/search/models/SearchState.d.ts +23 -2
- package/models/search/models/SearchUtil.d.ts +3 -3
- package/models/search/redux/getIn.d.ts +2 -2
- package/models/search/redux/reducers.d.ts +3 -4
- package/models/search/redux/sagas.d.ts +13 -14
- package/models/search/redux/schema.d.ts +3 -3
- package/models/search/redux/selectors.d.ts +64 -42
- package/models/search/redux/util.d.ts +10 -1
- package/models/search/search/ContensisDeliveryApi.d.ts +6 -26
- package/models/search/search/expressions.d.ts +6 -4
- package/models/search/search/util.d.ts +9 -7
- package/models/search/transformations/state-to-queryparams.mapper.d.ts +1 -1
- package/models/server/features/linkdepth-api/search.d.ts +1 -1
- package/models/server/features/response-handler/render-stream.d.ts +2 -4
- package/models/server/features/static-assets/index.d.ts +4 -3
- package/models/server/internalServer.d.ts +1 -2
- package/models/server/middleware/subsiteDebug.d.ts +11 -0
- package/models/server/root.d.ts +3 -0
- package/models/server/util/bundles.d.ts +9 -9
- package/models/server/util/jsx.d.ts +2 -14
- package/models/user/components.styled/Login.styled.d.ts +1 -1
- package/models/user/components.styled/LoginForm.styled.d.ts +1 -1
- package/models/user/hocs/withRegistration.d.ts +1 -1
- package/models/util/CachedDeliveryApi.d.ts +8 -2
- package/models/util/ContensisDeliveryApi.d.ts +2 -4
- package/models/util/NoSSR.d.ts +6 -0
- package/models/util/SSRContext.d.ts +3 -19
- package/models/util/donotuse_useHistory.d.ts +6 -0
- package/models/util/errors.d.ts +16 -0
- package/models/util/index.d.ts +7 -2
- package/models/util/subsite.d.ts +12 -0
- package/models/util/urls.d.ts +1 -2
- package/models/util/useIsClient.d.ts +6 -0
- package/package.json +37 -39
- package/cjs/App-vZrUfVgQ.js.map +0 -1
- package/cjs/ChangePassword.container-ECjEXixF.js.map +0 -1
- package/cjs/CookieHelper.class-C3Eqoze9.js.map +0 -1
- package/cjs/RouteLoader-D5Yg7EB5.js.map +0 -1
- package/cjs/SSRContext-DVj_QAC1.js.map +0 -1
- package/cjs/ToJs-C9jwV7YB.js.map +0 -1
- package/cjs/VersionInfo-B_dKCubg.js.map +0 -1
- package/cjs/sagas-BVX4Ps1e.js.map +0 -1
- package/cjs/selectors-wCs5fHD4.js.map +0 -1
- package/cjs/store-D07FOXvM.js.map +0 -1
- package/cjs/version-B7XFkBhY.js.map +0 -1
- package/esm/App-DLZweVSp.js.map +0 -1
- package/esm/ChangePassword.container-BgzIy8dA.js.map +0 -1
- package/esm/CookieHelper.class-FTURFpz3.js.map +0 -1
- package/esm/RouteLoader-xeQBXywk.js.map +0 -1
- package/esm/SSRContext-BE8ElZ3X.js.map +0 -1
- package/esm/ToJs-CNzfvyxJ.js.map +0 -1
- package/esm/VersionInfo-Cno7K0OA.js.map +0 -1
- package/esm/sagas-JI51CS37.js.map +0 -1
- package/esm/selectors-DO2ocdOp.js.map +0 -1
- package/esm/store-3u0RzHZ0.js.map +0 -1
- package/esm/version-BlsI7hX2.js.map +0 -1
- package/models/redux/store/injectors.d.ts +0 -31
- package/models/search/search/ToJs.d.ts +0 -4
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var ContensisDeliveryApi = require('./ContensisDeliveryApi-MfcvdfDR.js');
|
|
6
6
|
var contensisDeliveryApi = require('contensis-delivery-api');
|
|
7
7
|
var React = require('react');
|
|
8
8
|
var reactRedux = require('react-redux');
|
|
9
|
+
var slice = require('./slice-5xJMH24n.js');
|
|
9
10
|
var mapJson = require('jsonpath-mapper');
|
|
10
|
-
var sagas = require('./sagas-
|
|
11
|
+
var sagas = require('./sagas-BCy9u6zA.js');
|
|
11
12
|
require('reselect');
|
|
12
13
|
require('immer');
|
|
13
14
|
require('deep-equal');
|
|
14
15
|
require('deepmerge');
|
|
15
16
|
require('query-string');
|
|
16
17
|
var contensisCoreApi = require('contensis-core-api');
|
|
17
|
-
var
|
|
18
|
+
var urls = require('./urls-DGZlAs0y.js');
|
|
18
19
|
require('isomorphic-fetch');
|
|
19
20
|
var express = require('express');
|
|
20
21
|
var http = require('http');
|
|
21
22
|
var httpProxy = require('http-proxy');
|
|
23
|
+
var App = require('./App-Bg1MzW4V.js');
|
|
22
24
|
var fs = require('fs');
|
|
23
25
|
var path = require('path');
|
|
24
26
|
var appRootPath = require('app-root-path');
|
|
@@ -29,31 +31,38 @@ var styled = require('styled-components');
|
|
|
29
31
|
var serialize = require('serialize-javascript');
|
|
30
32
|
var lodash = require('lodash');
|
|
31
33
|
var lodashClean = require('lodash-clean');
|
|
32
|
-
var CookieHelper_class = require('./CookieHelper.class-
|
|
34
|
+
var CookieHelper_class = require('./CookieHelper.class-Det3qfdU.js');
|
|
33
35
|
var cookiesMiddleware = require('universal-cookie-express');
|
|
34
|
-
var store = require('./store-
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var RouteLoader = require('./RouteLoader-D5Yg7EB5.js');
|
|
36
|
+
var store = require('./store-B7SJs5Hf.js');
|
|
37
|
+
var version = require('./version-yjHMrfVz.js');
|
|
38
|
+
var selectors = require('./selectors-BrxJ8-F8.js');
|
|
39
|
+
var RouteLoader = require('./RouteLoader-DJeM8cym.js');
|
|
39
40
|
var stream = require('stream');
|
|
40
41
|
var server$2 = require('@loadable/server');
|
|
41
42
|
var chalk = require('chalk');
|
|
42
43
|
var minifyCssString = require('minify-css-string');
|
|
43
44
|
var reactCookie = require('react-cookie');
|
|
45
|
+
var reactHelmetAsync = require('react-helmet-async');
|
|
44
46
|
var server$3 = require('react-router-dom/server');
|
|
47
|
+
var SSRContext = require('./SSRContext-tMufQDHY.js');
|
|
48
|
+
require('./VersionInfo-zFPsvS8q.js');
|
|
49
|
+
require('./CookieConstants-DfPiWCRZ.js');
|
|
50
|
+
require('@reduxjs/toolkit');
|
|
45
51
|
require('loglevel');
|
|
46
52
|
require('@redux-saga/core/effects');
|
|
53
|
+
require('./version-rFG9Y6_B.js');
|
|
54
|
+
require('./util-eOjxDjxF.js');
|
|
55
|
+
require('./selectors-DAQR0uZa.js');
|
|
47
56
|
require('./_commonjsHelpers-BJu3ubxk.js');
|
|
48
|
-
require('
|
|
57
|
+
require('history');
|
|
58
|
+
require('await-to-js');
|
|
59
|
+
require('redux-saga');
|
|
60
|
+
require('./ChangePassword.container-C4Du3Wb1.js');
|
|
61
|
+
require('./matchGroups-dqONU-vY.js');
|
|
62
|
+
require('./ToJs-BsWqWjdm.js');
|
|
49
63
|
require('redux');
|
|
50
64
|
require('redux-thunk');
|
|
51
|
-
require('redux-saga');
|
|
52
65
|
require('redux-injectors-19');
|
|
53
|
-
require('history');
|
|
54
|
-
require('await-to-js');
|
|
55
|
-
require('./ChangePassword.container-ECjEXixF.js');
|
|
56
|
-
require('./ToJs-C9jwV7YB.js');
|
|
57
66
|
|
|
58
67
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
59
68
|
|
|
@@ -64,6 +73,7 @@ var http__default = /*#__PURE__*/_interopDefault(http);
|
|
|
64
73
|
var httpProxy__default = /*#__PURE__*/_interopDefault(httpProxy);
|
|
65
74
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
66
75
|
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
76
|
+
var appRootPath__default = /*#__PURE__*/_interopDefault(appRootPath);
|
|
67
77
|
var serialize__default = /*#__PURE__*/_interopDefault(serialize);
|
|
68
78
|
var cookiesMiddleware__default = /*#__PURE__*/_interopDefault(cookiesMiddleware);
|
|
69
79
|
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
@@ -240,7 +250,7 @@ const resolveParentEntries = async (parentContentTypeIds, replaceContentTypeIds,
|
|
|
240
250
|
});
|
|
241
251
|
query.fields = params.fields ? [...JSON.parse(params.fields), parentFieldId] : [];
|
|
242
252
|
if (debug) console.log(`\nResolve parent entries query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
243
|
-
const parentResults = await
|
|
253
|
+
const parentResults = await ContensisDeliveryApi.cachedSearch.searchUsingPost(query, Number(params.linkDepth || 0), params.projectId);
|
|
244
254
|
return mergeResults(results, Util.GetItems(parentResults), replaceContentTypeIds, parentFieldId);
|
|
245
255
|
};
|
|
246
256
|
|
|
@@ -286,7 +296,7 @@ class QueryLevelResults {
|
|
|
286
296
|
}
|
|
287
297
|
if (runFirstQuery) {
|
|
288
298
|
if (this.debug) console.log(`\nLevel ${this.level} - First query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
289
|
-
this.firstResults = await
|
|
299
|
+
this.firstResults = await ContensisDeliveryApi.cachedSearch.searchUsingPost(query, 0, params.projectId);
|
|
290
300
|
|
|
291
301
|
// mapResultsToValidatedLinks
|
|
292
302
|
for (const linkFieldId of this.linkFieldIds) {
|
|
@@ -323,7 +333,7 @@ class QueryLevelResults {
|
|
|
323
333
|
}
|
|
324
334
|
if (runFinalQuery) {
|
|
325
335
|
if (this.debug) console.log(`\nLevel ${this.level} - Final query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
326
|
-
this.finalResults = await
|
|
336
|
+
this.finalResults = await ContensisDeliveryApi.cachedSearch.searchUsingPost(query, Number(params.linkDepth) || 0, params.projectId);
|
|
327
337
|
if (this.parent) this.parent.runFinalQuery = true;
|
|
328
338
|
|
|
329
339
|
// mapResultsToValidatedLinks
|
|
@@ -464,7 +474,7 @@ class LinkDepthSearchService {
|
|
|
464
474
|
};
|
|
465
475
|
})) || []);
|
|
466
476
|
if (this.debug) console.log(`\nFinal query: ${derivedIds.reduce((accumulator, object) => accumulator + object.entryIds.length, 0)} derived ids \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
467
|
-
const finalQueryResult = await
|
|
477
|
+
const finalQueryResult = await ContensisDeliveryApi.cachedSearch.searchUsingPost(query, Number(params.linkDepth) || 0, params.projectId);
|
|
468
478
|
|
|
469
479
|
// Resolve any parent entries
|
|
470
480
|
|
|
@@ -591,7 +601,7 @@ const makeLinkDepthMiddleware = ({
|
|
|
591
601
|
const linkDepthMiddleware = async (req, res) => {
|
|
592
602
|
try {
|
|
593
603
|
// Short cache duration copied from canterbury project
|
|
594
|
-
|
|
604
|
+
urls.setCachingHeaders(res, {
|
|
595
605
|
cacheControl: 'private',
|
|
596
606
|
surrogateControl: '10'
|
|
597
607
|
});
|
|
@@ -627,42 +637,66 @@ const makeLinkDepthMiddleware = ({
|
|
|
627
637
|
}
|
|
628
638
|
};
|
|
629
639
|
|
|
640
|
+
/**
|
|
641
|
+
* Development proxy for Subsite PoC
|
|
642
|
+
* Catch all routes before they hit CRB handlers
|
|
643
|
+
* and rewrite them to include the subsite base path,
|
|
644
|
+
* this allows us to run the subsite in a subfolder in development
|
|
645
|
+
* In production we will handle this with a path rewrite in the Cloud Dashboard site configuration,
|
|
646
|
+
* @param subsitePath the content base path we will rewrite to
|
|
647
|
+
* @param exceptions an array of path prefixes to ignore when rewriting, useful for ignoring assets that do not live in the subsite base path
|
|
648
|
+
*/
|
|
649
|
+
const subsiteDebugMiddleware = (subsitePath, exceptions = []) => (req, res, next) => {
|
|
650
|
+
if (!subsitePath || req.hostname !== 'localhost' || req.path.startsWith('/api/') || exceptions.some(exception => req.path.startsWith(exception))) return next();
|
|
651
|
+
if (!req.path.startsWith(`${subsitePath}/`)) {
|
|
652
|
+
console.warn(`[subsite-debug-middleware] Rewriting (${subsitePath})${req.url}`);
|
|
653
|
+
if (req.path === '/' || req.path === subsitePath) req.url = subsitePath;else req.url = `${subsitePath}${req.url}`;
|
|
654
|
+
res.setHeader('x-crb-subsite-content-path', req.url);
|
|
655
|
+
|
|
656
|
+
// Important to set the subsite_path header as this drives the subsite-scoped routing logic
|
|
657
|
+
req.headers['subsite_path'] = subsitePath;
|
|
658
|
+
}
|
|
659
|
+
next();
|
|
660
|
+
};
|
|
661
|
+
|
|
630
662
|
const servers$1 = SERVERS; /* global SERVERS */
|
|
631
663
|
const project = PROJECT; /* global PROJECT */
|
|
632
664
|
const alias$1 = ALIAS; /* global ALIAS */
|
|
633
|
-
const deliveryApiHostname =
|
|
665
|
+
const deliveryApiHostname = urls.urls(alias$1, project).api;
|
|
666
|
+
const proxyTimeoutMs = 45_000;
|
|
634
667
|
const assetProxy = httpProxy__default.default.createProxyServer();
|
|
635
668
|
const deliveryProxy = httpProxy__default.default.createProxyServer();
|
|
636
669
|
const reverseProxies = (app, reverseProxyPaths = []) => {
|
|
637
670
|
deliveryApiProxy(deliveryProxy, app);
|
|
638
|
-
app.all(reverseProxyPaths
|
|
639
|
-
|
|
671
|
+
app.all(reverseProxyPaths.map(proxyPath =>
|
|
672
|
+
// Patch to update paths for express v5
|
|
673
|
+
proxyPath.endsWith('/*') ? `${proxyPath.slice(0, -2)}/{*splat}` : proxyPath.endsWith('/**') ? `${proxyPath.slice(0, -3)}/{*splat}` : proxyPath), (req, res) => {
|
|
674
|
+
const target = req.hostname.includes('preview-') || req.hostname.includes('preview.') || req.hostname === 'localhost' ? servers$1.previewIis || servers$1.iis : servers$1.iis;
|
|
640
675
|
assetProxy.web(req, res, {
|
|
641
676
|
target,
|
|
642
|
-
changeOrigin: true
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
/* eslint-disable no-console */
|
|
646
|
-
console.log(`Proxy Request for ${req.path} HostName:${req.hostname} failed with ${e}`);
|
|
647
|
-
/* eslint-enable no-console */
|
|
677
|
+
changeOrigin: true,
|
|
678
|
+
proxyTimeout: proxyTimeoutMs,
|
|
679
|
+
timeout: proxyTimeoutMs
|
|
648
680
|
});
|
|
649
681
|
});
|
|
682
|
+
assetProxy.on('error', (e, req) => {
|
|
683
|
+
console.log(`[assetProxy] "${req.method} ${req.url}" host: ${req.headers.host} failed with ${e}`);
|
|
684
|
+
});
|
|
650
685
|
};
|
|
651
686
|
const deliveryApiProxy = (apiProxy, app) => {
|
|
652
687
|
// This is just here to stop cors requests on localhost. In Production this is mapped using varnish.
|
|
653
|
-
app.all(['/api/delivery
|
|
654
|
-
|
|
655
|
-
console.log(`Proxying api request to ${servers$1.alias}`);
|
|
688
|
+
app.all(['/api/delivery/{*splat}', '/api/forms/{*splat}', '/api/image/{*splat}', '/authenticate/{*splat}'], (req, res) => {
|
|
689
|
+
console.log(`[apiProxy] "${req.method} ${App.shorten(req.url)}" target: ${servers$1.alias}`);
|
|
656
690
|
apiProxy.web(req, res, {
|
|
657
691
|
target: deliveryApiHostname,
|
|
658
|
-
changeOrigin: true
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
/* eslint-disable no-console */
|
|
662
|
-
console.log(`Proxy request for ${req.path} HostName:${req.hostname} failed with ${e}`);
|
|
663
|
-
/* eslint-enable no-console */
|
|
692
|
+
changeOrigin: true,
|
|
693
|
+
proxyTimeout: proxyTimeoutMs,
|
|
694
|
+
timeout: proxyTimeoutMs
|
|
664
695
|
});
|
|
665
696
|
});
|
|
697
|
+
apiProxy.on('error', (e, req) => {
|
|
698
|
+
console.log(`[apiProxy] "${req.method} ${req.url}" host: ${req.headers.host} failed with ${e}`);
|
|
699
|
+
});
|
|
666
700
|
};
|
|
667
701
|
|
|
668
702
|
const CacheDuration = {
|
|
@@ -737,9 +771,8 @@ const resolveStartupMiddleware = ({
|
|
|
737
771
|
if (maxage) res.set('Cache-Control', `public, max-age=${maxage}`);
|
|
738
772
|
res.sendFile(startupFileLocation);
|
|
739
773
|
} catch (sendFileError) {
|
|
740
|
-
// eslint-disable-next-line no-console
|
|
741
774
|
console.log(`Unable to send file startup.js at '${startupFileLocation}'`, sendFileError);
|
|
742
|
-
|
|
775
|
+
res.status(404).send();
|
|
743
776
|
}
|
|
744
777
|
} else {
|
|
745
778
|
next();
|
|
@@ -747,8 +780,11 @@ const resolveStartupMiddleware = ({
|
|
|
747
780
|
};
|
|
748
781
|
|
|
749
782
|
// Serving static assets
|
|
783
|
+
const {
|
|
784
|
+
path: appPath
|
|
785
|
+
} = appRootPath__default.default;
|
|
750
786
|
const staticAssets = (app, {
|
|
751
|
-
appRootPath
|
|
787
|
+
appRootPath = appPath,
|
|
752
788
|
scripts = {},
|
|
753
789
|
startupScriptFilename = 'startup.js',
|
|
754
790
|
staticFolderPath = 'static',
|
|
@@ -756,20 +792,18 @@ const staticAssets = (app, {
|
|
|
756
792
|
staticRoutePaths = []
|
|
757
793
|
}) => {
|
|
758
794
|
app.use([`/${staticRoutePath}`, ...staticRoutePaths.map(p => `/${p}`), `/${staticFolderPath}`], bundleManipulationMiddleware({
|
|
759
|
-
appRootPath
|
|
795
|
+
appRootPath,
|
|
760
796
|
// these maxage values are different in config but the same in runtime,
|
|
761
797
|
// this one is the true value in seconds
|
|
762
798
|
maxage: CacheDuration.static,
|
|
763
799
|
staticFolderPath,
|
|
764
800
|
staticRoutePath
|
|
765
801
|
}), resolveStartupMiddleware({
|
|
766
|
-
appRootPath
|
|
802
|
+
appRootPath,
|
|
767
803
|
maxage: CacheDuration.static,
|
|
768
804
|
startupScriptFilename: scripts.startup || startupScriptFilename,
|
|
769
805
|
staticFolderPath
|
|
770
|
-
}),
|
|
771
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
772
|
-
express__default.default.static(`dist/${staticFolderPath}`, {
|
|
806
|
+
}), express__default.default.static(`dist/${staticFolderPath}`, {
|
|
773
807
|
// these maxage values are different in config but the same in runtime,
|
|
774
808
|
// this one is somehow converted and should end up being the same as CacheDuration.static
|
|
775
809
|
maxAge: CacheDuration.expressStatic
|
|
@@ -819,7 +853,31 @@ const handleResponse = (request, response, content, send = 'send') => {
|
|
|
819
853
|
* @param response the express Response object
|
|
820
854
|
* @param stream all chunks are piped to this stream to add additional style elements to each streamed chunk
|
|
821
855
|
*/
|
|
822
|
-
const renderStream = (getContextHtml, jsx, response, stream) => {
|
|
856
|
+
const renderStream = (getContextHtml, jsx, request, response, stream) => {
|
|
857
|
+
// Store timeout reference for cleanup on normal or abnormal termination
|
|
858
|
+
let timeoutId = null;
|
|
859
|
+
const disposeTimeout = () => {
|
|
860
|
+
if (timeoutId) {
|
|
861
|
+
clearTimeout(timeoutId);
|
|
862
|
+
timeoutId = null;
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
// Only used for abnormal termination
|
|
867
|
+
const abortCleanup = err => {
|
|
868
|
+
disposeTimeout();
|
|
869
|
+
stream.destroy(err instanceof Error ? err : undefined);
|
|
870
|
+
abort();
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
// Guard against client disconnect
|
|
874
|
+
request.on('close', () => abortCleanup());
|
|
875
|
+
|
|
876
|
+
// Guard against transform errors
|
|
877
|
+
stream.on('error', err => {
|
|
878
|
+
abortCleanup(err);
|
|
879
|
+
if (!response.headersSent) response.destroy(err);
|
|
880
|
+
});
|
|
823
881
|
const {
|
|
824
882
|
abort,
|
|
825
883
|
pipe
|
|
@@ -828,7 +886,7 @@ const renderStream = (getContextHtml, jsx, response, stream) => {
|
|
|
828
886
|
const html = getContextHtml(false);
|
|
829
887
|
if (!html) {
|
|
830
888
|
// this means we have finished with the response already
|
|
831
|
-
|
|
889
|
+
abortCleanup();
|
|
832
890
|
} else {
|
|
833
891
|
const header = html.split('{{APP}}')[0];
|
|
834
892
|
response.setHeader('content-type', 'text/html; charset=utf-8');
|
|
@@ -839,11 +897,15 @@ const renderStream = (getContextHtml, jsx, response, stream) => {
|
|
|
839
897
|
onAllReady() {
|
|
840
898
|
const footer = getContextHtml(true).split('{{APP}}')[1];
|
|
841
899
|
stream.write(footer);
|
|
900
|
+
disposeTimeout(); // Clear the timeout, let stream end naturally
|
|
842
901
|
},
|
|
843
902
|
onShellError(error) {
|
|
844
|
-
|
|
845
|
-
response.
|
|
846
|
-
|
|
903
|
+
abortCleanup(error); // Abnormal - destroy everything
|
|
904
|
+
if (!response.headersSent) {
|
|
905
|
+
response.statusCode = 500;
|
|
906
|
+
response.setHeader('content-type', 'text/html; charset=utf-8');
|
|
907
|
+
response.send('<h1>Something went wrong</h1>');
|
|
908
|
+
}
|
|
847
909
|
console.error(`[renderToPipeableStream:onShellError]`, error);
|
|
848
910
|
},
|
|
849
911
|
onError(error) {
|
|
@@ -851,10 +913,13 @@ const renderStream = (getContextHtml, jsx, response, stream) => {
|
|
|
851
913
|
}
|
|
852
914
|
});
|
|
853
915
|
|
|
854
|
-
// Abandon and switch to client rendering
|
|
916
|
+
// Abandon and switch to client rendering after 30s.
|
|
855
917
|
// Try lowering this to see the client recover.
|
|
856
|
-
setTimeout(() =>
|
|
857
|
-
|
|
918
|
+
timeoutId = setTimeout(() => {
|
|
919
|
+
timeoutId = null;
|
|
920
|
+
abortCleanup();
|
|
921
|
+
}, 30_000);
|
|
922
|
+
stream.pipe(response);
|
|
858
923
|
};
|
|
859
924
|
|
|
860
925
|
/**
|
|
@@ -894,6 +959,23 @@ const styledComponentsStream = sheet => {
|
|
|
894
959
|
this.push(styledCSS + renderedHtml);
|
|
895
960
|
}
|
|
896
961
|
callback();
|
|
962
|
+
},
|
|
963
|
+
destroy(err, callback) {
|
|
964
|
+
// Called on both stream.destroy() and natural end
|
|
965
|
+
// Stops the sheet intercepting styles & releases its references
|
|
966
|
+
|
|
967
|
+
// try/catch is required if sheet.seal() throws for any reason,
|
|
968
|
+
// callback(err) must still be called, as Node.js stream internals depend
|
|
969
|
+
// on it to complete teardown. Omitting it causes the stream to hang.
|
|
970
|
+
try {
|
|
971
|
+
sheet.seal();
|
|
972
|
+
} catch (sealErr) {
|
|
973
|
+
// Catch any errors from sealing the sheet, we MUST always call the
|
|
974
|
+
// callback to prevent hanging the stream
|
|
975
|
+
|
|
976
|
+
console.error('[styledComponentsStream] sheet.seal() failed - styles may leak:', sealErr);
|
|
977
|
+
}
|
|
978
|
+
callback(err);
|
|
897
979
|
}
|
|
898
980
|
});
|
|
899
981
|
return readerWriter;
|
|
@@ -1055,6 +1137,7 @@ const unhandledExceptionHandler = (handleExceptions = handleDefaultEvents) => {
|
|
|
1055
1137
|
}
|
|
1056
1138
|
};
|
|
1057
1139
|
|
|
1140
|
+
const logPrefix = '[addHeaders]';
|
|
1058
1141
|
const addStandardHeaders = (state, response, packagejson, groups) => {
|
|
1059
1142
|
if (state) {
|
|
1060
1143
|
try {
|
|
@@ -1068,14 +1151,14 @@ const addStandardHeaders = (state, response, packagejson, groups) => {
|
|
|
1068
1151
|
// - add `any-update` header that will indiscriminately
|
|
1069
1152
|
// invalidate the SSR page cache when any content is updated
|
|
1070
1153
|
const addAnyUpdateHeader = routingSurrogateKeys.length >= 2000 || response.statusCode >= 400 || anyApiError;
|
|
1071
|
-
console.info(
|
|
1154
|
+
console.info(`${logPrefix} ${addAnyUpdateHeader ? anyUpdateHeader : routingSurrogateKeys.length} surrogate keys for ${response.req.url}`);
|
|
1072
1155
|
const surrogateKeys = addAnyUpdateHeader ? anyUpdateHeader : routingSurrogateKeys.join(' ');
|
|
1073
1156
|
const surrogateKeyHeader = `${packagejson.name}-app ${surrogateKeys}`;
|
|
1074
1157
|
response.setHeader('surrogate-key', surrogateKeyHeader);
|
|
1075
1158
|
addVarnishAuthenticationHeaders(state, response, groups);
|
|
1076
1159
|
response.setHeader('surrogate-control', `max-age=${getCacheDuration(response.statusCode)}`);
|
|
1077
1160
|
} catch (e) {
|
|
1078
|
-
console.info(
|
|
1161
|
+
console.info(`${logPrefix} Error adding headers`, e.message);
|
|
1079
1162
|
}
|
|
1080
1163
|
}
|
|
1081
1164
|
};
|
|
@@ -1088,14 +1171,13 @@ const addVarnishAuthenticationHeaders = (state, response, groups = {}) => {
|
|
|
1088
1171
|
globalGroups,
|
|
1089
1172
|
allowedGroups
|
|
1090
1173
|
} = groups;
|
|
1091
|
-
// console.info(globalGroups, allowedGroups);
|
|
1092
1174
|
let allGroups = Array.from(globalGroups && globalGroups[project] || {});
|
|
1093
1175
|
if (stateEntry && selectors.getImmutableOrJS(stateEntry, ['authentication', 'isLoginRequired']) && allowedGroups && allowedGroups[project]) {
|
|
1094
1176
|
allGroups = [...allGroups, ...allowedGroups[project]];
|
|
1095
1177
|
}
|
|
1096
1178
|
response.header('x-contensis-viewer-groups', allGroups.join('|'));
|
|
1097
1179
|
} catch (e) {
|
|
1098
|
-
console.info(
|
|
1180
|
+
console.info(`${logPrefix} Error adding authentication header`, e);
|
|
1099
1181
|
}
|
|
1100
1182
|
}
|
|
1101
1183
|
};
|
|
@@ -1172,13 +1254,15 @@ const replaceHtml = ({
|
|
|
1172
1254
|
*/
|
|
1173
1255
|
const ssrJsxProducer = (ReactApp, {
|
|
1174
1256
|
providers,
|
|
1175
|
-
props
|
|
1176
|
-
ssrAssets
|
|
1257
|
+
props
|
|
1258
|
+
// ssrAssets,
|
|
1177
1259
|
}) => {
|
|
1178
1260
|
var _providers$styledComp;
|
|
1179
1261
|
// Recast ChunkExtractorManager to avoid TS error `Property 'children' does not exist on type...`
|
|
1180
1262
|
const ChunkExtractor = server$2.ChunkExtractorManager;
|
|
1181
|
-
const jsx = /*#__PURE__*/React__default.default.createElement(
|
|
1263
|
+
const jsx = /*#__PURE__*/React__default.default.createElement(reactHelmetAsync.HelmetProvider, {
|
|
1264
|
+
context: providers.helmet
|
|
1265
|
+
}, /*#__PURE__*/React__default.default.createElement(ChunkExtractor, {
|
|
1182
1266
|
extractor: providers.loadable.extractor
|
|
1183
1267
|
}, /*#__PURE__*/React__default.default.createElement(reactCookie.CookiesProvider, {
|
|
1184
1268
|
cookies: providers.cookies
|
|
@@ -1187,16 +1271,20 @@ const ssrJsxProducer = (ReactApp, {
|
|
|
1187
1271
|
}, /*#__PURE__*/React__default.default.createElement(RouteLoader.HttpContext.Provider, {
|
|
1188
1272
|
value: providers.httpContext
|
|
1189
1273
|
}, /*#__PURE__*/React__default.default.createElement(server$3.StaticRouter, {
|
|
1190
|
-
location: providers.router.url
|
|
1274
|
+
location: providers.router.url,
|
|
1275
|
+
future: {
|
|
1276
|
+
v7_startTransition: true,
|
|
1277
|
+
v7_relativeSplatPath: true
|
|
1278
|
+
}
|
|
1191
1279
|
}, /*#__PURE__*/React__default.default.createElement(SSRContext.SSRContextProvider, {
|
|
1192
1280
|
accessMethod: providers.ssrContext.accessMethod,
|
|
1193
1281
|
request: providers.ssrContext.request,
|
|
1194
|
-
response: providers.ssrContext.response
|
|
1195
|
-
|
|
1282
|
+
response: providers.ssrContext.response
|
|
1283
|
+
// ssrAssets={ssrAssets}
|
|
1196
1284
|
}, /*#__PURE__*/React__default.default.createElement(ReactApp, {
|
|
1197
1285
|
routes: props.routes,
|
|
1198
1286
|
withEvents: props.withEvents
|
|
1199
|
-
})))))));
|
|
1287
|
+
}))))))));
|
|
1200
1288
|
|
|
1201
1289
|
// Wrap the JSX in a StyleSheetManager if a ServerStyleSheet is provided
|
|
1202
1290
|
return !((_providers$styledComp = providers.styledComponents) !== null && _providers$styledComp !== void 0 && _providers$styledComp.sheet) ? jsx : providers.styledComponents.sheet.collectStyles(jsx);
|
|
@@ -1218,8 +1306,12 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1218
1306
|
disableSsrRedux,
|
|
1219
1307
|
enableSsrCookies,
|
|
1220
1308
|
handleResponses,
|
|
1221
|
-
handleExceptions = true
|
|
1309
|
+
handleExceptions = true,
|
|
1310
|
+
i18n
|
|
1222
1311
|
} = config;
|
|
1312
|
+
|
|
1313
|
+
// process locales in static routes for i18n
|
|
1314
|
+
const localeRoutes = App.createLocaleRoutes(routes);
|
|
1223
1315
|
const staticRoutePath = config.staticRoutePath || staticFolderPath;
|
|
1224
1316
|
let isRenderingJsxToString = config.renderToString || false;
|
|
1225
1317
|
const bundleData = getBundleData(config, staticRoutePath);
|
|
@@ -1233,8 +1325,16 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1233
1325
|
if (handleExceptions !== false) unhandledExceptionHandler(handleExceptions); // Create `process.on` event handlers for unhandled exceptions (Node v15+)
|
|
1234
1326
|
|
|
1235
1327
|
const versionInfo = getVersionInfo(staticFolderPath);
|
|
1236
|
-
app.get('
|
|
1237
|
-
|
|
1328
|
+
app.get('/{*splat}', cookiesMiddleware__default.default(), async (request, response) => {
|
|
1329
|
+
/*
|
|
1330
|
+
* Do not inject url directly into HTML as it can lead to XSS attacks
|
|
1331
|
+
* CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
|
|
1332
|
+
* CWE-96: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
|
|
1333
|
+
* Removed URL encoding as it causes inconsistencies when routes contain encoded characters in SSR
|
|
1334
|
+
* e.g. /search?category=sport%20and%20wellbeing becomes /search?category=sport%2520and%2520wellbeing
|
|
1335
|
+
* // const url = encodeURI(request.url);
|
|
1336
|
+
*/
|
|
1337
|
+
const url = request.url;
|
|
1238
1338
|
const matchedStaticRoute = reactRouterDom.matchRoutes(routes.StaticRoutes, request.path);
|
|
1239
1339
|
const isStaticRoute = matchedStaticRoute && matchedStaticRoute.length > 0;
|
|
1240
1340
|
if (isStaticRoute) {
|
|
@@ -1269,30 +1369,27 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1269
1369
|
}), stateType);
|
|
1270
1370
|
|
|
1271
1371
|
// dispatch any global and non-saga related actions before calling our JSX
|
|
1272
|
-
const versionStatus =
|
|
1372
|
+
const versionStatus = ContensisDeliveryApi.deliveryApi.getServerSideVersionStatus(request);
|
|
1273
1373
|
|
|
1274
1374
|
// In server-side blocks world, the hostname requested by the client resides in the x-orig-host header
|
|
1275
1375
|
// Because of this, we prioritize x-orig-host when setting our hostname
|
|
1276
1376
|
const hostname = request.headers['x-orig-host'] || request.hostname;
|
|
1277
|
-
|
|
1377
|
+
const subsitePath = SSRContext.getSubsitePath(request);
|
|
1378
|
+
const subsitePathScript = subsitePath ? `window.subsitePath = ${serialize__default.default(subsitePath)};` : '';
|
|
1379
|
+
console.info(`[webApp] "${request.method} ${request.path}" hostname: ${hostname} versionStatus: ${versionStatus}`);
|
|
1278
1380
|
store$1.dispatch(version.setVersionStatus(versionStatus));
|
|
1279
1381
|
store$1.dispatch(version.setVersion(versionInfo.commitRef, versionInfo.buildNo));
|
|
1280
1382
|
const project = App.pickProject(hostname, request.query);
|
|
1281
1383
|
const groups = allowedGroups && allowedGroups[project];
|
|
1282
1384
|
store$1.dispatch(selectors.setCurrentProject(project, groups, hostname));
|
|
1385
|
+
if (i18n) {
|
|
1386
|
+
store$1.dispatch(slice.actions.INIT_LOCALES({
|
|
1387
|
+
locales: {},
|
|
1388
|
+
routes: localeRoutes,
|
|
1389
|
+
...i18n
|
|
1390
|
+
}));
|
|
1391
|
+
}
|
|
1283
1392
|
const loadableExtractor = loadableChunkExtractors();
|
|
1284
|
-
|
|
1285
|
-
// type ChunkExtractorManagerPropsForReact18 = ChunkExtractorManagerProps & {
|
|
1286
|
-
// children?: React.ReactNode;
|
|
1287
|
-
// };
|
|
1288
|
-
|
|
1289
|
-
// // Recast ChunkExtractorManager to avoid TS error `Property 'children' does not exist on type...`
|
|
1290
|
-
// const ChunkExtractor = ChunkExtractorManager as ClassType<
|
|
1291
|
-
// ChunkExtractorManagerPropsForReact18,
|
|
1292
|
-
// Component<ChunkExtractorManagerPropsForReact18>,
|
|
1293
|
-
// ComponentClass<ChunkExtractorManagerPropsForReact18>
|
|
1294
|
-
// >;
|
|
1295
|
-
|
|
1296
1393
|
const ssrCookies = enableSsrCookies ?
|
|
1297
1394
|
// these cookies are managed by the cookiesMiddleware and contain listeners
|
|
1298
1395
|
// when cookies are read or written in ssr can be added to the `set-cookie` response header
|
|
@@ -1307,12 +1404,17 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1307
1404
|
// and read back any context props set by the ReactApp
|
|
1308
1405
|
const context = {};
|
|
1309
1406
|
|
|
1407
|
+
// Per-request helmet context object — populated by HelmetProvider during renderToString
|
|
1408
|
+
// Using a fresh object per request ensures thread safety under concurrent SSR requests
|
|
1409
|
+
const helmetContext = {};
|
|
1410
|
+
|
|
1310
1411
|
// Amalgamate all props for the various Providers we wrap the ReactApp with
|
|
1311
1412
|
const jsxProviderProps = {
|
|
1312
1413
|
loadable: {
|
|
1313
1414
|
extractor: loadableExtractor.commonLoadableExtractor
|
|
1314
1415
|
},
|
|
1315
1416
|
cookies: ssrCookies,
|
|
1417
|
+
helmet: helmetContext,
|
|
1316
1418
|
redux: store$1,
|
|
1317
1419
|
httpContext: context,
|
|
1318
1420
|
router: {
|
|
@@ -1342,13 +1444,10 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1342
1444
|
// Dynamic doesn't need sagas
|
|
1343
1445
|
// or styles, or any split component bundles
|
|
1344
1446
|
// nor are we streaming responses
|
|
1345
|
-
const isDynamicHints = `<script ${attributes}>window.
|
|
1447
|
+
const isDynamicHints = `<script ${attributes}>window.isDynamic = true; ${subsitePathScript}</script>`;
|
|
1346
1448
|
const jsx = ssrJsxProducer(ReactApp, {
|
|
1347
1449
|
providers: jsxProviderProps,
|
|
1348
|
-
props: jsxReactAppProps
|
|
1349
|
-
ssrAssets: {
|
|
1350
|
-
serializedState: isDynamicHints
|
|
1351
|
-
}
|
|
1450
|
+
props: jsxReactAppProps
|
|
1352
1451
|
});
|
|
1353
1452
|
server$1.renderToString(jsx);
|
|
1354
1453
|
|
|
@@ -1407,10 +1506,7 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1407
1506
|
return true;
|
|
1408
1507
|
}
|
|
1409
1508
|
if (!disableSsrRedux) {
|
|
1410
|
-
|
|
1411
|
-
// where a consumer may not be using the contensisVersionStatus in redux and calling
|
|
1412
|
-
// the `getClientSideVersionStatus()` method directly
|
|
1413
|
-
serialisedReduxData = `<script ${attributes}>window.versionStatus = "${versionStatus}"; window.REDUX_DATA = ${serialisedReduxData}</script>`;
|
|
1509
|
+
serialisedReduxData = `<script ${attributes}>${subsitePathScript} window.__USE_HYDRATE__ = true; window.REDUX_DATA = ${serialisedReduxData}</script>`;
|
|
1414
1510
|
}
|
|
1415
1511
|
}
|
|
1416
1512
|
|
|
@@ -1419,22 +1515,6 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1419
1515
|
allowedGroups,
|
|
1420
1516
|
globalGroups
|
|
1421
1517
|
});
|
|
1422
|
-
|
|
1423
|
-
// // Produce the ssr jsx one time so we can get any style tags to pass back in
|
|
1424
|
-
// ssrJsxProducer(ReactApp, {
|
|
1425
|
-
// providers: { ...jsxProviderProps, styledComponents: { sheet } },
|
|
1426
|
-
// props: jsxReactAppProps,
|
|
1427
|
-
// });
|
|
1428
|
-
|
|
1429
|
-
// // After running rootSaga (and rendering subsquent children)
|
|
1430
|
-
// // there should be additional react-loadable
|
|
1431
|
-
// // code-split bundles for any page components as well as core app bundles
|
|
1432
|
-
// const bundleTags = getBundleTags(
|
|
1433
|
-
// loadableExtractor,
|
|
1434
|
-
// scripts,
|
|
1435
|
-
// staticRoutePath
|
|
1436
|
-
// );
|
|
1437
|
-
|
|
1438
1518
|
const sheet = new styled.ServerStyleSheet();
|
|
1439
1519
|
const styledJsx = ssrJsxProducer(ReactApp, {
|
|
1440
1520
|
providers: {
|
|
@@ -1443,13 +1523,7 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1443
1523
|
sheet
|
|
1444
1524
|
}
|
|
1445
1525
|
},
|
|
1446
|
-
props: jsxReactAppProps
|
|
1447
|
-
ssrAssets: {
|
|
1448
|
-
// bundleTags,
|
|
1449
|
-
// htmlAttributes,
|
|
1450
|
-
// metadata,
|
|
1451
|
-
// title,
|
|
1452
|
-
}
|
|
1526
|
+
props: jsxReactAppProps
|
|
1453
1527
|
});
|
|
1454
1528
|
|
|
1455
1529
|
// We have to call renderToString() in order for all components to have
|
|
@@ -1457,15 +1531,23 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1457
1531
|
const html = server$1.renderToString(styledJsx);
|
|
1458
1532
|
// Helmet.renderStatic() has to be called synchronously immediately after calling renderToString()
|
|
1459
1533
|
// as it is not thread-safe (or specifically scoped to only this request)
|
|
1534
|
+
// TODO: deprecate `react-helmet`
|
|
1460
1535
|
const helmet = reactHelmet.Helmet.renderStatic();
|
|
1461
1536
|
|
|
1537
|
+
// helmetContext is populated synchronously by HelmetProvider during renderToString()
|
|
1538
|
+
// It is scoped per-request via the helmetContext object, making this thread-safe
|
|
1539
|
+
// under concurrent SSR requests (unlike the previous Helmet.renderStatic() global singleton)
|
|
1540
|
+
const {
|
|
1541
|
+
helmet: helmetAsync
|
|
1542
|
+
} = helmetContext;
|
|
1543
|
+
|
|
1462
1544
|
// Because we have had to call renderToString() here to reliably gather all helmet metadata
|
|
1463
1545
|
// We could potentially call sheet.getStyleTags() here too and avoid piping a react-rendered
|
|
1464
1546
|
// stream to a second stream to inject styled-components CSS
|
|
1465
1547
|
|
|
1466
|
-
const htmlAttributes = helmet.htmlAttributes.toString();
|
|
1467
|
-
let title = helmet.title.toString();
|
|
1468
|
-
const metadata = helmet.meta.toString().concat(helmet.base.toString()).concat(helmet.link.toString()).concat(helmet.script.toString()).concat(helmet.noscript.toString());
|
|
1548
|
+
const htmlAttributes = helmetAsync.htmlAttributes.toString() || helmet.htmlAttributes.toString();
|
|
1549
|
+
let title = helmet.title.toString().includes('><') ? helmetAsync.title.toString() : helmet.title.toString();
|
|
1550
|
+
const metadata = helmetAsync.meta.toString().concat(helmetAsync.base.toString()).concat(helmetAsync.priority.toString()).concat(helmetAsync.link.toString()).concat(helmetAsync.script.toString()).concat(helmetAsync.noscript.toString()).concat(helmet.meta.toString()).concat(helmet.base.toString()).concat(helmet.link.toString()).concat(helmet.script.toString()).concat(helmet.noscript.toString());
|
|
1469
1551
|
try {
|
|
1470
1552
|
/**
|
|
1471
1553
|
* Loads all page assets into the provided templateHTML
|
|
@@ -1477,6 +1559,7 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1477
1559
|
* if the context has requested a redirect
|
|
1478
1560
|
* */
|
|
1479
1561
|
const getContextHtml = (isFinal = false, styleTags, renderedJsxMarkup) => {
|
|
1562
|
+
var _loadableExtractor$mo;
|
|
1480
1563
|
if (context.url) {
|
|
1481
1564
|
response.redirect(context.statusCode || 302, context.url);
|
|
1482
1565
|
return '';
|
|
@@ -1491,13 +1574,18 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1491
1574
|
// Set response.status from React StaticRouter
|
|
1492
1575
|
if (typeof context.statusCode === 'number') response.status(context.statusCode);
|
|
1493
1576
|
const bundleTags = isFinal ? getBundleTags(loadableExtractor, scripts, staticRoutePath) : '';
|
|
1577
|
+
|
|
1578
|
+
// Getting style tags generated by "CSS Modules" because they will be
|
|
1579
|
+
// available to loadable stats if we have built parts of the app with CSS
|
|
1580
|
+
// plugins that are not within styled-components
|
|
1581
|
+
const styles = loadableExtractor === null || loadableExtractor === void 0 || (_loadableExtractor$mo = loadableExtractor.modern) === null || _loadableExtractor$mo === void 0 ? void 0 : _loadableExtractor$mo.getStyleTags();
|
|
1494
1582
|
const html = replaceHtml({
|
|
1495
1583
|
bundleTags,
|
|
1496
1584
|
html: renderedJsxMarkup,
|
|
1497
1585
|
htmlAttributes,
|
|
1498
1586
|
metadata,
|
|
1499
1587
|
state: serialisedReduxData,
|
|
1500
|
-
styleTags
|
|
1588
|
+
styleTags: `${styleTags || ''}${styles || ''}`,
|
|
1501
1589
|
title,
|
|
1502
1590
|
templateHTML,
|
|
1503
1591
|
templateHTMLFragment,
|
|
@@ -1513,7 +1601,7 @@ const webApp = (app, ReactApp, config) => {
|
|
|
1513
1601
|
const responseHTML = getContextHtml(true, styleTags, html);
|
|
1514
1602
|
responseHandler(request, response, responseHTML);
|
|
1515
1603
|
} else {
|
|
1516
|
-
renderStream(getContextHtml, styledJsx, response, styledComponentsStream(sheet));
|
|
1604
|
+
renderStream(getContextHtml, styledJsx, request, response, styledComponentsStream(sheet));
|
|
1517
1605
|
}
|
|
1518
1606
|
} catch (err) {
|
|
1519
1607
|
console.info(err.message);
|
|
@@ -1576,6 +1664,7 @@ var internalServer = {
|
|
|
1576
1664
|
};
|
|
1577
1665
|
|
|
1578
1666
|
exports.ReactApp = App.AppRoot;
|
|
1667
|
+
exports.DO_NOT_COMMIT_subsiteDebugMiddleware = subsiteDebugMiddleware;
|
|
1579
1668
|
exports.default = internalServer;
|
|
1580
1669
|
exports.linkDepthApi = makeLinkDepthApi;
|
|
1581
1670
|
//# sourceMappingURL=contensis-react-base.js.map
|