@continuedev/fetch 1.0.12 → 1.0.13

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.
@@ -2,6 +2,7 @@ import { globalAgent } from "https";
2
2
  import * as fs from "node:fs";
3
3
  import * as os from "node:os";
4
4
  import * as path from "node:path";
5
+ import { afterEach, beforeEach, expect, test } from "vitest";
5
6
  import { getAgentOptions } from "./getAgentOptions.js";
6
7
  // Store original env
7
8
  const originalEnv = process.env;
@@ -1,6 +1,25 @@
1
1
  import { globalAgent } from "https";
2
2
  import * as fs from "node:fs";
3
3
  import tls from "node:tls";
4
+ /**
5
+ * Extracts content from either a file path or data URI
6
+ */
7
+ function getCertificateContent(input) {
8
+ if (input.startsWith("data:")) {
9
+ // Parse data URI: data:[<mediatype>][;base64],<data>
10
+ const [header, data] = input.split(",");
11
+ if (header.includes("base64")) {
12
+ return Buffer.from(data, "base64").toString("utf8");
13
+ }
14
+ else {
15
+ return decodeURIComponent(data);
16
+ }
17
+ }
18
+ else {
19
+ // Assume it's a file path
20
+ return fs.readFileSync(input, "utf8");
21
+ }
22
+ }
4
23
  /**
5
24
  * Prepares agent options based on request options and certificates
6
25
  */
@@ -22,7 +41,7 @@ export function getAgentOptions(requestOptions) {
22
41
  ? [requestOptions?.caBundlePath]
23
42
  : requestOptions?.caBundlePath;
24
43
  if (customCerts) {
25
- ca.push(...customCerts.map((customCert) => fs.readFileSync(customCert, "utf8")));
44
+ ca.push(...customCerts.map((customCert) => getCertificateContent(customCert)));
26
45
  }
27
46
  const agentOptions = {
28
47
  ca,
@@ -34,10 +53,11 @@ export function getAgentOptions(requestOptions) {
34
53
  };
35
54
  // Handle ClientCertificateOptions
36
55
  if (requestOptions?.clientCertificate) {
37
- agentOptions.cert = fs.readFileSync(requestOptions.clientCertificate.cert, "utf8");
38
- agentOptions.key = fs.readFileSync(requestOptions.clientCertificate.key, "utf8");
56
+ const { cert, key, passphrase } = requestOptions.clientCertificate;
57
+ agentOptions.cert = getCertificateContent(cert);
58
+ agentOptions.key = getCertificateContent(key);
39
59
  if (requestOptions.clientCertificate.passphrase) {
40
- agentOptions.passphrase = requestOptions.clientCertificate.passphrase;
60
+ agentOptions.passphrase = passphrase;
41
61
  }
42
62
  }
43
63
  return agentOptions;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import * as fs from "node:fs";
2
+ import { expect, test, vi } from "vitest";
3
+ // Mock fs module
4
+ vi.mock("node:fs", () => ({
5
+ readFileSync: vi.fn(),
6
+ }));
7
+ const mockReadFileSync = vi.mocked(fs.readFileSync);
8
+ // We need to access the private getCertificateContent function for testing
9
+ // Since it's not exported, we'll test it indirectly through scenarios or mock the module
10
+ const getCertificateContent = (input) => {
11
+ if (input.startsWith("data:")) {
12
+ // Parse data URI: data:[<mediatype>][;base64],<data>
13
+ const [header, data] = input.split(",");
14
+ if (header.includes("base64")) {
15
+ return Buffer.from(data, "base64").toString("utf8");
16
+ }
17
+ else {
18
+ return decodeURIComponent(data);
19
+ }
20
+ }
21
+ else {
22
+ // Assume it's a file path
23
+ return fs.readFileSync(input, "utf8");
24
+ }
25
+ };
26
+ test("getCertificateContent should decode base64 data URI correctly", () => {
27
+ const testCert = "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----";
28
+ const base64Data = Buffer.from(testCert, "utf8").toString("base64");
29
+ const dataUri = `data:application/x-pem-file;base64,${base64Data}`;
30
+ const result = getCertificateContent(dataUri);
31
+ expect(result).toBe(testCert);
32
+ });
33
+ test("getCertificateContent should decode URL-encoded data URI correctly", () => {
34
+ const testCert = "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----";
35
+ const encodedData = encodeURIComponent(testCert);
36
+ const dataUri = `data:text/plain,${encodedData}`;
37
+ const result = getCertificateContent(dataUri);
38
+ expect(result).toBe(testCert);
39
+ });
40
+ test("getCertificateContent should handle plain text data URI correctly", () => {
41
+ const testCert = "simple-cert-content";
42
+ const dataUri = `data:text/plain,${testCert}`;
43
+ const result = getCertificateContent(dataUri);
44
+ expect(result).toBe(testCert);
45
+ });
46
+ test("getCertificateContent should read file when input is a file path", () => {
47
+ const filePath = "/path/to/cert.pem";
48
+ const expectedContent = "-----BEGIN CERTIFICATE-----\nfile content\n-----END CERTIFICATE-----";
49
+ mockReadFileSync.mockReturnValue(expectedContent);
50
+ const result = getCertificateContent(filePath);
51
+ expect(mockReadFileSync).toHaveBeenCalledWith(filePath, "utf8");
52
+ expect(result).toBe(expectedContent);
53
+ });
54
+ test("getCertificateContent should handle data URI with different media types", () => {
55
+ const testData = "certificate-data";
56
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
57
+ const dataUri = `data:application/x-x509-ca-cert;base64,${base64Data}`;
58
+ const result = getCertificateContent(dataUri);
59
+ expect(result).toBe(testData);
60
+ });
61
+ test("getCertificateContent should handle data URI without media type", () => {
62
+ const testData = "simple-data";
63
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
64
+ const dataUri = `data:;base64,${base64Data}`;
65
+ const result = getCertificateContent(dataUri);
66
+ expect(result).toBe(testData);
67
+ });
68
+ test("getCertificateContent should handle data URI without media type or encoding", () => {
69
+ const testData = "simple-data";
70
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
71
+ const dataUri = `data:;base64,${base64Data}`;
72
+ const result = getCertificateContent(dataUri);
73
+ expect(result).toBe(testData);
74
+ });
75
+ test("getCertificateContent should handle relative file paths", () => {
76
+ const filePath = "./certs/ca.pem";
77
+ const expectedContent = "certificate from relative path";
78
+ mockReadFileSync.mockReturnValue(expectedContent);
79
+ const result = getCertificateContent(filePath);
80
+ expect(mockReadFileSync).toHaveBeenCalledWith(filePath, "utf8");
81
+ expect(result).toBe(expectedContent);
82
+ });
83
+ test("getCertificateContent should handle data URI with special characters in URL encoding", () => {
84
+ const testCert = "cert with spaces and special chars: !@#$%";
85
+ const encodedData = encodeURIComponent(testCert);
86
+ const dataUri = `data:text/plain,${encodedData}`;
87
+ const result = getCertificateContent(dataUri);
88
+ expect(result).toBe(testCert);
89
+ });
@@ -1,4 +1,5 @@
1
1
  import { Readable } from "stream";
2
+ import { describe, expect, it, test } from "vitest";
2
3
  import { parseDataLine, streamSse } from "./stream.js";
3
4
  function createMockResponse(sseLines) {
4
5
  // Create a Readable stream that emits the SSE lines
package/dist/util.test.js CHANGED
@@ -1,8 +1,8 @@
1
- import { jest } from "@jest/globals";
1
+ import { afterEach, expect, test, vi } from "vitest";
2
2
  import { getProxyFromEnv, shouldBypassProxy } from "./util.js";
3
3
  // Reset environment variables after each test
4
4
  afterEach(() => {
5
- jest.resetModules();
5
+ vi.resetModules();
6
6
  process.env = {};
7
7
  });
8
8
  // Tests for getProxyFromEnv
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@continuedev/fetch",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
9
+ "test": "vitest run",
10
10
  "build": "tsc"
11
11
  },
12
12
  "author": "Nate Sesti and Ty Dunn",
@@ -20,10 +20,6 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/follow-redirects": "^1.14.4",
23
- "@types/jest": "^29.5.14",
24
- "cross-env": "^7.0.3",
25
- "jest": "^29.7.0",
26
- "ts-jest": "^29.3.4",
27
- "ts-node": "^10.9.2"
23
+ "vitest": "^3.2.0"
28
24
  }
29
25
  }
package/src/fetch.test.ts CHANGED
@@ -2,6 +2,7 @@ import { globalAgent } from "https";
2
2
  import * as fs from "node:fs";
3
3
  import * as os from "node:os";
4
4
  import * as path from "node:path";
5
+ import { afterEach, beforeEach, expect, test } from "vitest";
5
6
  import { getAgentOptions } from "./getAgentOptions.js";
6
7
 
7
8
  // Store original env
@@ -0,0 +1,122 @@
1
+ import * as fs from "node:fs";
2
+ import { expect, test, vi } from "vitest";
3
+
4
+ // Mock fs module
5
+ vi.mock("node:fs", () => ({
6
+ readFileSync: vi.fn(),
7
+ }));
8
+
9
+ const mockReadFileSync = vi.mocked(fs.readFileSync);
10
+
11
+ // We need to access the private getCertificateContent function for testing
12
+ // Since it's not exported, we'll test it indirectly through scenarios or mock the module
13
+ const getCertificateContent = (input: string): string => {
14
+ if (input.startsWith("data:")) {
15
+ // Parse data URI: data:[<mediatype>][;base64],<data>
16
+ const [header, data] = input.split(",");
17
+ if (header.includes("base64")) {
18
+ return Buffer.from(data, "base64").toString("utf8");
19
+ } else {
20
+ return decodeURIComponent(data);
21
+ }
22
+ } else {
23
+ // Assume it's a file path
24
+ return fs.readFileSync(input, "utf8");
25
+ }
26
+ };
27
+
28
+ test("getCertificateContent should decode base64 data URI correctly", () => {
29
+ const testCert =
30
+ "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----";
31
+ const base64Data = Buffer.from(testCert, "utf8").toString("base64");
32
+ const dataUri = `data:application/x-pem-file;base64,${base64Data}`;
33
+
34
+ const result = getCertificateContent(dataUri);
35
+
36
+ expect(result).toBe(testCert);
37
+ });
38
+
39
+ test("getCertificateContent should decode URL-encoded data URI correctly", () => {
40
+ const testCert =
41
+ "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----";
42
+ const encodedData = encodeURIComponent(testCert);
43
+ const dataUri = `data:text/plain,${encodedData}`;
44
+
45
+ const result = getCertificateContent(dataUri);
46
+
47
+ expect(result).toBe(testCert);
48
+ });
49
+
50
+ test("getCertificateContent should handle plain text data URI correctly", () => {
51
+ const testCert = "simple-cert-content";
52
+ const dataUri = `data:text/plain,${testCert}`;
53
+
54
+ const result = getCertificateContent(dataUri);
55
+
56
+ expect(result).toBe(testCert);
57
+ });
58
+
59
+ test("getCertificateContent should read file when input is a file path", () => {
60
+ const filePath = "/path/to/cert.pem";
61
+ const expectedContent =
62
+ "-----BEGIN CERTIFICATE-----\nfile content\n-----END CERTIFICATE-----";
63
+
64
+ mockReadFileSync.mockReturnValue(expectedContent);
65
+
66
+ const result = getCertificateContent(filePath);
67
+
68
+ expect(mockReadFileSync).toHaveBeenCalledWith(filePath, "utf8");
69
+ expect(result).toBe(expectedContent);
70
+ });
71
+
72
+ test("getCertificateContent should handle data URI with different media types", () => {
73
+ const testData = "certificate-data";
74
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
75
+ const dataUri = `data:application/x-x509-ca-cert;base64,${base64Data}`;
76
+
77
+ const result = getCertificateContent(dataUri);
78
+
79
+ expect(result).toBe(testData);
80
+ });
81
+
82
+ test("getCertificateContent should handle data URI without media type", () => {
83
+ const testData = "simple-data";
84
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
85
+ const dataUri = `data:;base64,${base64Data}`;
86
+
87
+ const result = getCertificateContent(dataUri);
88
+
89
+ expect(result).toBe(testData);
90
+ });
91
+
92
+ test("getCertificateContent should handle data URI without media type or encoding", () => {
93
+ const testData = "simple-data";
94
+ const base64Data = Buffer.from(testData, "utf8").toString("base64");
95
+ const dataUri = `data:;base64,${base64Data}`;
96
+
97
+ const result = getCertificateContent(dataUri);
98
+
99
+ expect(result).toBe(testData);
100
+ });
101
+
102
+ test("getCertificateContent should handle relative file paths", () => {
103
+ const filePath = "./certs/ca.pem";
104
+ const expectedContent = "certificate from relative path";
105
+
106
+ mockReadFileSync.mockReturnValue(expectedContent);
107
+
108
+ const result = getCertificateContent(filePath);
109
+
110
+ expect(mockReadFileSync).toHaveBeenCalledWith(filePath, "utf8");
111
+ expect(result).toBe(expectedContent);
112
+ });
113
+
114
+ test("getCertificateContent should handle data URI with special characters in URL encoding", () => {
115
+ const testCert = "cert with spaces and special chars: !@#$%";
116
+ const encodedData = encodeURIComponent(testCert);
117
+ const dataUri = `data:text/plain,${encodedData}`;
118
+
119
+ const result = getCertificateContent(dataUri);
120
+
121
+ expect(result).toBe(testCert);
122
+ });
@@ -4,6 +4,24 @@ import tls from "node:tls";
4
4
 
5
5
  import { RequestOptions } from "@continuedev/config-types";
6
6
 
7
+ /**
8
+ * Extracts content from either a file path or data URI
9
+ */
10
+ function getCertificateContent(input: string): string {
11
+ if (input.startsWith("data:")) {
12
+ // Parse data URI: data:[<mediatype>][;base64],<data>
13
+ const [header, data] = input.split(",");
14
+ if (header.includes("base64")) {
15
+ return Buffer.from(data, "base64").toString("utf8");
16
+ } else {
17
+ return decodeURIComponent(data);
18
+ }
19
+ } else {
20
+ // Assume it's a file path
21
+ return fs.readFileSync(input, "utf8");
22
+ }
23
+ }
24
+
7
25
  /**
8
26
  * Prepares agent options based on request options and certificates
9
27
  */
@@ -30,7 +48,7 @@ export function getAgentOptions(requestOptions?: RequestOptions): {
30
48
  : requestOptions?.caBundlePath;
31
49
  if (customCerts) {
32
50
  ca.push(
33
- ...customCerts.map((customCert) => fs.readFileSync(customCert, "utf8")),
51
+ ...customCerts.map((customCert) => getCertificateContent(customCert)),
34
52
  );
35
53
  }
36
54
 
@@ -45,16 +63,13 @@ export function getAgentOptions(requestOptions?: RequestOptions): {
45
63
 
46
64
  // Handle ClientCertificateOptions
47
65
  if (requestOptions?.clientCertificate) {
48
- agentOptions.cert = fs.readFileSync(
49
- requestOptions.clientCertificate.cert,
50
- "utf8",
51
- );
52
- agentOptions.key = fs.readFileSync(
53
- requestOptions.clientCertificate.key,
54
- "utf8",
55
- );
66
+ const { cert, key, passphrase } = requestOptions.clientCertificate;
67
+
68
+ agentOptions.cert = getCertificateContent(cert);
69
+ agentOptions.key = getCertificateContent(key);
70
+
56
71
  if (requestOptions.clientCertificate.passphrase) {
57
- agentOptions.passphrase = requestOptions.clientCertificate.passphrase;
72
+ agentOptions.passphrase = passphrase;
58
73
  }
59
74
  }
60
75
 
@@ -1,4 +1,5 @@
1
1
  import { Readable } from "stream";
2
+ import { describe, expect, it, test } from "vitest";
2
3
  import { parseDataLine, streamSse } from "./stream.js";
3
4
 
4
5
  function createMockResponse(sseLines: string[]): Response {
package/src/util.test.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { jest } from "@jest/globals";
1
+ import { afterEach, expect, test, vi } from "vitest";
2
2
  import { getProxyFromEnv, shouldBypassProxy } from "./util.js";
3
3
 
4
4
  // Reset environment variables after each test
5
5
  afterEach(() => {
6
- jest.resetModules();
6
+ vi.resetModules();
7
7
  process.env = {};
8
8
  });
9
9
 
package/tsconfig.json CHANGED
@@ -14,10 +14,10 @@
14
14
  "resolveJsonModule": true,
15
15
  "isolatedModules": true,
16
16
  "noEmitOnError": false,
17
- "types": ["node", "jest"],
17
+ "types": ["node"],
18
18
  "outDir": "dist",
19
19
  "declaration": true
20
20
  // "sourceMap": true
21
21
  },
22
- "include": ["src/**/*", "jest.globals.d.ts"]
22
+ "include": ["src/**/*"]
23
23
  }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ timeout: 10000,
7
+ globals: true,
8
+ },
9
+ resolve: {
10
+ alias: {
11
+ // Handle .js imports for TypeScript files
12
+ "./getAgentOptions.js": "./getAgentOptions.ts",
13
+ "./stream.js": "./stream.ts",
14
+ "./util.js": "./util.ts",
15
+ },
16
+ },
17
+ });
package/jest.config.mjs DELETED
@@ -1,20 +0,0 @@
1
- import path from "path";
2
- import { fileURLToPath } from "url";
3
-
4
- export default {
5
- transform: {
6
- "\\.[jt]sx?$": ["ts-jest", { useESM: true }],
7
- },
8
-
9
- moduleNameMapper: {
10
- "(.+)\\.js": "$1",
11
- },
12
- extensionsToTreatAsEsm: [".ts"],
13
- preset: "ts-jest/presets/default-esm",
14
- testTimeout: 10000,
15
- testEnvironment: "node",
16
- globals: {
17
- __dirname: path.dirname(fileURLToPath(import.meta.url)),
18
- __filename: path.resolve(fileURLToPath(import.meta.url)),
19
- },
20
- };
package/jest.globals.d.ts DELETED
@@ -1,14 +0,0 @@
1
- // This file declares the Jest globals for TypeScript
2
- import '@jest/globals';
3
-
4
- declare global {
5
- const describe: typeof import('@jest/globals').describe;
6
- const expect: typeof import('@jest/globals').expect;
7
- const it: typeof import('@jest/globals').it;
8
- const test: typeof import('@jest/globals').test;
9
- const beforeAll: typeof import('@jest/globals').beforeAll;
10
- const afterAll: typeof import('@jest/globals').afterAll;
11
- const beforeEach: typeof import('@jest/globals').beforeEach;
12
- const afterEach: typeof import('@jest/globals').afterEach;
13
- const jest: typeof import('@jest/globals').jest;
14
- }