@speedkit/cli 3.10.0 → 3.11.1

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,23 @@
1
+ ## [3.11.1](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.11.0...v3.11.1) (2025-10-21)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **wizard:** doc handler config typing ([764195d](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/764195ddc82c3936e024a0355cc3f5c4340a06c3))
7
+
8
+ # [3.11.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.10.0...v3.11.0) (2025-10-16)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * broken version reference in updated puppeteer package ([91c474f](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/91c474fcb774e61e772a55734df7fc7a2c0c4811))
14
+
15
+
16
+ ### Features
17
+
18
+ * improve default Shopify tracking code ([84496f3](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/84496f3a015587b986fa9394bacd9ddd80c7ff04))
19
+ * integrate new SPA bundle ([8330322](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/8330322a187c8659e84f1946d9f57d507a852842))
20
+
1
21
  # [3.10.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.9.1...v3.10.0) (2025-10-15)
2
22
 
3
23
 
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.10.0 linux-x64 node-v20.19.5
24
+ @speedkit/cli/3.11.1 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
  }
@@ -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" });
@@ -44,6 +44,9 @@
44
44
  ];
45
45
 
46
46
  {{/if}}
47
+ /**
48
+ * @type {DomDocumentHandlerConfig}
49
+ */
47
50
  const config = {
48
51
  rejectHTML({db, document, variation, url, headers}) {
49
52
  /* Use to configure guards to prevent e.g. error and captcha pages from being cached */
@@ -1,6 +1,6 @@
1
1
  import { BaseBundle } from 'rum/BaseBundle';
2
2
  {{#if hasSoftNavigations}}
3
- import { HistoryApiPlugin } from 'rum/HistoryApiPlugin';
3
+ import { SpaBundle } from 'rum/SpaBundle';
4
4
  {{/if}}
5
5
  {{#if useGATracking}}
6
6
  import { GAEcommerceTrackingPlugin } from 'rum/GAEcommerceTrackingPlugin';
@@ -16,12 +16,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
16
16
  if (window !== window.top) {
17
17
  return;
18
18
  }
19
- {{#if hasSoftNavigations}}
20
-
21
- // Soft Navigation Handling:
22
- var softLcpPending = false;
23
- var latestUrl = location.href;
24
- {{/if}}
25
19
  {{#if isOxid}}
26
20
 
27
21
  var pageTypeSent = false;
@@ -52,7 +46,7 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
52
46
  }
53
47
  {{/if}}),
54
48
  {{#if hasSoftNavigations}}
55
- new HistoryApiPlugin(), // Soft Navigation Tracking using History API
49
+ new SpaBundle(), // Soft Navigation Tracking using History API
56
50
  {{/if}}
57
51
  {{#if useGATracking}}
58
52
  new GAEcommerceTrackingPlugin({
@@ -67,9 +61,27 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
67
61
  new UserFrictionPlugin(),
68
62
  new ClickPlugin(),
69
63
  {{/if}}
64
+ {{#if isShopify}}
65
+ {
66
+ key: "loggedIn",
67
+ type: "PiDimension",
68
+ on: "window.ShopifyAnalytics",
69
+ set: function () {
70
+ return !!window.ShopifyAnalytics?.meta?.page?.customerId;
71
+ },
72
+ },
73
+ {
74
+ key: "pageType",
75
+ type: "PiDimension",
76
+ on: "window.ShopifyAnalytics",
77
+ set: function () {
78
+ return window.ShopifyAnalytics?.meta?.page?.pageType;
79
+ },
80
+ },
81
+ {{else}}
70
82
  {
71
83
  key: 'loggedIn',
72
- type: 'SessionDimension',
84
+ type: 'PiDimension',
73
85
  {{#if useGATracking}}
74
86
  on: 'dataLayer',
75
87
  set: function(pushedEvent) {
@@ -85,24 +97,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
85
97
  {
86
98
  key: 'pageType',
87
99
  type: 'PiDimension',
88
- {{#if isShopify}}
89
- on: 'window.ShopifyAnalytics',
90
- set: function() {
91
- var pathname = window.location.pathname;
92
- // TODO: verify pathname patterns
93
- if (pathname.indexOf('/checkouts/') > -1) {
94
- return 'checkout';
95
- } if (pathname.indexOf('/account/login') > -1) {
96
- return 'login';
97
- } if (pathname.indexOf('/account/register') > -1) {
98
- return 'register';
99
- } if (pathname.indexOf('/account') > -1) {
100
- return 'account';
101
- } else {
102
- return window.ShopifyAnalytics?.meta?.page?.pageType;
103
- }
104
- },
105
- {{else}}
106
100
  {{#if useGATracking}}
107
101
  on: 'dataLayer',
108
102
  set: function (pushedEvent) {
@@ -131,7 +125,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
131
125
  {{/if}}
132
126
  },
133
127
  {{/if}}
134
- {{/if}}
135
128
  },
136
129
  {{#if isOxid}}
137
130
  // OXID eShop specific fallback tracking for page type using URL:
@@ -160,6 +153,7 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
160
153
  },
161
154
  },
162
155
  {{/if}}
156
+ {{/if}}
163
157
  {{#if useGATracking}}
164
158
 
165
159
  // TODO: remove or adapt if events are not properly covered by GAEcommerceTrackingPlugin
@@ -218,36 +212,25 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
218
212
  // },
219
213
  {{else}}
220
214
  {{#if isShopify}}
221
-
222
- // {
223
- // key: 'ecAddToCart',
224
- // on: onAddToCartClick,
225
- // append: function () {
226
- // if (window.ShopifyAnalytics?.lib) {
227
- // var shopifyData = window.ShopifyAnalytics.lib;
228
- // var product;
229
- //
230
- // if (shopifyData && shopifyData.length) {
231
- // shopifyData.forEach(item => {
232
- // if (item[1] === "Viewed Product Variant") {
233
- // if(item.length > 2){
234
- // product = item[2];
235
- // }
236
- // }
237
- // });
238
- //
239
- // if (product) {
240
- // return {
241
- // id: product.productId + '_' + product.variantId, // optional – remove if no id is available
242
- // price: Number(product.price),
243
- // currencyCode: product.currency || defaultCurrency,
244
- // quantity: 1,
245
- // }
246
- // }
247
- // }
248
- // }
249
- // },
250
- // },
215
+ {
216
+ key: "ecAddToCart",
217
+ // TODO depending on the used theme different events are in use variant:added, product-ajax:added, product:added
218
+ // TODO the correct event can easily spotted by search for the initiator of the /cart/add request after doing a addToCart
219
+ on: (callback) => document.addEventListener("product-ajax:added", callback),
220
+ append: function (event) {
221
+ // TODO depending on the used event the product is exposed under a different property
222
+ var product = event.detail.product;
223
+
224
+ if (product) {
225
+ return {
226
+ id: product.product_id,
227
+ price: (product.discounted_price ?? product.price) / 100, // price is in cents
228
+ currencyCode: window.Shopify?.currency?.active || defaultCurrency,
229
+ quantity: product.quantity,
230
+ };
231
+ }
232
+ },
233
+ },
251
234
 
252
235
  // No custom ecConversion tracking event as it is already handled by the Speed Kit Extension for Shopify
253
236
  {{else}}
@@ -286,106 +269,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
286
269
  },
287
270
  {{/if}}
288
271
  {{/if}}
289
- {{#if hasSoftNavigations}}
290
- {
291
- on: "softNavigation",
292
- track: (controller) => {
293
- var onlyHashChanged =
294
- latestUrl.split("#")[0] === location.href.split("#")[0];
295
- latestUrl = location.href;
296
-
297
- if (onlyHashChanged) {
298
- controller.trackCustomEvent("hashChanged", location.href, Date.now());
299
- return;
300
- }
301
-
302
- controller.trackCustomEvent("softNav", location.href, Date.now());
303
-
304
- // Only capture soft LCP on following pages/page types:
305
- // TODO: update to match the resp. page types to capture
306
- var isProduct = location.href.indexOf("/p/") !== -1;
307
- var isCategory = location.href.indexOf("/c/") !== -1;
308
-
309
- if (!isCategory && !isProduct) return;
310
-
311
- var navStartMark = "soft-nav_" + location.pathname;
312
- performance.mark(navStartMark);
313
-
314
- softLcpPending = true;
315
-
316
- var softNavigationPerformanceObserver = new PerformanceObserver(
317
- (entries, observer) => {
318
- // TODO: update exemplary selectors within this block
319
-
320
- // Wait for product image resources to be loaded:
321
- var imageEntries = Array.from(entries.getEntries()).filter(
322
- (item) => item.name.indexOf("/product/image/") !== -1,
323
- );
324
-
325
- // Ensure product images can be found in requested resources list:
326
- if (!imageEntries || imageEntries.length < 1) {
327
- return;
328
- }
329
-
330
- // Wait for product hero image / first product image in list to be referenced in DOM:
331
- var imageElementSelector = isProduct
332
- ? ".product-details .slick-slide.slick-active img" // PDP hero image
333
- : ".product-list .product-image img"; // PLP list image(s)
334
-
335
- var imageElement = document.querySelector(imageElementSelector);
336
-
337
- // Ensure image element can be found in document:
338
- if (!imageElement) {
339
- return;
340
- }
341
- var imageUrl = imageElement.currentSrc || imageElement.srcset || "";
342
-
343
- var imageMatchingRequestedResource = imageEntries.filter(
344
- (entry) => {
345
- var urlObj = new URL(entry.name);
346
- return imageUrl.indexOf(urlObj.pathname) > -1;
347
- },
348
- )[0];
349
-
350
- // Ensure the resp. image source referenced in the document can be found in requested resources list:
351
- if (!imageMatchingRequestedResource) {
352
- return;
353
- }
354
-
355
- // Ensure Soft LCP is still pending:
356
- if (!softLcpPending) {
357
- return;
358
- }
359
-
360
- var measure = performance.measure("lcp_" + location.pathname, {
361
- start: navStartMark,
362
- end: imageMatchingRequestedResource.responseEnd,
363
- });
364
-
365
- var timing = {
366
- start: measure.startTime,
367
- duration: measure.duration,
368
- image: imageMatchingRequestedResource.name,
369
- url: window.location.href,
370
- };
371
- controller.trackCustomEvent(
372
- "softNavLcp",
373
- JSON.stringify(timing),
374
- Date.now(),
375
- );
376
-
377
- softNavigationPerformanceObserver.disconnect();
378
- softLcpPending = false;
379
- },
380
- );
381
-
382
- softNavigationPerformanceObserver.observe({
383
- buffered: true,
384
- type: "resource",
385
- });
386
- },
387
- },
388
- {{/if}}
389
272
  {{#if isPlentymarkets}}
390
273
  {
391
274
  on: "domInteractive",
@@ -396,20 +279,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
396
279
  },
397
280
  {{/if}}
398
281
  );
399
- {{#if isShopify}}
400
- // Shopify specific:
401
-
402
- // function onAddToCartClick(cb, controller) {
403
- // controller.onDOMInteractive(function() {
404
- // var addToCartBtn = document.querySelector('.button--add-to-cart');
405
- // if(addToCartBtn) {
406
- // addToCartBtn.addEventListener('click', function (t) {
407
- // cb(controller);
408
- // }, true);
409
- // }
410
- // })
411
- // }
412
- {{/if}}
413
282
  {{#if isPlentymarkets}}
414
283
 
415
284
  /* ==== */
@@ -4,7 +4,7 @@ exports.ExecutableValidator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  // import CLI from puppeteer to use function as sames as `npx puppeteer browsers install`
6
6
  const browsers_1 = require("@puppeteer/browsers");
7
- const version_js_1 = require("puppeteer-core/internal/generated/version.js");
7
+ const version_js_1 = require("puppeteer-core/lib/cjs/puppeteer/util/version.js");
8
8
  const node_fs_1 = require("node:fs");
9
9
  const application_error_1 = tslib_1.__importDefault(require("../../../error-handling/error/application-error"));
10
10
  const browsers_2 = require("@puppeteer/browsers");
@@ -732,5 +732,5 @@
732
732
  ]
733
733
  }
734
734
  },
735
- "version": "3.10.0"
735
+ "version": "3.11.1"
736
736
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "3.10.0",
4
+ "version": "3.11.1",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"
@@ -95,7 +95,7 @@
95
95
  "nypm": "^0.6.2",
96
96
  "parse5": "7.1",
97
97
  "parse5-htmlparser2-tree-adapter": "7.0.0",
98
- "puppeteer": "^24.16.0",
98
+ "puppeteer": "^24.25.0",
99
99
  "puppeteer-extra": "^3.3.6",
100
100
  "semver": "^7.6.3",
101
101
  "strip-comments": "^2.0.1",