@speedkit/cli 2.20.0 → 2.22.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/CHANGELOG.md +17 -0
- package/README.md +1 -1
- package/dist/services/customer-config/customer-config-service-model.d.ts +1 -0
- package/dist/services/customer-config/customer-config-service.js +5 -1
- package/dist/services/customer-config/templates/config_SpeedKit.js.hbs +35 -1
- package/dist/services/customer-config/templates/config_customer.js.hbs +6 -2
- package/dist/services/customer-config/templates/config_documentHandler.js.hbs +5 -0
- package/dist/services/document-handler-runtime/document-handler-server.d.ts +2 -1
- package/dist/services/document-handler-runtime/document-handler-server.js +27 -14
- package/dist/services/integration-api/handler/customer-config-handler.js +6 -3
- package/dist/services/integration-api/struct/customer-config-file.js +4 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [2.22.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.21.0...v2.22.0) (2024-04-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **customer-config:** add blacklist html returning false by default to document handler config ([954014c](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/954014ca9211e8da4129e781a5762362da6b8f9f))
|
|
7
|
+
* **customer-config:** implement scopes handling ([8f8f0c4](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/8f8f0c413a3e9166d26105f567bb6af884adbba7))
|
|
8
|
+
* **customer-config:** update scopes handling ([257090b](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/257090ba71cc04ecb298345948367545e0564589))
|
|
9
|
+
|
|
10
|
+
# [2.21.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.20.0...v2.21.0) (2024-04-10)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **onboarding:** add filePath to all vm.evalCalls) ([cf2ef00](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/cf2ef009283400b9c490f52f47f8c8000005adea))
|
|
16
|
+
* **onboarding:** enable advanced debugging ([96130c1](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/96130c1c7339f991a3c35b2eec7528ba0d26da25))
|
|
17
|
+
|
|
1
18
|
# [2.20.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.19.0...v2.20.0) (2024-04-10)
|
|
2
19
|
|
|
3
20
|
|
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ export interface CustomerConfigSettings {
|
|
|
23
23
|
appName?: string;
|
|
24
24
|
production?: EnvironmentConfig;
|
|
25
25
|
staging?: EnvironmentConfig;
|
|
26
|
+
subRouteScope?: string;
|
|
26
27
|
includeServiceWorker?: string;
|
|
27
28
|
activateImageOptimisation?: boolean;
|
|
28
29
|
removeLazyLoading?: boolean;
|
|
@@ -161,7 +161,7 @@ class CustomerConfigService {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
async getConfigSettings() {
|
|
164
|
-
let { production, staging, includeServiceWorker, activateImageOptimisation, removeLazyLoading, addPreRendering, activateRumTracking, useGATracking, withGoogleOptimize, activateCfRocketLoaderWorkaround, isShopify, isShopware, isSalesforce, isPlentymarkets, shopifyId, } = {};
|
|
164
|
+
let { production, staging, subRouteScope, includeServiceWorker, activateImageOptimisation, removeLazyLoading, addPreRendering, activateRumTracking, useGATracking, withGoogleOptimize, activateCfRocketLoaderWorkaround, isShopify, isShopware, isSalesforce, isPlentymarkets, shopifyId, } = {};
|
|
165
165
|
this.appName = await this.cli.prompt(`Enter SK App Name:`, {
|
|
166
166
|
validator: (input) => /^[\da-z]+(?:-[\da-z]+)*$/.test(input) ? "" : "No valid kebab-case",
|
|
167
167
|
defaultAnswer: this.appName,
|
|
@@ -199,6 +199,9 @@ class CustomerConfigService {
|
|
|
199
199
|
staging = await this.getEnvironmentConfig(customer_config_service_model_1.EnvironmentType.STAGING, production.host.replace("www", "stg"));
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
+
if (await this.cli.confirm("Should SK only be active on specific sub-routes? (e.g. /de-de)", false)) {
|
|
203
|
+
subRouteScope = await this.cli.prompt("Enter one exemplary sub-route to scope to (without leading/trailing slashes):", { defaultAnswer: "de-de" });
|
|
204
|
+
}
|
|
202
205
|
if (await this.cli.confirm("Is there a Service Worker which needs to be included?", false)) {
|
|
203
206
|
includeServiceWorker = await this.cli.prompt("Enter path of Service Worker to be included:", { defaultAnswer: "/sw.js" });
|
|
204
207
|
}
|
|
@@ -217,6 +220,7 @@ class CustomerConfigService {
|
|
|
217
220
|
appName: this.appName,
|
|
218
221
|
production,
|
|
219
222
|
staging,
|
|
223
|
+
subRouteScope,
|
|
220
224
|
includeServiceWorker,
|
|
221
225
|
activateImageOptimisation,
|
|
222
226
|
removeLazyLoading,
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
// Production:
|
|
4
4
|
{
|
|
5
5
|
hosts: ["{{production.host}}"],
|
|
6
|
+
{{#if subRouteScope}}
|
|
7
|
+
scopes: ["{{subRouteScope}}"],
|
|
8
|
+
{{/if}}
|
|
6
9
|
split: 0,
|
|
7
10
|
splitTestId: "0vs100_20xx-xx-xx",
|
|
8
11
|
},
|
|
@@ -11,6 +14,9 @@
|
|
|
11
14
|
// Staging:
|
|
12
15
|
{
|
|
13
16
|
hosts: ["{{staging.host}}"],
|
|
17
|
+
{{#if subRouteScope}}
|
|
18
|
+
scopes: ["{{subRouteScope}}"],
|
|
19
|
+
{{/if}}
|
|
14
20
|
},
|
|
15
21
|
{{else}}
|
|
16
22
|
// No Staging configured
|
|
@@ -100,7 +106,7 @@
|
|
|
100
106
|
// – unless this has been explicitly requested!
|
|
101
107
|
contentType: ["script", "style", "font"],
|
|
102
108
|
},
|
|
103
|
-
|
|
109
|
+
|
|
104
110
|
// Shopify specific:
|
|
105
111
|
{
|
|
106
112
|
url: [
|
|
@@ -323,7 +329,14 @@
|
|
|
323
329
|
|
|
324
330
|
// Lookup for matching enabled hosts config
|
|
325
331
|
for (var i = 0; i < enabledHostsConfigs.length; i++) {
|
|
332
|
+
{{#if subRouteScope}}
|
|
333
|
+
if (
|
|
334
|
+
enabledHostsConfigs[i].hosts.indexOf(currentHost) !== -1 &&
|
|
335
|
+
isCurrentScopeEnabled(enabledHostsConfigs[i].scopes)
|
|
336
|
+
) {
|
|
337
|
+
{{else}}
|
|
326
338
|
if (enabledHostsConfigs[i].hosts.indexOf(currentHost) !== -1) {
|
|
339
|
+
{{/if}}
|
|
327
340
|
foundHostConfig = enabledHostsConfigs[i];
|
|
328
341
|
break; // Break out of the loop once the config related to the host is found
|
|
329
342
|
}
|
|
@@ -348,4 +361,25 @@
|
|
|
348
361
|
};
|
|
349
362
|
}
|
|
350
363
|
}
|
|
364
|
+
{{#if subRouteScope}}
|
|
365
|
+
|
|
366
|
+
function isCurrentScopeEnabled(enabledScopes) {
|
|
367
|
+
// Check if enabled scopes are provided
|
|
368
|
+
if (!enabledScopes) {
|
|
369
|
+
// If not: consider current scope as enabled due to no scoping
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Check if enabled scopes are provided as array
|
|
374
|
+
if (!Array.isArray(enabledScopes)) {
|
|
375
|
+
// If not: consider current scope as disabled due to faulty scoping
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Test if current scope matches enabled scopes
|
|
380
|
+
var pattern = "^/(" + enabledScopes.join("|") + ")/";
|
|
381
|
+
var regex = new RegExp(pattern);
|
|
382
|
+
return regex.test(location.pathname);
|
|
383
|
+
}
|
|
384
|
+
{{/if}}
|
|
351
385
|
})();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shop
|
|
2
|
+
* Shop/Frontend system in use:
|
|
3
3
|
{{#if isShopify}}
|
|
4
4
|
* - Shopify
|
|
5
5
|
{{else if isShopware}}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{{else if isPlentymarkets}}
|
|
10
10
|
* - Plentymarkets
|
|
11
11
|
{{else}}
|
|
12
|
-
* - TODO: enter name of
|
|
12
|
+
* - TODO: enter name of system in use
|
|
13
13
|
{{/if}}
|
|
14
14
|
*/
|
|
15
15
|
|
|
@@ -25,7 +25,11 @@ const shared = {
|
|
|
25
25
|
{{else}}
|
|
26
26
|
swPath: "/wrapper-sw.js",
|
|
27
27
|
{{/if}}
|
|
28
|
+
{{#if subRouteScope}}
|
|
29
|
+
scope: "/{{subRouteScope}}/",
|
|
30
|
+
{{else}}
|
|
28
31
|
scope: "/",
|
|
32
|
+
{{/if}}
|
|
29
33
|
};
|
|
30
34
|
|
|
31
35
|
const configs = {
|
|
@@ -45,6 +45,11 @@ const lazyLoadList = [
|
|
|
45
45
|
{{/unless}}
|
|
46
46
|
const config = {
|
|
47
47
|
rejectHTML({ db, {{#if addPreRendering}}document{{else}}html{{/if}}, variation, url, headers }) {
|
|
48
|
+
/* Use to configure guards to prevent e.g. error and captcha pages from being cached */
|
|
49
|
+
return false;
|
|
50
|
+
},
|
|
51
|
+
blacklistHTML({ db, {{#if addPreRendering}}document{{else}}html{{/if}}, variation, url, headers }) {
|
|
52
|
+
/* Use to configure guards to black-list e.g. specific page types */
|
|
48
53
|
return false;
|
|
49
54
|
},
|
|
50
55
|
shouldTransform({ db, {{#if addPreRendering}}document{{else}}html{{/if}}, variation, url, headers }) {
|
|
@@ -9,6 +9,7 @@ export declare class DocumentHandlerServer {
|
|
|
9
9
|
private cli;
|
|
10
10
|
private verboseLevel;
|
|
11
11
|
private documentHandlerCode;
|
|
12
|
+
private documentHandlerConfigCode;
|
|
12
13
|
private database;
|
|
13
14
|
constructor(customerConfig: CustomerConfig, files: FileListInterface, bundler: BundleService, cli: CliService, verboseLevel?: boolean);
|
|
14
15
|
transform(html: string, variation: string, url: string, headers: {
|
|
@@ -16,7 +17,7 @@ export declare class DocumentHandlerServer {
|
|
|
16
17
|
}): Promise<string>;
|
|
17
18
|
private getTransformFunctionWrapper;
|
|
18
19
|
buildDocumentHandler(): Promise<void>;
|
|
19
|
-
private
|
|
20
|
+
private createDocumentHandlerConfigFile;
|
|
20
21
|
private getDocumentHandler;
|
|
21
22
|
private getDynamicFetcher;
|
|
22
23
|
private getDynamicFetcherConfig;
|
|
@@ -18,6 +18,7 @@ class DocumentHandlerServer {
|
|
|
18
18
|
cli;
|
|
19
19
|
verboseLevel;
|
|
20
20
|
documentHandlerCode;
|
|
21
|
+
documentHandlerConfigCode;
|
|
21
22
|
database;
|
|
22
23
|
constructor(customerConfig, files, bundler, cli, verboseLevel = false) {
|
|
23
24
|
this.customerConfig = customerConfig;
|
|
@@ -44,20 +45,32 @@ class DocumentHandlerServer {
|
|
|
44
45
|
DYNAMIC_FETCHER: await this.getDynamicFetcher(),
|
|
45
46
|
DYNAMIC_FETCHER_CONFIG: await this.getDynamicFetcherConfig(),
|
|
46
47
|
CUSTOM_STYLES: this.getStyles(),
|
|
48
|
+
...this.getContextVars(),
|
|
47
49
|
...this.createNodeVmContext(),
|
|
48
50
|
};
|
|
49
|
-
const
|
|
51
|
+
const customDocumentHandlerFile = this.files.getByName(files_1.INTEGRATION_FILES.CUSTOM.DOCUMENT_HANDLER);
|
|
52
|
+
if (customDocumentHandlerFile.path) {
|
|
53
|
+
vm.runInNewContext(this.documentHandlerCode, vmContext, {
|
|
54
|
+
filename: customDocumentHandlerFile.path,
|
|
55
|
+
displayErrors: true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
vm.runInNewContext(this.documentHandlerCode, vmContext);
|
|
60
|
+
}
|
|
61
|
+
const configDocumentHandlerPath = this.files.getByName("config_documentHandler").path;
|
|
62
|
+
const script = new vm.Script(this.documentHandlerConfigCode + this.getTransformFunctionWrapper(), {
|
|
63
|
+
filename: configDocumentHandlerPath,
|
|
64
|
+
});
|
|
50
65
|
try {
|
|
51
66
|
return await (async () => {
|
|
52
67
|
return await new Promise((resolve, reject) => {
|
|
53
|
-
|
|
54
|
-
// @ts-expect-error
|
|
68
|
+
// @ts-expect-error resolve is unknown
|
|
55
69
|
vmContext.resolve = resolve;
|
|
56
|
-
// @ts-expect-error
|
|
70
|
+
// @ts-expect-error reject is unknown
|
|
57
71
|
vmContext.reject = reject;
|
|
58
|
-
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
|
59
72
|
const context = vm.createContext(vmContext);
|
|
60
|
-
script.runInContext(context);
|
|
73
|
+
script.runInContext(context, { displayErrors: true });
|
|
61
74
|
});
|
|
62
75
|
})();
|
|
63
76
|
}
|
|
@@ -72,13 +85,13 @@ class DocumentHandlerServer {
|
|
|
72
85
|
return `\n\ndocumentHandler.transform(db, skInternalRequest).then(result => {resolve(result);}).catch((err)=>{reject(err);});`;
|
|
73
86
|
}
|
|
74
87
|
async buildDocumentHandler() {
|
|
75
|
-
this.documentHandlerCode = await this.
|
|
88
|
+
this.documentHandlerCode = await this.getDocumentHandler();
|
|
89
|
+
this.documentHandlerConfigCode =
|
|
90
|
+
await this.createDocumentHandlerConfigFile();
|
|
76
91
|
this.cli.writeSuccess("rebuild documentHandler");
|
|
77
92
|
}
|
|
78
|
-
async
|
|
79
|
-
|
|
80
|
-
const documentHandlerConfig = this.getDocumentHandlerConfig().replace("export const post", "const post");
|
|
81
|
-
return `${this.getContextVars()} ${documentHandler} ${documentHandlerConfig}`;
|
|
93
|
+
async createDocumentHandlerConfigFile() {
|
|
94
|
+
return this.getDocumentHandlerConfig().replace("export const post", "const post");
|
|
82
95
|
}
|
|
83
96
|
async getDocumentHandler() {
|
|
84
97
|
return this.files
|
|
@@ -113,11 +126,11 @@ class DocumentHandlerServer {
|
|
|
113
126
|
return documentHandlerFile.getContent();
|
|
114
127
|
}
|
|
115
128
|
getContextVars() {
|
|
116
|
-
|
|
129
|
+
const contextVariables = {};
|
|
117
130
|
for (const key in this.customerConfig) {
|
|
118
|
-
|
|
131
|
+
contextVariables[key.toUpperCase()] = this.customerConfig[key];
|
|
119
132
|
}
|
|
120
|
-
return
|
|
133
|
+
return contextVariables;
|
|
121
134
|
}
|
|
122
135
|
async createDataBaseMock() {
|
|
123
136
|
const vmConsole = {
|
|
@@ -25,11 +25,11 @@ class CustomerConfigHandler extends file_handler_1.default {
|
|
|
25
25
|
}
|
|
26
26
|
async handle(filePath) {
|
|
27
27
|
const fileContent = await this.fileReader.getContent(filePath);
|
|
28
|
-
const config = await this.loadConfig(fileContent);
|
|
28
|
+
const config = await this.loadConfig(fileContent, filePath);
|
|
29
29
|
this.validator.validate(config);
|
|
30
30
|
return new customer_config_file_1.default(this.getFileName(filePath), filePath, fileContent, config, this.configName, this.testApp);
|
|
31
31
|
}
|
|
32
|
-
async loadConfig(fileContent) {
|
|
32
|
+
async loadConfig(fileContent, filePath) {
|
|
33
33
|
if ((fileContent.includes("process.env.TEST_APP") && this.testApp === null) ||
|
|
34
34
|
this.testApp.length === 0) {
|
|
35
35
|
throw new customer_config_error_1.default("please specify env TEST_APP in your .env or configFile file");
|
|
@@ -40,7 +40,10 @@ class CustomerConfigHandler extends file_handler_1.default {
|
|
|
40
40
|
env: { TEST_APP: this.testApp }, // make TEST_APP available for vm
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
|
-
vm.runInNewContext(fileContent, customerConfigContext
|
|
43
|
+
vm.runInNewContext(fileContent, customerConfigContext, {
|
|
44
|
+
filename: filePath,
|
|
45
|
+
displayErrors: true,
|
|
46
|
+
});
|
|
44
47
|
const configs = customerConfigContext?.module?.exports;
|
|
45
48
|
if (Array.isArray(configs) ||
|
|
46
49
|
typeof configs === "string" ||
|
|
@@ -25,7 +25,10 @@ class CustomerConfigFile extends file_1.default {
|
|
|
25
25
|
env: { TEST_APP: this.testApp }, // make TEST_APP available for vm
|
|
26
26
|
},
|
|
27
27
|
};
|
|
28
|
-
vm.runInNewContext(this.getContent(), customerConfigContext
|
|
28
|
+
vm.runInNewContext(this.getContent(), customerConfigContext, {
|
|
29
|
+
filename: this.path,
|
|
30
|
+
displayErrors: true,
|
|
31
|
+
});
|
|
29
32
|
if (this.configName in customerConfigContext.module.exports) {
|
|
30
33
|
this.config = customer_config_1.default.createFrom(customerConfigContext.module.exports[this.configName], this.configName);
|
|
31
34
|
}
|
package/oclif.manifest.json
CHANGED