@speedkit/cli 2.23.2 → 2.25.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 +18 -0
- package/README.md +6 -5
- package/dist/commands/onboarding.d.ts +3 -5
- package/dist/commands/onboarding.js +3 -15
- package/dist/services/cli/cli-service-model.d.ts +2 -0
- package/dist/services/cli/cli-service.d.ts +1 -11
- package/dist/services/cli/cli-service.js +2 -0
- package/dist/services/deploy/checks/post-deploy/revalidated-module-check.d.ts +1 -1
- package/dist/services/deploy/checks/post-deploy/save-files-check.d.ts +1 -1
- package/dist/services/deploy/checks/pre-deploy/split-change-check.d.ts +18 -0
- package/dist/services/deploy/checks/pre-deploy/split-change-check.js +178 -0
- package/dist/services/deploy/context/deploy-context.d.ts +1 -0
- package/dist/services/deploy/context/deploy-context.js +2 -0
- package/dist/services/deploy/deploy-service-factory.js +4 -1
- package/dist/services/deploy/deploy-service-model.d.ts +12 -0
- package/dist/services/deploy/deploy-service.d.ts +7 -6
- package/dist/services/deploy/deploy-service.js +12 -7
- package/dist/services/onboarding/fetch-events/customer-domain-document-response.d.ts +16 -1
- package/dist/services/onboarding/fetch-events/customer-domain-document-response.js +30 -2
- package/dist/services/onboarding/onboarding-model.d.ts +4 -6
- package/dist/services/onboarding/onboarding-model.js +23 -1
- package/dist/services/onboarding/onboarding-service-factory.js +1 -1
- package/oclif.manifest.json +8 -1
- package/package.json +1 -1
- package/dist/services/deploy/interface/post-deploy-check-interface.d.ts +0 -3
- /package/dist/services/deploy/{interface/post-deploy-check-interface.js → deploy-service-model.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# [2.25.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.24.0...v2.25.0) (2024-04-17)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **onboarding:** add a flagInput to optin for ignoring the contentPolicy ([760764d](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/760764d6c1826b46f8e8d0164f2ada0d0ae71fd4))
|
|
7
|
+
* **onboarding:** remove content-policy-header ([c0ee577](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/c0ee577416ebbac6314463a93528cb5ccb68f3b2))
|
|
8
|
+
* **onboarding:** remove unnecessary unpacking ([5f16138](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/5f161387536201b46c1270eb2cab4d10e3f3cffa))
|
|
9
|
+
|
|
10
|
+
# [2.24.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.23.2...v2.24.0) (2024-04-17)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **deploy:** add more detailed browserContext for vm ([4a32740](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/4a32740947c14b9c5d083ab022d3bcd6aa7d9113))
|
|
16
|
+
* **deploy:** catch error on splitTestIdCheck ([34844bd](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/34844bddf2ecc165ebc62e38ddca43be8c8763f2))
|
|
17
|
+
* **deploy:** implement splitChangeDetection ([ab0a56b](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/ab0a56bf43f8d5e20fd9d0a6669ae2a04180e232))
|
|
18
|
+
|
|
1
19
|
## [2.23.2](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v2.23.1...v2.23.2) (2024-04-16)
|
|
2
20
|
|
|
3
21
|
|
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.
|
|
24
|
+
@speedkit/cli/2.25.0 linux-x64 node-v20.12.2
|
|
25
25
|
$ sk --help [COMMAND]
|
|
26
26
|
USAGE
|
|
27
27
|
$ sk COMMAND
|
|
@@ -364,15 +364,16 @@ Start a local dev environment for building and testing the Speed Kit configurati
|
|
|
364
364
|
|
|
365
365
|
```
|
|
366
366
|
USAGE
|
|
367
|
-
$ sk onboarding CUSTOMERPATH [-c <value>] [-l] [-v]
|
|
367
|
+
$ sk onboarding CUSTOMERPATH [-c <value>] [-l] [-v] [-s]
|
|
368
368
|
|
|
369
369
|
ARGUMENTS
|
|
370
370
|
CUSTOMERPATH The customer config path
|
|
371
371
|
|
|
372
372
|
FLAGS
|
|
373
|
-
-c, --configName=<value>
|
|
374
|
-
-l, --local
|
|
375
|
-
-
|
|
373
|
+
-c, --configName=<value> [default: production] The costumer config name
|
|
374
|
+
-l, --local Run with local documentHandler
|
|
375
|
+
-s, --ignoreContentSecurityPolicy Removes header/meta "content-security-policy" for origin-responses
|
|
376
|
+
-v, --verboseLevel Show all messages
|
|
376
377
|
|
|
377
378
|
DESCRIPTION
|
|
378
379
|
Start a local dev environment for building and testing the Speed Kit configuration
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
export default class Onboarding extends Command {
|
|
3
3
|
static description: string;
|
|
4
|
-
static flags: {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
configName: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
-
};
|
|
4
|
+
static flags: import("@oclif/core/lib/interfaces/parser").FlagInput<{
|
|
5
|
+
[flag: string]: any;
|
|
6
|
+
}>;
|
|
9
7
|
static args: {
|
|
10
8
|
customerPath: import("@oclif/core/lib/interfaces").Arg<string, {
|
|
11
9
|
exists?: boolean;
|
|
@@ -6,27 +6,15 @@ const onboarding_1 = require("../services/onboarding");
|
|
|
6
6
|
const cli_config_1 = require("../helpers/cli-config");
|
|
7
7
|
class Onboarding extends core_1.Command {
|
|
8
8
|
static description = "Start a local dev environment for building and testing the Speed Kit configuration";
|
|
9
|
-
static flags =
|
|
10
|
-
...cli_parameters_1.CLI_CONFIG_NAME,
|
|
11
|
-
local: core_1.Flags.boolean({
|
|
12
|
-
char: "l",
|
|
13
|
-
default: false,
|
|
14
|
-
description: "Run with local documentHandler",
|
|
15
|
-
}),
|
|
16
|
-
verboseLevel: core_1.Flags.boolean({
|
|
17
|
-
char: "v",
|
|
18
|
-
default: false,
|
|
19
|
-
description: "Show all messages",
|
|
20
|
-
}),
|
|
21
|
-
};
|
|
9
|
+
static flags = onboarding_1.OnboardingContext.flags;
|
|
22
10
|
static args = cli_parameters_1.CLI_CUSTOMER_CONFIG;
|
|
23
11
|
static examples = [
|
|
24
12
|
`$ sk onboarding <${cli_parameters_1.CLIParameters.CustomerPath}> -${cli_parameters_1.CLIParametersChar.ConfigName} <${cli_parameters_1.CLIParameters.ConfigName}>`,
|
|
25
13
|
`$ sk onboarding ${cli_parameters_1.CLIParametersExample.CustomerPath} -${cli_parameters_1.CLIParametersChar.ConfigName} ${cli_parameters_1.CLIParametersExample.ConfigName}`,
|
|
26
14
|
];
|
|
27
15
|
async run() {
|
|
28
|
-
const { args: { customerPath }, flags: { configName, local, verboseLevel }, } = await this.parse(Onboarding);
|
|
29
|
-
const service = await new onboarding_1.OnboardingServiceFactory(new onboarding_1.OnboardingContext(customerPath, configName, local, verboseLevel), new cli_config_1.CliConfig(this.config).load()).getService();
|
|
16
|
+
const { args: { customerPath }, flags: { configName, local, verboseLevel, ignoreContentSecurityPolicy }, } = await this.parse(Onboarding);
|
|
17
|
+
const service = await new onboarding_1.OnboardingServiceFactory(new onboarding_1.OnboardingContext(customerPath, configName, local, verboseLevel, ignoreContentSecurityPolicy), new cli_config_1.CliConfig(this.config).load()).getService();
|
|
30
18
|
await service.run();
|
|
31
19
|
}
|
|
32
20
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { table } from "@oclif/core/lib/cli-ux/styled/table";
|
|
2
2
|
import { Options } from "cli-progress";
|
|
3
|
+
import chalk from "chalk";
|
|
3
4
|
export declare class CliContext {
|
|
4
5
|
readonly quiet: boolean;
|
|
5
6
|
constructor(quiet?: boolean);
|
|
@@ -10,6 +11,7 @@ export declare enum CliActionStatus {
|
|
|
10
11
|
SKIPPED = "skipped"
|
|
11
12
|
}
|
|
12
13
|
export interface CliServiceInterface {
|
|
14
|
+
style: chalk.Chalk;
|
|
13
15
|
code(code: string, buffered?: boolean): void;
|
|
14
16
|
codeStyle(code: string): string;
|
|
15
17
|
comment(message: string, buffered?: boolean): void;
|
|
@@ -4,17 +4,7 @@ import { Options } from "cli-progress";
|
|
|
4
4
|
import { CliActionStatus, CliServiceInterface } from "./cli-service-model";
|
|
5
5
|
export declare class CliService implements CliServiceInterface {
|
|
6
6
|
private readonly quiet;
|
|
7
|
-
style: chalk.Chalk
|
|
8
|
-
supportsColor: false | chalk.ColorSupport;
|
|
9
|
-
Level: chalk.Level;
|
|
10
|
-
Color: ("white" | "black" | "blue" | "yellow" | "green" | "red" | "magenta" | "cyan" | "gray" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright" | "grey") | ("bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright" | "bgGrey");
|
|
11
|
-
ForegroundColor: "white" | "black" | "blue" | "yellow" | "green" | "red" | "magenta" | "cyan" | "gray" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright" | "grey";
|
|
12
|
-
BackgroundColor: "bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright" | "bgGrey";
|
|
13
|
-
Modifiers: "bold" | "hidden" | "underline" | "dim" | "italic" | "strikethrough" | "visible" | "reset" | "inverse";
|
|
14
|
-
stderr: chalk.Chalk & {
|
|
15
|
-
supportsColor: false | chalk.ColorSupport;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
7
|
+
style: chalk.Chalk;
|
|
18
8
|
private buffer;
|
|
19
9
|
private progressBar?;
|
|
20
10
|
constructor(quiet?: boolean);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliService } from "../../../cli";
|
|
2
2
|
import ConfigApiService from "../../../config-api/config-api-service";
|
|
3
|
-
import PostDeployCheckInterface from "../../
|
|
3
|
+
import { PostDeployCheckInterface } from "../../deploy-service-model";
|
|
4
4
|
export default class RevalidatedModuleCheck implements PostDeployCheckInterface {
|
|
5
5
|
private readonly configApi;
|
|
6
6
|
private cli;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliService } from "../../../cli";
|
|
2
|
-
import PostDeployCheckInterface from "../../interface/post-deploy-check-interface";
|
|
3
2
|
import { FileListInterface } from "../../../integration-api/integration-api-model";
|
|
3
|
+
import { PostDeployCheckInterface } from "../../deploy-service-model";
|
|
4
4
|
export default class SaveFilesCheck implements PostDeployCheckInterface {
|
|
5
5
|
private fileList;
|
|
6
6
|
private readonly cli;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FileListInterface } from "../../../integration-api/integration-api-model";
|
|
2
|
+
import { CliServiceInterface } from "../../../cli";
|
|
3
|
+
import ConfigApiService from "../../../config-api/config-api-service";
|
|
4
|
+
import CustomerConfig from "../../../integration-api/struct/customer-config";
|
|
5
|
+
export declare class SplitChangeCheck {
|
|
6
|
+
private cli;
|
|
7
|
+
private fileList;
|
|
8
|
+
private configApi;
|
|
9
|
+
private customerConfig;
|
|
10
|
+
private configName;
|
|
11
|
+
private isProduction;
|
|
12
|
+
constructor(cli: CliServiceInterface, fileList: FileListInterface, configApi: ConfigApiService, customerConfig: CustomerConfig, configName: string, isProduction: boolean);
|
|
13
|
+
check(): Promise<void>;
|
|
14
|
+
private checkSplitsForEachOrigin;
|
|
15
|
+
private evaluateLocalAndRemoteSpeedKit;
|
|
16
|
+
private getActiveInstallResource;
|
|
17
|
+
private buildBrowserMock;
|
|
18
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SplitChangeCheck = 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
|
+
class SplitChangeCheck {
|
|
10
|
+
cli;
|
|
11
|
+
fileList;
|
|
12
|
+
configApi;
|
|
13
|
+
customerConfig;
|
|
14
|
+
configName;
|
|
15
|
+
isProduction;
|
|
16
|
+
constructor(cli, fileList, configApi, customerConfig, configName, isProduction) {
|
|
17
|
+
this.cli = cli;
|
|
18
|
+
this.fileList = fileList;
|
|
19
|
+
this.configApi = configApi;
|
|
20
|
+
this.customerConfig = customerConfig;
|
|
21
|
+
this.configName = configName;
|
|
22
|
+
this.isProduction = isProduction;
|
|
23
|
+
}
|
|
24
|
+
async check() {
|
|
25
|
+
this.cli.startAction("check SplitTestId");
|
|
26
|
+
if (
|
|
27
|
+
// do not check for others then production
|
|
28
|
+
!this.isProduction ||
|
|
29
|
+
// check if we deploy a speedKitConfigFile
|
|
30
|
+
!this.fileList.hasFile(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT) ||
|
|
31
|
+
// check if we skipped the speedKitConfigFile
|
|
32
|
+
this.fileList
|
|
33
|
+
.getByName(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT)
|
|
34
|
+
.shouldSkipFile()) {
|
|
35
|
+
this.cli.endAction(cli_1.CliActionStatus.SKIPPED);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const speedKitConfigFile = this.fileList.getByName(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT);
|
|
39
|
+
const activeInstallResource = await this.getActiveInstallResource();
|
|
40
|
+
const activeSpeedKitConfig = activeInstallResource[speedKitConfigFile.remoteKey];
|
|
41
|
+
const changesResponse = (0, safe_1.safe)(() => {
|
|
42
|
+
return this.checkSplitsForEachOrigin(speedKitConfigFile, activeSpeedKitConfig);
|
|
43
|
+
});
|
|
44
|
+
if (changesResponse.success === false) {
|
|
45
|
+
this.cli.endAction(cli_1.CliActionStatus.FAILED);
|
|
46
|
+
this.cli.writeError(`Unable to evaluate changes: ${changesResponse.error}`);
|
|
47
|
+
if (changesResponse.errorObj) {
|
|
48
|
+
console.error(changesResponse.errorObj);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const changes = changesResponse.data;
|
|
53
|
+
this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
|
|
54
|
+
if (changes.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.cli.table(changes, { origin: {}, type: {}, old: {}, new: {} });
|
|
58
|
+
const result = await this.cli.confirm("Split change detected. Do you want to continue?", false);
|
|
59
|
+
if (!result) {
|
|
60
|
+
this.cli.exit(0);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
checkSplitsForEachOrigin(speedKitConfigFile, activeSpeedKitConfig) {
|
|
64
|
+
const changes = [];
|
|
65
|
+
for (const origin of this.customerConfig.origins) {
|
|
66
|
+
const { localSpeedKit, remoteSpeedKit } = this.evaluateLocalAndRemoteSpeedKit(origin, speedKitConfigFile, activeSpeedKitConfig);
|
|
67
|
+
// check for split change
|
|
68
|
+
if (localSpeedKit.split !== remoteSpeedKit.split) {
|
|
69
|
+
changes.push({
|
|
70
|
+
origin,
|
|
71
|
+
type: "split",
|
|
72
|
+
new: this.cli.style.green(localSpeedKit.split),
|
|
73
|
+
old: remoteSpeedKit.split,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// check for splitId change
|
|
77
|
+
if (localSpeedKit.splitTestId !== remoteSpeedKit.splitTestId) {
|
|
78
|
+
changes.push({
|
|
79
|
+
origin,
|
|
80
|
+
type: "splitTestId",
|
|
81
|
+
new: this.cli.style.green(localSpeedKit.splitTestId),
|
|
82
|
+
old: remoteSpeedKit.splitTestId,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// check for split change without splitId change
|
|
86
|
+
if (localSpeedKit.split !== remoteSpeedKit.split &&
|
|
87
|
+
localSpeedKit.splitTestId === remoteSpeedKit.splitTestId) {
|
|
88
|
+
changes.push({
|
|
89
|
+
origin,
|
|
90
|
+
type: this.cli.style.yellow("split changed\nwithout id change"),
|
|
91
|
+
new: `${localSpeedKit.split}\n${this.cli.style.red(localSpeedKit.splitTestId)}`,
|
|
92
|
+
old: `${remoteSpeedKit.split}\n${remoteSpeedKit.splitTestId}`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// check for splitId change without split change
|
|
96
|
+
if (localSpeedKit.split === remoteSpeedKit.split &&
|
|
97
|
+
localSpeedKit.splitTestId !== remoteSpeedKit.splitTestId) {
|
|
98
|
+
changes.push({
|
|
99
|
+
origin,
|
|
100
|
+
type: this.cli.style.yellow("id changed\nwithout split change"),
|
|
101
|
+
new: `${this.cli.style.red(localSpeedKit.split)}\n${localSpeedKit.splitTestId}`,
|
|
102
|
+
old: `${remoteSpeedKit.split}\n${remoteSpeedKit.splitTestId}`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// check for invalid split value
|
|
106
|
+
if (localSpeedKit.split > 1 || localSpeedKit.split < 0) {
|
|
107
|
+
changes.push({
|
|
108
|
+
origin,
|
|
109
|
+
type: this.cli.style.red("invalid"),
|
|
110
|
+
new: this.cli.style.red(localSpeedKit.split),
|
|
111
|
+
old: remoteSpeedKit.split,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return changes;
|
|
116
|
+
}
|
|
117
|
+
evaluateLocalAndRemoteSpeedKit(origin, speedKitConfigFile, activeSpeedKitConfig) {
|
|
118
|
+
const localBrowserContext = this.buildBrowserMock(origin, this.customerConfig.app);
|
|
119
|
+
vm.runInNewContext(speedKitConfigFile.getContent(), localBrowserContext, {
|
|
120
|
+
filename: speedKitConfigFile.path,
|
|
121
|
+
displayErrors: true,
|
|
122
|
+
});
|
|
123
|
+
const remoteBrowserContext = this.buildBrowserMock(origin, this.customerConfig.app);
|
|
124
|
+
vm.runInNewContext(activeSpeedKitConfig, remoteBrowserContext, {
|
|
125
|
+
displayErrors: true,
|
|
126
|
+
});
|
|
127
|
+
const localSpeedKit = localBrowserContext.window.speedKit;
|
|
128
|
+
const remoteSpeedKit = remoteBrowserContext.window.speedKit;
|
|
129
|
+
return { localSpeedKit, remoteSpeedKit };
|
|
130
|
+
}
|
|
131
|
+
async getActiveInstallResource() {
|
|
132
|
+
const activeInstallResourceResponse = await (0, safe_1.safe)(this.configApi.getActiveInstall(this.configName));
|
|
133
|
+
if (activeInstallResourceResponse.success !== true) {
|
|
134
|
+
this.cli.endAction(cli_1.CliActionStatus.FAILED);
|
|
135
|
+
this.cli.writeError("Could not load active installResource");
|
|
136
|
+
this.cli.exit(1);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
return activeInstallResourceResponse.data;
|
|
140
|
+
}
|
|
141
|
+
buildBrowserMock(origin, app) {
|
|
142
|
+
const originUrl = new URL(origin);
|
|
143
|
+
const window = {
|
|
144
|
+
location: originUrl,
|
|
145
|
+
APP: app,
|
|
146
|
+
speedKit: {
|
|
147
|
+
split: undefined,
|
|
148
|
+
splitTestId: undefined,
|
|
149
|
+
},
|
|
150
|
+
serviceWorkerUrl: "",
|
|
151
|
+
screen: { width: 0, height: 0 },
|
|
152
|
+
devicePixelRatio: 1,
|
|
153
|
+
top: {},
|
|
154
|
+
};
|
|
155
|
+
window.top = window;
|
|
156
|
+
const document = {
|
|
157
|
+
cookie: "",
|
|
158
|
+
querySelector: () => { },
|
|
159
|
+
querySelectorAll: () => { },
|
|
160
|
+
createElement: () => { },
|
|
161
|
+
addEventListener: () => { },
|
|
162
|
+
head: {},
|
|
163
|
+
body: {},
|
|
164
|
+
};
|
|
165
|
+
document.head = document;
|
|
166
|
+
document.body = document;
|
|
167
|
+
return {
|
|
168
|
+
...window,
|
|
169
|
+
window,
|
|
170
|
+
document,
|
|
171
|
+
navigator: { userAgent: "" },
|
|
172
|
+
localStorage: { getItem: () => { }, setItem: () => { } },
|
|
173
|
+
JSON: JSON,
|
|
174
|
+
decodeURIComponent: decodeURIComponent,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.SplitChangeCheck = SplitChangeCheck;
|
|
@@ -4,6 +4,7 @@ export default class DeployContext {
|
|
|
4
4
|
readonly slackToken?: string;
|
|
5
5
|
readonly dryRun: boolean;
|
|
6
6
|
readonly artifacts?: string[];
|
|
7
|
+
readonly isProduction: boolean;
|
|
7
8
|
constructor(customerPath: string, configName?: string, slackToken?: string, artifacts?: string, dryRun?: boolean);
|
|
8
9
|
hasArtifacts(): boolean;
|
|
9
10
|
}
|
|
@@ -11,12 +11,14 @@ class DeployContext {
|
|
|
11
11
|
slackToken;
|
|
12
12
|
dryRun;
|
|
13
13
|
artifacts;
|
|
14
|
+
isProduction;
|
|
14
15
|
constructor(customerPath, configName = DEFAULT_CONFIG_NAME, slackToken, artifacts, dryRun = false) {
|
|
15
16
|
this.customerPath = customerPath;
|
|
16
17
|
this.configName = configName;
|
|
17
18
|
this.slackToken = slackToken;
|
|
18
19
|
this.dryRun = dryRun;
|
|
19
20
|
this.artifacts = artifacts ? artifacts.split(ARTIFACTS_SEPARATOR) : [];
|
|
21
|
+
this.isProduction = configName.toLowerCase().includes("prod");
|
|
20
22
|
}
|
|
21
23
|
hasArtifacts() {
|
|
22
24
|
return this.artifacts?.length > 0;
|
|
@@ -17,6 +17,7 @@ const deleted_file_check_1 = tslib_1.__importDefault(require("./handler/install-
|
|
|
17
17
|
const module_handler_1 = tslib_1.__importDefault(require("./handler/module-handler"));
|
|
18
18
|
const deployment_detection_modifier_1 = tslib_1.__importDefault(require("./handler/module-modifier/deployment-detection-modifier"));
|
|
19
19
|
const server_config_handler_1 = tslib_1.__importDefault(require("./handler/server-config-handler"));
|
|
20
|
+
const split_change_check_1 = require("./checks/pre-deploy/split-change-check");
|
|
20
21
|
class DeployServiceFactory {
|
|
21
22
|
context;
|
|
22
23
|
cliConfig;
|
|
@@ -48,7 +49,9 @@ class DeployServiceFactory {
|
|
|
48
49
|
new deployment_detection_modifier_1.default(slackToken),
|
|
49
50
|
]),
|
|
50
51
|
new server_config_handler_1.default(configApi, diffService, cliService),
|
|
51
|
-
], cliService,
|
|
52
|
+
], cliService, [
|
|
53
|
+
new split_change_check_1.SplitChangeCheck(cliService, files, configApi, customer, configName, this.context.isProduction),
|
|
54
|
+
], this.getPostDeployChecks(files, cliService, configApi, customer.app), this.context.dryRun);
|
|
52
55
|
}
|
|
53
56
|
getConfigApi(app) {
|
|
54
57
|
const configApiContext = new config_api_context_1.default(app);
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import DeployHandlerInterface from "./interface/deploy-handler-interface";
|
|
2
2
|
import { CliService } from "../cli";
|
|
3
|
-
import PostDeployCheckInterface from "./interface/post-deploy-check-interface";
|
|
4
|
-
import AbstractAsyncErrorHandlingService from "../error-handling/abstract/abstract-async-error-handling-service";
|
|
5
3
|
import { FileListInterface } from "../integration-api/integration-api-model";
|
|
6
|
-
|
|
4
|
+
import { PostDeployCheckInterface, PreDeployCheckInterface } from "./deploy-service-model";
|
|
5
|
+
export default class DeployService {
|
|
7
6
|
private readonly fileList;
|
|
8
7
|
private readonly deployHandler;
|
|
9
8
|
private readonly cli;
|
|
10
|
-
private readonly
|
|
9
|
+
private readonly preDeployChecks;
|
|
11
10
|
private readonly postDeployChecks;
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
private readonly dryRun;
|
|
12
|
+
constructor(fileList: FileListInterface, deployHandler: DeployHandlerInterface[], cli: CliService, preDeployChecks: PreDeployCheckInterface[], postDeployChecks: PostDeployCheckInterface[], dryRun: boolean);
|
|
13
|
+
run(): Promise<void>;
|
|
14
14
|
private handleType;
|
|
15
15
|
private uploadType;
|
|
16
|
+
private runPreDeployChecks;
|
|
16
17
|
private runPostDeployChecks;
|
|
17
18
|
}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const abstract_async_error_handling_service_1 = tslib_1.__importDefault(require("../error-handling/abstract/abstract-async-error-handling-service"));
|
|
5
|
-
class DeployService extends abstract_async_error_handling_service_1.default {
|
|
3
|
+
class DeployService {
|
|
6
4
|
fileList;
|
|
7
5
|
deployHandler;
|
|
8
6
|
cli;
|
|
9
|
-
|
|
7
|
+
preDeployChecks;
|
|
10
8
|
postDeployChecks;
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
dryRun;
|
|
10
|
+
constructor(fileList, deployHandler, cli, preDeployChecks, postDeployChecks, dryRun) {
|
|
13
11
|
this.fileList = fileList;
|
|
14
12
|
this.deployHandler = deployHandler;
|
|
15
13
|
this.cli = cli;
|
|
14
|
+
this.preDeployChecks = preDeployChecks;
|
|
16
15
|
this.postDeployChecks = postDeployChecks;
|
|
17
16
|
this.dryRun = dryRun;
|
|
18
17
|
}
|
|
19
|
-
async
|
|
18
|
+
async run() {
|
|
20
19
|
const types = this.fileList.getTypes();
|
|
21
20
|
this.cli.spacer();
|
|
22
21
|
this.cli.write(`App: "${this.fileList.getCustomerConfig().config.app}", Install: "${this.fileList.getCustomerConfig().config.name}"`);
|
|
@@ -25,6 +24,7 @@ class DeployService extends abstract_async_error_handling_service_1.default {
|
|
|
25
24
|
for (const type of types) {
|
|
26
25
|
await this.handleType(type);
|
|
27
26
|
}
|
|
27
|
+
await this.runPreDeployChecks();
|
|
28
28
|
if (this.dryRun) {
|
|
29
29
|
this.cli.comment("dryRunFlag -d is set, skip upload");
|
|
30
30
|
}
|
|
@@ -51,6 +51,11 @@ class DeployService extends abstract_async_error_handling_service_1.default {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
async runPreDeployChecks() {
|
|
55
|
+
for (const preDeploy of this.preDeployChecks) {
|
|
56
|
+
await preDeploy.check();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
async runPostDeployChecks() {
|
|
55
60
|
for (let iterator = 0; iterator < this.postDeployChecks.length; iterator++) {
|
|
56
61
|
const check = this.postDeployChecks[iterator];
|
|
@@ -11,8 +11,9 @@ export declare class CustomerDomainDocumentResponse implements FetchRequestPause
|
|
|
11
11
|
private customerConfig;
|
|
12
12
|
private configDynamicBlock;
|
|
13
13
|
private configDynamicStyles;
|
|
14
|
+
private removeContentSecurityPolicy;
|
|
14
15
|
get patterns(): Protocol.Fetch.RequestPattern[];
|
|
15
|
-
constructor(customerConfig: CustomerConfig, configDynamicBlock: ConfigFileInterface, configDynamicStyles: ConfigFileInterface);
|
|
16
|
+
constructor(customerConfig: CustomerConfig, configDynamicBlock: ConfigFileInterface, configDynamicStyles: ConfigFileInterface, removeContentSecurityPolicy: boolean);
|
|
16
17
|
handle(event: Protocol.Fetch.RequestPausedEvent, client: CDPSession): Promise<Partial<Protocol.Fetch.FulfillRequestRequest> | void>;
|
|
17
18
|
private isValidHtmlContent;
|
|
18
19
|
private isValidResponse;
|
|
@@ -21,4 +22,18 @@ export declare class CustomerDomainDocumentResponse implements FetchRequestPause
|
|
|
21
22
|
private isSpeedKitResponse;
|
|
22
23
|
private rewriteInstallResource;
|
|
23
24
|
private rewriteHtmlToLocalConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Removes content policy headers from the given array of headers.
|
|
27
|
+
*
|
|
28
|
+
* @param {Protocol.Fetch.HeaderEntry[]} headers - The array of header entries.
|
|
29
|
+
* @returns {Protocol.Fetch.HeaderEntry[]} - The modified array of header entries with content policy headers removed.
|
|
30
|
+
*/
|
|
31
|
+
private removeContentSecurityHeaderFromResponse;
|
|
32
|
+
/**
|
|
33
|
+
* Removes the content security meta tag from the provided HTML content.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} htmlContent - The HTML content from which to remove the meta tag.
|
|
36
|
+
* @returns {string} - The HTML content without the content security meta tag.
|
|
37
|
+
*/
|
|
38
|
+
private removeContentSecurityMetaTag;
|
|
24
39
|
}
|
|
@@ -10,6 +10,7 @@ class CustomerDomainDocumentResponse {
|
|
|
10
10
|
customerConfig;
|
|
11
11
|
configDynamicBlock;
|
|
12
12
|
configDynamicStyles;
|
|
13
|
+
removeContentSecurityPolicy;
|
|
13
14
|
get patterns() {
|
|
14
15
|
const result = [];
|
|
15
16
|
for (const origin of this.customerConfig.origins) {
|
|
@@ -44,10 +45,11 @@ class CustomerDomainDocumentResponse {
|
|
|
44
45
|
}
|
|
45
46
|
return result;
|
|
46
47
|
}
|
|
47
|
-
constructor(customerConfig, configDynamicBlock, configDynamicStyles) {
|
|
48
|
+
constructor(customerConfig, configDynamicBlock, configDynamicStyles, removeContentSecurityPolicy) {
|
|
48
49
|
this.customerConfig = customerConfig;
|
|
49
50
|
this.configDynamicBlock = configDynamicBlock;
|
|
50
51
|
this.configDynamicStyles = configDynamicStyles;
|
|
52
|
+
this.removeContentSecurityPolicy = removeContentSecurityPolicy;
|
|
51
53
|
}
|
|
52
54
|
async handle(event, client) {
|
|
53
55
|
if (!this.isValidResponse(event)) {
|
|
@@ -66,7 +68,13 @@ class CustomerDomainDocumentResponse {
|
|
|
66
68
|
if (this.isSpeedKitResponse(text)) {
|
|
67
69
|
text = this.rewriteHtmlToLocalConfig(text);
|
|
68
70
|
}
|
|
69
|
-
|
|
71
|
+
const headers = this.removeContentSecurityPolicy
|
|
72
|
+
? this.removeContentSecurityHeaderFromResponse(event.responseHeaders)
|
|
73
|
+
: event.responseHeaders;
|
|
74
|
+
const content = this.removeContentSecurityPolicy
|
|
75
|
+
? this.removeContentSecurityMetaTag(text)
|
|
76
|
+
: text;
|
|
77
|
+
return new origin_response_1.OriginResponse(content, headers, event.responseStatusCode);
|
|
70
78
|
}
|
|
71
79
|
isValidHtmlContent(text) {
|
|
72
80
|
return text.includes("<html");
|
|
@@ -116,5 +124,25 @@ class CustomerDomainDocumentResponse {
|
|
|
116
124
|
html = html.replaceAll(DF_STYLES_PATTERN, (_, tag, end) => `${tag}${this.configDynamicStyles.getContent()}${end}`);
|
|
117
125
|
return html;
|
|
118
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Removes content policy headers from the given array of headers.
|
|
129
|
+
*
|
|
130
|
+
* @param {Protocol.Fetch.HeaderEntry[]} headers - The array of header entries.
|
|
131
|
+
* @returns {Protocol.Fetch.HeaderEntry[]} - The modified array of header entries with content policy headers removed.
|
|
132
|
+
*/
|
|
133
|
+
removeContentSecurityHeaderFromResponse(headers) {
|
|
134
|
+
return headers.filter((header) => {
|
|
135
|
+
return !header.name.toLowerCase().includes("content-security-policy");
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Removes the content security meta tag from the provided HTML content.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} htmlContent - The HTML content from which to remove the meta tag.
|
|
142
|
+
* @returns {string} - The HTML content without the content security meta tag.
|
|
143
|
+
*/
|
|
144
|
+
removeContentSecurityMetaTag(htmlContent) {
|
|
145
|
+
return htmlContent.replace(/<meta[^>]*http-equiv=["']content-security-policy[^>]*>/is, "");
|
|
146
|
+
}
|
|
119
147
|
}
|
|
120
148
|
exports.CustomerDomainDocumentResponse = CustomerDomainDocumentResponse;
|
|
@@ -2,6 +2,7 @@ import { CDPSession } from "puppeteer";
|
|
|
2
2
|
import { Protocol } from "puppeteer-core";
|
|
3
3
|
import { UserCliConfig } from "../../helpers/cli-config";
|
|
4
4
|
import { AbortResponse } from "./browser/abort-response";
|
|
5
|
+
import { FlagInput } from "@oclif/core/lib/interfaces/parser";
|
|
5
6
|
export declare class BrowserContext {
|
|
6
7
|
readonly domain: string;
|
|
7
8
|
readonly chromeFlags?: string[];
|
|
@@ -20,17 +21,14 @@ export declare class OnboardingContext {
|
|
|
20
21
|
readonly configName: string;
|
|
21
22
|
readonly local: boolean;
|
|
22
23
|
readonly verboseLevel?: boolean;
|
|
24
|
+
readonly ignoreContentSecurityPolicy: boolean;
|
|
25
|
+
static flags: FlagInput;
|
|
23
26
|
readonly DEFAULT_DF_PATH = "https://www.baqend.com/speed-kit/latest/dynamic-fetcher.js";
|
|
24
27
|
readonly DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
|
|
25
28
|
readonly DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
|
|
26
29
|
readonly DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
|
|
27
|
-
constructor(customerPath: string, configName: string, local: boolean, verboseLevel?: boolean);
|
|
30
|
+
constructor(customerPath: string, configName: string, local: boolean, verboseLevel?: boolean, ignoreContentSecurityPolicy?: boolean);
|
|
28
31
|
}
|
|
29
|
-
export type awsCredentials = {
|
|
30
|
-
accessKeyId: string;
|
|
31
|
-
region: string;
|
|
32
|
-
secretAccessKey: string;
|
|
33
|
-
};
|
|
34
32
|
export type SpeedKitServerConfigAuthentication = {
|
|
35
33
|
password: string;
|
|
36
34
|
type: "basic";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OnboardingContext = exports.BrowserContext = void 0;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const cli_parameters_1 = require("../../models/cli-parameters");
|
|
4
6
|
const DEFAULT_BROWSER_ARGS = [
|
|
5
7
|
"--enable-features=NetworkService",
|
|
6
8
|
"--no-first-run",
|
|
@@ -40,15 +42,35 @@ class OnboardingContext {
|
|
|
40
42
|
configName;
|
|
41
43
|
local;
|
|
42
44
|
verboseLevel;
|
|
45
|
+
ignoreContentSecurityPolicy;
|
|
46
|
+
static flags = {
|
|
47
|
+
...cli_parameters_1.CLI_CONFIG_NAME,
|
|
48
|
+
local: core_1.Flags.boolean({
|
|
49
|
+
char: "l",
|
|
50
|
+
default: false,
|
|
51
|
+
description: "Run with local documentHandler",
|
|
52
|
+
}),
|
|
53
|
+
verboseLevel: core_1.Flags.boolean({
|
|
54
|
+
char: "v",
|
|
55
|
+
default: false,
|
|
56
|
+
description: "Show all messages",
|
|
57
|
+
}),
|
|
58
|
+
ignoreContentSecurityPolicy: core_1.Flags.boolean({
|
|
59
|
+
char: "s",
|
|
60
|
+
default: false,
|
|
61
|
+
description: `Removes header/meta "content-security-policy" for origin-responses`,
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
43
64
|
DEFAULT_DF_PATH = "https://www.baqend.com/speed-kit/latest/dynamic-fetcher.js";
|
|
44
65
|
DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
|
|
45
66
|
DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
|
|
46
67
|
DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
|
|
47
|
-
constructor(customerPath, configName, local, verboseLevel) {
|
|
68
|
+
constructor(customerPath, configName, local, verboseLevel, ignoreContentSecurityPolicy = false) {
|
|
48
69
|
this.customerPath = customerPath;
|
|
49
70
|
this.configName = configName;
|
|
50
71
|
this.local = local;
|
|
51
72
|
this.verboseLevel = verboseLevel;
|
|
73
|
+
this.ignoreContentSecurityPolicy = ignoreContentSecurityPolicy;
|
|
52
74
|
}
|
|
53
75
|
}
|
|
54
76
|
exports.OnboardingContext = OnboardingContext;
|
|
@@ -97,7 +97,7 @@ class OnboardingServiceFactory {
|
|
|
97
97
|
const DiffService = new diff_1.DiffServiceFactory(new diff_1.DiffContext(this.cliConfig.diffExec, this.cliConfig.diffExecTemplate)).getService();
|
|
98
98
|
const requestDiffService = new request_diff_service_1.RequestDiffService(DiffService, documentHandler);
|
|
99
99
|
const handlers = [
|
|
100
|
-
new customer_domain_document_response_1.CustomerDomainDocumentResponse(customerConfig, files.getByName(files_1.INTEGRATION_FILES.CONFIG.DYNAMIC_BLOCKS), files.getByName(files_1.INTEGRATION_FILES.CONFIG.DYNAMIC_STYLES)),
|
|
100
|
+
new customer_domain_document_response_1.CustomerDomainDocumentResponse(customerConfig, files.getByName(files_1.INTEGRATION_FILES.CONFIG.DYNAMIC_BLOCKS), files.getByName(files_1.INTEGRATION_FILES.CONFIG.DYNAMIC_STYLES), this.context.ignoreContentSecurityPolicy),
|
|
101
101
|
new speed_kit_install_html_1.SpeedKitInstallHtml(customerConfig, browserContext, new install_speed_kit_html_template_1.InstallSpeedKitHtmlTemplate()),
|
|
102
102
|
new speed_kit_install_js_1.SpeedKitInstallJs(customerConfig, files.getByName(files_1.INTEGRATION_FILES.BUILD.INSTALL)),
|
|
103
103
|
new customer_service_worker_js_1.CustomerServiceWorkerJs(customerConfig),
|
package/oclif.manifest.json
CHANGED
|
@@ -459,6 +459,13 @@
|
|
|
459
459
|
"name": "verboseLevel",
|
|
460
460
|
"allowNo": false,
|
|
461
461
|
"type": "boolean"
|
|
462
|
+
},
|
|
463
|
+
"ignoreContentSecurityPolicy": {
|
|
464
|
+
"char": "s",
|
|
465
|
+
"description": "Removes header/meta \"content-security-policy\" for origin-responses",
|
|
466
|
+
"name": "ignoreContentSecurityPolicy",
|
|
467
|
+
"allowNo": false,
|
|
468
|
+
"type": "boolean"
|
|
462
469
|
}
|
|
463
470
|
},
|
|
464
471
|
"hasDynamicHelp": false,
|
|
@@ -660,5 +667,5 @@
|
|
|
660
667
|
]
|
|
661
668
|
}
|
|
662
669
|
},
|
|
663
|
-
"version": "2.
|
|
670
|
+
"version": "2.25.0"
|
|
664
671
|
}
|
package/package.json
CHANGED
/package/dist/services/deploy/{interface/post-deploy-check-interface.js → deploy-service-model.js}
RENAMED
|
File without changes
|