@speedkit/cli 3.9.1 → 3.11.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 CHANGED
@@ -1,3 +1,37 @@
1
+ # [3.11.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.10.0...v3.11.0) (2025-10-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * broken version reference in updated puppeteer package ([91c474f](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/91c474fcb774e61e772a55734df7fc7a2c0c4811))
7
+
8
+
9
+ ### Features
10
+
11
+ * improve default Shopify tracking code ([84496f3](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/84496f3a015587b986fa9394bacd9ddd80c7ff04))
12
+ * integrate new SPA bundle ([8330322](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/8330322a187c8659e84f1946d9f57d507a852842))
13
+
14
+ # [3.10.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.9.1...v3.10.0) (2025-10-15)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **wizard:** ssr ([7f48214](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/7f48214e04aae0183b4027e1d0b103f22bbb8499))
20
+ * **wizard:** ssr ([a848bb2](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/a848bb26f3fcafd79d12d7acbf4b9b4a32105ff4))
21
+
22
+
23
+ ### Features
24
+
25
+ * **customer-config:** improve root-referencing style handling by parallelizing css fetching ([907d487](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/907d4875ed738ac6ba773562907a947a529ac198))
26
+ * **customer-config:** move css processing from dh to lambda ([409da9b](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/409da9ba8c542ddcdc45feb5f25c06b3d98d37a3))
27
+ * **customer-config:** optimise ssr handling + provide dom-parsing dh as default ([ac0c2fa](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/ac0c2fab72f926d8a818d21dd8c0a67c736d033d))
28
+ * **customer-config:** prevent ssr shadow root container from being accessible by screen readers ([0743a91](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/0743a91a111ed1207fa3e8079c1a0f22166bc67c))
29
+ * **customer-config:** remove ssr tv blacklisting due to deprecation ([5a7e6c2](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/5a7e6c2bfb12678153d1f7dd2b16790a47c27484))
30
+ * **customer-config:** remove unnecessary ssr tablet disabling ([a48582f](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/a48582f65bb0f55019cc77476998c206f415d0ae))
31
+ * **customer-config:** scope shadow app root container positioning to pre-rendered pages ([46e970b](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/46e970b35295794b9e05c588bf34fc80470a2f84))
32
+ * **customer-config:** update ssr variation detection ([56a79b5](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/56a79b55f49b12628682bfbe9a23c403a39ebdba))
33
+ * **customer-config:** update ssr variation detection ([8744274](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/87442749b5a3dc730195d5f009316501d80ed95c))
34
+
1
35
  ## [3.9.1](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.9.0...v3.9.1) (2025-10-15)
2
36
 
3
37
 
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @speedkit/cli
21
21
  $ sk COMMAND
22
22
  running command...
23
23
  $ sk (--version)
24
- @speedkit/cli/3.9.1 linux-x64 node-v20.19.5
24
+ @speedkit/cli/3.11.0 linux-x64 node-v20.19.5
25
25
  $ sk --help [COMMAND]
26
26
  USAGE
27
27
  $ sk COMMAND
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const core_1 = require("@oclif/core");
5
5
  const cli_1 = require("baqend/cli");
6
- const promises_1 = require("node:fs/promises");
7
6
  const file_helper_1 = require("../helpers/file-helper");
8
7
  const cli_parameters_1 = require("../models/cli-parameters");
9
8
  const cli_2 = require("../services/cli");
10
9
  const config_api_service_1 = tslib_1.__importDefault(require("../services/config-api-service"));
11
- const diff_service_1 = require("../services/diff-service");
12
10
  const pop_config_1 = require("../services/pop-config");
11
+ const diff_1 = require("../services/diff");
12
+ const cli_config_1 = require("../helpers/cli-config");
13
13
  const POP_REMAPPING = {
14
14
  HHN: "FRA",
15
15
  };
@@ -131,16 +131,19 @@ class GeneratePopConfig extends core_1.Command {
131
131
  const database = await cli_1.account.login({ app });
132
132
  const configService = new config_api_service_1.default(database, app);
133
133
  const cliService = new cli_2.CliServiceFactory().getService();
134
- const diffService = new diff_service_1.DiffService(cliService);
134
+ const userConfig = new cli_config_1.CliConfig(this.config).load();
135
+ const diffService = new diff_1.DiffServiceFactory(new diff_1.DiffContext(userConfig.diffExec, userConfig.diffExecTemplate)).getService();
136
+ // new DiffService(cliService);
135
137
  const popPrewarmingCode = await this.createPopPrewarmingCode(config);
136
- const popPrewarmingCodePath = await diffService.writeContentToTemporalFile(`generated_${moduleName}`, popPrewarmingCode);
137
138
  const remoteConfig = await configService.getRemoteModule(moduleName);
138
- const doDeploy = deploy ??
139
- (await diffService.shouldDeployModule(moduleName, remoteConfig, popPrewarmingCodePath));
139
+ const result = await diffService.diffContent(moduleName, popPrewarmingCode, remoteConfig);
140
+ const content = result.changedOrigins;
141
+ const isEqual = result.diff;
142
+ if (isEqual) {
143
+ cliService.write(`created config is the same as the deployed one`);
144
+ }
145
+ const doDeploy = !isEqual && (deploy ?? (await cliService.confirm("deploy changes?")));
140
146
  if (doDeploy) {
141
- const content = await (0, promises_1.readFile)(popPrewarmingCodePath, {
142
- encoding: "utf8",
143
- });
144
147
  await configService.saveRemoteModule(content, moduleName);
145
148
  this.log(`Changes for module ${moduleName} were updated successfully`);
146
149
  }
@@ -29,11 +29,9 @@ export interface CustomerConfigSettings {
29
29
  includeServiceWorker?: string;
30
30
  activateImageOptimisation?: boolean;
31
31
  removeLazyLoading?: boolean;
32
- addPreRendering?: boolean;
33
- addUADetection?: boolean;
34
- supportShadowDomInPreRendering?: boolean;
35
- shadowDomCustomElementPrefix?: string;
36
- activateRumTracking?: boolean;
32
+ addSSR?: boolean;
33
+ addSSRInnerShadowDomSupport?: boolean;
34
+ addDeviceDetection?: boolean;
37
35
  useGATracking?: boolean;
38
36
  useScrapingBee?: boolean;
39
37
  withGoogleOptimize?: boolean;
@@ -136,7 +136,7 @@ class CustomerConfigService {
136
136
  return true;
137
137
  }
138
138
  async getConfigSettings() {
139
- let { production, staging, activateScopedDeployments, subRouteScope, includeServiceWorker, activateImageOptimisation, removeLazyLoading, addPreRendering, addUADetection, supportShadowDomInPreRendering, shadowDomCustomElementPrefix, activateRumTracking, useGATracking, useScrapingBee, withGoogleOptimize, activateCfRocketLoaderWorkaround, hasSoftNavigations, isShopify, isShopware, isSalesforce, isOxid, isPlentymarkets, isPOV, } = {};
139
+ let { production, staging, activateScopedDeployments, subRouteScope, includeServiceWorker, activateImageOptimisation, removeLazyLoading, addSSR, addSSRInnerShadowDomSupport, addDeviceDetection, useGATracking, useScrapingBee, withGoogleOptimize, activateCfRocketLoaderWorkaround, hasSoftNavigations, isShopify, isShopware, isSalesforce, isOxid, isPlentymarkets, isPOV, } = {};
140
140
  this.appName = await this.cli.prompt(`[App Name] Enter desired SK app name:`, {
141
141
  validator: (input) => /^[\da-z]+(?:-[\da-z]+)*$/.test(input) ? "" : "No valid kebab-case",
142
142
  defaultAnswer: this.appName,
@@ -173,7 +173,7 @@ class CustomerConfigService {
173
173
  staging = await this.getEnvironmentConfig(customer_config_service_model_1.EnvironmentType.STAGING, production.host.replace("www", "staging"));
174
174
  }
175
175
  }
176
- activateScopedDeployments = await this.cli.confirm("[Scoping] Is the shop using (locale-based) sub-routes, like e.g. /de-de, on the basis of which scoped deployments should to be activated to prevent local-based changes from triggering a global deployment job?", false);
176
+ activateScopedDeployments = await this.cli.confirm("[Scoping] Is the shop using (locale-based) sub-resources, like e.g. /de-de/main.js, on the basis of which scoped deployments should to be activated to prevent local-based changes from triggering a global deployment job?", false);
177
177
  if (activateScopedDeployments &&
178
178
  (await this.cli.confirm("[Scoping] Should SK only be active on specific sub-routes? (e.g. /de-de)", false))) {
179
179
  subRouteScope = await this.cli.prompt("[Scoping] Enter one exemplary sub-route to scope SK to (without leading/trailing slashes):", { defaultAnswer: "de-de" });
@@ -181,29 +181,23 @@ class CustomerConfigService {
181
181
  if (await this.cli.confirm("[Service Worker] Is there a Service Worker which needs to be included?", false)) {
182
182
  includeServiceWorker = await this.cli.prompt("[Service Worker] Enter path of Service Worker to be included:", { defaultAnswer: "/sw.js" });
183
183
  }
184
- addUADetection = await this.cli.confirm("[Variation handling] Do mobile and desktop versions of the website differ in their HTML structure, which would require us to add variations?", false);
185
184
  activateImageOptimisation = await this.cli.confirm("[IO] Should image optimisation be activated?", false);
186
- removeLazyLoading = await this.cli.confirm("[Lazy-Loading] Does the shop require us to resolve lazy-loaded content?");
187
- if (await this.cli.confirm("[Lambda-SSR] Add server-side-rendering? This requires a set-up Lambda function to work. Also requires usage of the DOM-based DocumentHandler.", false)) {
188
- addPreRendering = true;
189
- if (await this.cli.confirm("[Lambda-SSR] Does the customer utilize Shadow DOMs? If so additional handling for this will be added.", false)) {
190
- supportShadowDomInPreRendering = true;
191
- shadowDomCustomElementPrefix = await this.cli.prompt("[Lambda-SSR] Please specify the prefix of the custom elements used (e.g. o2 uses tef-): ", { defaultAnswer: "custom-" });
185
+ removeLazyLoading = await this.cli.confirm("[Lazy Loading] Does the shop require us to resolve lazy-loaded content?");
186
+ if (await this.cli.confirm("[Lambda SSR] Add server-side-rendering? This requires a set-up Lambda function to work.", false)) {
187
+ addSSR = true;
188
+ if (await this.cli.confirm("[Lambda SSR] Does the customer utilize Shadow DOMs? If so additional handling for this will be added.", false)) {
189
+ addSSRInnerShadowDomSupport = true;
192
190
  }
193
- await this.cli.confirm("Confirm that you increased the Node memory limit to at least 1024 as the SSR setup is memory intensive." +
194
- ' BBQ App -> Data -> App -> Search for App -> Addons -> "nodeMemLimit": 1024', false);
195
191
  }
192
+ // ask for variation handling only if adding Lambda SSR is not needed, as it will come with device detection anyway
193
+ addDeviceDetection = addSSR
194
+ ? true
195
+ : await this.cli.confirm("[Device Detection] Do mobile and desktop versions of the website differ in their HTML structure, which would require us to add variations?", false);
196
196
  useScrapingBee = await this.cli.confirm("[ScrapingBee] Do customer responses differ geo-location-based which would require ScrapingBee API to fetch documents?", false);
197
- activateRumTracking = true;
198
- // activateRumTracking = await this.cli.confirm(
199
- // "[Tracking] Activate RUM Tracking?",
200
- // );
201
- // if (activateRumTracking) {
202
197
  if (!isShopify) {
203
198
  useGATracking = await this.cli.confirm("[Tracking] Add tracking based on Google Analytics' DataLayer?");
204
199
  }
205
200
  hasSoftNavigations = await this.cli.confirm("[Tracking] Add tracking for Soft Navigations?", false);
206
- // }
207
201
  isPOV = await this.cli.confirm("[Tracking] Is a POV (proof of value) anticipated, so that additional tracking is needed?", false);
208
202
  withGoogleOptimize = await this.cli.confirm("[Services] Is Google Optimize used?", false);
209
203
  activateCfRocketLoaderWorkaround = isShopify
@@ -218,11 +212,9 @@ class CustomerConfigService {
218
212
  includeServiceWorker,
219
213
  activateImageOptimisation,
220
214
  removeLazyLoading,
221
- addPreRendering,
222
- addUADetection,
223
- supportShadowDomInPreRendering,
224
- shadowDomCustomElementPrefix,
225
- activateRumTracking,
215
+ addSSR,
216
+ addSSRInnerShadowDomSupport,
217
+ addDeviceDetection,
226
218
  useGATracking,
227
219
  useScrapingBee,
228
220
  withGoogleOptimize,
@@ -25,30 +25,6 @@
25
25
  var ENABLED_HOSTS = getEnabledHosts(ENABLED_HOSTS_CONFIGS);
26
26
  var CURRENT_HOST_CONFIG = getCurrentHostConfig(ENABLED_HOSTS_CONFIGS);
27
27
 
28
- {{#if addPreRendering}}
29
- // Lambda SSR specific: disable SK for tablets as they are not covered in lambda
30
- function isTablet() {
31
- var userAgent = window.navigator.userAgent.toLowerCase();
32
- var tabletUAs = [
33
- /tablet/,
34
- /ipad/,
35
- /nexus 7/,
36
- /nexus 10/,
37
- /silk\//,
38
- /\bgt-[pn]\d{4}\b/,
39
- /\bsm-t\d{3}\b/,
40
- /^.*android(?!.*mobile|.*smart-tv|.*smarttv|.*aft[tm]|.*crkey).*$/,
41
- ];
42
-
43
- if ("ontouchend" in document && userAgent.indexOf("Macintosh") > -1) {
44
- return true;
45
- }
46
- return tabletUAs.some(function (ua) {
47
- return ua.test(userAgent);
48
- });
49
- }
50
- {{/if}}
51
-
52
28
  /**
53
29
  * @type {SpeedKitConfig}
54
30
  */
@@ -66,22 +42,36 @@
66
42
  includeServiceWorker: "{{includeServiceWorker}}",
67
43
  {{/if}}
68
44
  preloadDynamicBlocks: true,
69
- rumTracking: {{activateRumTracking}},
70
- {{#if addPreRendering}}
71
- // Lambda SSR specific: detect device to cover different resolutions when rendered in lambda
72
- userAgentDetection: true,
73
- {{else if addUADetection}}
74
- userAgentDetection: true,
45
+ rumTracking: true,
46
+ {{#if addDeviceDetection}}
47
+ {{#unless addSSR}}
48
+ userAgentDetection: true,
49
+ {{/unless}}
50
+ detectDevice: function(doc) {
51
+ {{#if addSSR}}
52
+ // SSR specific – identify device based on screen width:
53
+ // TODO: adjust devices + breakpoints to your needs
54
+ var width = window?.screen?.width || 1024;
55
+ if (width < 768) return "mobile";
56
+ return "desktop";
57
+ {{else}}
58
+ // TODO: adjust condition to your needs
59
+ return doc.querySelector('<mobile-specific-element>') ? "mobile" : "desktop";
60
+ {{/if}}
61
+ },
75
62
  {{/if}}
76
- {{#if addUADetection}}
77
- detectDevice: function(doc) {
78
- // TODO adjust condition to your needs
79
- return doc.querySelector('<mobile-specific-element>') ? "mobile" : "desktop";
80
- },
63
+ {{#if addSSR}}
64
+ customVariation: [
65
+ {
66
+ variationFunction: function (request, device, cookies) {
67
+ // SSR specific – don't report a variation for specific page types NOT covered by SSR:
68
+ // TODO: adjust and activate if needed
69
+ // if (request.url.indexOf("<url-page-type-idenfier>") > -1) return "desktop";
70
+ return device;
71
+ },
72
+ },
73
+ ],
81
74
  {{/if}}
82
- split: CURRENT_HOST_CONFIG.split,
83
- splitTestId: CURRENT_HOST_CONFIG.splitTestId,
84
- disabled: !CURRENT_HOST_CONFIG.enabled{{#if addPreRendering}} || isTablet(){{/if}},
85
75
  {{#if useScrapingBee}}
86
76
  customVariation: [
87
77
  {
@@ -94,6 +84,9 @@
94
84
  },
95
85
  ],
96
86
  {{/if}}
87
+ split: CURRENT_HOST_CONFIG.split,
88
+ splitTestId: CURRENT_HOST_CONFIG.splitTestId,
89
+ disabled: !CURRENT_HOST_CONFIG.enabled,
97
90
  enabledSites: [
98
91
  {
99
92
  pathname: [
@@ -150,12 +143,6 @@
150
143
  {{/if}}
151
144
  ],
152
145
  blacklist: [
153
- {{#if addPreRendering}}
154
- // blacklist tv variations
155
- {
156
- tv: true,
157
- },
158
- {{/if}}
159
146
  {
160
147
  pathname: [
161
148
  // TODO: adjust/replace this exemplary list
@@ -1,56 +1,46 @@
1
1
  {
2
- "production": {
3
- "_meta": {
4
- "shopSystem":
5
- {{#if isShopify}}
6
- "Shopify"
7
- {{else if isShopware}}
8
- "Shopware"
9
- {{else if isSalesforce}}
10
- "Salesforce Commerce Cloud"
11
- {{else if isOxid}}
12
- "OXID eShop"
13
- {{else if isPlentymarkets}}
14
- "Plentymarkets"
15
- {{else}}
16
- "TODO: enter name of system in use"
17
- {{/if}}
18
- },
19
- "app": "{{appName}}",
20
- "domain": "{{production.host}}",
21
- "origins": [
22
- "https://{{production.host}}"
23
- ],
24
- {{#if isShopify}}
25
- "swPath": "/apps/speed-kit/sw.js",
26
- {{else}}
27
- "swPath": "/wrapper-sw.js",
28
- {{/if}}
29
- {{#if subRouteScope}}
30
- "scope": "/{{subRouteScope}}/",
31
- {{else}}
32
- "scope": "/",
33
- {{/if}}
34
- "forceInstall": {{production.forceInstall}}
35
- }
36
- {{#if staging.host}},
37
- "staging": {
38
- "name": "staging",
39
- "domain": "{{staging.host}}",
40
- "origins": [
41
- "https://{{staging.host}}"
42
- ],
43
- "forceInstall": {{staging.forceInstall}},
44
- {{#if isShopify}}
45
- "swPath": "/apps/speed-kit/sw.js",
46
- {{else}}
47
- "swPath": "/wrapper-sw.js",
48
- {{/if}}
49
- {{#if subRouteScope}}
50
- "scope": "/{{subRouteScope}}/"
51
- {{else}}
52
- "scope": "/"
53
- {{/if}}
54
- }
55
- {{/if}}
2
+ "production": {
3
+ "_meta": {
4
+ "shopSystem":
5
+ {{#if isShopify}}
6
+ "Shopify"
7
+ {{else if isShopware}}
8
+ "Shopware"
9
+ {{else if isSalesforce}}
10
+ "Salesforce Commerce Cloud"
11
+ {{else if isOxid}}
12
+ "OXID eShop"
13
+ {{else if isPlentymarkets}}
14
+ "Plentymarkets"
15
+ {{else}}
16
+ "TODO: enter name of system in use"
17
+ {{/if}}
18
+ },
19
+ "app": "{{appName}}",
20
+ "domain": "{{production.host}}",
21
+ "origins": [
22
+ "https://{{production.host}}"
23
+ ],
24
+ {{#if isShopify}}
25
+ "swPath": "/apps/speed-kit/sw.js",
26
+ {{else}}
27
+ "swPath": "/wrapper-sw.js",
28
+ {{/if}}
29
+ {{#if subRouteScope}}
30
+ "scope": "/{{subRouteScope}}/",
31
+ {{else}}
32
+ "scope": "/",
33
+ {{/if}}
34
+ "forceInstall": {{production.forceInstall}}
35
+ }
36
+ {{#if staging.host}},
37
+ "staging": {
38
+ "name": "staging",
39
+ "domain": "{{staging.host}}",
40
+ "origins": [
41
+ "https://{{staging.host}}"
42
+ ],
43
+ "forceInstall": {{staging.forceInstall}},
44
+ }
45
+ {{/if}}
56
46
  }