@salesforce/pwa-kit-runtime 3.17.0-preview.2 → 3.17.1-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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/pwa-kit-runtime",
|
|
3
|
-
"version": "3.17.
|
|
3
|
+
"version": "3.17.1-preview.0",
|
|
4
4
|
"description": "The PWAKit Runtime",
|
|
5
5
|
"homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/pwa-kit-runtime#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@loadable/component": "^5.15.3",
|
|
51
|
-
"@salesforce/pwa-kit-dev": "3.17.
|
|
51
|
+
"@salesforce/pwa-kit-dev": "3.17.1-preview.0",
|
|
52
52
|
"@serverless/event-mocks": "^1.1.1",
|
|
53
53
|
"aws-lambda-mock-context": "^3.2.1",
|
|
54
54
|
"fs-extra": "^11.1.1",
|
|
55
|
-
"internal-lib-build": "3.17.
|
|
55
|
+
"internal-lib-build": "3.17.1-preview.0",
|
|
56
56
|
"nock": "^13.3.0",
|
|
57
57
|
"nodemon": "^2.0.22",
|
|
58
58
|
"sinon": "^13.0.2",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"supertest": "^4.0.2"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@salesforce/pwa-kit-dev": "3.17.
|
|
63
|
+
"@salesforce/pwa-kit-dev": "3.17.1-preview.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependenciesMeta": {
|
|
66
66
|
"@salesforce/pwa-kit-dev": {
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"publishConfig": {
|
|
75
75
|
"directory": "dist"
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "beabe8a971b6170bddfe08ae3f5ca2f1bfe66aa7"
|
|
78
78
|
}
|
|
@@ -515,8 +515,9 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
|
|
|
515
515
|
return next();
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
// For other routes, only proceed if path
|
|
519
|
-
|
|
518
|
+
// For other routes, only proceed if path equals basePath or path starts with basePath + '/'
|
|
519
|
+
const pathMatchesBasePath = req.path === basePath || req.path.startsWith(basePath + '/');
|
|
520
|
+
if (!pathMatchesBasePath) {
|
|
520
521
|
return next();
|
|
521
522
|
}
|
|
522
523
|
|
|
@@ -13,6 +13,7 @@ var _ssrCache = require("../../utils/ssr-cache");
|
|
|
13
13
|
var _ssrServer = require("../../utils/ssr-server");
|
|
14
14
|
var ssrServerUtils = _interopRequireWildcard(require("../../utils/ssr-server/utils"));
|
|
15
15
|
var ssrConfig = _interopRequireWildcard(require("../../utils/ssr-config"));
|
|
16
|
+
var ssrNamespacePaths = _interopRequireWildcard(require("../../utils/ssr-namespace-paths"));
|
|
16
17
|
var _buildRemoteServer = require("./build-remote-server");
|
|
17
18
|
var _constants = require("./constants");
|
|
18
19
|
var _express2 = require("./express");
|
|
@@ -1191,10 +1192,11 @@ describe('SLAS private client proxy', () => {
|
|
|
1191
1192
|
}));
|
|
1192
1193
|
});
|
|
1193
1194
|
describe('Base path tests', () => {
|
|
1195
|
+
afterEach(() => {
|
|
1196
|
+
jest.restoreAllMocks();
|
|
1197
|
+
});
|
|
1194
1198
|
test('Base path is removed from /mobify request path and still gets through to /mobify endpoint', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1195
|
-
jest.spyOn(
|
|
1196
|
-
envBasePath: '/basepath'
|
|
1197
|
-
});
|
|
1199
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1198
1200
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1199
1201
|
return (0, _supertest.default)(app).get('/basepath/mobify/ping').then(response => {
|
|
1200
1202
|
expect(response.status).toBe(200);
|
|
@@ -1202,9 +1204,7 @@ describe('Base path tests', () => {
|
|
|
1202
1204
|
}), 15000);
|
|
1203
1205
|
test('should not remove base path from non /mobify non-express routes', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1204
1206
|
// Set base path to something that might also be a site id used by react router routes
|
|
1205
|
-
jest.spyOn(
|
|
1206
|
-
envBasePath: '/us'
|
|
1207
|
-
});
|
|
1207
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/us');
|
|
1208
1208
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1209
1209
|
|
|
1210
1210
|
// Add a middleware to capture the request path after base path processing
|
|
@@ -1221,9 +1221,7 @@ describe('Base path tests', () => {
|
|
|
1221
1221
|
});
|
|
1222
1222
|
}), 15000);
|
|
1223
1223
|
test('should remove base path from routes with path parameters', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1224
|
-
jest.spyOn(
|
|
1225
|
-
envBasePath: '/basepath'
|
|
1226
|
-
});
|
|
1224
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1227
1225
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1228
1226
|
app.get('/api/users/:id', (req, res) => {
|
|
1229
1227
|
res.status(200).json({
|
|
@@ -1236,9 +1234,7 @@ describe('Base path tests', () => {
|
|
|
1236
1234
|
});
|
|
1237
1235
|
}), 15000);
|
|
1238
1236
|
test('should remove base path from routes defined with regex', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1239
|
-
jest.spyOn(
|
|
1240
|
-
envBasePath: '/basepath'
|
|
1241
|
-
});
|
|
1237
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1242
1238
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1243
1239
|
app.get(/\/api\/users\/\d+/, (req, res) => {
|
|
1244
1240
|
// Extract the user ID from the URL path since regex routes don't create req.params automatically
|
|
@@ -1253,25 +1249,8 @@ describe('Base path tests', () => {
|
|
|
1253
1249
|
expect(response.body.userId).toBe('123');
|
|
1254
1250
|
});
|
|
1255
1251
|
}), 15000);
|
|
1256
|
-
test('remove base path can handle multi-part base paths', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1257
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
1258
|
-
envBasePath: '/my/base/path'
|
|
1259
|
-
});
|
|
1260
|
-
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1261
|
-
app.get('/api/test', (req, res) => {
|
|
1262
|
-
res.status(200).json({
|
|
1263
|
-
message: 'test'
|
|
1264
|
-
});
|
|
1265
|
-
});
|
|
1266
|
-
return (0, _supertest.default)(app).get('/my/base/path/api/test').then(response => {
|
|
1267
|
-
expect(response.status).toBe(200);
|
|
1268
|
-
expect(response.body.message).toBe('test');
|
|
1269
|
-
});
|
|
1270
|
-
}), 15000);
|
|
1271
1252
|
test('should handle optional characters in route pattern', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1272
|
-
jest.spyOn(
|
|
1273
|
-
envBasePath: '/basepath'
|
|
1274
|
-
});
|
|
1253
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1275
1254
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1276
1255
|
|
|
1277
1256
|
// This route is intentionally made complex to test the following:
|
|
@@ -4,9 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.ssrNamespace = exports.slasPrivateProxyPath = exports.proxyBasePath = exports.healthCheckPath = exports.getEnvBasePath = exports.cachingBasePath = exports.bundleBasePath = void 0;
|
|
7
|
-
var _ssrConfig = require("./ssr-config");
|
|
8
|
-
var _loggerInstance = _interopRequireDefault(require("./logger-instance"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
7
|
/*
|
|
11
8
|
* Copyright (c) 2025, salesforce.com, inc.
|
|
12
9
|
* All rights reserved.
|
|
@@ -32,35 +29,39 @@ const SLAS_PRIVATE_CLIENT_PROXY_PATH = `${MOBIFY_PATH}/slas/private`;
|
|
|
32
29
|
|
|
33
30
|
/*
|
|
34
31
|
* Returns the base path. This is prepended to a /mobify path.
|
|
35
|
-
* Returns an empty string if the base path is not set
|
|
32
|
+
* Returns an empty string if the base path is not set.
|
|
33
|
+
* Throws an error if the base path is not valid.
|
|
34
|
+
*
|
|
35
|
+
* Use this function if you are working with an express route
|
|
36
|
+
* (ie. The route is defined in ssr.js).
|
|
37
|
+
*
|
|
38
|
+
* Use getRouterBasePath (pwa-kit-react-sdk) if you are working
|
|
39
|
+
* with a React Router route
|
|
40
|
+
* (ie. The route is defined in routes.jsx).
|
|
36
41
|
*/
|
|
37
42
|
const getEnvBasePath = () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
return '';
|
|
43
|
+
let basePath = '';
|
|
44
|
+
if (typeof window !== 'undefined') {
|
|
45
|
+
basePath = window.__MRT_ENV_BASE_PATH__ || '';
|
|
46
|
+
} else {
|
|
47
|
+
basePath = process.env.MRT_ENV_BASE_PATH || '';
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
.replace(/\/+/g, '/') // Normalize multiple slashes
|
|
50
|
-
.replace(/\/$/, ''); // Remove trailing slash
|
|
51
|
-
|
|
52
|
-
// Return empty string for root path or empty result
|
|
53
|
-
if (basePath === '/' || !basePath) {
|
|
50
|
+
// Return empty string if no base path is set
|
|
51
|
+
if (!basePath) {
|
|
54
52
|
return '';
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
// MRT will throw an error on bundle upload if the base path does not match
|
|
56
|
+
// the following regex: /^\/[a-zA-Z0-9_.+$~"'@:-]{1,63}$/
|
|
57
|
+
// This validates:
|
|
58
|
+
// - Starts with /
|
|
59
|
+
// - Followed by 1-63 characters (letters, numbers, and special chars: - _ . + $ ~ " ' @ :)
|
|
60
|
+
// - No additional slashes (multi-part paths not allowed, no trailing slashes)
|
|
61
|
+
// - No spaces
|
|
62
|
+
// - Total max length of 64 characters (1 slash + 63 chars)
|
|
63
|
+
if (!/^\/[a-zA-Z0-9_.+$~"'@:-]{1,63}$/.test(basePath)) {
|
|
64
|
+
throw new Error("Invalid envBasePath configuration. Base path must start with '/' followed by 1-63 characters. Only letters, numbers, and the following special characters are allowed: - _ . + $ ~ \" ' @ :");
|
|
64
65
|
}
|
|
65
66
|
return basePath;
|
|
66
67
|
};
|
|
@@ -1,55 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _ssrNamespacePaths = require("./ssr-namespace-paths");
|
|
4
|
-
var
|
|
5
|
-
function
|
|
6
|
-
|
|
4
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
7
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
8
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*
|
|
7
9
|
* Copyright (c) 2024, Salesforce, Inc.
|
|
8
10
|
* All rights reserved.
|
|
9
11
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
10
12
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
11
13
|
*/
|
|
12
|
-
|
|
13
|
-
jest.mock('./ssr-config');
|
|
14
14
|
describe('ssr-namespace-paths tests', () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
|
|
15
|
+
const originalEnv = process.env;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.resetModules();
|
|
18
|
+
process.env = _objectSpread({}, originalEnv);
|
|
19
|
+
delete process.env.MRT_ENV_BASE_PATH;
|
|
20
|
+
// Ensure we're in Node environment (no window)
|
|
21
|
+
delete global.window;
|
|
20
22
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
process.env = originalEnv;
|
|
25
|
+
delete global.window;
|
|
24
26
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
describe('Node environment (process.env)', () => {
|
|
28
|
+
test('getEnvBasePath returns base path from environment variable', () => {
|
|
29
|
+
process.env.MRT_ENV_BASE_PATH = '/sample';
|
|
30
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
28
31
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
test('getEnvBasePath removes trailing slash', () => {
|
|
32
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
33
|
-
envBasePath: '/sample/'
|
|
32
|
+
test('getEnvBasePath returns empty string if no base path is set', () => {
|
|
33
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('');
|
|
34
34
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
39
|
-
envBasePath: '/sample.*'
|
|
35
|
+
test('getEnvBasePath throws error for base path with trailing slash', () => {
|
|
36
|
+
process.env.MRT_ENV_BASE_PATH = '/sample/';
|
|
37
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
40
38
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
test('getEnvBasePath throws error for just a slash', () => {
|
|
40
|
+
process.env.MRT_ENV_BASE_PATH = '/';
|
|
41
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
42
|
+
});
|
|
43
|
+
test('getEnvBasePath throws error if invalid characters are detected in envBasePath', () => {
|
|
44
|
+
process.env.MRT_ENV_BASE_PATH = '/sample<script>';
|
|
45
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
46
|
+
});
|
|
47
|
+
test('getEnvBasePath throws error for envBasePath with whitespace', () => {
|
|
48
|
+
process.env.MRT_ENV_BASE_PATH = ' /sample ';
|
|
49
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
50
|
+
});
|
|
51
|
+
test('getEnvBasePath throws error for multi-part base paths with slashes', () => {
|
|
52
|
+
process.env.MRT_ENV_BASE_PATH = '/test/sample';
|
|
53
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
54
|
+
});
|
|
55
|
+
test('getEnvBasePath allows special characters: . + $ ~ " \' @ : -', () => {
|
|
56
|
+
process.env.MRT_ENV_BASE_PATH = '/a.b+c$d~e"f\'g@h:i-j_k';
|
|
57
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/a.b+c$d~e"f\'g@h:i-j_k');
|
|
58
|
+
});
|
|
59
|
+
test('getEnvBasePath throws error if base path exceeds 64 characters', () => {
|
|
60
|
+
// 65 characters total (1 slash + 64 chars)
|
|
61
|
+
process.env.MRT_ENV_BASE_PATH = '/' + 'a'.repeat(64);
|
|
62
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
63
|
+
});
|
|
64
|
+
test('getEnvBasePath allows base path of exactly 64 characters', () => {
|
|
65
|
+
// 64 characters total (1 slash + 63 chars)
|
|
66
|
+
process.env.MRT_ENV_BASE_PATH = '/' + 'a'.repeat(63);
|
|
67
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/' + 'a'.repeat(63));
|
|
46
68
|
});
|
|
47
|
-
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
48
69
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
70
|
+
describe('Browser environment (window)', () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
global.window = {};
|
|
73
|
+
});
|
|
74
|
+
test('getEnvBasePath returns base path from window global', () => {
|
|
75
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample';
|
|
76
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
77
|
+
});
|
|
78
|
+
test('getEnvBasePath returns empty string if window global is not set', () => {
|
|
79
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('');
|
|
80
|
+
});
|
|
81
|
+
test('getEnvBasePath throws error for base path with trailing slash from window global', () => {
|
|
82
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample/';
|
|
83
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
84
|
+
});
|
|
85
|
+
test('getEnvBasePath throws error for window global value with whitespace', () => {
|
|
86
|
+
global.window.__MRT_ENV_BASE_PATH__ = ' /sample ';
|
|
87
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
88
|
+
});
|
|
89
|
+
test('getEnvBasePath throws error if invalid characters in window global', () => {
|
|
90
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample<script>';
|
|
91
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
92
|
+
});
|
|
93
|
+
test('getEnvBasePath throws error for multi-part base paths in window global', () => {
|
|
94
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/test/sample';
|
|
95
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
52
96
|
});
|
|
53
|
-
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/test/sample');
|
|
54
97
|
});
|
|
55
98
|
});
|