@salesforce/pwa-kit-react-sdk 4.0.0-extensibility-preview.1 → 4.0.0-extensibility-preview.3
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 +8 -0
- package/package.json +6 -6
- package/ssr/server/react-rendering.js +1 -1
- package/ssr/server/react-rendering.test.js +23 -0
- package/ssr/universal/components/redirect-with-status/index.d.ts +3 -0
- package/ssr/universal/components/redirect-with-status/index.d.ts.map +1 -0
- package/ssr/universal/components/redirect-with-status/index.js +46 -0
- package/ssr/universal/components/redirect-with-status/index.test.js +46 -0
- package/ssr/universal/hooks/index.d.ts +3 -0
- package/ssr/universal/hooks/index.d.ts.map +1 -1
- package/ssr/universal/hooks/index.js +35 -3
- package/utils/performance.js +2 -2
- package/utils/url.d.ts.map +1 -1
- package/utils/url.js +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
## v4.0.0-extensibility-preview.3 (Dec 13, 2024)
|
|
2
|
+
## v4.0.0-extensibility-preview.2 (Dec 09, 2024)
|
|
1
3
|
## v4.0.0-extensibility-preview.1 (Dec 09, 2024)
|
|
2
4
|
## v4.0.0-extensibility-preview.0 (Nov 28, 2024)
|
|
3
5
|
- Integrate Application Extensions Project. (#2099)[https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2099]
|
|
4
6
|
- Add new `getStaticAssetUrl` utility to access assets specifically in the `/static` folder. (#2040)[https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2040]
|
|
5
7
|
- Update Application Extensions import in `react-rendering.js` and `main.js` (#2004)[https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2004]
|
|
6
8
|
- Define interface of the app extension's config [#2010](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2010)
|
|
9
|
+
## v3.9.0-dev (Oct 29, 2024)
|
|
10
|
+
- Add RedirectWithStatus component, allowing finer grained control of rediriects and their status code [#2173](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2173)
|
|
11
|
+
|
|
12
|
+
## v3.8.0 (Oct 28, 2024)
|
|
13
|
+
- [Server Affinity] - Attach dwsid to SCAPI request headers [#2090](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2090)
|
|
14
|
+
- Create useOrigin hook to return an app origin that takes x-forwarded-host header into consideration. [#2050](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2050)
|
|
7
15
|
|
|
8
16
|
## v3.7.0 (Aug 07, 2024)
|
|
9
17
|
- Add `beforeHydrate` option to withReactQuery component [#1912](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/1912)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/pwa-kit-react-sdk",
|
|
3
|
-
"version": "4.0.0-extensibility-preview.
|
|
3
|
+
"version": "4.0.0-extensibility-preview.3",
|
|
4
4
|
"description": "A library that supports the isomorphic React rendering pipeline for Commerce Cloud Managed Runtime apps",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/pwa-kit-react-sdk#readme",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"@loadable/babel-plugin": "^5.15.3",
|
|
39
39
|
"@loadable/server": "^5.15.3",
|
|
40
40
|
"@loadable/webpack-plugin": "^5.15.2",
|
|
41
|
-
"@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.
|
|
42
|
-
"@salesforce/pwa-kit-runtime": "4.0.0-extensibility-preview.
|
|
41
|
+
"@salesforce/pwa-kit-extension-sdk": "4.0.0-extensibility-preview.3",
|
|
42
|
+
"@salesforce/pwa-kit-runtime": "4.0.0-extensibility-preview.3",
|
|
43
43
|
"@tanstack/react-query": "^4.28.0",
|
|
44
44
|
"cross-env": "^5.2.1",
|
|
45
45
|
"event-emitter": "^0.3.5",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@loadable/component": "^5.15.3",
|
|
55
|
-
"@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.
|
|
55
|
+
"@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.3",
|
|
56
56
|
"@testing-library/jest-dom": "^5.16.5",
|
|
57
57
|
"@testing-library/react": "^14.0.0",
|
|
58
58
|
"@testing-library/user-event": "^14.4.3",
|
|
59
59
|
"@types/hoist-non-react-statics": "~3.3.5",
|
|
60
60
|
"@types/react": "~18.2.0",
|
|
61
61
|
"@types/react-dom": "~18.2.1",
|
|
62
|
-
"internal-lib-build": "4.0.0-extensibility-preview.
|
|
62
|
+
"internal-lib-build": "4.0.0-extensibility-preview.3",
|
|
63
63
|
"node-html-parser": "^3.3.6",
|
|
64
64
|
"nodemon": "^2.0.22",
|
|
65
65
|
"react": "^18.2.0",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"publishConfig": {
|
|
85
85
|
"directory": "dist"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "904de01e826117febeea952e034478349e16ea4d"
|
|
88
88
|
}
|
|
@@ -252,7 +252,7 @@ const render = exports.render = /*#__PURE__*/function () {
|
|
|
252
252
|
res.setHeader('Server-Timing', res.__performanceTimer.buildServerTimingHeader());
|
|
253
253
|
}
|
|
254
254
|
if (redirectUrl) {
|
|
255
|
-
res.redirect(302, redirectUrl);
|
|
255
|
+
res.redirect(routerContext.status || 302, redirectUrl);
|
|
256
256
|
} else {
|
|
257
257
|
res.status(status).send(html);
|
|
258
258
|
}
|
|
@@ -58,6 +58,7 @@ jest.mock('../universal/routes', () => {
|
|
|
58
58
|
const React = require('react');
|
|
59
59
|
const PropTypes = require('prop-types');
|
|
60
60
|
const errors = require('../universal/errors');
|
|
61
|
+
const RedirectWithStatus = require('../universal/components/redirect-with-status').default;
|
|
61
62
|
const {
|
|
62
63
|
Redirect
|
|
63
64
|
} = require('react-router-dom');
|
|
@@ -175,6 +176,17 @@ jest.mock('../universal/routes', () => {
|
|
|
175
176
|
});
|
|
176
177
|
}
|
|
177
178
|
}
|
|
179
|
+
class RedirectWithStatusPage extends React.Component {
|
|
180
|
+
static getProps() {
|
|
181
|
+
return Promise.resolve();
|
|
182
|
+
}
|
|
183
|
+
render() {
|
|
184
|
+
return /*#__PURE__*/React.createElement(RedirectWithStatus, {
|
|
185
|
+
to: "/elsewhere/",
|
|
186
|
+
status: 301
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
178
190
|
class HelmetPage extends React.Component {
|
|
179
191
|
static getProps() {
|
|
180
192
|
return Promise.resolve();
|
|
@@ -289,6 +301,9 @@ jest.mock('../universal/routes', () => {
|
|
|
289
301
|
}, {
|
|
290
302
|
path: '/redirect/',
|
|
291
303
|
component: RedirectPage
|
|
304
|
+
}, {
|
|
305
|
+
path: '/redirectWithStatus/',
|
|
306
|
+
component: RedirectWithStatusPage
|
|
292
307
|
}, {
|
|
293
308
|
path: '/init-sets-status/',
|
|
294
309
|
component: InitSetsStatusPage
|
|
@@ -512,6 +527,14 @@ describe('The Node SSR Environment', () => {
|
|
|
512
527
|
assertions: res => {
|
|
513
528
|
expect(res.statusCode).toBe(302);
|
|
514
529
|
}
|
|
530
|
+
}, {
|
|
531
|
+
description: `can redirect with HTTP 301 status`,
|
|
532
|
+
req: {
|
|
533
|
+
url: '/redirectWithStatus/'
|
|
534
|
+
},
|
|
535
|
+
assertions: res => {
|
|
536
|
+
expect(res.statusCode).toBe(301);
|
|
537
|
+
}
|
|
515
538
|
}, {
|
|
516
539
|
description: `500 on unknown errors in getProps`,
|
|
517
540
|
req: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ssr/universal/components/redirect-with-status/index.jsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _reactRouterDom = require("react-router-dom");
|
|
9
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
+
const _excluded = ["status", "staticContext"];
|
|
11
|
+
/*
|
|
12
|
+
* Copyright (c) 2024, 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
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
19
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
|
20
|
+
/**
|
|
21
|
+
* The `RedirectWithStatus` component is used to specify a different status code when redirecting via
|
|
22
|
+
* the Redirect component.
|
|
23
|
+
* The default redirect behavior when this component is not used is to set a 302 status.
|
|
24
|
+
*
|
|
25
|
+
* @param {number} status - The HTTP status code. Defaults to 302 if not specified
|
|
26
|
+
* @param {object} staticContext - The router context
|
|
27
|
+
* @param {string} to - The redirect's target path
|
|
28
|
+
*/
|
|
29
|
+
const RedirectWithStatus = _ref => {
|
|
30
|
+
let {
|
|
31
|
+
status = 302,
|
|
32
|
+
staticContext
|
|
33
|
+
} = _ref,
|
|
34
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
35
|
+
// Handle server-side rendering
|
|
36
|
+
if (staticContext) {
|
|
37
|
+
staticContext.status = status;
|
|
38
|
+
}
|
|
39
|
+
return /*#__PURE__*/_react.default.createElement(_reactRouterDom.Redirect, props);
|
|
40
|
+
};
|
|
41
|
+
RedirectWithStatus.propTypes = {
|
|
42
|
+
status: _propTypes.default.number,
|
|
43
|
+
staticContext: _propTypes.default.object,
|
|
44
|
+
to: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object])
|
|
45
|
+
};
|
|
46
|
+
var _default = exports.default = (0, _reactRouterDom.withRouter)(RedirectWithStatus);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _react = _interopRequireDefault(require("react"));
|
|
4
|
+
var _react2 = require("@testing-library/react");
|
|
5
|
+
var _reactRouterDom = require("react-router-dom");
|
|
6
|
+
var _history = require("history");
|
|
7
|
+
var _index = _interopRequireDefault(require("./index"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
10
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } /*
|
|
11
|
+
* Copyright (c) 2024, salesforce.com, inc.
|
|
12
|
+
* All rights reserved.
|
|
13
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
14
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
15
|
+
*/
|
|
16
|
+
describe('RedirectWithStatus', () => {
|
|
17
|
+
test('Redirects if no status or context is provided', () => {
|
|
18
|
+
const targetUrl = '/target';
|
|
19
|
+
const history = (0, _history.createMemoryHistory)();
|
|
20
|
+
history.push('/redirect');
|
|
21
|
+
(0, _react2.render)(/*#__PURE__*/_react.default.createElement(_reactRouterDom.Router, {
|
|
22
|
+
history: history
|
|
23
|
+
}, /*#__PURE__*/_react.default.createElement(_reactRouterDom.Route, {
|
|
24
|
+
path: "/redirect"
|
|
25
|
+
}, /*#__PURE__*/_react.default.createElement(_index.default, {
|
|
26
|
+
to: targetUrl
|
|
27
|
+
}))));
|
|
28
|
+
expect(history.location.pathname).toBe(targetUrl);
|
|
29
|
+
});
|
|
30
|
+
test('Redirect renders with correct status', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
31
|
+
const context = {};
|
|
32
|
+
const status = 303;
|
|
33
|
+
const targetUrl = '/target';
|
|
34
|
+
(0, _react2.render)(/*#__PURE__*/_react.default.createElement(_reactRouterDom.StaticRouter, {
|
|
35
|
+
location: "/redirect",
|
|
36
|
+
context: context
|
|
37
|
+
}, /*#__PURE__*/_react.default.createElement(_reactRouterDom.Route, {
|
|
38
|
+
path: "/redirect"
|
|
39
|
+
}, /*#__PURE__*/_react.default.createElement(_index.default, {
|
|
40
|
+
status: status,
|
|
41
|
+
to: targetUrl
|
|
42
|
+
}))));
|
|
43
|
+
expect(context.status).toBe(status);
|
|
44
|
+
expect(context.url).toBe(targetUrl);
|
|
45
|
+
}));
|
|
46
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ssr/universal/hooks/index.js"],"names":[],"mappings":"AAgBO,oCAFM,MAAM,CAQlB;AAiBM,oCANM,aAAa,CAUzB;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ssr/universal/hooks/index.js"],"names":[],"mappings":"AAgBO,oCAFM,MAAM,CAQlB;AAiBM,oCANM,aAAa,CAUzB;AAcM;;IAHM,MAAM,CAiBlB;;;;;;;;SA5Ca,MAAM;;;;SACN,MAAM"}
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.useServerContext = exports.useCorrelationId = void 0;
|
|
6
|
+
exports.useServerContext = exports.useOrigin = exports.useCorrelationId = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _contexts = require("../contexts");
|
|
9
9
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
10
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
11
|
/*
|
|
12
|
-
* Copyright (c)
|
|
12
|
+
* Copyright (c) 2024, salesforce.com, inc.
|
|
13
13
|
* All rights reserved.
|
|
14
14
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
15
15
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
@@ -49,4 +49,36 @@ const useServerContext = () => {
|
|
|
49
49
|
const serverContext = (0, _react.useContext)(_contexts.ServerContext);
|
|
50
50
|
return serverContext;
|
|
51
51
|
};
|
|
52
|
-
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Returns the application's origin.
|
|
55
|
+
*
|
|
56
|
+
* By default, it will return the ORIGIN under which we are serving the page.
|
|
57
|
+
*
|
|
58
|
+
* If `fromXForwardedHeader` is true, it will use the value of `x-forwarded-proto` and `x-forwarded-host` headers in req
|
|
59
|
+
* to build origin. (it is false by default)
|
|
60
|
+
*
|
|
61
|
+
* NOTE: this is a React hook, so it has to be used in a React rendering pipeline.
|
|
62
|
+
* @returns {string} origin string
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
exports.useServerContext = useServerContext;
|
|
66
|
+
const useOrigin = ({
|
|
67
|
+
fromXForwardedHeader = false
|
|
68
|
+
}) => {
|
|
69
|
+
const {
|
|
70
|
+
res
|
|
71
|
+
} = useServerContext();
|
|
72
|
+
if (typeof window !== 'undefined') {
|
|
73
|
+
return window.location.origin;
|
|
74
|
+
}
|
|
75
|
+
const {
|
|
76
|
+
APP_ORIGIN
|
|
77
|
+
} = process.env;
|
|
78
|
+
const xForwardedOrigin = res.locals.xForwardedOrigin;
|
|
79
|
+
if (fromXForwardedHeader && xForwardedOrigin) {
|
|
80
|
+
return xForwardedOrigin;
|
|
81
|
+
}
|
|
82
|
+
return APP_ORIGIN;
|
|
83
|
+
};
|
|
84
|
+
exports.useOrigin = useOrigin;
|
package/utils/performance.js
CHANGED
|
@@ -73,7 +73,7 @@ class PerformanceTimer {
|
|
|
73
73
|
*/
|
|
74
74
|
log() {
|
|
75
75
|
this.metrics.forEach(metric => {
|
|
76
|
-
_loggerInstance.default.info(`${metric.name} - ${metric.duration}ms ${metric.detail || ''}`, {
|
|
76
|
+
_loggerInstance.default.info(`${metric.name} - ${metric.duration.toFixed(4)}ms ${metric.detail || ''}`, {
|
|
77
77
|
namespace: 'performance'
|
|
78
78
|
});
|
|
79
79
|
});
|
|
@@ -115,7 +115,7 @@ class PerformanceTimer {
|
|
|
115
115
|
if (startMark) {
|
|
116
116
|
const measurement = {
|
|
117
117
|
name,
|
|
118
|
-
duration:
|
|
118
|
+
duration: timestamp - startMark.timestamp,
|
|
119
119
|
detail: options.detail
|
|
120
120
|
};
|
|
121
121
|
this.metrics.push(measurement);
|
package/utils/url.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.js"],"names":[],"mappings":"AAsBO,gCANM,MAAM,CAoBlB"}
|
package/utils/url.js
CHANGED
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getAppOrigin = void 0;
|
|
7
7
|
/*
|
|
8
|
-
* Copyright (c)
|
|
8
|
+
* Copyright (c) 2024, salesforce.com, inc.
|
|
9
9
|
* All rights reserved.
|
|
10
10
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
11
11
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
@@ -18,6 +18,8 @@ exports.getAppOrigin = void 0;
|
|
|
18
18
|
* initialized using the `_createApp` method (This happens in your /app/ssr.js file).
|
|
19
19
|
*
|
|
20
20
|
* @function
|
|
21
|
+
* @deprecated use `useOrigin()` instead.
|
|
22
|
+
* This function will be removed in version 4.0.0.
|
|
21
23
|
* @returns {string} Returns the ORIGIN under which we are serving the page.
|
|
22
24
|
* @example
|
|
23
25
|
* import {getAppOrigin} from '@salesforce/pwa-kit-react-sdk/utils/url'
|