@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.
Files changed (53) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +14 -0
  3. package/README.md +37 -0
  4. package/package.json +82 -0
  5. package/scripts/file-utils.js +80 -0
  6. package/scripts/file-utils.test.js +189 -0
  7. package/scripts/setup-jsdom.js +20 -0
  8. package/scripts/version.js +22 -0
  9. package/ssr/browser/main.js +122 -0
  10. package/ssr/browser/main.test.js +54 -0
  11. package/ssr/server/react-rendering.js +405 -0
  12. package/ssr/server/react-rendering.test.js +708 -0
  13. package/ssr/universal/compatibility.js +31 -0
  14. package/ssr/universal/components/_app/index.js +35 -0
  15. package/ssr/universal/components/_app/index.test.js +20 -0
  16. package/ssr/universal/components/_app-config/index.js +88 -0
  17. package/ssr/universal/components/_app-config/index.test.js +21 -0
  18. package/ssr/universal/components/_document/index.js +93 -0
  19. package/ssr/universal/components/_document/index.test.js +58 -0
  20. package/ssr/universal/components/_error/index.js +56 -0
  21. package/ssr/universal/components/_error/index.test.js +28 -0
  22. package/ssr/universal/components/app-error-boundary/index.js +115 -0
  23. package/ssr/universal/components/app-error-boundary/index.test.js +109 -0
  24. package/ssr/universal/components/fetch-strategy/index.js +42 -0
  25. package/ssr/universal/components/route-component/index.js +409 -0
  26. package/ssr/universal/components/route-component/index.test.js +375 -0
  27. package/ssr/universal/components/switch/index.js +63 -0
  28. package/ssr/universal/components/throw-404/index.js +37 -0
  29. package/ssr/universal/components/throw-404/index.test.js +26 -0
  30. package/ssr/universal/components/with-correlation-id/index.js +36 -0
  31. package/ssr/universal/components/with-legacy-get-props/index.js +86 -0
  32. package/ssr/universal/components/with-legacy-get-props/index.test.js +35 -0
  33. package/ssr/universal/components/with-react-query/index.js +103 -0
  34. package/ssr/universal/components/with-react-query/index.test.js +44 -0
  35. package/ssr/universal/contexts/index.js +71 -0
  36. package/ssr/universal/contexts/index.test.js +101 -0
  37. package/ssr/universal/errors.js +34 -0
  38. package/ssr/universal/errors.test.js +20 -0
  39. package/ssr/universal/events.js +40 -0
  40. package/ssr/universal/events.test.js +39 -0
  41. package/ssr/universal/hooks/index.js +52 -0
  42. package/ssr/universal/routes.js +16 -0
  43. package/ssr/universal/utils.client.test.js +46 -0
  44. package/ssr/universal/utils.js +60 -0
  45. package/ssr/universal/utils.server.test.js +24 -0
  46. package/utils/assets.js +120 -0
  47. package/utils/assets.test.js +106 -0
  48. package/utils/url.js +39 -0
  49. package/utils/url.test.js +47 -0
  50. package/utils/uuidv4.client.js +21 -0
  51. package/utils/uuidv4.client.test.js +27 -0
  52. package/utils/warnings.js +81 -0
  53. 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;