@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 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.1",
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.1",
42
- "@salesforce/pwa-kit-runtime": "4.0.0-extensibility-preview.1",
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.1",
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.1",
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": "5728f89cb53ab1b0c89418578f3e90c755efb0f8"
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,3 @@
1
+ declare const _default: any;
2
+ export default _default;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,5 +1,8 @@
1
1
  export function useCorrelationId(): object;
2
2
  export function useServerContext(): ServerContext;
3
+ export function useOrigin({ fromXForwardedHeader }: {
4
+ fromXForwardedHeader?: boolean | undefined;
5
+ }): string;
3
6
  /**
4
7
  * Server context
5
8
  */
@@ -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;;;;;;;;SAhBa,MAAM;;;;SACN,MAAM"}
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) 2022, salesforce.com, inc.
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
- exports.useServerContext = useServerContext;
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;
@@ -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: (timestamp - startMark.timestamp).toFixed(2),
118
+ duration: timestamp - startMark.timestamp,
119
119
  detail: options.detail
120
120
  };
121
121
  this.metrics.push(measurement);
@@ -1 +1 @@
1
- {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.js"],"names":[],"mappings":"AAoBO,gCANM,MAAM,CAoBlB"}
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) 2021, salesforce.com, inc.
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'