@bigcommerce/stencil-cli 10.0.0 → 10.1.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/README.md +12 -0
- package/lib/MakeswiftPreview.js +253 -0
- package/lib/PreviewSessionClient.js +158 -0
- package/lib/PreviewSessionHeartbeat.js +117 -0
- package/lib/TunnelManager.js +134 -0
- package/lib/cloudflared-binary.js +266 -0
- package/lib/cloudflared-manifest.js +41 -0
- package/lib/makeswift-proxy-health.js +33 -0
- package/lib/preview-proxy.js +224 -0
- package/lib/stencil-start.js +38 -6
- package/lib/storefront-link-rewrite.js +46 -0
- package/package.json +3 -1
- package/server/index.js +7 -1
- package/server/plugins/preview-auth/preview-auth.module.js +38 -0
- package/server/plugins/renderer/responses/pencil-response.js +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigcommerce/stencil-cli",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI tool to run BigCommerce Stores locally for theme development.",
|
|
6
6
|
"main": "index.js",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"front-matter": "^4.0.2",
|
|
74
74
|
"glob": "^7.1.6",
|
|
75
75
|
"graceful-fs": "^4.2.4",
|
|
76
|
+
"http-proxy": "^1.18.1",
|
|
76
77
|
"husky": "^8.0.1",
|
|
77
78
|
"image-size": "^0.9.1",
|
|
78
79
|
"inquirer": "^8.1.5",
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
"recursive-readdir": "^2.2.2",
|
|
93
94
|
"semver": "^7.3.2",
|
|
94
95
|
"simple-git": "^3.26.0",
|
|
96
|
+
"tar": "^7.5.2",
|
|
95
97
|
"tarjan-graph": "^2.0.0",
|
|
96
98
|
"tmp-promise": "^3.0.2",
|
|
97
99
|
"upath": "^1.2.0",
|
package/server/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import 'colors';
|
|
|
8
8
|
|
|
9
9
|
const getDirname = dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
|
-
function buildManifest(srcManifest, options) {
|
|
11
|
+
export function buildManifest(srcManifest, options) {
|
|
12
12
|
const resManifest = _.cloneDeep(srcManifest);
|
|
13
13
|
const pluginsByName = resManifest.register.plugins;
|
|
14
14
|
const parsedSecureUrl = new URL(options.dotStencilFile.storeUrl); // The url to a secure page (prompted as login page)
|
|
@@ -42,6 +42,12 @@ function buildManifest(srcManifest, options) {
|
|
|
42
42
|
(pluginsArr, opts, plugin) => [...pluginsArr, { plugin, options: opts }],
|
|
43
43
|
[],
|
|
44
44
|
);
|
|
45
|
+
if (options.previewSecret) {
|
|
46
|
+
resManifest.register.plugins.unshift({
|
|
47
|
+
plugin: './plugins/preview-auth/preview-auth.module.js',
|
|
48
|
+
options: { secret: options.previewSecret },
|
|
49
|
+
});
|
|
50
|
+
}
|
|
45
51
|
return resManifest;
|
|
46
52
|
}
|
|
47
53
|
async function create(options) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import Boom from '@hapi/boom';
|
|
3
|
+
|
|
4
|
+
const PREVIEW_SECRET_HEADER = 'x-stencil-preview-secret';
|
|
5
|
+
|
|
6
|
+
// Hash both values so the comparison takes the same time for any input length.
|
|
7
|
+
function secretsMatch(expected, supplied) {
|
|
8
|
+
const digest = (value) => createHash('sha256').update(value).digest();
|
|
9
|
+
return timingSafeEqual(digest(expected), digest(supplied));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Loaded only in Makeswift preview mode.
|
|
14
|
+
*/
|
|
15
|
+
function register(server, { secret }) {
|
|
16
|
+
if (typeof secret !== 'string' || !secret) {
|
|
17
|
+
throw new Error('PreviewAuth requires a non-empty secret');
|
|
18
|
+
}
|
|
19
|
+
server.ext('onRequest', (request, h) => {
|
|
20
|
+
const supplied = request.headers[PREVIEW_SECRET_HEADER];
|
|
21
|
+
if (typeof supplied !== 'string') {
|
|
22
|
+
return Boom.unauthorized();
|
|
23
|
+
}
|
|
24
|
+
if (!secretsMatch(secret, supplied)) {
|
|
25
|
+
return Boom.forbidden();
|
|
26
|
+
}
|
|
27
|
+
delete request.headers[PREVIEW_SECRET_HEADER];
|
|
28
|
+
return h.continue;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export const name = 'PreviewAuth';
|
|
32
|
+
export const version = '0.0.1';
|
|
33
|
+
export { register };
|
|
34
|
+
export default {
|
|
35
|
+
register,
|
|
36
|
+
name,
|
|
37
|
+
version,
|
|
38
|
+
};
|
|
@@ -56,6 +56,15 @@ const isSupportedHandlebarsVersion = (version) =>
|
|
|
56
56
|
* @param {string} version
|
|
57
57
|
*/
|
|
58
58
|
const compatibilizeTemplateEngine = (version) => version.replace('_', '-');
|
|
59
|
+
/**
|
|
60
|
+
* Storefront headers that the Makeswift worker reads from the rendered page to find its
|
|
61
|
+
* Makeswift content.
|
|
62
|
+
*/
|
|
63
|
+
const MAKESWIFT_PAGE_HEADERS = [
|
|
64
|
+
'x-makeswift-stable-page-reference',
|
|
65
|
+
'x-makeswift-page-locale',
|
|
66
|
+
'x-makeswift-storefront-token',
|
|
67
|
+
];
|
|
59
68
|
/**
|
|
60
69
|
* Output post-processing
|
|
61
70
|
*
|
|
@@ -134,6 +143,11 @@ class PencilResponse {
|
|
|
134
143
|
if (this.data.headers['set-cookie']) {
|
|
135
144
|
response.header('set-cookie', this.data.headers['set-cookie']);
|
|
136
145
|
}
|
|
146
|
+
for (const name of MAKESWIFT_PAGE_HEADERS) {
|
|
147
|
+
if (this.data.headers[name]) {
|
|
148
|
+
response.header(name, this.data.headers[name]);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
137
151
|
return response;
|
|
138
152
|
} catch (err) {
|
|
139
153
|
console.error(err.message.red);
|