@speedkit/cli 2.94.0 → 3.0.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +10 -7
  3. package/dist/commands/build-parameter-query.d.ts +0 -1
  4. package/dist/commands/build-parameter-query.js +9 -76
  5. package/dist/commands/build-prewarm-query.d.ts +0 -1
  6. package/dist/commands/build-prewarm-query.js +9 -48
  7. package/dist/commands/deploy.d.ts +3 -6
  8. package/dist/commands/deploy.js +3 -17
  9. package/dist/commands/onboarding.js +2 -2
  10. package/dist/helpers/array-helper.d.ts +1 -0
  11. package/dist/helpers/array-helper.js +9 -0
  12. package/dist/helpers/customer-config.d.ts +0 -1
  13. package/dist/helpers/customer-config.js +0 -2
  14. package/dist/models/cli-parameters.d.ts +7 -2
  15. package/dist/models/cli-parameters.js +12 -1
  16. package/dist/services/customer-config/customer-config-service-model.d.ts +0 -1
  17. package/dist/services/customer-config/customer-config-service.js +2 -8
  18. package/dist/services/customer-config/templates/config_customer.json.hbs +56 -0
  19. package/dist/services/deploy/context/deploy-context.d.ts +4 -2
  20. package/dist/services/deploy/context/deploy-context.js +28 -3
  21. package/dist/services/deploy/deploy-service-factory.js +2 -6
  22. package/dist/services/deploy/handler/customer-config-handler.d.ts +0 -1
  23. package/dist/services/deploy/handler/customer-config-handler.js +3 -8
  24. package/dist/services/deploy/handler/install-resource-handler.js +2 -2
  25. package/dist/services/deploy/handler/module-handler.js +2 -2
  26. package/dist/services/deploy/handler/server-config-handler.js +2 -2
  27. package/dist/services/diff/diff-service.d.ts +1 -1
  28. package/dist/services/diff/diff-service.js +1 -1
  29. package/dist/services/integration-api/error/invalid-config-format-error.d.ts +4 -0
  30. package/dist/services/integration-api/error/invalid-config-format-error.js +15 -0
  31. package/dist/services/integration-api/file-reader.d.ts +1 -0
  32. package/dist/services/integration-api/file-reader.js +4 -0
  33. package/dist/services/integration-api/handler/customer-config-handler.d.ts +2 -1
  34. package/dist/services/integration-api/handler/customer-config-handler.js +42 -25
  35. package/dist/services/integration-api/integration-api-factory.js +3 -3
  36. package/dist/services/integration-api/integration-api-model.d.ts +4 -2
  37. package/dist/services/integration-api/integration-api-model.js +6 -4
  38. package/dist/services/integration-api/spec/customer-config-validator.spec.js +1 -1
  39. package/dist/services/integration-api/spec/file-list.spec.js +2 -2
  40. package/dist/services/integration-api/spec/file-reader.spec.js +17 -3
  41. package/dist/services/integration-api/spec/integration-api-service.spec.js +15 -1
  42. package/dist/services/integration-api/struct/customer-config-file.d.ts +1 -0
  43. package/dist/services/integration-api/struct/customer-config-file.js +24 -12
  44. package/dist/services/integration-api/struct/customer-config.d.ts +5 -1
  45. package/dist/services/integration-api/validator/customer-config-validator.js +1 -1
  46. package/dist/services/onboarding/onboarding-model.d.ts +2 -1
  47. package/dist/services/onboarding/onboarding-model.js +4 -1
  48. package/dist/services/onboarding/onboarding-service-factory.js +1 -1
  49. package/dist/services/onboarding/templates/install-speed-kit-html-template.js +5 -2
  50. package/dist/services/pull/pull-service.d.ts +1 -0
  51. package/dist/services/pull/pull-service.js +13 -0
  52. package/dist/services/query-builder/error/parse-config-speed-kit-error.d.ts +4 -0
  53. package/dist/services/query-builder/error/parse-config-speed-kit-error.js +11 -0
  54. package/dist/services/query-builder/query/parameter.d.ts +4 -0
  55. package/dist/services/query-builder/query/parameter.js +49 -0
  56. package/dist/services/query-builder/query/prewarm.d.ts +4 -0
  57. package/dist/services/query-builder/query/prewarm.js +23 -0
  58. package/dist/services/query-builder/query-builder-factory.d.ts +11 -0
  59. package/dist/services/query-builder/query-builder-factory.js +48 -0
  60. package/dist/services/query-builder/query-builder-model.d.ts +20 -0
  61. package/dist/services/query-builder/query-builder-model.js +8 -0
  62. package/dist/services/query-builder/query-builder-service.d.ts +10 -0
  63. package/dist/services/query-builder/query-builder-service.js +48 -0
  64. package/oclif.manifest.json +36 -16
  65. package/package.json +1 -1
  66. package/dist/services/customer-config/templates/config_customer.js.hbs +0 -62
  67. package/dist/services/deploy/handler/module-modifier/deployment-detection-modifier.d.ts +0 -9
  68. package/dist/services/deploy/handler/module-modifier/deployment-detection-modifier.js +0 -24
@@ -11,7 +11,6 @@ const customer_config_handler_1 = tslib_1.__importDefault(require("./handler/cus
11
11
  const install_resource_handler_1 = tslib_1.__importDefault(require("./handler/install-resource-handler"));
12
12
  const deleted_file_check_1 = tslib_1.__importDefault(require("./handler/install-resource-modifier/deleted-file-check"));
13
13
  const module_handler_1 = tslib_1.__importDefault(require("./handler/module-handler"));
14
- const deployment_detection_modifier_1 = tslib_1.__importDefault(require("./handler/module-modifier/deployment-detection-modifier"));
15
14
  const server_config_handler_1 = tslib_1.__importDefault(require("./handler/server-config-handler"));
16
15
  const integration_api_1 = require("../integration-api");
17
16
  const split_change_check_1 = require("./checks/pre-deploy/split-change-check");
@@ -41,13 +40,10 @@ class DeployServiceFactory {
41
40
  const cliService = new cli_1.CliServiceFactory().getService();
42
41
  const installResourceBuilder = new install_resource_builder_1.default(configApi);
43
42
  const deletedFilesChecker = new deleted_file_check_1.default(cliService, this.context.hasArtifacts());
44
- const slackToken = this.context.slackToken || this.cliConfig.slackToken;
45
43
  this.service = new deploy_service_1.default(files, [
46
44
  new customer_config_handler_1.default(customer, configApi, configName, diffService, cliService, installResourceBuilder),
47
45
  new install_resource_handler_1.default(customer, configApi, configName, diffService, cliService, installResourceBuilder, deletedFilesChecker),
48
- new module_handler_1.default(configApi, diffService, cliService, [
49
- new deployment_detection_modifier_1.default(slackToken),
50
- ]),
46
+ new module_handler_1.default(configApi, diffService, cliService, []),
51
47
  new server_config_handler_1.default(configApi, diffService, cliService),
52
48
  ], cliService, [
53
49
  new split_change_check_1.SplitChangeCheck(cliService, files, configApi, customer, configName, this.context.isProduction),
@@ -59,7 +55,7 @@ class DeployServiceFactory {
59
55
  return new config_api_1.ConfigApiServiceFactory(configApiContext).getService();
60
56
  }
61
57
  async getIntegrationFiles() {
62
- const integrationApiContext = new integration_api_1.IntegrationApiContext(this.context.customerPath, this.context.configName, this.context.artifacts);
58
+ const integrationApiContext = new integration_api_1.IntegrationApiContext(this.context.customerPath, this.context.configName, this.context.artifacts, integration_api_1.DEFAULT_BLOCKED_FOLDERS, this.context.useTestConfig);
63
59
  const integrationApi = new integration_api_1.IntegrationApiFactory(integrationApiContext, this.cliConfig).buildService();
64
60
  return integrationApi.run();
65
61
  }
@@ -16,5 +16,4 @@ export default class CustomerConfigHandler implements DeployHandlerInterface {
16
16
  handle(files: CustomerConfigFile[]): Promise<void>;
17
17
  upload(files: CustomerConfigFile[]): Promise<void>;
18
18
  private handleMissingRemoteInstallResource;
19
- private prepareOriginDiff;
20
19
  }
@@ -42,10 +42,10 @@ class CustomerConfigHandler {
42
42
  file.skipFile();
43
43
  return;
44
44
  }
45
- // todo: only diff origins update local file if tmp file was changed
46
45
  // todo: add changedThrowable, let the handler catch and decide what to do with it
47
- const { changedFile } = await this.diffService.diffContent(file.name, file.getContent(), this.prepareOriginDiff(installResource));
48
- file.setContent(changedFile);
46
+ const { changedOrigins } = await this.diffService.diffContent(file.name, JSON.stringify(config.origins, null, 4), JSON.stringify(installResource.origins, null, 4));
47
+ const origins = JSON.parse(changedOrigins);
48
+ file.updateOrigins(origins);
49
49
  if (!(await this.cli.confirm("Update origins?", true))) {
50
50
  file.skipFile();
51
51
  return;
@@ -77,10 +77,5 @@ class CustomerConfigHandler {
77
77
  this.cli.exit();
78
78
  }
79
79
  }
80
- prepareOriginDiff(installResource) {
81
- const remoteConfig = {};
82
- remoteConfig[this.configName] = { origins: installResource.origins };
83
- return JSON.stringify(remoteConfig, null, 4);
84
- }
85
80
  }
86
81
  exports.default = CustomerConfigHandler;
@@ -94,8 +94,8 @@ class InstallResourceHandler {
94
94
  await this.confirm(file, true);
95
95
  return;
96
96
  }
97
- const { changedFile, diff } = await this.diffService.diffContent(file.name, file.getContent(), installResource[file.remoteKey]);
98
- file.setContent(changedFile);
97
+ const { changedOrigins, diff } = await this.diffService.diffContent(file.name, file.getContent(), installResource[file.remoteKey]);
98
+ file.setContent(changedOrigins);
99
99
  if (diff) {
100
100
  this.cli.writeWarning(`skipped ${file.name} (identical with remote)`);
101
101
  file.skipFile();
@@ -32,8 +32,8 @@ class ModuleHandler {
32
32
  await this.confirm(file, true);
33
33
  continue;
34
34
  }
35
- const { changedFile, diff } = await this.diffService.diffContent(file.name, file.getContent(), remote);
36
- file.setContent(changedFile);
35
+ const { changedOrigins, diff } = await this.diffService.diffContent(file.name, file.getContent(), remote);
36
+ file.setContent(changedOrigins);
37
37
  if (diff) {
38
38
  this.cli.writeWarning(`skipped ${file.name} (identical with remote)`);
39
39
  file.skipFile();
@@ -27,8 +27,8 @@ class ServerConfigHandler {
27
27
  const remoteConfig = JSON.parse(remote);
28
28
  // @ts-expect-error revision is unknown
29
29
  file.config.revision.version = remoteConfig.revision.version;
30
- const { changedFile, diff } = await this.diffService.diffContent(file.name, file.getContent(), remote);
31
- file.setContent(changedFile);
30
+ const { changedOrigins, diff } = await this.diffService.diffContent(file.name, file.getContent(), remote);
31
+ file.setContent(changedOrigins);
32
32
  if (diff) {
33
33
  this.cli.writeWarning(`skipped ${file.name} (identical with remote)`);
34
34
  file.skipFile();
@@ -7,7 +7,7 @@ export declare class DiffService {
7
7
  constructor(cli: CliService, diffExecutablePath?: string, diffExecutableTemplate?: string);
8
8
  diff(localPath: string, fileName: string, temporaryContent: string): Promise<boolean>;
9
9
  diffContent(fileName: string, localContent: string, remoteContent: string): Promise<{
10
- changedFile: string;
10
+ changedOrigins: string;
11
11
  diff: boolean;
12
12
  }>;
13
13
  /**
@@ -27,7 +27,7 @@ class DiffService {
27
27
  const temporaryRemoteFilePath = await this.writeContentToTemporalFile(`${fileName}-remote`, remoteContent);
28
28
  const diff = await this.executeDiff(temporaryLocalFilePath, temporaryRemoteFilePath);
29
29
  const changedFile = await (0, promises_1.readFile)(temporaryLocalFilePath, "utf-8");
30
- return { changedFile, diff };
30
+ return { changedOrigins: changedFile, diff };
31
31
  }
32
32
  /**
33
33
  * Returns a temporal directory path.
@@ -0,0 +1,4 @@
1
+ import { ConfigFileError } from "../../error-handling/error/config-file-error";
2
+ export default class InvalidConfigFormatError extends ConfigFileError {
3
+ constructor(filePath: string);
4
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_file_error_1 = require("../../error-handling/error/config-file-error");
4
+ const node_path_1 = require("node:path");
5
+ class InvalidConfigFormatError extends config_file_error_1.ConfigFileError {
6
+ constructor(filePath) {
7
+ super("config_customer.js is deprecated");
8
+ const folderName = (0, node_path_1.basename)((0, node_path_1.dirname)(filePath));
9
+ this.suggestions = [
10
+ `Please convert ${filePath} to json`,
11
+ `please execute "node ./tools/convert_config_customer.mjs ${folderName}"`,
12
+ ];
13
+ }
14
+ }
15
+ exports.default = InvalidConfigFormatError;
@@ -18,5 +18,6 @@ export default class FileReader {
18
18
  private isAllowedFile;
19
19
  private getFileExtension;
20
20
  private isWhiteListed;
21
+ isValidateFileExtension(filePath: string, expectedExtension: string): boolean;
21
22
  private mapEnvironment;
22
23
  }
@@ -75,6 +75,10 @@ class FileReader {
75
75
  return fileName.includes(entry);
76
76
  });
77
77
  }
78
+ isValidateFileExtension(filePath, expectedExtension) {
79
+ const extension = this.getFileExtension(filePath);
80
+ return extension === expectedExtension;
81
+ }
78
82
  mapEnvironment(fileList) {
79
83
  const environmentFileList = {};
80
84
  // create mapped object with all environment versions of a file
@@ -8,8 +8,9 @@ export default class CustomerConfigHandler extends FileHandler {
8
8
  private validator;
9
9
  private configName;
10
10
  private testApp?;
11
+ private useTestConfig;
11
12
  allowedFile: string;
12
- constructor(fileReader: FileReader, cli: CliService, validator: CustomerConfigValidator, configName: string, testApp?: string);
13
+ constructor(fileReader: FileReader, cli: CliService, validator: CustomerConfigValidator, configName: string, testApp?: string, useTestConfig?: boolean);
13
14
  canHandle(filePath: string): boolean;
14
15
  handle(filePath: string): Promise<CustomerConfigInterface>;
15
16
  private loadConfig;
@@ -1,31 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- const vm = tslib_1.__importStar(require("node:vm"));
5
4
  const customer_config_error_1 = tslib_1.__importDefault(require("../error/customer-config-error"));
6
- const customer_config_legacy_error_1 = tslib_1.__importDefault(require("../error/customer-config-legacy-error"));
7
5
  const customer_config_1 = require("../struct/customer-config");
8
6
  const customer_config_file_1 = require("../struct/customer-config-file");
9
7
  const file_handler_1 = tslib_1.__importDefault(require("./file-handler"));
10
8
  const application_error_1 = tslib_1.__importDefault(require("../../error-handling/error/application-error"));
11
9
  const safe_1 = require("../../../helpers/safe");
10
+ const invalid_config_format_error_1 = tslib_1.__importDefault(require("../error/invalid-config-format-error"));
12
11
  class CustomerConfigHandler extends file_handler_1.default {
13
12
  cli;
14
13
  validator;
15
14
  configName;
16
15
  testApp;
16
+ useTestConfig;
17
17
  allowedFile = "config_customer";
18
- constructor(fileReader, cli, validator, configName, testApp) {
18
+ constructor(fileReader, cli, validator, configName, testApp, useTestConfig = false) {
19
19
  super(fileReader);
20
20
  this.cli = cli;
21
21
  this.validator = validator;
22
22
  this.configName = configName;
23
23
  this.testApp = testApp;
24
+ this.useTestConfig = useTestConfig;
24
25
  }
25
26
  canHandle(filePath) {
26
27
  return this.allowedFile === this.getFileName(filePath);
27
28
  }
28
29
  async handle(filePath) {
30
+ if (!this.fileReader.isValidateFileExtension(filePath, "json")) {
31
+ throw new invalid_config_format_error_1.default(filePath);
32
+ }
29
33
  const fileContent = await this.fileReader.getContent(filePath);
30
34
  const config = await this.loadConfig(fileContent, filePath);
31
35
  this.validator.validate(config);
@@ -36,36 +40,49 @@ class CustomerConfigHandler extends file_handler_1.default {
36
40
  this.testApp.length === 0) {
37
41
  throw new application_error_1.default("please specify env TEST_APP in your .env or configFile file");
38
42
  }
39
- const customerConfigContext = {
40
- module: { exports: {} }, // make TEST_APP available for vm
41
- process: {
42
- env: { TEST_APP: this.testApp }, // make TEST_APP available for vm
43
- },
44
- };
45
- vm.runInNewContext(fileContent, customerConfigContext, {
46
- filename: filePath,
47
- displayErrors: true,
43
+ const configsResult = (0, safe_1.safe)(() => {
44
+ return JSON.parse(fileContent);
48
45
  });
49
- const configs = customerConfigContext?.module?.exports;
50
- if (Array.isArray(configs) ||
51
- typeof configs === "string" ||
52
- "origins" in configs ||
53
- "name" in configs) {
54
- throw new customer_config_legacy_error_1.default(`Config "${this.configName}" not found`, [
55
- `Check file ${filePath}`,
56
- `module.exports must be an array of customerConfigObjects`,
46
+ if (configsResult.success !== true) {
47
+ throw new customer_config_error_1.default(configsResult.error, [
48
+ `error parsing file ${filePath}`,
57
49
  ]);
58
50
  }
59
- if (this.configName in configs) {
60
- return this.createCustomerConfigFromSelected(configs, this.configName, filePath);
51
+ const configs = {};
52
+ for (const key in configsResult.data) {
53
+ if (key === "$schema") {
54
+ continue;
55
+ }
56
+ configs[key] = configsResult.data[key];
57
+ }
58
+ let selectedConfig = this.configName;
59
+ // check if given configName can be found in parsed file
60
+ if (!(this.configName in configs)) {
61
+ this.cli.writeWarning(`config: ${this.configName} does not exist.`);
62
+ // create a dropdown to select a configName from given file
63
+ selectedConfig = await this.cli.select("Please select config: ", Object.keys(configs).map((option) => ({ name: option, value: option })));
64
+ }
65
+ if (this.useTestConfig && !this.testApp) {
66
+ throw new application_error_1.default("To use the testConfig feature you must configure a TEST_APP");
67
+ }
68
+ // create testConfig from production and selectedConfig
69
+ if (this.useTestConfig && this.testApp) {
70
+ this.cli.writeWarning(`Use TEST_APP: "${this.testApp}" instead of "${configs["production"].app} from config "${this.configName}"`);
71
+ configs["test"] = {
72
+ ...configs["production"],
73
+ ...configs[selectedConfig],
74
+ app: this.testApp,
75
+ name: configs["production"].app,
76
+ };
77
+ selectedConfig = "test";
61
78
  }
62
- this.cli.writeWarning(`config: ${this.configName} does not exist.`);
63
- const selectedConfig = await this.cli.select("Please select config: ", Object.keys(configs).map((option) => ({ name: option, value: option })));
64
79
  return this.createCustomerConfigFromSelected(configs, selectedConfig, filePath);
65
80
  }
66
81
  createCustomerConfigFromSelected(configs, selectedConfig, filePath) {
82
+ // extend configs[production] with configs[selectedConfig]
83
+ const configFile = { ...configs["production"], ...configs[selectedConfig] };
67
84
  const configResponse = (0, safe_1.safe)(() => {
68
- return customer_config_1.CustomerConfig.createFrom(configs[selectedConfig], selectedConfig);
85
+ return customer_config_1.CustomerConfig.createFrom(configFile, selectedConfig);
69
86
  });
70
87
  if (configResponse.success === true) {
71
88
  return configResponse.data;
@@ -34,15 +34,15 @@ class IntegrationApiFactory {
34
34
  const cli = new cli_1.CliServiceFactory().getService();
35
35
  const virtualFileHandler = new virtual_file_handler_1.VirtualFileHandler(cli);
36
36
  this.service = new integration_api_service_1.IntegrationApiService(fileReader, virtualFileHandler, new mandatory_files_validator_1.default(), [
37
- new customer_config_handler_1.default(fileReader, cli, new customer_config_validator_1.default(), this.context.configName, this.cliConfig.testApp),
37
+ new customer_config_handler_1.default(fileReader, cli, new customer_config_validator_1.default(), this.context.configName, this.cliConfig.testApp, this.context.useTestConfig),
38
38
  new install_resource_handler_1.default(fileReader),
39
39
  new server_config_handler_1.default(fileReader),
40
40
  new module_handler_1.default(fileReader),
41
- ], new file_writer_1.default(node_fs_1.default, this.context.basePath), this.context.whiteList.length === 0);
41
+ ], new file_writer_1.default(node_fs_1.default, this.context.basePath), this.context.whitelist.length === 0);
42
42
  }
43
43
  getFileReader() {
44
44
  if (!this.fileReader) {
45
- this.fileReader = new file_reader_1.default(node_fs_1.default, this.context.configName, this.context.basePath, this.context.whiteList, this.context.blockedFolders);
45
+ this.fileReader = new file_reader_1.default(node_fs_1.default, this.context.configName, this.context.basePath, this.context.whitelist, this.context.blockedFolders);
46
46
  }
47
47
  return this.fileReader;
48
48
  }
@@ -85,6 +85,7 @@ export interface InstallResourceInterface extends ConfigFileInterface, FileInter
85
85
  }
86
86
  export interface CustomerConfigInterface extends ConfigFileInterface {
87
87
  config: CustomerConfig;
88
+ updateOrigins(origins: string[]): void;
88
89
  readonly configName: string;
89
90
  }
90
91
  export interface VirtualFileRecipe {
@@ -102,7 +103,8 @@ export declare const DEFAULT_BLOCKED_FOLDERS: string[];
102
103
  export declare class IntegrationApiContext {
103
104
  readonly basePath: string;
104
105
  readonly configName: string;
105
- readonly whiteList: string[];
106
+ readonly whitelist: string[];
106
107
  readonly blockedFolders: string[];
107
- constructor(basePath: string, configName: string, whitelist: string[], blockedFolders?: string[]);
108
+ readonly useTestConfig: boolean;
109
+ constructor(basePath: string, configName: string, whitelist?: string[], blockedFolders?: string[], useTestConfig?: boolean);
108
110
  }
@@ -27,13 +27,15 @@ exports.DEFAULT_BLOCKED_FOLDERS = ["test", ".local", ".git", ".idea"];
27
27
  class IntegrationApiContext {
28
28
  basePath;
29
29
  configName;
30
- whiteList;
30
+ whitelist;
31
31
  blockedFolders;
32
- constructor(basePath, configName, whitelist, blockedFolders) {
32
+ useTestConfig;
33
+ constructor(basePath, configName, whitelist = [], blockedFolders = exports.DEFAULT_BLOCKED_FOLDERS, useTestConfig = false) {
33
34
  this.basePath = basePath;
34
35
  this.configName = configName;
35
- this.whiteList = whitelist;
36
- this.blockedFolders = blockedFolders || exports.DEFAULT_BLOCKED_FOLDERS;
36
+ this.whitelist = whitelist;
37
+ this.blockedFolders = blockedFolders;
38
+ this.useTestConfig = useTestConfig;
37
39
  }
38
40
  }
39
41
  exports.IntegrationApiContext = IntegrationApiContext;
@@ -24,7 +24,7 @@ const customer_config_1 = require("../struct/customer-config");
24
24
  const customerConfig = new customer_config_1.CustomerConfig("test", [], "test.dev", "/wrapper.sw", "/");
25
25
  (0, chai_1.expect)(() => {
26
26
  validator.validate(customerConfig);
27
- }).to.throw("No origins were found in local config_customer.js! Add origins and restart deploy!");
27
+ }).to.throw("No origins were found in local config_customer.json! Add origins and restart deploy!");
28
28
  });
29
29
  (0, mocha_1.it)("should throw error not having a protocol", () => {
30
30
  const validator = new customer_config_validator_1.default();
@@ -92,7 +92,7 @@ const __1 = require("../");
92
92
  (0, mocha_1.describe)("fileList getCustomerConfig", () => {
93
93
  (0, mocha_1.it)("get all CustomerConfig files", () => {
94
94
  const fileList = new file_list_1.default();
95
- fileList.addFile(new __1.CustomerConfigFile("config_customer", "/test/config_customer.js", "{}", {}, "test"));
95
+ fileList.addFile(new __1.CustomerConfigFile("config_customer", "/test/config_customer.json", "{}", {}, "test"));
96
96
  fileList.addFile(new __1.VirtualFile("custom_sw2.js", {}));
97
97
  // Assert that our function returned the correct value
98
98
  (0, chai_1.expect)(fileList.getCustomerConfig().configName).to.equal("test");
@@ -100,7 +100,7 @@ const __1 = require("../");
100
100
  });
101
101
  (0, mocha_1.describe)("fileList getTypes", () => {
102
102
  const fileList = new file_list_1.default();
103
- fileList.addFile(new __1.CustomerConfigFile("config_customer", "/test/config_customer.js", "{}", {}, "test"));
103
+ fileList.addFile(new __1.CustomerConfigFile("config_customer", "/test/config_customer.json", "{}", {}, "test"));
104
104
  fileList.addFile(new __1.VirtualFile("custom_sw.js", {}));
105
105
  fileList.addFile(new __1.VirtualFile("custom_sw2.js", {}));
106
106
  fileList.addFile(new __1.ModuleFile("deploymentDetection_test", "/test/deploymentDetection_test.es6", "{}", "{}"));
@@ -10,9 +10,23 @@ const afterTest = () => {
10
10
  };
11
11
  (0, mocha_1.describe)("FileReader getFileList ", () => {
12
12
  (0, mocha_1.before)(() => {
13
+ const customerJson = {
14
+ $schema: "../../sk-typings/customerConfig.schema.json",
15
+ test: {
16
+ _meta: {
17
+ shopsystem: "TEST",
18
+ },
19
+ app: "test",
20
+ name: "test",
21
+ origins: ["https://www.speed-kit.com"],
22
+ swPath: "/wrapper-sw.js",
23
+ scope: "/",
24
+ forceInstall: true,
25
+ },
26
+ };
13
27
  memfs_1.vol.fromNestedJSON({
14
28
  "/test_customer": {
15
- "config_customer.js": "module.export = {production}",
29
+ "config_customer.json": `${JSON.stringify(customerJson)}`,
16
30
  "config_SpeedKit.js": "skConfig",
17
31
  ".local/test.js": "test",
18
32
  "magic/test3.js": "test3",
@@ -51,12 +65,12 @@ const afterTest = () => {
51
65
  /**
52
66
  * add asdf to whitelist
53
67
  */
54
- (0, mocha_1.it)("fileList should include config_customer.js", () => {
68
+ (0, mocha_1.it)("fileList should include config_customer.json", () => {
55
69
  const fileReader = new file_reader_1.default(
56
70
  // @ts-expect-error fs is not compatible
57
71
  memfs_1.fs, "test", "test_customer", ["asdf"], ["magic"]);
58
72
  const fileList = fileReader.getFileList("/test_customer");
59
- (0, chai_1.expect)(fileList).to.include("/test_customer/config_customer.js");
73
+ (0, chai_1.expect)(fileList).to.include("/test_customer/config_customer.json");
60
74
  });
61
75
  /**
62
76
  * if whitelist is set, only files from whitelist or config_SpeedKit.js should be returned
@@ -38,9 +38,23 @@ function prepareDependencies() {
38
38
  }
39
39
  (0, mocha_1.describe)("integration service run", () => {
40
40
  (0, mocha_1.before)(() => {
41
+ const customerJson = {
42
+ $schema: "../../sk-typings/customerConfig.schema.json",
43
+ test: {
44
+ _meta: {
45
+ shopsystem: "TEST",
46
+ },
47
+ app: "test",
48
+ // name: "test",
49
+ origins: ["https://www.speed-kit.com"],
50
+ swPath: "/wrapper-sw.js",
51
+ scope: "/",
52
+ forceInstall: true,
53
+ },
54
+ };
41
55
  memfs_1.vol.fromNestedJSON({
42
56
  "/test_customer": {
43
- "config_customer.js": `module.exports = {test:{app:"test",domain:"test.dev",origins:["https://test.dev"],scope:"/",swPath: "/wrapper-sw.js"}}`,
57
+ "config_customer.json": `${JSON.stringify(customerJson)}`,
44
58
  "config_SpeedKit.js": "",
45
59
  "config_dynamicBlocks.js": "",
46
60
  "config_dynamicStyles.css": "",
@@ -6,5 +6,6 @@ export declare class CustomerConfigFile extends File implements CustomerConfigIn
6
6
  readonly type = FILE_TYPE.CUSTOMER_FILE;
7
7
  constructor(name: string, path: string, content: string, config: CustomerConfig, configName: string, testApp?: string);
8
8
  setContent(content: string): void;
9
+ updateOrigins(origins: string[]): void;
9
10
  private updateConfigByContent;
10
11
  }
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CustomerConfigFile = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const vm = tslib_1.__importStar(require("node:vm"));
6
5
  const integration_api_model_1 = require("../integration-api-model");
6
+ const safe_1 = require("../../../helpers/safe");
7
+ const customer_config_error_1 = tslib_1.__importDefault(require("../error/customer-config-error"));
8
+ const array_helper_1 = require("../../../helpers/array-helper");
7
9
  class CustomerConfigFile extends integration_api_model_1.File {
8
10
  config;
9
11
  configName;
@@ -19,19 +21,29 @@ class CustomerConfigFile extends integration_api_model_1.File {
19
21
  super.setContent(content);
20
22
  this.updateConfigByContent();
21
23
  }
24
+ updateOrigins(origins) {
25
+ // if the origins are the same, do nothing
26
+ if ((0, array_helper_1.isSame)(this.config.origins, origins)) {
27
+ return;
28
+ }
29
+ // if the origins differ, update the config and save its content
30
+ this.config.origins = origins;
31
+ const configContent = JSON.parse(this.getContent());
32
+ configContent[this.configName].origins = origins;
33
+ this.setContent(JSON.stringify(configContent, null, 2));
34
+ }
22
35
  updateConfigByContent() {
23
- const customerConfigContext = {
24
- module: { exports: {} }, // make TEST_APP available for vm
25
- process: {
26
- env: { TEST_APP: this.testApp }, // make TEST_APP available for vm
27
- },
28
- };
29
- vm.runInNewContext(this.getContent(), customerConfigContext, {
30
- filename: this.path,
31
- displayErrors: true,
36
+ const configsResult = (0, safe_1.safe)(() => {
37
+ return JSON.parse(this.getContent());
32
38
  });
33
- if (this.configName in customerConfigContext.module.exports) {
34
- this.config = integration_api_model_1.CustomerConfig.createFrom(customerConfigContext.module.exports[this.configName], this.configName);
39
+ if (configsResult.success !== true) {
40
+ throw new customer_config_error_1.default(configsResult.error, [
41
+ `error parsing file config_customer.json`,
42
+ ]);
43
+ }
44
+ const configs = configsResult.data;
45
+ if (this.configName in configs) {
46
+ this.config = integration_api_model_1.CustomerConfig.createFrom({ ...configs["production"], ...configs[this.configName] }, this.configName);
35
47
  }
36
48
  }
37
49
  }
@@ -1,6 +1,10 @@
1
+ export type CustomerConfigs = {
2
+ production: CustomerConfig;
3
+ [configName: string]: CustomerConfig;
4
+ };
1
5
  export declare class CustomerConfig {
2
6
  readonly app: string;
3
- readonly origins: string[];
7
+ origins: string[];
4
8
  readonly domain: string;
5
9
  readonly swPath: string;
6
10
  readonly scope: string;
@@ -14,7 +14,7 @@ class CustomerConfigValidator {
14
14
  }
15
15
  validateOrigins(config) {
16
16
  if (config.origins.length === 0) {
17
- throw new origin_error_1.default("No origins were found in local config_customer.js! Add origins and restart deploy!");
17
+ throw new origin_error_1.default("No origins were found in local config_customer.json! Add origins and restart deploy!");
18
18
  }
19
19
  if (this.hasProtocol(config.origins)) {
20
20
  throw new origin_error_1.default("There was at least one origin configured in the local customer_config.js not having a protocol.");
@@ -50,12 +50,13 @@ export declare class OnboardingContext {
50
50
  readonly ignoreContentSecurityPolicy: boolean;
51
51
  readonly cliPath: string;
52
52
  readonly verboseLevel?: boolean;
53
+ readonly useTestConfig: boolean;
53
54
  static flags: FlagInput;
54
55
  readonly DEFAULT_DF_PATH = "https://www.baqend.com/speed-kit/latest/dynamic-fetcher.js";
55
56
  readonly DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
56
57
  readonly DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
57
58
  readonly DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
58
- constructor(customerPath: string, configName: string, domain: string, local: boolean, ignoreContentSecurityPolicy: boolean, cliPath: string, verboseLevel?: boolean);
59
+ constructor(customerPath: string, configName: string, domain: string, local: boolean, ignoreContentSecurityPolicy: boolean, cliPath: string, verboseLevel?: boolean, useTestConfig?: boolean);
59
60
  }
60
61
  export type SpeedKitServerConfigAuthentication = {
61
62
  password: string;
@@ -79,8 +79,10 @@ class OnboardingContext {
79
79
  ignoreContentSecurityPolicy;
80
80
  cliPath;
81
81
  verboseLevel;
82
+ useTestConfig;
82
83
  static flags = {
83
84
  ...cli_parameters_1.CLI_CONFIG_NAME,
85
+ ...cli_parameters_1.CLI_CONFIG_IS_TEST,
84
86
  [cli_parameters_1.CLIParameters.Domain]: core_1.Flags.string({
85
87
  char: cli_parameters_1.CLIParametersChar.Domain,
86
88
  description: "Startup domain (optional)",
@@ -105,7 +107,7 @@ class OnboardingContext {
105
107
  DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
106
108
  DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
107
109
  DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
108
- constructor(customerPath, configName, domain, local, ignoreContentSecurityPolicy = false, cliPath, verboseLevel) {
110
+ constructor(customerPath, configName, domain, local, ignoreContentSecurityPolicy = false, cliPath, verboseLevel, useTestConfig = false) {
109
111
  this.customerPath = customerPath;
110
112
  this.configName = configName;
111
113
  this.domain = domain;
@@ -113,6 +115,7 @@ class OnboardingContext {
113
115
  this.ignoreContentSecurityPolicy = ignoreContentSecurityPolicy;
114
116
  this.cliPath = cliPath;
115
117
  this.verboseLevel = verboseLevel;
118
+ this.useTestConfig = useTestConfig;
116
119
  }
117
120
  }
118
121
  exports.OnboardingContext = OnboardingContext;
@@ -152,7 +152,7 @@ class OnboardingServiceFactory {
152
152
  const swPath = path.join(speedKitBuildPath, "sw.js");
153
153
  const dfPath = path.join(speedKitBuildPath, "dynamic-fetcher.js");
154
154
  const loaderPath = path.join(speedKitBuildPath, "snippet.js");
155
- const integrationApiContext = new integration_api_1.IntegrationApiContext(this.context.customerPath, this.context.configName, []);
155
+ const integrationApiContext = new integration_api_1.IntegrationApiContext(this.context.customerPath, this.context.configName, [], [], this.context.useTestConfig);
156
156
  const integrationApi = new integration_api_1.IntegrationApiFactory(integrationApiContext, this.cliConfig).buildService();
157
157
  const externalFileReader = new integration_api_1.ExternalFileReader();
158
158
  const integrationApiArray = [
@@ -222,8 +222,11 @@ aside.loader:not(.stop)::after {
222
222
  const step4 = document.querySelector('[data-step="4"]')
223
223
  step4.classList.add('loading')
224
224
 
225
- const response = await fetch("{{{domain}}}")
226
-
225
+ try {
226
+ SpeedKit.preload(["{{{domain}}}"])
227
+ } catch (e) {
228
+ console.error(e);
229
+ }
227
230
 
228
231
  location.href = new URL(location.href).searchParams.get('url') || '/';
229
232
 
@@ -15,4 +15,5 @@ export declare class PullService {
15
15
  private readLocalFile;
16
16
  private createFile;
17
17
  private hasGitChanges;
18
+ private handleConfigCustomer;
18
19
  }
@@ -37,6 +37,7 @@ class PullService {
37
37
  }
38
38
  this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
39
39
  const installResource = installResourceResult.data;
40
+ await this.handleConfigCustomer(installResource);
40
41
  for (const key in _1.InstallResourceToFileMapping) {
41
42
  await this.updateLocalFileByInstallResource(installResource, key);
42
43
  }
@@ -107,5 +108,17 @@ class PullService {
107
108
  this.cli.exit(1);
108
109
  }
109
110
  }
111
+ async handleConfigCustomer(installResource) {
112
+ const customerConfigFile = this.fileList.getCustomerConfig();
113
+ const config = customerConfigFile.config;
114
+ if (JSON.stringify(installResource.origins.sort()) !==
115
+ JSON.stringify(config.origins.sort())) {
116
+ this.cli.writeWarning(`update: config_customer(origins)`);
117
+ customerConfigFile.updateOrigins(installResource.origins);
118
+ await customerConfigFile.updateFile();
119
+ return;
120
+ }
121
+ this.cli.writeSuccess("equal, skip: config_customer(origins)");
122
+ }
110
123
  }
111
124
  exports.PullService = PullService;