@speedkit/cli 4.23.3 → 4.24.1

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 (29) hide show
  1. package/.env.sample +7 -0
  2. package/CHANGELOG.md +21 -0
  3. package/README.md +1 -1
  4. package/dist/helpers/origin-proxy.d.ts +89 -0
  5. package/dist/helpers/origin-proxy.js +207 -0
  6. package/dist/helpers/origin-proxy.spec.d.ts +1 -0
  7. package/dist/helpers/origin-proxy.spec.js +167 -0
  8. package/dist/helpers/scrape.js +2 -2
  9. package/dist/helpers/site-analyzer.js +2 -2
  10. package/dist/services/bundler/bundle-service-factory.d.ts +2 -1
  11. package/dist/services/bundler/bundle-service-factory.js +4 -2
  12. package/dist/services/bundler/bundle-service.d.ts +30 -2
  13. package/dist/services/bundler/bundle-service.js +81 -6
  14. package/dist/services/bundler/bundle-service.spec.js +124 -0
  15. package/dist/services/document-handler-runtime/document-handler-server.d.ts +23 -3
  16. package/dist/services/document-handler-runtime/document-handler-server.js +66 -43
  17. package/dist/services/document-handler-runtime/factory/document-handler-runtime-service-factory.d.ts +11 -0
  18. package/dist/services/document-handler-runtime/factory/document-handler-runtime-service-factory.js +30 -3
  19. package/dist/services/onboarding/dashboard/request-diff-service.js +5 -11
  20. package/dist/services/onboarding/onboarding-service-factory.d.ts +0 -2
  21. package/dist/services/onboarding/onboarding-service-factory.js +5 -43
  22. package/dist/services/onboarding/virtual-orestes-app/crawler.d.ts +1 -3
  23. package/dist/services/onboarding/virtual-orestes-app/crawler.js +6 -10
  24. package/dist/services/onboarding/virtual-orestes-app/crawler.spec.d.ts +1 -0
  25. package/dist/services/onboarding/virtual-orestes-app/crawler.spec.js +49 -0
  26. package/dist/services/origin-request/origin-request-service-factory.js +5 -1
  27. package/dist/services/origin-request/origin-request-service.js +2 -1
  28. package/oclif.manifest.json +1 -1
  29. package/package.json +2 -1
@@ -1,13 +1,11 @@
1
1
  import { SpeedKitServerConfig } from "../onboarding-model.js";
2
2
  import { CliService } from "../../cli/index.js";
3
- import { Agent } from "undici";
4
3
  export declare class Crawler {
5
4
  private cli;
6
- private agentConfig;
7
5
  private speedKitServerConfig?;
8
6
  /** Warnings already shown, so a per-fetch condition is reported once per session. */
9
7
  private readonly warned;
10
- constructor(cli: CliService, agentConfig: Agent, speedKitServerConfig?: SpeedKitServerConfig);
8
+ constructor(cli: CliService, speedKitServerConfig?: SpeedKitServerConfig);
11
9
  private warnOnce;
12
10
  fetchRemote(originUrl: string, variation: string): Promise<{
13
11
  response: Response;
@@ -1,15 +1,14 @@
1
1
  import { safe } from "../../../helpers/safe.js";
2
2
  import { resolveRequest, UndefinedVariationError, } from "../../origin-request/index.js";
3
+ import { originFetch } from "../../../helpers/origin-proxy.js";
3
4
  import { randomUUID } from "node:crypto";
4
5
  export class Crawler {
5
6
  cli;
6
- agentConfig;
7
7
  speedKitServerConfig;
8
8
  /** Warnings already shown, so a per-fetch condition is reported once per session. */
9
9
  warned = new Set();
10
- constructor(cli, agentConfig, speedKitServerConfig) {
10
+ constructor(cli, speedKitServerConfig) {
11
11
  this.cli = cli;
12
- this.agentConfig = agentConfig;
13
12
  this.speedKitServerConfig = speedKitServerConfig;
14
13
  }
15
14
  warnOnce(key, message) {
@@ -22,13 +21,9 @@ export class Crawler {
22
21
  // origin URL with the variation's query params applied — returned so callers compare it
23
22
  // (not the bare originUrl) against response.url for redirect detection
24
23
  const { url, init } = this.prepareOriginRequest(originUrl, variation);
25
- const requestInit = {
26
- ...init,
27
- agent: this.agentConfig,
28
- };
29
24
  const uuid = randomUUID();
30
25
  this.cli.startAction(`DOCUMENTHANDLER:FETCH:${uuid}`, `[documentHandler:fetch]: ${url}`);
31
- const fetchResponse = await safe(fetch(url, requestInit));
26
+ const fetchResponse = await safe(originFetch(url, init));
32
27
  if (fetchResponse.success === true) {
33
28
  this.cli.successAction(`DOCUMENTHANDLER:FETCH:${uuid}`);
34
29
  return { response: fetchResponse.data, url };
@@ -79,8 +74,9 @@ export class Crawler {
79
74
  return { url: resolved.url, init };
80
75
  }
81
76
  prepareAuthRequest(originUrl) {
82
- if (!this.speedKitServerConfig ||
83
- this.speedKitServerConfig.speedKit?.authentications?.length < 1) {
77
+ // A missing `authentications` has to leave through the same door as an empty one. Comparing
78
+ // `undefined < 1` yields false, so the previous guard fell through and iterated undefined.
79
+ if (!this.speedKitServerConfig?.speedKit?.authentications?.length) {
84
80
  return;
85
81
  }
86
82
  const origin = new URL(originUrl).origin;
@@ -0,0 +1,49 @@
1
+ import { expect } from "chai";
2
+ import { describe, beforeEach, afterEach, it } from "mocha";
3
+ import http from "node:http";
4
+ import { Crawler } from "./crawler.js";
5
+ /** Records the lines the crawler reports, so a spec can assert on them. */
6
+ function stubCli() {
7
+ const warnings = [];
8
+ const errors = [];
9
+ const actions = [];
10
+ return {
11
+ warnings,
12
+ errors,
13
+ actions,
14
+ cli: {
15
+ startAction: (name) => actions.push(name),
16
+ successAction: (name) => actions.push(`${name}:ok`),
17
+ failAction: (name) => actions.push(`${name}:fail`),
18
+ writeWarning: (message) => warnings.push(message),
19
+ writeError: (message) => errors.push(message),
20
+ },
21
+ };
22
+ }
23
+ describe("Crawler.fetchRemote", () => {
24
+ let server;
25
+ let url;
26
+ beforeEach(async () => {
27
+ server = http.createServer((_request, response) => response.end("origin"));
28
+ await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
29
+ url = `http://127.0.0.1:${server.address().port}/`;
30
+ });
31
+ afterEach(() => server.close());
32
+ it("fetches an origin whose runtime config carries no authentications", async () => {
33
+ const { cli } = stubCli();
34
+ // The config API omits the key for an app without origin auth. Comparing `undefined < 1`
35
+ // yielded false, so the crawler used to iterate undefined and throw on every fetch.
36
+ const serverConfig = {
37
+ speedKit: { variations: { "*": { headers: {} } } },
38
+ };
39
+ const result = await new Crawler(cli, serverConfig).fetchRemote(url, "DEFAULT");
40
+ expect(result).to.not.equal(undefined);
41
+ expect(await result.response.text()).to.equal("origin");
42
+ });
43
+ it("fetches an origin when no runtime config loaded at all", async () => {
44
+ const { cli, warnings } = stubCli();
45
+ const result = await new Crawler(cli, undefined).fetchRemote(url, "DEFAULT");
46
+ expect(await result.response.text()).to.equal("origin");
47
+ expect(warnings.join(" ")).to.contain("no variations available");
48
+ });
49
+ });
@@ -1,6 +1,7 @@
1
1
  import { CliServiceFactory } from "../cli/index.js";
2
2
  import { ConfigApiContext, ConfigApiServiceFactory, } from "../config-api/index.js";
3
3
  import { IntegrationApiContext, IntegrationApiFactory, } from "../integration-api/index.js";
4
+ import { applyOriginProxy } from "../../helpers/origin-proxy.js";
4
5
  import { OriginRequestService } from "./origin-request-service.js";
5
6
  export class OriginRequestServiceFactory {
6
7
  context;
@@ -19,7 +20,10 @@ export class OriginRequestServiceFactory {
19
20
  async build() {
20
21
  const files = await this.getIntegrationFiles();
21
22
  const customer = files.getCustomerConfig().config;
22
- this.service = new OriginRequestService(this.context, new CliServiceFactory().getService(), this.getConfigApi(customer.app));
23
+ const cli = new CliServiceFactory().getService();
24
+ // `--json` owns stdout, so the proxy line stays out of a machine-readable run.
25
+ applyOriginProxy(customer.chromeFlags, this.context.json ? undefined : cli);
26
+ this.service = new OriginRequestService(this.context, cli, this.getConfigApi(customer.app));
23
27
  }
24
28
  async getIntegrationFiles() {
25
29
  const integrationApiContext = new IntegrationApiContext(this.context.customerPath, this.context.configName, []);
@@ -1,5 +1,6 @@
1
1
  import { readFile, writeFile } from "node:fs/promises";
2
2
  import { safe } from "../../helpers/safe.js";
3
+ import { originFetch } from "../../helpers/origin-proxy.js";
3
4
  import { DEFAULT_TYPE, resolveRequest, toCurl, UndefinedVariationError, } from "./asset-variations.js";
4
5
  /**
5
6
  * Fetches a page from origin with exactly the headers Speed Kit's server would send for a cache
@@ -43,7 +44,7 @@ export class OriginRequestService {
43
44
  }
44
45
  throw error;
45
46
  }
46
- const response = await fetch(resolved.url, {
47
+ const response = await originFetch(resolved.url, {
47
48
  headers: resolved.headers,
48
49
  redirect: "manual",
49
50
  });
@@ -1220,5 +1220,5 @@
1220
1220
  ]
1221
1221
  }
1222
1222
  },
1223
- "version": "4.23.3"
1223
+ "version": "4.24.1"
1224
1224
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "4.23.3",
4
+ "version": "4.24.1",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"
@@ -124,6 +124,7 @@
124
124
  "strip-comments": "^2.0.1",
125
125
  "tsx": "^4.21.0",
126
126
  "tty-table": "^5.0.0",
127
+ "undici": "^8.1.0",
127
128
  "uuid": "^13.0.0"
128
129
  },
129
130
  "devDependencies": {