@salesforce/pwa-kit-react-sdk 3.0.0-preview.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/CHANGELOG.md +86 -0
- package/LICENSE +14 -0
- package/README.md +37 -0
- package/package.json +82 -0
- package/scripts/file-utils.js +80 -0
- package/scripts/file-utils.test.js +189 -0
- package/scripts/setup-jsdom.js +20 -0
- package/scripts/version.js +22 -0
- package/ssr/browser/main.js +122 -0
- package/ssr/browser/main.test.js +54 -0
- package/ssr/server/react-rendering.js +405 -0
- package/ssr/server/react-rendering.test.js +708 -0
- package/ssr/universal/compatibility.js +31 -0
- package/ssr/universal/components/_app/index.js +35 -0
- package/ssr/universal/components/_app/index.test.js +20 -0
- package/ssr/universal/components/_app-config/index.js +88 -0
- package/ssr/universal/components/_app-config/index.test.js +21 -0
- package/ssr/universal/components/_document/index.js +93 -0
- package/ssr/universal/components/_document/index.test.js +58 -0
- package/ssr/universal/components/_error/index.js +56 -0
- package/ssr/universal/components/_error/index.test.js +28 -0
- package/ssr/universal/components/app-error-boundary/index.js +115 -0
- package/ssr/universal/components/app-error-boundary/index.test.js +109 -0
- package/ssr/universal/components/fetch-strategy/index.js +42 -0
- package/ssr/universal/components/route-component/index.js +409 -0
- package/ssr/universal/components/route-component/index.test.js +375 -0
- package/ssr/universal/components/switch/index.js +63 -0
- package/ssr/universal/components/throw-404/index.js +37 -0
- package/ssr/universal/components/throw-404/index.test.js +26 -0
- package/ssr/universal/components/with-correlation-id/index.js +36 -0
- package/ssr/universal/components/with-legacy-get-props/index.js +86 -0
- package/ssr/universal/components/with-legacy-get-props/index.test.js +35 -0
- package/ssr/universal/components/with-react-query/index.js +103 -0
- package/ssr/universal/components/with-react-query/index.test.js +44 -0
- package/ssr/universal/contexts/index.js +71 -0
- package/ssr/universal/contexts/index.test.js +101 -0
- package/ssr/universal/errors.js +34 -0
- package/ssr/universal/errors.test.js +20 -0
- package/ssr/universal/events.js +40 -0
- package/ssr/universal/events.test.js +39 -0
- package/ssr/universal/hooks/index.js +52 -0
- package/ssr/universal/routes.js +16 -0
- package/ssr/universal/utils.client.test.js +46 -0
- package/ssr/universal/utils.js +60 -0
- package/ssr/universal/utils.server.test.js +24 -0
- package/utils/assets.js +120 -0
- package/utils/assets.test.js +106 -0
- package/utils/url.js +39 -0
- package/utils/url.test.js +47 -0
- package/utils/uuidv4.client.js +21 -0
- package/utils/uuidv4.client.test.js +27 -0
- package/utils/warnings.js +81 -0
- package/utils/warnings.test.js +48 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FetchStrategy = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
10
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
11
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } /*
|
|
12
|
+
* Copyright (c) 2022, Salesforce, Inc.
|
|
13
|
+
* All rights reserved.
|
|
14
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
15
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
class FetchStrategy extends _react.default.Component {
|
|
21
|
+
/**
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
static initAppState(args) {
|
|
25
|
+
var _this = this;
|
|
26
|
+
return _asyncToGenerator(function* () {
|
|
27
|
+
try {
|
|
28
|
+
const promises = _this.getInitializers().map(fn => fn(args));
|
|
29
|
+
return {
|
|
30
|
+
error: undefined,
|
|
31
|
+
appState: _extends({}, ...(yield Promise.all(promises)))
|
|
32
|
+
};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return {
|
|
35
|
+
error: error || new Error(),
|
|
36
|
+
appState: {}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
})();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.FetchStrategy = FetchStrategy;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.routeComponent = exports.getRoutes = void 0;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _reactRouterDom = require("react-router-dom");
|
|
10
|
+
var _hoistNonReactStatics = _interopRequireDefault(require("hoist-non-react-statics"));
|
|
11
|
+
var _appErrorBoundary = require("../../components/app-error-boundary");
|
|
12
|
+
var _throw2 = _interopRequireDefault(require("../../components/throw-404"));
|
|
13
|
+
var _compatibility = require("../../compatibility");
|
|
14
|
+
var _routes2 = _interopRequireDefault(require("../../routes"));
|
|
15
|
+
var _events = require("../../events");
|
|
16
|
+
var _withLegacyGetProps = require("../../components/with-legacy-get-props");
|
|
17
|
+
const _excluded = ["component"];
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
20
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
21
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
22
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
23
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
24
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
25
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
26
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
27
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
28
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /*
|
|
29
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
30
|
+
* All rights reserved.
|
|
31
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
32
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
33
|
+
*/
|
|
34
|
+
const noop = () => undefined;
|
|
35
|
+
const isServerSide = typeof window === 'undefined';
|
|
36
|
+
const isHydrating = () => !isServerSide && window.__HYDRATING__;
|
|
37
|
+
const hasPerformanceAPI = !isServerSide && window.performance && window.performance.timing;
|
|
38
|
+
|
|
39
|
+
/* istanbul ignore next */
|
|
40
|
+
const now = () => {
|
|
41
|
+
return hasPerformanceAPI ? window.performance.timing.navigationStart + window.performance.now() : Date.now();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
const withErrorHandling = Wrapped => {
|
|
48
|
+
/* istanbul ignore next */
|
|
49
|
+
const wrappedComponentName = Wrapped.displayName || Wrapped.name;
|
|
50
|
+
const WithErrorHandling = props => /*#__PURE__*/_react.default.createElement(_appErrorBoundary.AppErrorContext.Consumer, null, ctx => /*#__PURE__*/_react.default.createElement(Wrapped, _extends({}, props, ctx)));
|
|
51
|
+
|
|
52
|
+
// Expose statics from the wrapped component on the HOC
|
|
53
|
+
(0, _hoistNonReactStatics.default)(WithErrorHandling, Wrapped);
|
|
54
|
+
WithErrorHandling.displayName = `WithErrorHandling(${wrappedComponentName})`;
|
|
55
|
+
return WithErrorHandling;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The `routeComponent` HOC is automatically used on every component in a project's
|
|
60
|
+
* route-config. It provides an interface, via static methods on React components,
|
|
61
|
+
* that can be used to fetch data on the server and on the client, seamlessly.
|
|
62
|
+
*/
|
|
63
|
+
const routeComponent = (Wrapped, isPage, locals) => {
|
|
64
|
+
const AppConfig = (0, _compatibility.getAppConfig)();
|
|
65
|
+
const hocs = AppConfig.getHOCsInUse();
|
|
66
|
+
const getPropsEnabled = hocs.indexOf(_withLegacyGetProps.withLegacyGetProps) >= 0;
|
|
67
|
+
const extraArgs = getPropsEnabled ? AppConfig.extraGetPropsArgs(locals) : {};
|
|
68
|
+
|
|
69
|
+
/* istanbul ignore next */
|
|
70
|
+
const wrappedComponentName = Wrapped.displayName || Wrapped.name;
|
|
71
|
+
class RouteComponent extends _react.default.Component {
|
|
72
|
+
constructor(props, context) {
|
|
73
|
+
super(props, context);
|
|
74
|
+
this.state = {
|
|
75
|
+
childProps: _objectSpread(_objectSpread({}, isServerSide || isHydrating() ? this.props.preloadedProps : undefined), {}, {
|
|
76
|
+
isLoading: false
|
|
77
|
+
})
|
|
78
|
+
};
|
|
79
|
+
this._suppressUpdate = false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Route-components implement `shouldGetProps()` to control when the
|
|
84
|
+
* component should fetch data from the server by calling `getProps()`.
|
|
85
|
+
* Typically, this is done by looking at the request URL.
|
|
86
|
+
*
|
|
87
|
+
* If not implemented, route-components will call `getProps()` again whenever
|
|
88
|
+
* `location.pathname` changes.
|
|
89
|
+
*
|
|
90
|
+
* The `shouldGetProps` function is called once on the server and every time
|
|
91
|
+
* a component updates on the client.
|
|
92
|
+
*
|
|
93
|
+
* @param {Object} args
|
|
94
|
+
*
|
|
95
|
+
* @param {Location} args.previousLocation - the previous value of
|
|
96
|
+
* window.location, or a server-side equivalent.
|
|
97
|
+
*
|
|
98
|
+
* @param {Location} args.location - the current value of window.location,
|
|
99
|
+
* or a server-side equivalent.
|
|
100
|
+
*
|
|
101
|
+
* @param {Object} args.previousParams - the previous parameters that were
|
|
102
|
+
* parsed from the URL by react-router.
|
|
103
|
+
*
|
|
104
|
+
* @param {Object} args.params - the current parameters that were parsed
|
|
105
|
+
* from the URL by react-router.
|
|
106
|
+
*
|
|
107
|
+
* @return {Promise<Boolean>}
|
|
108
|
+
*/
|
|
109
|
+
static shouldGetProps(args) {
|
|
110
|
+
return _asyncToGenerator(function* () {
|
|
111
|
+
if (!getPropsEnabled) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
const defaultImpl = () => {
|
|
115
|
+
const {
|
|
116
|
+
previousLocation,
|
|
117
|
+
location
|
|
118
|
+
} = args;
|
|
119
|
+
return !previousLocation || previousLocation.pathname !== location.pathname;
|
|
120
|
+
};
|
|
121
|
+
const component = yield RouteComponent.getComponent();
|
|
122
|
+
return component.shouldGetProps ? component.shouldGetProps(args) : defaultImpl();
|
|
123
|
+
})();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Route-components implement `getProps()` to fetch the data they need to
|
|
128
|
+
* display. The `getProps` function must return an Object which is later
|
|
129
|
+
* passed to the component as props for rendering. The returned Object is
|
|
130
|
+
* serialzied and embedded into the rendered HTML as the initial app
|
|
131
|
+
* state when running server-side.
|
|
132
|
+
*
|
|
133
|
+
* Throwing or rejecting inside `getProps` will cause the server to return
|
|
134
|
+
* an Error, with an appropriate status code.
|
|
135
|
+
*
|
|
136
|
+
* Note that `req` and `res` are only defined on the server – the only place
|
|
137
|
+
* the code actually has access to Express requests or responses.
|
|
138
|
+
*
|
|
139
|
+
* If not implemented `getProps()` does nothing and the component will not
|
|
140
|
+
* fetch any data.
|
|
141
|
+
*
|
|
142
|
+
* Before the promise is returned, a reference is stored for later
|
|
143
|
+
* comparision with a call to isLatestPropsPromise. This is used to
|
|
144
|
+
* resolve race conditions when there are multiple getProps calls
|
|
145
|
+
* active.
|
|
146
|
+
*
|
|
147
|
+
* @param {Object} args
|
|
148
|
+
*
|
|
149
|
+
* @param {Request} args.req - an Express HTTP Request object on the server,
|
|
150
|
+
* undefined on the client.
|
|
151
|
+
*
|
|
152
|
+
* @param {Response} args.res - an Express HTTP Response object on the server,
|
|
153
|
+
* undefined on the client.
|
|
154
|
+
*
|
|
155
|
+
* @param {Object} args.params - the parameters that were parsed from the URL
|
|
156
|
+
* by react-router.
|
|
157
|
+
*
|
|
158
|
+
* @param {Location} args.location - the current value of window.location,
|
|
159
|
+
* or a server-side equivalent.
|
|
160
|
+
*
|
|
161
|
+
* @param {Boolean} args.isLoading - the current execution state of `getProps`,
|
|
162
|
+
* `true` while `getProp` is executing, and `false` when it's not.
|
|
163
|
+
*
|
|
164
|
+
* @return {Promise<Object>}
|
|
165
|
+
*/
|
|
166
|
+
static getProps(args) {
|
|
167
|
+
if (!getPropsEnabled) {
|
|
168
|
+
return Promise.resolve({});
|
|
169
|
+
}
|
|
170
|
+
RouteComponent._latestPropsPromise = RouteComponent.getComponent().then(component => component.getProps ? component.getProps(_objectSpread(_objectSpread({}, args), extraArgs)) : Promise.resolve());
|
|
171
|
+
return RouteComponent._latestPropsPromise;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get the underlying component this HoC wraps. This handles loading of
|
|
176
|
+
* `@loadable/component` components.
|
|
177
|
+
*
|
|
178
|
+
* @return {Promise<React.Component>}
|
|
179
|
+
*/
|
|
180
|
+
static getComponent() {
|
|
181
|
+
return _asyncToGenerator(function* () {
|
|
182
|
+
return Wrapped.load ? Wrapped.load().then(module => module.default) : Promise.resolve(Wrapped);
|
|
183
|
+
})();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Route-components implement `getTemplateName()` to return a readable
|
|
188
|
+
* name for the component that is used internally for analytics-tracking –
|
|
189
|
+
* eg. performance/page-view events.
|
|
190
|
+
*
|
|
191
|
+
* If not implemented defaults to the `displayName` of the React component.
|
|
192
|
+
*
|
|
193
|
+
* @return {Promise<String>}
|
|
194
|
+
*/
|
|
195
|
+
static getTemplateName() {
|
|
196
|
+
return _asyncToGenerator(function* () {
|
|
197
|
+
return RouteComponent.getComponent().then(c => c.getTemplateName ? c.getTemplateName() : Promise.resolve(wrappedComponentName));
|
|
198
|
+
})();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Check if a promise is still the latest call to getProps. This is used
|
|
203
|
+
* to check if the results are outdated before using them.
|
|
204
|
+
*
|
|
205
|
+
* @param {Promise} propsPromise - The promise from the call to getProps to check
|
|
206
|
+
* @returns true or false
|
|
207
|
+
*/
|
|
208
|
+
static isLatestPropsPromise(propsPromise) {
|
|
209
|
+
return propsPromise === RouteComponent._latestPropsPromise;
|
|
210
|
+
}
|
|
211
|
+
componentDidMount() {
|
|
212
|
+
this.componentDidUpdate({});
|
|
213
|
+
}
|
|
214
|
+
componentDidUpdate(previousProps) {
|
|
215
|
+
var _this = this;
|
|
216
|
+
return _asyncToGenerator(function* () {
|
|
217
|
+
// Because we are setting the component state from within this function we need a
|
|
218
|
+
// guard prevent various events (update, error, complete, and load) from being
|
|
219
|
+
// called multiple times.
|
|
220
|
+
if (_this._suppressUpdate) {
|
|
221
|
+
_this._suppressUpdate = false;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const {
|
|
225
|
+
location: previousLocation,
|
|
226
|
+
match: previousMatch
|
|
227
|
+
} = previousProps;
|
|
228
|
+
const {
|
|
229
|
+
location,
|
|
230
|
+
match,
|
|
231
|
+
onGetPropsComplete,
|
|
232
|
+
onGetPropsError,
|
|
233
|
+
onUpdateComplete
|
|
234
|
+
} = _this.props;
|
|
235
|
+
const {
|
|
236
|
+
params
|
|
237
|
+
} = match || {};
|
|
238
|
+
const {
|
|
239
|
+
params: previousParams
|
|
240
|
+
} = previousMatch || {};
|
|
241
|
+
|
|
242
|
+
// The wasHydratingOnUpdate flag MUST only be used to decide whether
|
|
243
|
+
// or not to call static lifecycle methods. Do not use it in
|
|
244
|
+
// component rendering - you will not be able to trigger updates,
|
|
245
|
+
// because this is intentionally outside of a component's
|
|
246
|
+
// state/props.
|
|
247
|
+
const wasHydratingOnUpdate = isHydrating();
|
|
248
|
+
|
|
249
|
+
/* istanbul ignore next */
|
|
250
|
+
// Don't getProps() when hydrating - the server has already done
|
|
251
|
+
// getProps() frozen the state in the page.
|
|
252
|
+
const shouldGetPropsNow = /*#__PURE__*/function () {
|
|
253
|
+
var _ref = _asyncToGenerator(function* () {
|
|
254
|
+
return !wasHydratingOnUpdate && (yield RouteComponent.shouldGetProps({
|
|
255
|
+
previousLocation,
|
|
256
|
+
location,
|
|
257
|
+
previousParams,
|
|
258
|
+
params
|
|
259
|
+
}));
|
|
260
|
+
});
|
|
261
|
+
return function shouldGetPropsNow() {
|
|
262
|
+
return _ref.apply(this, arguments);
|
|
263
|
+
};
|
|
264
|
+
}();
|
|
265
|
+
const setStateAsync = newState => {
|
|
266
|
+
return new Promise(resolve => {
|
|
267
|
+
_this.setState(newState, resolve);
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Note: We've built a reasonable notion of a "page load time" here:
|
|
272
|
+
//
|
|
273
|
+
// 1. For first loads the load time is the time elapsed between the
|
|
274
|
+
// user pressing enter in the URL bar and the first pageLoad event
|
|
275
|
+
// fired by this component.
|
|
276
|
+
//
|
|
277
|
+
// 2. For subsequent loads the load time is the time elapsed while
|
|
278
|
+
// running the getProps() function.
|
|
279
|
+
//
|
|
280
|
+
// Since the time is overwhelmingly spent fetching data on soft-navs,
|
|
281
|
+
// we think this is a good approximation in both cases.
|
|
282
|
+
|
|
283
|
+
const templateName = yield RouteComponent.getTemplateName();
|
|
284
|
+
const start = now();
|
|
285
|
+
const emitPageLoadEvent = (templateName, end) => isPage && _events.pages.pageLoad(templateName, start, end);
|
|
286
|
+
const emitPageErrorEvent = (name, content) => isPage && _events.pages.error(name, content);
|
|
287
|
+
|
|
288
|
+
// If hydrating, we know that the server just fetched and
|
|
289
|
+
// rendered for us, embedding the app-state in the page HTML.
|
|
290
|
+
// For that reason, we don't ever do getProps while Hydrating.
|
|
291
|
+
// However, we still want to report a page load time for this
|
|
292
|
+
// initial render. Rather than fetching again, trigger the event
|
|
293
|
+
// right away and do nothing.
|
|
294
|
+
|
|
295
|
+
if (wasHydratingOnUpdate) {
|
|
296
|
+
emitPageLoadEvent(templateName, now());
|
|
297
|
+
}
|
|
298
|
+
const willGetProps = yield shouldGetPropsNow();
|
|
299
|
+
if (!willGetProps) {
|
|
300
|
+
onUpdateComplete();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
_this._suppressUpdate = true;
|
|
305
|
+
yield setStateAsync({
|
|
306
|
+
childProps: _objectSpread(_objectSpread({}, _this.state.childProps), {}, {
|
|
307
|
+
isLoading: true
|
|
308
|
+
})
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* When a user triggers two getProps for the same component,
|
|
313
|
+
* we'd like to always use the one for the later user action
|
|
314
|
+
* instead of the one that resolves last. getProps
|
|
315
|
+
* stores a reference to the promise that we check before we use
|
|
316
|
+
* the results from it.
|
|
317
|
+
*/
|
|
318
|
+
const req = undefined;
|
|
319
|
+
const res = undefined;
|
|
320
|
+
const propsPromise = RouteComponent.getProps({
|
|
321
|
+
req,
|
|
322
|
+
res,
|
|
323
|
+
params,
|
|
324
|
+
location
|
|
325
|
+
});
|
|
326
|
+
const childProps = yield propsPromise;
|
|
327
|
+
_this._suppressUpdate = false;
|
|
328
|
+
if (RouteComponent.isLatestPropsPromise(propsPromise)) {
|
|
329
|
+
yield setStateAsync({
|
|
330
|
+
childProps: _objectSpread(_objectSpread({}, childProps), {}, {
|
|
331
|
+
isLoading: false
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
onGetPropsComplete();
|
|
336
|
+
emitPageLoadEvent(templateName, now());
|
|
337
|
+
} catch (err) {
|
|
338
|
+
onGetPropsError(err);
|
|
339
|
+
emitPageErrorEvent(templateName, err);
|
|
340
|
+
}
|
|
341
|
+
onUpdateComplete();
|
|
342
|
+
})();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Return the props that are intended for the wrapped component, excluding
|
|
347
|
+
* private or test-only props for this HOC.
|
|
348
|
+
*/
|
|
349
|
+
getChildProps() {
|
|
350
|
+
const excludes = ['onGetPropsComplete', 'onGetPropsError', 'onUpdateComplete', 'preloadedProps'];
|
|
351
|
+
return _extends({}, ...Object.entries(this.props).filter(entry => excludes.indexOf(entry[0]) < 0).map(([k, v]) => ({
|
|
352
|
+
[k]: v
|
|
353
|
+
})));
|
|
354
|
+
}
|
|
355
|
+
render() {
|
|
356
|
+
return /*#__PURE__*/_react.default.createElement(Wrapped, _extends({}, this.getChildProps(), this.state.childProps));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
RouteComponent.displayName = `routeComponent(${wrappedComponentName})`;
|
|
360
|
+
RouteComponent.defaultProps = {
|
|
361
|
+
onGetPropsComplete: noop,
|
|
362
|
+
onGetPropsError: noop,
|
|
363
|
+
onUpdateComplete: noop
|
|
364
|
+
};
|
|
365
|
+
RouteComponent.propTypes = {
|
|
366
|
+
location: _propTypes.default.object,
|
|
367
|
+
match: _propTypes.default.object,
|
|
368
|
+
onGetPropsComplete: _propTypes.default.func,
|
|
369
|
+
onGetPropsError: _propTypes.default.func,
|
|
370
|
+
onUpdateComplete: _propTypes.default.func,
|
|
371
|
+
preloadedProps: _propTypes.default.object
|
|
372
|
+
};
|
|
373
|
+
const excludes = {
|
|
374
|
+
shouldGetProps: true,
|
|
375
|
+
getProps: true,
|
|
376
|
+
getTemplateName: true
|
|
377
|
+
};
|
|
378
|
+
(0, _hoistNonReactStatics.default)(RouteComponent, Wrapped, excludes);
|
|
379
|
+
return withErrorHandling((0, _reactRouterDom.withRouter)(RouteComponent));
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Wrap all the components found in the application's route config with the
|
|
384
|
+
* route-component HOC so that they all support `getProps` methods server-side
|
|
385
|
+
* and client-side in the same way.
|
|
386
|
+
*
|
|
387
|
+
* @private
|
|
388
|
+
*/
|
|
389
|
+
exports.routeComponent = routeComponent;
|
|
390
|
+
const getRoutes = locals => {
|
|
391
|
+
let _routes = _routes2.default;
|
|
392
|
+
if (typeof _routes2.default === 'function') {
|
|
393
|
+
_routes = (0, _routes2.default)();
|
|
394
|
+
}
|
|
395
|
+
const allRoutes = [..._routes, {
|
|
396
|
+
path: '*',
|
|
397
|
+
component: _throw2.default
|
|
398
|
+
}];
|
|
399
|
+
return allRoutes.map(_ref2 => {
|
|
400
|
+
let {
|
|
401
|
+
component
|
|
402
|
+
} = _ref2,
|
|
403
|
+
rest = _objectWithoutProperties(_ref2, _excluded);
|
|
404
|
+
return _objectSpread({
|
|
405
|
+
component: component ? routeComponent(component, true, locals) : component
|
|
406
|
+
}, rest);
|
|
407
|
+
});
|
|
408
|
+
};
|
|
409
|
+
exports.getRoutes = getRoutes;
|