@speedkit/cli 2.38.0 → 2.39.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 (56) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +5 -5
  3. package/dist/commands/build-parameter-query.d.ts +1 -1
  4. package/dist/commands/build-prewarm-query.d.ts +1 -1
  5. package/dist/commands/deploy.d.ts +1 -1
  6. package/dist/commands/document-handler.d.ts +1 -1
  7. package/dist/commands/find-pops.js +0 -1
  8. package/dist/commands/onboarding.d.ts +1 -1
  9. package/dist/commands/onboarding.js +1 -1
  10. package/dist/commands/prewarm.d.ts +1 -1
  11. package/dist/commands/pull.d.ts +1 -1
  12. package/dist/dummy.spec.js +2 -3
  13. package/dist/helpers/build-query-helper.js +5 -6
  14. package/dist/helpers/file-helper.js +2 -3
  15. package/dist/helpers/get-parsed-config.js +3 -4
  16. package/dist/helpers/is-directory.js +1 -2
  17. package/dist/helpers/is-file.js +1 -2
  18. package/dist/helpers/logging-helper.js +3 -4
  19. package/dist/helpers/normalize.d.ts +0 -1
  20. package/dist/helpers/normalize.js +4 -5
  21. package/dist/helpers/race.js +1 -2
  22. package/dist/helpers/safe.js +1 -2
  23. package/dist/helpers/scrape.js +1 -1
  24. package/dist/helpers/speed-kit-rule-to-reg-exp.js +1 -2
  25. package/dist/models/cli-parameters.d.ts +1 -1
  26. package/dist/services/athena/athena-service-factory.js +1 -1
  27. package/dist/services/athena/athena-service.d.ts +3 -1
  28. package/dist/services/athena/athena-service.js +14 -2
  29. package/dist/services/config-api-service.d.ts +1 -1
  30. package/dist/services/config-api-service.js +1 -0
  31. package/dist/services/integration-api/file-reader.d.ts +0 -1
  32. package/dist/services/onboarding/browser/extension/devtools-extension-api.d.ts +7 -0
  33. package/dist/services/onboarding/browser/extension/devtools-extension-api.js +16 -0
  34. package/dist/services/onboarding/browser/extension/extension-validator.d.ts +10 -0
  35. package/dist/services/onboarding/browser/extension/extension-validator.js +71 -0
  36. package/dist/services/onboarding/dashboard/index.d.ts +1 -0
  37. package/dist/services/onboarding/dashboard/index.js +23 -22
  38. package/dist/services/onboarding/dashboard/request-diff-service.d.ts +2 -1
  39. package/dist/services/onboarding/dashboard/request-diff-service.js +34 -6
  40. package/dist/services/onboarding/error/browser-extension-error.d.ts +5 -0
  41. package/dist/services/onboarding/error/browser-extension-error.js +12 -0
  42. package/dist/services/onboarding/fetch-event-handler.js +13 -14
  43. package/dist/services/onboarding/onboarding-model.d.ts +33 -3
  44. package/dist/services/onboarding/onboarding-model.js +32 -5
  45. package/dist/services/onboarding/onboarding-service-factory.d.ts +1 -0
  46. package/dist/services/onboarding/onboarding-service-factory.js +22 -4
  47. package/dist/services/onboarding/onboarding-service.d.ts +3 -3
  48. package/dist/services/onboarding/onboarding-service.js +35 -30
  49. package/dist/services/onboarding/todo-collector.d.ts +2 -2
  50. package/dist/services/onboarding/todo-collector.js +1 -1
  51. package/dist/services/prewarm/assets/asset-api-client.js +0 -1
  52. package/oclif.manifest.json +1 -1
  53. package/package.json +19 -19
  54. package/dist/services/onboarding/dashboard/frontend-dist/assets/index-e3bd4f6e.css +0 -1
  55. package/dist/services/onboarding/dashboard/frontend-dist/assets/main-215271c2.js +0 -9
  56. package/dist/services/onboarding/dashboard/frontend-dist/index.html +0 -18
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Dashboard = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const baqend_response_1 = require("../browser/baqend-response");
6
- const node_fs_1 = require("node:fs");
7
- const node_path_1 = tslib_1.__importDefault(require("node:path"));
8
6
  const safe_1 = require("../../../helpers/safe");
9
7
  const json2csv_1 = tslib_1.__importDefault(require("json2csv"));
10
8
  class Dashboard {
@@ -23,31 +21,24 @@ class Dashboard {
23
21
  }
24
22
  async getResponse(request) {
25
23
  const url = new URL(request.url);
26
- if (url.pathname === "/") {
27
- const filePath = node_path_1.default.join(__dirname, "./frontend-dist", "index.html");
28
- const content = (0, node_fs_1.readFileSync)(filePath, { encoding: "utf-8" });
29
- return new baqend_response_1.BaqendResponse(content);
24
+ const requestOrigin = request.headers["Origin"] || "*";
25
+ if ("Access-Control-Request-Method" in request.headers) {
26
+ return this.createBaqendResponse(requestOrigin, "preflight");
30
27
  }
31
- if (url.pathname.startsWith("/assets/")) {
32
- const filePath = node_path_1.default.join(__dirname, "./frontend-dist", url.pathname);
33
- const content = (0, node_fs_1.readFileSync)(filePath, { encoding: "utf-8" });
34
- let contentType = "application/javascript; charset=UTF-8";
35
- if (url.pathname.includes(".css")) {
36
- contentType = "text/css";
37
- }
38
- return new baqend_response_1.BaqendResponse(content, contentType);
28
+ if (request.method !== "POST" && request.method !== "GET") {
29
+ return this.createBaqendResponse(requestOrigin, "unsupported method");
39
30
  }
40
31
  if (url.pathname.startsWith("/query/create")) {
41
- return new baqend_response_1.BaqendResponse(JSON.stringify({ query: this.parameterQueryBuilder.getQuery() }), "application/json; charset=UTF-8");
32
+ return this.createBaqendResponse(requestOrigin, JSON.stringify({ query: this.parameterQueryBuilder.getQuery() }), "application/json; charset=UTF-8");
42
33
  }
43
34
  if (url.pathname.startsWith("/query/execute")) {
44
35
  const postData = request.postData;
45
36
  const data = JSON.parse(postData);
46
37
  const response = await (0, safe_1.safe)(this.athenaClient.getResult(data.query, []));
47
38
  if (response.success === true) {
48
- return new baqend_response_1.BaqendResponse(JSON.stringify(response.data), "application/json; charset=UTF-8");
39
+ return this.createBaqendResponse(requestOrigin, JSON.stringify(response.data), "application/json; charset=UTF-8");
49
40
  }
50
- return new baqend_response_1.BaqendResponse(response.error, null, [{ name: "x-error", value: response.error }], 500);
41
+ return this.createBaqendResponse(requestOrigin, response.error, null, [{ name: "x-error", value: response.error }], 500);
51
42
  }
52
43
  // @todo reImplement getLastResult
53
44
  if (url.pathname.startsWith("/query/download")) {
@@ -63,7 +54,7 @@ class Dashboard {
63
54
  "example3",
64
55
  ],
65
56
  });
66
- return new baqend_response_1.BaqendResponse(csv, "application/csv", [
57
+ return this.createBaqendResponse(requestOrigin, csv, "application/csv", [
67
58
  {
68
59
  name: "Content-disposition",
69
60
  value: `attachment; filename=parameter-${this.customerConfig.app}.csv`,
@@ -71,21 +62,31 @@ class Dashboard {
71
62
  ]);
72
63
  }
73
64
  if (url.pathname.startsWith("/api/config")) {
74
- return new baqend_response_1.BaqendResponse(JSON.stringify(this.customerConfig), "application/json; charset=UTF-8");
65
+ return this.createBaqendResponse(requestOrigin, JSON.stringify(this.customerConfig), "application/json; charset=UTF-8");
75
66
  }
76
67
  if (url.pathname.startsWith("/diff")) {
77
68
  const postData = request.postData;
78
69
  const data = JSON.parse(postData);
79
- return await this.requestDiffService.postDiff(data.url, data.paramKeys);
70
+ return this.requestDiffService.postDiff(requestOrigin, data.url, data.paramKeys, data.autoDiff);
80
71
  }
81
72
  if (url.pathname.startsWith("/cache/get")) {
82
73
  const response = [];
83
74
  for (const [url, baqendResponse] of this.cache.getAll()) {
84
75
  response.push({ url, response: baqendResponse });
85
76
  }
86
- return new baqend_response_1.BaqendResponse(JSON.stringify(response), "application/json; charset=UTF-8");
77
+ return this.createBaqendResponse(requestOrigin, JSON.stringify(response), "application/json; charset=UTF-8");
87
78
  }
88
- return new baqend_response_1.BaqendResponse("Not implemented");
79
+ return this.createBaqendResponse(requestOrigin, "Not implemented");
80
+ }
81
+ createBaqendResponse(origin, body, contentType, headers = [], status) {
82
+ headers.push({
83
+ name: "Access-Control-Allow-Origin",
84
+ value: origin,
85
+ }, {
86
+ name: "Access-Control-Allow-Headers",
87
+ value: "Content-Type,Access-Control-Allow-Origin,origin",
88
+ });
89
+ return new baqend_response_1.BaqendResponse(body, contentType, headers, status);
89
90
  }
90
91
  }
91
92
  exports.Dashboard = Dashboard;
@@ -5,9 +5,10 @@ export declare class RequestDiffService {
5
5
  private diffService;
6
6
  private documentHandlerRuntime;
7
7
  constructor(diffService: DiffService, documentHandlerRuntime: DocumentHandlerServer);
8
- postDiff(url: string, parametersString: string, autoCheck?: boolean): Promise<BaqendResponse>;
8
+ postDiff(requestOrigin: string, url: string, parametersString: string, autoCheck?: boolean): Promise<BaqendResponse>;
9
9
  private diffLocal;
10
10
  private doOriginVsContentDiff;
11
11
  private fetchHtml;
12
12
  private createUrlsForDiff;
13
+ private createBaqendResponse;
13
14
  }
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RequestDiffService = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const baqend_response_1 = require("../browser/baqend-response");
5
6
  const safe_1 = require("../../../helpers/safe");
7
+ const node_https_1 = require("node:https");
8
+ const node_crypto_1 = tslib_1.__importDefault(require("node:crypto"));
9
+ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
6
10
  class RequestDiffService {
7
11
  diffService;
8
12
  documentHandlerRuntime;
@@ -10,7 +14,7 @@ class RequestDiffService {
10
14
  this.diffService = diffService;
11
15
  this.documentHandlerRuntime = documentHandlerRuntime;
12
16
  }
13
- async postDiff(url, parametersString, autoCheck = false) {
17
+ async postDiff(requestOrigin, url, parametersString, autoCheck = false) {
14
18
  const parameters = parametersString
15
19
  .replace("[", "")
16
20
  .replace("]", "")
@@ -21,15 +25,15 @@ class RequestDiffService {
21
25
  const { urlWithParam, urlWithoutParam } = this.createUrlsForDiff(url, parameters);
22
26
  const result = await (0, safe_1.safe)(this.diffLocal(urlWithParam, urlWithoutParam, autoCheck));
23
27
  if (result.success === true) {
24
- return new baqend_response_1.BaqendResponse(JSON.stringify({
28
+ return this.createBaqendResponse(requestOrigin, JSON.stringify({
25
29
  status: "success",
26
30
  isIdentical: result.data,
27
31
  }), "application/json; charset=UTF-8");
28
32
  }
29
- return new baqend_response_1.BaqendResponse(JSON.stringify({
33
+ return this.createBaqendResponse(requestOrigin, JSON.stringify({
30
34
  status: "error",
31
35
  error: result.error,
32
- }), "application/json; charset=UTF-8", null, 500);
36
+ }), "application/json; charset=UTF-8", [], 500);
33
37
  }
34
38
  async diffLocal(urlWithParameter, urlWithoutParameter, checkIsEqual = false) {
35
39
  const htmlWithParameter = await this.fetchHtml(urlWithParameter);
@@ -56,8 +60,22 @@ class RequestDiffService {
56
60
  return await this.diffService.executeDiff(local, origin);
57
61
  }
58
62
  async fetchHtml(url) {
59
- const response = await fetch(url);
60
- return await response.text();
63
+ const agent = new node_https_1.Agent({
64
+ rejectUnauthorized: false,
65
+ keepAlive: true,
66
+ secureOptions: node_crypto_1.default.constants.SSL_OP_LEGACY_SERVER_CONNECT,
67
+ });
68
+ const response = await (0, safe_1.safe)((0, node_fetch_1.default)(url, {
69
+ agent: agent,
70
+ headers: {
71
+ "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36 SpeedKitCrawler/1.0",
72
+ },
73
+ }));
74
+ if (response.success !== true) {
75
+ console.log(response.errorObj);
76
+ throw response.errorObj;
77
+ }
78
+ return response.data.text();
61
79
  }
62
80
  createUrlsForDiff(urlWithParameter, parameters) {
63
81
  const url = new URL(urlWithParameter);
@@ -72,5 +90,15 @@ class RequestDiffService {
72
90
  urlWithoutParam: urlWithoutParameter,
73
91
  };
74
92
  }
93
+ createBaqendResponse(requestOrigin, body, contentType, headers = [], status) {
94
+ headers.push({
95
+ name: "Access-Control-Allow-Origin",
96
+ value: requestOrigin,
97
+ }, {
98
+ name: "Access-Control-Allow-Headers",
99
+ value: "Content-Type,Access-Control-Allow-Origin,origin",
100
+ });
101
+ return new baqend_response_1.BaqendResponse(body, contentType, headers, status);
102
+ }
75
103
  }
76
104
  exports.RequestDiffService = RequestDiffService;
@@ -0,0 +1,5 @@
1
+ import { PrettyPrintableError } from "@oclif/core/lib/errors";
2
+ export declare class BrowserExtensionError extends Error implements PrettyPrintableError {
3
+ readonly code = "BROWSER_EXTENSION_ERROR";
4
+ readonly suggestions: string[];
5
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BrowserExtensionError = void 0;
4
+ class BrowserExtensionError extends Error {
5
+ code = "BROWSER_EXTENSION_ERROR";
6
+ suggestions = [
7
+ "check paths in env $CHROME_EXTENSION_PATHS",
8
+ "or",
9
+ `"chromeExtensionPaths:" in .config/speed-kit-cli/config.js`,
10
+ ];
11
+ }
12
+ exports.BrowserExtensionError = BrowserExtensionError;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FetchEventHandler = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const onboarding_model_1 = require("./onboarding-model");
5
6
  const puppeteer_core_1 = require("puppeteer-core");
6
7
  const abort_response_1 = require("./browser/abort-response");
7
8
  const cli_1 = require("../cli");
@@ -19,8 +20,8 @@ class FetchEventHandler {
19
20
  this.client = client;
20
21
  }
21
22
  async handleRequestFetchEvents(target) {
22
- const browserClient = await target.createCDPSession();
23
- await browserClient.send("Fetch.enable", {
23
+ const cdpSession = await target.createCDPSession();
24
+ await (0, safe_1.safe)(cdpSession.send("Fetch.enable", {
24
25
  handleAuthRequests: true,
25
26
  //see: https://chromedevtools.github.io/devtools-protocol/tot/Fetch#type-RequestPattern
26
27
  patterns: [
@@ -29,16 +30,16 @@ class FetchEventHandler {
29
30
  }),
30
31
  ...this.getAuthPattern(),
31
32
  ],
32
- });
33
- browserClient.on("Fetch.authRequired", async (event) => {
34
- const response = await (0, safe_1.safe)(this.onFetchAuthRequired(event, browserClient));
33
+ }));
34
+ cdpSession.on(onboarding_model_1.BROWSER_EVENTS.FETCH_AUTH_REQUIRED, async (event) => {
35
+ const response = await (0, safe_1.safe)(this.onFetchAuthRequired(event, cdpSession));
35
36
  if (response.success === true) {
36
37
  return response.data;
37
38
  }
38
39
  this.cli.writeError(response.error);
39
40
  });
40
- browserClient.on("Fetch.requestPaused", async (event) => {
41
- const response = await (0, safe_1.safe)(this.onFetchRequestPaused(event, browserClient));
41
+ cdpSession.on(onboarding_model_1.BROWSER_EVENTS.FETCH_REQUEST_PAUSED, async (event) => {
42
+ const response = await (0, safe_1.safe)(this.onFetchRequestPaused(event, cdpSession));
42
43
  if (response.success === true) {
43
44
  return;
44
45
  }
@@ -62,32 +63,30 @@ class FetchEventHandler {
62
63
  return !pattern.resourceType || pattern.resourceType === resourceType;
63
64
  });
64
65
  }
65
- async onFetchRequestPaused(event, browserClient) {
66
+ async onFetchRequestPaused(event, cdpSession) {
66
67
  const requestId = event.requestId;
67
68
  for (const fetchEvent of this.browserFetchEvents) {
68
69
  // check if current request could be handled
69
70
  if (!this.canHandlePattern(fetchEvent, event.request.url, event.resourceType, event.responseHeaders ? "Response" : "Request")) {
70
71
  continue;
71
72
  }
72
- const response = await fetchEvent.handle(event, browserClient);
73
+ const response = await fetchEvent.handle(event, cdpSession);
73
74
  if (!response) {
74
75
  continue;
75
76
  }
76
77
  if (response instanceof abort_response_1.AbortResponse) {
77
- await browserClient.send("Fetch.failRequest", {
78
+ return cdpSession.send("Fetch.failRequest", {
78
79
  requestId: requestId,
79
80
  errorReason: response.errorReason,
80
81
  });
81
- return;
82
82
  }
83
- await browserClient.send("Fetch.fulfillRequest", {
83
+ return cdpSession.send("Fetch.fulfillRequest", {
84
84
  ...response,
85
85
  requestId,
86
86
  });
87
- return;
88
87
  }
89
88
  //see: https://chromedevtools.github.io/devtools-protocol/tot/Fetch#method-continueRequest
90
- await browserClient.send("Fetch.continueRequest", {
89
+ return cdpSession.send("Fetch.continueRequest", {
91
90
  requestId: requestId,
92
91
  });
93
92
  }
@@ -3,6 +3,32 @@ import { Protocol } from "puppeteer-core";
3
3
  import { UserCliConfig } from "../../helpers/cli-config";
4
4
  import { AbortResponse } from "./browser/abort-response";
5
5
  import { FlagInput } from "@oclif/core/lib/interfaces/parser";
6
+ export declare const BROWSER_EVENTS: {
7
+ DISCONNECTED: string;
8
+ FETCH_AUTH_REQUIRED: string;
9
+ FETCH_REQUEST_PAUSED: string;
10
+ };
11
+ export declare const CDP_SESSION: {
12
+ EVENTS: {
13
+ SERVICE_WORKER: {
14
+ REGISTRATION_UPDATED: string;
15
+ };
16
+ };
17
+ MESSAGE: {
18
+ SERVICE_WORKER: {
19
+ ENABLE: string;
20
+ UNREGISTER: string;
21
+ };
22
+ STORAGE: {
23
+ CLEAR_COOKIES: string;
24
+ CLEAR_DATA: string;
25
+ };
26
+ EMULATION: {
27
+ CLEAR_DEVICE: string;
28
+ CLEAR_GEOLOCATION: string;
29
+ };
30
+ };
31
+ };
6
32
  export declare class BrowserContext {
7
33
  readonly domain: string;
8
34
  readonly chromeFlags?: string[];
@@ -10,7 +36,6 @@ export declare class BrowserContext {
10
36
  userAgent?: string;
11
37
  readonly browserArgs: string[];
12
38
  readonly chromePath: string;
13
- startParameterDashboard: boolean;
14
39
  constructor(domain: string, chromeFlags?: string[], userConfig?: UserCliConfig, userAgent?: string);
15
40
  }
16
41
  export interface FetchRequestPausedEventHandler {
@@ -22,14 +47,15 @@ export declare class OnboardingContext {
22
47
  readonly configName: string;
23
48
  readonly domain: string;
24
49
  readonly local: boolean;
25
- readonly verboseLevel?: boolean;
26
50
  readonly ignoreContentSecurityPolicy: boolean;
51
+ readonly cliPath: string;
52
+ readonly verboseLevel?: boolean;
27
53
  static flags: FlagInput;
28
54
  readonly DEFAULT_DF_PATH = "https://www.baqend.com/speed-kit/latest/dynamic-fetcher.js";
29
55
  readonly DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
30
56
  readonly DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
31
57
  readonly DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
32
- constructor(customerPath: string, configName: string, domain: string, local: boolean, verboseLevel?: boolean, ignoreContentSecurityPolicy?: boolean);
58
+ constructor(customerPath: string, configName: string, domain: string, local: boolean, ignoreContentSecurityPolicy: boolean, cliPath: string, verboseLevel?: boolean);
33
59
  }
34
60
  export type SpeedKitServerConfigAuthentication = {
35
61
  password: string;
@@ -69,6 +95,10 @@ export type SpeedKitServerConfig = {
69
95
  variations: SpeedKitServerConfigVariation;
70
96
  };
71
97
  };
98
+ export type DevelopmentToolsMessage = {
99
+ id: string;
100
+ data: any;
101
+ };
72
102
  export declare const USER_AGENT: {
73
103
  DESKTOP: string;
74
104
  MOBILE: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SpeedKitInstallRegex = exports.USER_AGENT = exports.OnboardingContext = exports.BrowserContext = void 0;
3
+ exports.SpeedKitInstallRegex = exports.USER_AGENT = exports.OnboardingContext = exports.BrowserContext = exports.CDP_SESSION = exports.BROWSER_EVENTS = void 0;
4
4
  const core_1 = require("@oclif/core");
5
5
  const cli_parameters_1 = require("../../models/cli-parameters");
6
6
  const DEFAULT_BROWSER_ARGS = [
@@ -8,6 +8,32 @@ const DEFAULT_BROWSER_ARGS = [
8
8
  "--no-first-run",
9
9
  "--disable-infobars",
10
10
  ];
11
+ exports.BROWSER_EVENTS = {
12
+ DISCONNECTED: "disconnected",
13
+ FETCH_AUTH_REQUIRED: "Fetch.authRequired",
14
+ FETCH_REQUEST_PAUSED: "Fetch.requestPaused",
15
+ };
16
+ exports.CDP_SESSION = {
17
+ EVENTS: {
18
+ SERVICE_WORKER: {
19
+ REGISTRATION_UPDATED: "ServiceWorker.workerRegistrationUpdated",
20
+ },
21
+ },
22
+ MESSAGE: {
23
+ SERVICE_WORKER: {
24
+ ENABLE: "ServiceWorker.enable",
25
+ UNREGISTER: "ServiceWorker.unregister",
26
+ },
27
+ STORAGE: {
28
+ CLEAR_COOKIES: "Storage.clearCookies",
29
+ CLEAR_DATA: "Storage.clearDataForOrigin",
30
+ },
31
+ EMULATION: {
32
+ CLEAR_DEVICE: "Emulation.clearDeviceMetricsOverride",
33
+ CLEAR_GEOLOCATION: "Emulation.clearGeolocationOverride",
34
+ },
35
+ },
36
+ };
11
37
  class BrowserContext {
12
38
  domain;
13
39
  chromeFlags;
@@ -15,7 +41,6 @@ class BrowserContext {
15
41
  userAgent;
16
42
  browserArgs;
17
43
  chromePath;
18
- startParameterDashboard = false;
19
44
  constructor(domain, chromeFlags, userConfig, userAgent) {
20
45
  this.domain = domain;
21
46
  this.chromeFlags = chromeFlags;
@@ -44,8 +69,9 @@ class OnboardingContext {
44
69
  configName;
45
70
  domain;
46
71
  local;
47
- verboseLevel;
48
72
  ignoreContentSecurityPolicy;
73
+ cliPath;
74
+ verboseLevel;
49
75
  static flags = {
50
76
  ...cli_parameters_1.CLI_CONFIG_NAME,
51
77
  [cli_parameters_1.CLIParameters.Domain]: core_1.Flags.string({
@@ -72,13 +98,14 @@ class OnboardingContext {
72
98
  DEFAULT_DOCUMENT_HANDLER_PATH = "https://www.baqend.com/speed-kit-handler/latest/DocumentHandler.js";
73
99
  DEFAULT_SNIPPET_PATH = "https://www.baqend.com/speed-kit/latest/snippet.js";
74
100
  DEFAULT_SW_PATH = "https://www.baqend.com/speed-kit/latest/sw.js";
75
- constructor(customerPath, configName, domain, local, verboseLevel, ignoreContentSecurityPolicy = false) {
101
+ constructor(customerPath, configName, domain, local, ignoreContentSecurityPolicy = false, cliPath, verboseLevel) {
76
102
  this.customerPath = customerPath;
77
103
  this.configName = configName;
78
104
  this.domain = domain;
79
105
  this.local = local;
80
- this.verboseLevel = verboseLevel;
81
106
  this.ignoreContentSecurityPolicy = ignoreContentSecurityPolicy;
107
+ this.cliPath = cliPath;
108
+ this.verboseLevel = verboseLevel;
82
109
  }
83
110
  }
84
111
  exports.OnboardingContext = OnboardingContext;
@@ -6,6 +6,7 @@ export declare class OnboardingServiceFactory {
6
6
  private cliConfig;
7
7
  constructor(context: OnboardingContext, cliConfig: UserCliConfig);
8
8
  getService(): Promise<OnboardingService>;
9
+ private prepareMessagehandler;
9
10
  private buildInstallResource;
10
11
  private getAthenaClient;
11
12
  private getConfigApi;
@@ -32,6 +32,9 @@ const onboarding_service_1 = require("./onboarding-service");
32
32
  const cache_1 = require("./request-cache/cache");
33
33
  const install_speed_kit_html_template_1 = require("./templates/install-speed-kit-html-template");
34
34
  const install_speed_kit_js_template_1 = require("./templates/install-speed-kit-js-template");
35
+ // import { TodoCollector } from "./todo-collector";
36
+ const extension_validator_1 = require("./browser/extension/extension-validator");
37
+ const devtools_extension_api_1 = require("./browser/extension/devtools-extension-api");
35
38
  const todo_collector_1 = require("./todo-collector");
36
39
  const crawler_1 = require("./virtual-orestes-app/crawler");
37
40
  const virtual_orestes_app_1 = require("./virtual-orestes-app");
@@ -60,11 +63,27 @@ class OnboardingServiceFactory {
60
63
  const skTemplate = new install_speed_kit_js_template_1.InstallSpeedKitJsTemplate();
61
64
  const speedKitInstallContext = new speed_kit_install_context_1.SpeedKitInstallContext(customerConfig, this.context.configName, files, bundler, skTemplate, this.context.local);
62
65
  await this.buildInstallResource(speedKitInstallContext, files, cli);
66
+ const extensionPaths = await new extension_validator_1.ExtensionValidator(this.cliConfig, this.context.cliPath, cli).getValidBrowserExtensionPaths();
67
+ this.cliConfig.chromeExtensionPaths = extensionPaths.join(",");
63
68
  const browserContext = new onboarding_model_1.BrowserContext(domainToStart, customerConfig.chromeFlags || [], this.cliConfig);
64
69
  const fileWatcher = new file_watcher_1.FileWatcher(cli, customerConfig, files, documentHandler, browserContext, cache);
65
- const fetchHandler = await this.getFetchEventHandler(files, customerConfig, documentHandler, cache, cli, browserContext);
70
+ const athenaClient = (await this.getAthenaClient()) || null;
71
+ const fetchHandler = await this.getFetchEventHandler(files, customerConfig, documentHandler, cache, cli, browserContext, athenaClient);
72
+ const messageHandler = this.prepareMessagehandler(athenaClient, files);
73
+ return new onboarding_service_1.OnboardingService(browserContext, customerConfig, fetchHandler, fileWatcher, cli, messageHandler);
74
+ }
75
+ prepareMessagehandler(athenaClient, files) {
76
+ const messageHandler = new devtools_extension_api_1.DevtoolsExtensionApi();
77
+ messageHandler.addMessage({
78
+ id: "athena",
79
+ data: { client: !!athenaClient },
80
+ });
66
81
  const fileTodoCollector = new todo_collector_1.TodoCollector(files.getInstallResources());
67
- return new onboarding_service_1.OnboardingService(browserContext, customerConfig, fetchHandler, fileWatcher, cli, fileTodoCollector);
82
+ messageHandler.addMessage({
83
+ id: "todo",
84
+ data: [...fileTodoCollector.getOpenTasks()],
85
+ });
86
+ return messageHandler;
68
87
  }
69
88
  async buildInstallResource(speedKitInstallContext, files, cli) {
70
89
  cli.startAction("build file install_resource");
@@ -89,7 +108,7 @@ class OnboardingServiceFactory {
89
108
  const configApiContext = new config_api_context_1.default(app);
90
109
  return new config_api_service_factory_1.default(configApiContext).getService();
91
110
  }
92
- async getFetchEventHandler(files, customerConfig, documentHandler, cache, cli, browserContext) {
111
+ async getFetchEventHandler(files, customerConfig, documentHandler, cache, cli, browserContext, athenaClient) {
93
112
  const configApi = this.getConfigApi(customerConfig.app);
94
113
  const serverConfig = await this.getSpeedKitServerConfig(configApi, cli);
95
114
  const parameterQueryBuilder = new parameter_query_builder_1.ParameterQueryBuilder(customerConfig, files.getByName(files_1.INTEGRATION_FILES.CONFIG.SPEED_KIT));
@@ -107,7 +126,6 @@ class OnboardingServiceFactory {
107
126
  const orestesApp = new virtual_orestes_app_1.VirtualOrestesApp(customerConfig, crawler, documentHandler, cache, cli);
108
127
  handlers.push(new speed_kit_asset_request_1.SpeedKitAssetRequest(customerConfig, orestesApp), new speed_kit_rum_pi_request_1.SpeedKitRumPiRequest(customerConfig, cache, cli));
109
128
  }
110
- const athenaClient = await this.getAthenaClient();
111
129
  if (athenaClient) {
112
130
  handlers.push(new dashboard_request_1.DashboardRequest(new dashboard_1.Dashboard(customerConfig, parameterQueryBuilder, athenaClient, requestDiffService, cache)));
113
131
  }
@@ -3,7 +3,7 @@ import { BrowserContext } from "./onboarding-model";
3
3
  import { FetchEventHandler } from "./fetch-event-handler";
4
4
  import { FileWatcher } from "./file-events/file-watcher";
5
5
  import { CliService } from "../cli";
6
- import { TodoCollector } from "./todo-collector";
6
+ import { DevtoolsExtensionApi } from "./browser/extension/devtools-extension-api";
7
7
  /**
8
8
  * Represents the OnboardingService which is responsible for setting up the browser to test a config using Puppeteer.
9
9
  */
@@ -13,9 +13,9 @@ export declare class OnboardingService {
13
13
  private fetchEventHandler;
14
14
  private fileWatcher;
15
15
  private cli;
16
- private taskCollector;
16
+ private developmentToolsMessages;
17
17
  private reinstallOnNextNavigate;
18
- constructor(browserContext: BrowserContext, customerConfig: CustomerConfig, fetchEventHandler: FetchEventHandler, fileWatcher: FileWatcher, cli: CliService, taskCollector: TodoCollector);
18
+ constructor(browserContext: BrowserContext, customerConfig: CustomerConfig, fetchEventHandler: FetchEventHandler, fileWatcher: FileWatcher, cli: CliService, developmentToolsMessages: DevtoolsExtensionApi);
19
19
  /**
20
20
  * prepare puppeteerBrowser, add eventListeners and start
21
21
  */
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OnboardingService = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const puppeteer_extra_1 = tslib_1.__importDefault(require("puppeteer-extra"));
6
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const onboarding_model_1 = require("./onboarding-model");
7
7
  const cli_1 = require("../cli");
8
8
  const safe_1 = require("../../helpers/safe");
9
9
  /**
@@ -15,15 +15,15 @@ class OnboardingService {
15
15
  fetchEventHandler;
16
16
  fileWatcher;
17
17
  cli;
18
- taskCollector;
18
+ developmentToolsMessages;
19
19
  reinstallOnNextNavigate = false;
20
- constructor(browserContext, customerConfig, fetchEventHandler, fileWatcher, cli, taskCollector) {
20
+ constructor(browserContext, customerConfig, fetchEventHandler, fileWatcher, cli, developmentToolsMessages) {
21
21
  this.browserContext = browserContext;
22
22
  this.customerConfig = customerConfig;
23
23
  this.fetchEventHandler = fetchEventHandler;
24
24
  this.fileWatcher = fileWatcher;
25
25
  this.cli = cli;
26
- this.taskCollector = taskCollector;
26
+ this.developmentToolsMessages = developmentToolsMessages;
27
27
  }
28
28
  /**
29
29
  * prepare puppeteerBrowser, add eventListeners and start
@@ -33,10 +33,6 @@ class OnboardingService {
33
33
  const browser = await this.prepareBrowser();
34
34
  const page = await this.preparePage(browser);
35
35
  this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
36
- if (this.browserContext.startParameterDashboard) {
37
- const { goto } = await browser.newPage();
38
- await goto("http://skonboarding.local/");
39
- }
40
36
  await this.navigate(page, `${this.customerConfig.scope}speed-kit-install.html?url=${this.customerConfig.scope}`);
41
37
  }
42
38
  async prepareBrowser() {
@@ -52,7 +48,7 @@ class OnboardingService {
52
48
  await this.fetchEventHandler.handleRequestFetchEvents(target);
53
49
  }
54
50
  }
55
- browser.on("disconnected", () => {
51
+ browser.on(onboarding_model_1.BROWSER_EVENTS.DISCONNECTED, () => {
56
52
  this.cli.writeError("Browser disconnected, shutting down");
57
53
  process.exit(-1);
58
54
  });
@@ -60,14 +56,18 @@ class OnboardingService {
60
56
  }
61
57
  async preparePage(browser) {
62
58
  const page = await this.findPage(browser);
63
- await this.prepareCleanState(page);
59
+ await (0, safe_1.safe)(this.prepareCleanState(page));
64
60
  this.registerFileWatcher(page);
65
61
  this.registerReinstallSpeedKitOnNavigate(page);
66
- page.on("framenavigated", async (_frame) => {
67
- // inject open Todos from configFiles
68
- const tasks = this.taskCollector.getOpenTasks();
69
- await (0, safe_1.safe)(page.evaluate(`window.skOnboarding = ${JSON.stringify(tasks)}`));
62
+ this.developmentToolsMessages.addMessage({
63
+ id: "cli",
64
+ data: `config loaded for app "${this.customerConfig.app}"`,
70
65
  });
66
+ const messages = this.developmentToolsMessages.messages;
67
+ await page.evaluateOnNewDocument((messages) => {
68
+ // @ts-expect-error unknown method getSkCliMessages
69
+ window.skCliMessages = messages;
70
+ }, messages);
71
71
  return page;
72
72
  }
73
73
  async findPage(browser) {
@@ -80,27 +80,33 @@ class OnboardingService {
80
80
  return browser.newPage();
81
81
  }
82
82
  async prepareCleanState(page) {
83
- const pageClient = await page.target().createCDPSession();
84
- pageClient.on("ServiceWorker.workerRegistrationUpdated", ({ registrations, }) => {
85
- for (const registration of registrations) {
86
- if (registration.isDeleted) {
87
- this.cli.writeWarning((0, chalk_1.default) `{yellow Unregistered Service Worker} at {bold ${registration.scopeURL}} (${registration.registrationId})`);
88
- }
89
- }
90
- });
83
+ const cdpSession = await page.target().createCDPSession();
91
84
  // cleanUp old serviceWorkers
92
- await pageClient.send("ServiceWorker.enable");
93
- await pageClient.send("ServiceWorker.unregister", {
85
+ await cdpSession.send("ServiceWorker.enable");
86
+ await cdpSession.send("ServiceWorker.unregister", {
94
87
  scopeURL: this.browserContext.domain,
95
88
  });
96
89
  // clear storage for a clean start
97
- await pageClient.send("Storage.clearCookies");
98
- await pageClient.send("Storage.clearDataForOrigin", {
90
+ await cdpSession.send("Storage.clearCookies");
91
+ await cdpSession.send("Storage.clearDataForOrigin", {
99
92
  origin: this.browserContext.domain,
100
93
  storageTypes: "all",
101
94
  });
102
- await pageClient.send("Emulation.clearDeviceMetricsOverride");
103
- await pageClient.send("Emulation.clearGeolocationOverride");
95
+ await cdpSession.send("Emulation.clearDeviceMetricsOverride");
96
+ await cdpSession.send("Emulation.clearGeolocationOverride");
97
+ (0, safe_1.safe)(() => {
98
+ cdpSession.on(onboarding_model_1.CDP_SESSION.EVENTS.SERVICE_WORKER.REGISTRATION_UPDATED, ({ registrations, }) => {
99
+ for (const registration of registrations) {
100
+ if (registration.isDeleted) {
101
+ this.developmentToolsMessages.addMessage({
102
+ id: "serviceWorker",
103
+ data: `Unregistered Service Worker at ${registration.scopeURL} id: ${registration.registrationId}`,
104
+ });
105
+ this.cli.writeWarning(`${this.cli.style.yellow("Unregistered Service Worker")} at ${this.cli.style.bold(registration.scopeURL)} (${registration.registrationId})`);
106
+ }
107
+ }
108
+ });
109
+ });
104
110
  }
105
111
  async reinstallSpeedKit(page, pathname) {
106
112
  const url = new URL(page.url());
@@ -129,8 +135,7 @@ class OnboardingService {
129
135
  }
130
136
  async navigate(page, pathname) {
131
137
  const goto = new URL(pathname, `${this.browserContext.domain}`);
132
- await page.goto(goto.toString());
133
- await page.bringToFront();
138
+ await (0, safe_1.safe)(page.goto(goto.toString()));
134
139
  }
135
140
  }
136
141
  exports.OnboardingService = OnboardingService;