@speedkit/cli 2.63.0 → 2.65.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,17 @@
1
+ # [2.65.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.64.0...v2.65.0) (2024-11-01)
2
+
3
+
4
+ ### Features
5
+
6
+ * adding success to default blacklist as requested by Sven ([7e9cc40](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/7e9cc4020b4a564044ea4817905bd3450586e623))
7
+
8
+ # [2.64.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.63.0...v2.64.0) (2024-11-01)
9
+
10
+
11
+ ### Features
12
+
13
+ * **deploy:** add preDeployCheck for customVariation and customDevice ([eda9271](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/eda92715c21963a97b907795fecaa06e579d5629))
14
+
1
15
  # [2.63.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.62.1...v2.63.0) (2024-11-01)
2
16
 
3
17
 
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/2.63.0 linux-x64 node-v20.18.0
24
+ @speedkit/cli/2.65.0 linux-x64 node-v20.18.0
25
25
  $ sk --help [COMMAND]
26
26
  USAGE
27
27
  $ sk COMMAND
@@ -175,6 +175,7 @@
175
175
  /amazon/i,
176
176
  /ratepay/i,
177
177
  /payone/i,
178
+ /success/i,
178
179
 
179
180
  // Admin:
180
181
  /\/admin/i,
@@ -0,0 +1,18 @@
1
+ import { FileListInterface, CustomerConfig } from "../../../integration-api";
2
+ import { CliServiceInterface } from "../../../cli";
3
+ import { ConfigApiService } from "../../../config-api";
4
+ export declare class DeviceDetectionChangedCheck {
5
+ private cli;
6
+ private fileList;
7
+ private configApi;
8
+ private customerConfig;
9
+ private configName;
10
+ private isProduction;
11
+ constructor(cli: CliServiceInterface, fileList: FileListInterface, configApi: ConfigApiService, customerConfig: CustomerConfig, configName: string, isProduction: boolean);
12
+ check(): Promise<void>;
13
+ private checkForChangedDeviceDetection;
14
+ private evaluateLocalAndRemoteSpeedKit;
15
+ private getActiveInstallResource;
16
+ private buildBrowserMock;
17
+ safeFileContentWrapper(fileContent: string): string;
18
+ }
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeviceDetectionChangedCheck = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const cli_1 = require("../../../cli");
6
+ const files_1 = require("../../../../models/files");
7
+ const vm = tslib_1.__importStar(require("node:vm"));
8
+ const safe_1 = require("../../../../helpers/safe");
9
+ const evaluate_sk_config_error_1 = require("../../error/evaluate-sk-config-error");
10
+ class DeviceDetectionChangedCheck {
11
+ cli;
12
+ fileList;
13
+ configApi;
14
+ customerConfig;
15
+ configName;
16
+ isProduction;
17
+ constructor(cli, fileList, configApi, customerConfig, configName, isProduction) {
18
+ this.cli = cli;
19
+ this.fileList = fileList;
20
+ this.configApi = configApi;
21
+ this.customerConfig = customerConfig;
22
+ this.configName = configName;
23
+ this.isProduction = isProduction;
24
+ }
25
+ async check() {
26
+ if (
27
+ // do not check for environments other than production
28
+ !this.isProduction ||
29
+ // do not check if speedKitConfigFile is not to be deployed
30
+ !this.fileList.hasFile(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT) ||
31
+ this.fileList
32
+ .getByName(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT)
33
+ .shouldSkipFile()) {
34
+ return;
35
+ }
36
+ const activeInstallResource = await this.getActiveInstallResource();
37
+ // do not check if there is no active install resource to be updated
38
+ if (!activeInstallResource) {
39
+ return;
40
+ }
41
+ this.cli.startAction("Checking for customDeviceDetection");
42
+ const speedKitConfigFile = this.fileList.getByName(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT);
43
+ const activeSpeedKitConfig = activeInstallResource[speedKitConfigFile.remoteKey];
44
+ const changesResponse = (0, safe_1.safe)(() => {
45
+ return this.checkForChangedDeviceDetection(speedKitConfigFile, activeSpeedKitConfig);
46
+ });
47
+ if (changesResponse.success === false) {
48
+ this.cli.endAction(cli_1.CliActionStatus.FAILED);
49
+ this.cli.writeError(`Unable to evaluate changes: ${changesResponse.error}`);
50
+ return;
51
+ }
52
+ const changes = changesResponse.data.map((value) => {
53
+ return "config_SpeedKit." + value;
54
+ });
55
+ this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
56
+ if (changes.length === 0) {
57
+ return;
58
+ }
59
+ // this.cli.table(changes, { origin: {}, type: {}, old: {}, new: {} });
60
+ const result = await this.cli.confirm(`Detected change in ${changes.join(" | ")}. ${this.cli.style.red("Was this checked by QA?")}`, false);
61
+ if (!result) {
62
+ this.cli.exit(0);
63
+ }
64
+ }
65
+ checkForChangedDeviceDetection(speedKitConfigFile, activeSpeedKitConfig) {
66
+ const changes = [];
67
+ const { localSpeedKit, remoteSpeedKit } = this.evaluateLocalAndRemoteSpeedKit(this.customerConfig.origins[0], speedKitConfigFile, activeSpeedKitConfig);
68
+ if ((localSpeedKit.detectDevice && !remoteSpeedKit.detectDevice) ||
69
+ (!localSpeedKit.detectDevice && remoteSpeedKit.detectDevice)) {
70
+ changes.push("detectDevice");
71
+ }
72
+ if (localSpeedKit.detectDevice &&
73
+ remoteSpeedKit.detectDevice &&
74
+ localSpeedKit.detectDevice.toString() !==
75
+ remoteSpeedKit.detectDevice.toString()) {
76
+ changes.push("detectDevice");
77
+ }
78
+ if ((localSpeedKit.customVariation && !remoteSpeedKit.customVariation) ||
79
+ (!localSpeedKit.customVariation && remoteSpeedKit.customVariation)) {
80
+ changes.push("customVariation");
81
+ }
82
+ if (localSpeedKit.customVariation && remoteSpeedKit.customVariation) {
83
+ const localFunctionsAsString = localSpeedKit.customVariation
84
+ .map((rule) => {
85
+ return rule.variationFunction.toString();
86
+ })
87
+ .join("|");
88
+ const remoteFunctionsAsString = remoteSpeedKit.customVariation
89
+ .map((rule) => {
90
+ return rule.variationFunction.toString();
91
+ })
92
+ .join("|");
93
+ if (localFunctionsAsString !== remoteFunctionsAsString) {
94
+ changes.push("customVariation");
95
+ }
96
+ }
97
+ return changes;
98
+ }
99
+ evaluateLocalAndRemoteSpeedKit(origin, speedKitConfigFile, activeSpeedKitConfig) {
100
+ const localBrowserContext = this.buildBrowserMock(origin, this.customerConfig.app);
101
+ vm.runInNewContext(this.safeFileContentWrapper(speedKitConfigFile.getContent()), localBrowserContext, {
102
+ filename: speedKitConfigFile.path,
103
+ displayErrors: false,
104
+ breakOnSigint: true,
105
+ });
106
+ const remoteBrowserContext = this.buildBrowserMock(origin, this.customerConfig.app);
107
+ vm.runInNewContext(this.safeFileContentWrapper(activeSpeedKitConfig), remoteBrowserContext, {
108
+ displayErrors: false,
109
+ breakOnSigint: true,
110
+ });
111
+ if (localBrowserContext.vmError !== null) {
112
+ throw new evaluate_sk_config_error_1.EvaluateSkConfigError(`[config_Speedkit.js] ${localBrowserContext.vmError?.message}`);
113
+ }
114
+ if (remoteBrowserContext.vmError !== null) {
115
+ throw new evaluate_sk_config_error_1.EvaluateSkConfigError(`[remote_config] ${JSON.stringify(remoteBrowserContext.vmError?.message)}`);
116
+ }
117
+ const localSpeedKit = localBrowserContext.window.speedKit;
118
+ const remoteSpeedKit = remoteBrowserContext.window.speedKit;
119
+ return { localSpeedKit, remoteSpeedKit };
120
+ }
121
+ async getActiveInstallResource() {
122
+ const activeInstallResourceResponse = await (0, safe_1.safe)(this.configApi.getActiveInstall(this.configName));
123
+ if (activeInstallResourceResponse.success !== true) {
124
+ this.cli.endAction(cli_1.CliActionStatus.FAILED);
125
+ this.cli.writeError("Could not load active install resource");
126
+ this.cli.exit(1);
127
+ return;
128
+ }
129
+ return activeInstallResourceResponse.data;
130
+ }
131
+ buildBrowserMock(origin, app) {
132
+ const originUrl = new URL(origin);
133
+ const window = {
134
+ location: originUrl,
135
+ APP: app,
136
+ speedKit: {
137
+ split: undefined,
138
+ splitTestId: undefined,
139
+ },
140
+ serviceWorkerUrl: "",
141
+ screen: { width: 0, height: 0 },
142
+ devicePixelRatio: 1,
143
+ navigator: {
144
+ userAgent: "",
145
+ connection: {},
146
+ cookieEnabled: false,
147
+ languages: [],
148
+ online: true,
149
+ },
150
+ top: {},
151
+ };
152
+ window.top = window;
153
+ const document = {
154
+ cookie: "",
155
+ querySelector: () => { },
156
+ querySelectorAll: () => { },
157
+ createElement: () => { },
158
+ addEventListener: () => { },
159
+ head: {},
160
+ body: {},
161
+ };
162
+ document.head = document;
163
+ document.body = document;
164
+ return {
165
+ vmError: null,
166
+ ...window,
167
+ window,
168
+ document,
169
+ navigator: { userAgent: "" },
170
+ localStorage: {
171
+ getItem: () => { },
172
+ setItem: () => { },
173
+ },
174
+ JSON: JSON,
175
+ decodeURIComponent: decodeURIComponent,
176
+ URL: URL,
177
+ };
178
+ }
179
+ safeFileContentWrapper(fileContent) {
180
+ return `
181
+ try{
182
+ ${fileContent}
183
+ } catch (error){
184
+ vmError = error
185
+ }
186
+ `;
187
+ }
188
+ }
189
+ exports.DeviceDetectionChangedCheck = DeviceDetectionChangedCheck;
@@ -17,6 +17,7 @@ const integration_api_1 = require("../integration-api");
17
17
  const split_change_check_1 = require("./checks/pre-deploy/split-change-check");
18
18
  const config_api_1 = require("../config-api");
19
19
  const deprecated_deployment_detection_check_1 = require("./checks/post-deploy/deprecated-deployment-detection-check");
20
+ const device_detection_changed_check_1 = require("./checks/pre-deploy/device-detection-changed-check");
20
21
  class DeployServiceFactory {
21
22
  context;
22
23
  cliConfig;
@@ -50,6 +51,7 @@ class DeployServiceFactory {
50
51
  new server_config_handler_1.default(configApi, diffService, cliService),
51
52
  ], cliService, [
52
53
  new split_change_check_1.SplitChangeCheck(cliService, files, configApi, customer, configName, this.context.isProduction),
54
+ new device_detection_changed_check_1.DeviceDetectionChangedCheck(cliService, files, configApi, customer, configName, this.context.isProduction),
53
55
  ], this.getPostDeployChecks(files, cliService, configApi, customer.app), this.context.dryRun);
54
56
  }
55
57
  getConfigApi(app) {
@@ -10,3 +10,20 @@ export type Change = {
10
10
  old: string;
11
11
  new: string;
12
12
  };
13
+ export type speedKitVariationRule = {
14
+ contentType?: string[];
15
+ host?: string[];
16
+ pathname?: Array<string | RegExp>;
17
+ url?: Array<string | RegExp>;
18
+ };
19
+ export type speedKitVariationRules = {
20
+ rules?: speedKitVariationRule;
21
+ variationFunction: (request: Request, device: string, cookies: Map<string, string>) => string;
22
+ };
23
+ export type speedKit = {
24
+ split: number;
25
+ splitTestId: string;
26
+ userAgentDetection?: boolean;
27
+ detectDevice?: (doc: Document) => string | null;
28
+ customVariation?: speedKitVariationRules[];
29
+ };
@@ -712,5 +712,5 @@
712
712
  ]
713
713
  }
714
714
  },
715
- "version": "2.63.0"
715
+ "version": "2.65.0"
716
716
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "2.63.0",
4
+ "version": "2.65.0",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"