@speedkit/cli 3.10.0 → 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 +13 -0
- package/README.md +1 -1
- package/dist/commands/generate-pop-config.js +12 -9
- package/dist/services/customer-config/customer-config-service.js +1 -1
- package/dist/services/customer-config/templates/config_loadHandler.js.hbs +41 -172
- package/dist/services/onboarding/browser/executable/executable-validator.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
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
|
+
|
|
1
14
|
# [3.10.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.9.1...v3.10.0) (2025-10-15)
|
|
2
15
|
|
|
3
16
|
|
package/README.md
CHANGED
|
@@ -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
|
|
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
|
|
139
|
-
|
|
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-
|
|
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" });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseBundle } from 'rum/BaseBundle';
|
|
2
2
|
{{#if hasSoftNavigations}}
|
|
3
|
-
import {
|
|
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
|
|
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: '
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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/
|
|
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");
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speedkit/cli",
|
|
3
3
|
"description": "Speed Kit CLI",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.11.0",
|
|
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.
|
|
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",
|