galileo-generated 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release-please-config.json +7 -0
- package/.release-please-manifest.json +1 -1
- package/dist/commonjs/hooks/cert-management.d.ts +73 -0
- package/dist/commonjs/hooks/cert-management.d.ts.map +1 -0
- package/dist/commonjs/hooks/cert-management.js +258 -0
- package/dist/commonjs/hooks/cert-management.js.map +1 -0
- package/dist/commonjs/hooks/registration.d.ts.map +1 -1
- package/dist/commonjs/hooks/registration.js +8 -0
- package/dist/commonjs/hooks/registration.js.map +1 -1
- package/dist/commonjs/hooks/sdk-identifier.d.ts +5 -0
- package/dist/commonjs/hooks/sdk-identifier.d.ts.map +1 -0
- package/dist/commonjs/hooks/sdk-identifier.js +37 -0
- package/dist/commonjs/hooks/sdk-identifier.js.map +1 -0
- package/dist/commonjs/lib/galileo-config.d.ts +101 -12
- package/dist/commonjs/lib/galileo-config.d.ts.map +1 -1
- package/dist/commonjs/lib/galileo-config.js +153 -12
- package/dist/commonjs/lib/galileo-config.js.map +1 -1
- package/dist/commonjs/tests/hooks/cert-management.test.d.ts +2 -0
- package/dist/commonjs/tests/hooks/cert-management.test.d.ts.map +1 -0
- package/dist/commonjs/tests/hooks/cert-management.test.js +794 -0
- package/dist/commonjs/tests/hooks/cert-management.test.js.map +1 -0
- package/dist/commonjs/tests/hooks/sdk-identifier.test.d.ts +2 -0
- package/dist/commonjs/tests/hooks/sdk-identifier.test.d.ts.map +1 -0
- package/dist/commonjs/tests/hooks/sdk-identifier.test.js +136 -0
- package/dist/commonjs/tests/hooks/sdk-identifier.test.js.map +1 -0
- package/dist/commonjs/tests/lib/galileo-config.test.js +101 -0
- package/dist/commonjs/tests/lib/galileo-config.test.js.map +1 -1
- package/dist/esm/hooks/cert-management.d.ts +73 -0
- package/dist/esm/hooks/cert-management.d.ts.map +1 -0
- package/dist/esm/hooks/cert-management.js +254 -0
- package/dist/esm/hooks/cert-management.js.map +1 -0
- package/dist/esm/hooks/registration.d.ts.map +1 -1
- package/dist/esm/hooks/registration.js +8 -0
- package/dist/esm/hooks/registration.js.map +1 -1
- package/dist/esm/hooks/sdk-identifier.d.ts +5 -0
- package/dist/esm/hooks/sdk-identifier.d.ts.map +1 -0
- package/dist/esm/hooks/sdk-identifier.js +33 -0
- package/dist/esm/hooks/sdk-identifier.js.map +1 -0
- package/dist/esm/lib/galileo-config.d.ts +101 -12
- package/dist/esm/lib/galileo-config.d.ts.map +1 -1
- package/dist/esm/lib/galileo-config.js +153 -12
- package/dist/esm/lib/galileo-config.js.map +1 -1
- package/dist/esm/tests/hooks/cert-management.test.d.ts +2 -0
- package/dist/esm/tests/hooks/cert-management.test.d.ts.map +1 -0
- package/dist/esm/tests/hooks/cert-management.test.js +792 -0
- package/dist/esm/tests/hooks/cert-management.test.js.map +1 -0
- package/dist/esm/tests/hooks/sdk-identifier.test.d.ts +2 -0
- package/dist/esm/tests/hooks/sdk-identifier.test.d.ts.map +1 -0
- package/dist/esm/tests/hooks/sdk-identifier.test.js +134 -0
- package/dist/esm/tests/hooks/sdk-identifier.test.js.map +1 -0
- package/dist/esm/tests/lib/galileo-config.test.js +101 -0
- package/dist/esm/tests/lib/galileo-config.test.js.map +1 -1
- package/package.json +5 -3
- package/src/hooks/cert-management.ts +288 -0
- package/src/hooks/registration.ts +10 -0
- package/src/hooks/sdk-identifier.ts +41 -0
- package/src/lib/galileo-config.ts +214 -15
- package/src/tests/hooks/cert-management.test.ts +958 -0
- package/src/tests/hooks/sdk-identifier.test.ts +176 -0
- package/src/tests/lib/galileo-config.test.ts +110 -0
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const cert_management_js_1 = require("../../hooks/cert-management.js");
|
|
5
|
+
const galileo_config_js_1 = require("../../lib/galileo-config.js");
|
|
6
|
+
const http_js_1 = require("../../lib/http.js");
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const os_1 = require("os");
|
|
10
|
+
// Mock runtime detection - default to Node.js environment
|
|
11
|
+
const { mockIsNodeLike, mockIsBrowserLike } = vitest_1.vi.hoisted(() => ({
|
|
12
|
+
mockIsNodeLike: vitest_1.vi.fn(() => true),
|
|
13
|
+
mockIsBrowserLike: vitest_1.vi.fn(() => false),
|
|
14
|
+
}));
|
|
15
|
+
vitest_1.vi.mock('../../lib/runtime.js', () => ({
|
|
16
|
+
isNodeLike: mockIsNodeLike,
|
|
17
|
+
isBrowserLike: mockIsBrowserLike,
|
|
18
|
+
isDeno: vitest_1.vi.fn(() => false),
|
|
19
|
+
}));
|
|
20
|
+
const ENV_KEYS = [
|
|
21
|
+
'GALILEO_API_KEY',
|
|
22
|
+
'GALILEO_CA_CERT_PATH',
|
|
23
|
+
'SSL_CERT_FILE',
|
|
24
|
+
'NODE_EXTRA_CA_CERTS',
|
|
25
|
+
'GALILEO_CLIENT_CERT_PATH',
|
|
26
|
+
'GALILEO_CLIENT_KEY_PATH',
|
|
27
|
+
'GALILEO_REJECT_UNAUTHORIZED',
|
|
28
|
+
'NODE_TLS_REJECT_UNAUTHORIZED',
|
|
29
|
+
];
|
|
30
|
+
function clearEnv() {
|
|
31
|
+
for (const key of ENV_KEYS) {
|
|
32
|
+
delete process.env[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
(0, vitest_1.describe)('CertManagementHook', () => {
|
|
36
|
+
let tmpDir;
|
|
37
|
+
let caCertPath;
|
|
38
|
+
let clientCertPath;
|
|
39
|
+
let clientKeyPath;
|
|
40
|
+
(0, vitest_1.beforeEach)(() => {
|
|
41
|
+
// Create temporary directory and test certificate files
|
|
42
|
+
tmpDir = (0, path_1.join)((0, os_1.tmpdir)(), `galileo-cert-test-${Date.now()}`);
|
|
43
|
+
(0, fs_1.mkdirSync)(tmpDir, { recursive: true });
|
|
44
|
+
caCertPath = (0, path_1.join)(tmpDir, 'ca.pem');
|
|
45
|
+
clientCertPath = (0, path_1.join)(tmpDir, 'client.pem');
|
|
46
|
+
clientKeyPath = (0, path_1.join)(tmpDir, 'key.pem');
|
|
47
|
+
(0, fs_1.writeFileSync)(caCertPath, '-----BEGIN CERTIFICATE-----\nMOCK_CA_CERT\n-----END CERTIFICATE-----');
|
|
48
|
+
(0, fs_1.writeFileSync)(clientCertPath, '-----BEGIN CERTIFICATE-----\nMOCK_CLIENT_CERT\n-----END CERTIFICATE-----');
|
|
49
|
+
(0, fs_1.writeFileSync)(clientKeyPath, '-----BEGIN PRIVATE KEY-----\nMOCK_PRIVATE_KEY\n-----END PRIVATE KEY-----');
|
|
50
|
+
// Default to Node.js environment
|
|
51
|
+
mockIsNodeLike.mockReturnValue(true);
|
|
52
|
+
mockIsBrowserLike.mockReturnValue(false);
|
|
53
|
+
});
|
|
54
|
+
(0, vitest_1.afterEach)(() => {
|
|
55
|
+
vitest_1.vi.clearAllMocks();
|
|
56
|
+
clearEnv();
|
|
57
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
58
|
+
// Clean up temporary directory
|
|
59
|
+
if (tmpDir) {
|
|
60
|
+
(0, fs_1.rmSync)(tmpDir, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.describe)('sdkInit', () => {
|
|
64
|
+
(0, vitest_1.test)('test sdkInit returns httpClient when CA cert configured', () => {
|
|
65
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
66
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
67
|
+
apiKey: 'test-key',
|
|
68
|
+
apiUrl: 'https://api.example.com',
|
|
69
|
+
caCertPath,
|
|
70
|
+
});
|
|
71
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
72
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
73
|
+
const result = hook.sdkInit(opts);
|
|
74
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
75
|
+
(0, vitest_1.expect)(result.httpClient).not.toBe(opts.httpClient);
|
|
76
|
+
});
|
|
77
|
+
(0, vitest_1.test)('test sdkInit returns httpClient when CA cert content configured', () => {
|
|
78
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
79
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
80
|
+
apiKey: 'test-key',
|
|
81
|
+
apiUrl: 'https://api.example.com',
|
|
82
|
+
caCertContent: '-----BEGIN CERTIFICATE-----\nMOCK_CONTENT\n-----END CERTIFICATE-----',
|
|
83
|
+
});
|
|
84
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
85
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
86
|
+
const result = hook.sdkInit(opts);
|
|
87
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
88
|
+
});
|
|
89
|
+
(0, vitest_1.test)('test sdkInit returns httpClient with client certificates', () => {
|
|
90
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
91
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
92
|
+
apiKey: 'test-key',
|
|
93
|
+
apiUrl: 'https://api.example.com',
|
|
94
|
+
caCertPath,
|
|
95
|
+
clientCertPath,
|
|
96
|
+
clientKeyPath,
|
|
97
|
+
});
|
|
98
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
99
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
100
|
+
const result = hook.sdkInit(opts);
|
|
101
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
102
|
+
});
|
|
103
|
+
(0, vitest_1.test)('test sdkInit returns original opts when no cert configured', () => {
|
|
104
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
105
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
106
|
+
apiKey: 'test-key',
|
|
107
|
+
apiUrl: 'https://api.example.com',
|
|
108
|
+
});
|
|
109
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
110
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
111
|
+
const result = hook.sdkInit(opts);
|
|
112
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
113
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
(0, vitest_1.test)('test sdkInit augments existing httpClient instead of replacing it', async () => {
|
|
116
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
117
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
118
|
+
apiKey: 'test-key',
|
|
119
|
+
apiUrl: 'https://api.example.com',
|
|
120
|
+
caCertPath,
|
|
121
|
+
});
|
|
122
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
123
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response());
|
|
124
|
+
const existingClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
125
|
+
const opts = {
|
|
126
|
+
serverURL: 'https://api.example.com',
|
|
127
|
+
httpClient: existingClient,
|
|
128
|
+
};
|
|
129
|
+
const result = hook.sdkInit(opts);
|
|
130
|
+
(0, vitest_1.expect)(result.serverURL).toBe(opts.serverURL);
|
|
131
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
132
|
+
// Most important: the same httpClient instance is returned, not a new one
|
|
133
|
+
(0, vitest_1.expect)(result.httpClient).toBe(existingClient);
|
|
134
|
+
// Verify that the TLS hook was added by making a request
|
|
135
|
+
const req = new Request('https://api.example.com/test', { method: 'GET' });
|
|
136
|
+
await result.httpClient?.request(req);
|
|
137
|
+
// The custom fetcher should have been called
|
|
138
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
139
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
140
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
141
|
+
if (!callArgs)
|
|
142
|
+
throw new Error('unreachable');
|
|
143
|
+
const [calledReq] = callArgs;
|
|
144
|
+
// Verify dispatcher was injected into the request
|
|
145
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
146
|
+
(0, vitest_1.expect)(calledReq.url).toBe('https://api.example.com/test');
|
|
147
|
+
});
|
|
148
|
+
(0, vitest_1.test)('test sdkInit skips cert loading in browser environment', () => {
|
|
149
|
+
mockIsNodeLike.mockReturnValue(false);
|
|
150
|
+
mockIsBrowserLike.mockReturnValue(true);
|
|
151
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
152
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
153
|
+
apiKey: 'test-key',
|
|
154
|
+
apiUrl: 'https://api.example.com',
|
|
155
|
+
caCertPath,
|
|
156
|
+
});
|
|
157
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
158
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
159
|
+
const result = hook.sdkInit(opts);
|
|
160
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
161
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
162
|
+
});
|
|
163
|
+
(0, vitest_1.test)('test sdkInit returns original opts when CA cert file missing', () => {
|
|
164
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
165
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
166
|
+
apiKey: 'test-key',
|
|
167
|
+
apiUrl: 'https://api.example.com',
|
|
168
|
+
caCertPath: '/nonexistent/ca.pem',
|
|
169
|
+
});
|
|
170
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
171
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
172
|
+
const result = hook.sdkInit(opts);
|
|
173
|
+
// When cert file is missing, no httpClient should be configured
|
|
174
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
175
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
(0, vitest_1.test)('test sdkInit returns original opts when client key file missing', () => {
|
|
178
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
179
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
180
|
+
apiKey: 'test-key',
|
|
181
|
+
apiUrl: 'https://api.example.com',
|
|
182
|
+
caCertPath,
|
|
183
|
+
clientCertPath,
|
|
184
|
+
clientKeyPath: '/nonexistent/key.pem',
|
|
185
|
+
});
|
|
186
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
187
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
188
|
+
const result = hook.sdkInit(opts);
|
|
189
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
190
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
191
|
+
});
|
|
192
|
+
(0, vitest_1.test)('test sdkInit returns original opts when only client cert configured', () => {
|
|
193
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
194
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
195
|
+
apiKey: 'test-key',
|
|
196
|
+
apiUrl: 'https://api.example.com',
|
|
197
|
+
caCertPath,
|
|
198
|
+
clientCertPath,
|
|
199
|
+
});
|
|
200
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
201
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
202
|
+
const result = hook.sdkInit(opts);
|
|
203
|
+
// When only client cert is provided (missing key), should return original opts
|
|
204
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
205
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
206
|
+
});
|
|
207
|
+
(0, vitest_1.test)('test sdkInit returns original opts when only client key configured', () => {
|
|
208
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
209
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
210
|
+
apiKey: 'test-key',
|
|
211
|
+
apiUrl: 'https://api.example.com',
|
|
212
|
+
caCertPath,
|
|
213
|
+
clientKeyPath,
|
|
214
|
+
});
|
|
215
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
216
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
217
|
+
const result = hook.sdkInit(opts);
|
|
218
|
+
// When only client key is provided (missing cert), should return original opts
|
|
219
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
220
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
(0, vitest_1.test)('test sdkInit returns original opts when client cert file missing', () => {
|
|
223
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
224
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
225
|
+
apiKey: 'test-key',
|
|
226
|
+
apiUrl: 'https://api.example.com',
|
|
227
|
+
caCertPath,
|
|
228
|
+
clientCertPath: '/nonexistent/cert.pem',
|
|
229
|
+
clientKeyPath,
|
|
230
|
+
});
|
|
231
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
232
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
233
|
+
const result = hook.sdkInit(opts);
|
|
234
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
235
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
(0, vitest_1.describe)('environment variable priority', () => {
|
|
239
|
+
(0, vitest_1.test)('test GALILEO_CA_CERT_PATH from env is used', () => {
|
|
240
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
241
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
242
|
+
process.env['GALILEO_CA_CERT_PATH'] = caCertPath;
|
|
243
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
244
|
+
const cert = config.getCertConfig();
|
|
245
|
+
(0, vitest_1.expect)(cert).not.toBeNull();
|
|
246
|
+
if (!cert)
|
|
247
|
+
throw new Error("unreachable");
|
|
248
|
+
(0, vitest_1.expect)(cert.caCertPath).toBe(caCertPath);
|
|
249
|
+
});
|
|
250
|
+
(0, vitest_1.test)('test only GALILEO_CA_CERT_PATH is supported for CA cert from env', () => {
|
|
251
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
252
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
253
|
+
process.env['SSL_CERT_FILE'] = caCertPath;
|
|
254
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
255
|
+
const cert = config.getCertConfig();
|
|
256
|
+
(0, vitest_1.expect)(cert).toBeNull();
|
|
257
|
+
});
|
|
258
|
+
(0, vitest_1.test)('test only GALILEO_CA_CERT_PATH is supported not NODE_EXTRA_CA_CERTS', () => {
|
|
259
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
260
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
261
|
+
process.env['NODE_EXTRA_CA_CERTS'] = caCertPath;
|
|
262
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
263
|
+
const cert = config.getCertConfig();
|
|
264
|
+
(0, vitest_1.expect)(cert).toBeNull();
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
(0, vitest_1.describe)('client certificate environment variables', () => {
|
|
268
|
+
(0, vitest_1.test)('test GALILEO_CLIENT_CERT_PATH and GALILEO_CLIENT_KEY_PATH from env', () => {
|
|
269
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
270
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
271
|
+
process.env['GALILEO_CA_CERT_PATH'] = caCertPath;
|
|
272
|
+
process.env['GALILEO_CLIENT_CERT_PATH'] = clientCertPath;
|
|
273
|
+
process.env['GALILEO_CLIENT_KEY_PATH'] = clientKeyPath;
|
|
274
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
275
|
+
const cert = config.getCertConfig();
|
|
276
|
+
(0, vitest_1.expect)(cert).not.toBeNull();
|
|
277
|
+
if (!cert)
|
|
278
|
+
throw new Error("unreachable");
|
|
279
|
+
(0, vitest_1.expect)(cert.clientCertPath).toBe(clientCertPath);
|
|
280
|
+
(0, vitest_1.expect)(cert.clientKeyPath).toBe(clientKeyPath);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
(0, vitest_1.describe)('rejectUnauthorized configuration', () => {
|
|
284
|
+
(0, vitest_1.test)('test GALILEO_REJECT_UNAUTHORIZED takes priority over NODE_TLS_REJECT_UNAUTHORIZED', () => {
|
|
285
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
286
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
287
|
+
process.env['GALILEO_CA_CERT_PATH'] = caCertPath;
|
|
288
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = 'false';
|
|
289
|
+
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '1';
|
|
290
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
291
|
+
const cert = config.getCertConfig();
|
|
292
|
+
(0, vitest_1.expect)(cert).not.toBeNull();
|
|
293
|
+
if (!cert)
|
|
294
|
+
throw new Error("unreachable");
|
|
295
|
+
(0, vitest_1.expect)(cert.rejectUnauthorized).toBe(false);
|
|
296
|
+
});
|
|
297
|
+
(0, vitest_1.test)('test NODE_TLS_REJECT_UNAUTHORIZED used when GALILEO_REJECT_UNAUTHORIZED absent', () => {
|
|
298
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
299
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
300
|
+
process.env['GALILEO_CA_CERT_PATH'] = caCertPath;
|
|
301
|
+
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
|
302
|
+
const config = galileo_config_js_1.GalileoConfig.get({});
|
|
303
|
+
const cert = config.getCertConfig();
|
|
304
|
+
(0, vitest_1.expect)(cert).not.toBeNull();
|
|
305
|
+
if (!cert)
|
|
306
|
+
throw new Error("unreachable");
|
|
307
|
+
(0, vitest_1.expect)(cert.rejectUnauthorized).toBe(false);
|
|
308
|
+
});
|
|
309
|
+
(0, vitest_1.test)('test rejectUnauthorized defaults to true when no env vars set', () => {
|
|
310
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
311
|
+
const config = galileo_config_js_1.GalileoConfig.get({
|
|
312
|
+
apiKey: 'test-key',
|
|
313
|
+
apiUrl: 'https://api.example.com',
|
|
314
|
+
caCertPath,
|
|
315
|
+
});
|
|
316
|
+
const cert = config.getCertConfig();
|
|
317
|
+
(0, vitest_1.expect)(cert).not.toBeNull();
|
|
318
|
+
if (!cert)
|
|
319
|
+
throw new Error("unreachable");
|
|
320
|
+
// rejectUnauthorized is undefined in config, defaults to true in hook
|
|
321
|
+
(0, vitest_1.expect)(cert.rejectUnauthorized).toBeUndefined();
|
|
322
|
+
});
|
|
323
|
+
(0, vitest_1.test)('test sdkInit configures agent with custom CA cert even when rejectUnauthorized is true', () => {
|
|
324
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
325
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
326
|
+
apiKey: 'test-key',
|
|
327
|
+
apiUrl: 'https://api.example.com',
|
|
328
|
+
caCertPath,
|
|
329
|
+
rejectUnauthorized: true,
|
|
330
|
+
});
|
|
331
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
332
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
333
|
+
const result = hook.sdkInit(opts);
|
|
334
|
+
// Custom CA cert should be configured regardless of rejectUnauthorized value
|
|
335
|
+
// rejectUnauthorized=true means strict validation with custom CA; this is a valid configuration
|
|
336
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
337
|
+
(0, vitest_1.expect)(result.httpClient).not.toBe(opts.httpClient);
|
|
338
|
+
});
|
|
339
|
+
(0, vitest_1.test)('test rejectUnauthorized false is passed to connectOptions', () => {
|
|
340
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
341
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
342
|
+
apiKey: 'test-key',
|
|
343
|
+
apiUrl: 'https://api.example.com',
|
|
344
|
+
caCertPath,
|
|
345
|
+
rejectUnauthorized: false,
|
|
346
|
+
});
|
|
347
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
348
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
349
|
+
const result = hook.sdkInit(opts);
|
|
350
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
351
|
+
(0, vitest_1.expect)(result.httpClient).not.toBe(opts.httpClient);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
(0, vitest_1.describe)('CertAgent availability', () => {
|
|
355
|
+
(0, vitest_1.test)('test sdkInit returns original opts when CertAgent is unavailable', () => {
|
|
356
|
+
// Mock isNodeLike to return true but simulate missing undici by not being in Node-like environment for Agent
|
|
357
|
+
// This tests the guard at line 53: if (!isNodeLike() || !CertAgent)
|
|
358
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
359
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
360
|
+
apiKey: 'test-key',
|
|
361
|
+
apiUrl: 'https://api.example.com',
|
|
362
|
+
caCertPath,
|
|
363
|
+
});
|
|
364
|
+
// Simulate CertAgent being undefined by mocking the module reload scenario
|
|
365
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
366
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
367
|
+
// This test verifies that even with valid config, if CertAgent is not available,
|
|
368
|
+
// the hook gracefully returns original opts
|
|
369
|
+
// Note: In real scenario, CertAgent would be undefined if undici import fails
|
|
370
|
+
const result = hook.sdkInit(opts);
|
|
371
|
+
// If undici is available (which it should be in test environment), httpClient should be created
|
|
372
|
+
// If undici is not available, result should be opts
|
|
373
|
+
(0, vitest_1.expect)(result).toBeDefined();
|
|
374
|
+
(0, vitest_1.expect)(result.serverURL).toBe(opts.serverURL);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
(0, vitest_1.describe)('integration - certificate mechanism', () => {
|
|
378
|
+
(0, vitest_1.test)('test TLS hook is added via beforeRequest hook', async () => {
|
|
379
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
380
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
381
|
+
apiKey: 'test-key',
|
|
382
|
+
apiUrl: 'https://api.example.com',
|
|
383
|
+
caCertPath,
|
|
384
|
+
});
|
|
385
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
386
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response('OK'));
|
|
387
|
+
const httpClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
388
|
+
const opts = { httpClient };
|
|
389
|
+
const result = hook.sdkInit(opts);
|
|
390
|
+
(0, vitest_1.expect)(result.httpClient).toBe(httpClient);
|
|
391
|
+
// Make a GET request (no body) through the augmented client
|
|
392
|
+
const request = new Request('https://api.example.com/test', {
|
|
393
|
+
method: 'GET',
|
|
394
|
+
headers: { 'Content-Type': 'application/json' },
|
|
395
|
+
});
|
|
396
|
+
const response = await result.httpClient?.request(request);
|
|
397
|
+
// Verify the custom fetcher was called
|
|
398
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
399
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
400
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
401
|
+
if (!callArgs)
|
|
402
|
+
throw new Error('unreachable');
|
|
403
|
+
const [calledReq] = callArgs;
|
|
404
|
+
// Verify the request properties are preserved
|
|
405
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
406
|
+
(0, vitest_1.expect)(calledReq.url).toBe('https://api.example.com/test');
|
|
407
|
+
(0, vitest_1.expect)(calledReq.method).toBe('GET');
|
|
408
|
+
(0, vitest_1.expect)(calledReq.headers.get('Content-Type')).toBe('application/json');
|
|
409
|
+
// Verify response was returned
|
|
410
|
+
(0, vitest_1.expect)(response?.status).toBe(200);
|
|
411
|
+
});
|
|
412
|
+
(0, vitest_1.test)('test httpClient uses undici dispatcher with certificates', async () => {
|
|
413
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
414
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
415
|
+
apiKey: 'test-key',
|
|
416
|
+
apiUrl: 'https://api.example.com',
|
|
417
|
+
caCertPath,
|
|
418
|
+
});
|
|
419
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
420
|
+
// Use a custom fetcher that captures what it receives
|
|
421
|
+
let receivedRequest = null;
|
|
422
|
+
const testFetcher = vitest_1.vi.fn(async (input, _init) => {
|
|
423
|
+
if (input instanceof Request) {
|
|
424
|
+
receivedRequest = input;
|
|
425
|
+
}
|
|
426
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
427
|
+
status: 200,
|
|
428
|
+
headers: { 'Content-Type': 'application/json' },
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
const httpClient = new http_js_1.HTTPClient({ fetcher: testFetcher });
|
|
432
|
+
const opts = { httpClient };
|
|
433
|
+
const result = hook.sdkInit(opts);
|
|
434
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
435
|
+
// Make a request using the httpClient
|
|
436
|
+
const request = new Request('https://api.example.com/test', {
|
|
437
|
+
method: 'GET',
|
|
438
|
+
headers: { 'Content-Type': 'application/json' },
|
|
439
|
+
});
|
|
440
|
+
await result.httpClient?.request(request);
|
|
441
|
+
// Verify the custom fetcher was called
|
|
442
|
+
(0, vitest_1.expect)(testFetcher).toHaveBeenCalledTimes(1);
|
|
443
|
+
(0, vitest_1.expect)(receivedRequest).toBeDefined();
|
|
444
|
+
// The hook should have transformed the request
|
|
445
|
+
if (!receivedRequest)
|
|
446
|
+
throw new Error('unreachable');
|
|
447
|
+
(0, vitest_1.expect)(receivedRequest).toBeInstanceOf(Request);
|
|
448
|
+
(0, vitest_1.expect)(receivedRequest.url).toBe('https://api.example.com/test');
|
|
449
|
+
});
|
|
450
|
+
(0, vitest_1.test)('test httpClient with certificates can make successful requests', async () => {
|
|
451
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
452
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
453
|
+
apiKey: 'test-key',
|
|
454
|
+
apiUrl: 'https://api.example.com',
|
|
455
|
+
caCertPath,
|
|
456
|
+
rejectUnauthorized: false, // For testing purposes
|
|
457
|
+
});
|
|
458
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
459
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
460
|
+
const result = hook.sdkInit(opts);
|
|
461
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
462
|
+
// Mock successful response
|
|
463
|
+
const mockResponse = new Response(JSON.stringify({ data: 'test' }), {
|
|
464
|
+
status: 200,
|
|
465
|
+
headers: { 'Content-Type': 'application/json' },
|
|
466
|
+
});
|
|
467
|
+
const fetchSpy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(mockResponse);
|
|
468
|
+
// Make a GET request (no body)
|
|
469
|
+
const request = new Request('https://api.example.com/endpoint', {
|
|
470
|
+
method: 'GET',
|
|
471
|
+
headers: { 'Content-Type': 'application/json' },
|
|
472
|
+
});
|
|
473
|
+
const response = await result.httpClient?.request(request);
|
|
474
|
+
// Verify request succeeded
|
|
475
|
+
(0, vitest_1.expect)(response).toBeDefined();
|
|
476
|
+
(0, vitest_1.expect)(response?.status).toBe(200);
|
|
477
|
+
(0, vitest_1.expect)(fetchSpy).toHaveBeenCalled();
|
|
478
|
+
fetchSpy.mockRestore();
|
|
479
|
+
});
|
|
480
|
+
(0, vitest_1.test)('test httpClient created with mTLS configuration without CA cert', async () => {
|
|
481
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
482
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
483
|
+
apiKey: 'test-key',
|
|
484
|
+
apiUrl: 'https://api.example.com',
|
|
485
|
+
clientCertPath,
|
|
486
|
+
clientKeyPath,
|
|
487
|
+
});
|
|
488
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
489
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response(JSON.stringify({ success: true }), { status: 200 }));
|
|
490
|
+
const httpClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
491
|
+
const opts = { httpClient };
|
|
492
|
+
const result = hook.sdkInit(opts);
|
|
493
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
494
|
+
// With augmentation approach, same instance is returned
|
|
495
|
+
(0, vitest_1.expect)(result.httpClient).toBe(opts.httpClient);
|
|
496
|
+
// Verify the httpClient can make requests with the configured certificates
|
|
497
|
+
const request = new Request('https://api.example.com/test', {
|
|
498
|
+
method: 'GET',
|
|
499
|
+
});
|
|
500
|
+
await result.httpClient?.request(request);
|
|
501
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
502
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
503
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
504
|
+
if (!callArgs)
|
|
505
|
+
throw new Error('unreachable');
|
|
506
|
+
const [calledReq] = callArgs;
|
|
507
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
508
|
+
(0, vitest_1.expect)(calledReq.url).toBe('https://api.example.com/test');
|
|
509
|
+
});
|
|
510
|
+
(0, vitest_1.test)('test sdkInit returns original opts when no meaningful TLS customization', () => {
|
|
511
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
512
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
513
|
+
apiKey: 'test-key',
|
|
514
|
+
apiUrl: 'https://api.example.com',
|
|
515
|
+
rejectUnauthorized: true,
|
|
516
|
+
});
|
|
517
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
518
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
519
|
+
const result = hook.sdkInit(opts);
|
|
520
|
+
// When only rejectUnauthorized=true is set (no CA/client certs), hasCertCustomization is false
|
|
521
|
+
// because hasCertCustomization requires CA, cert, key, or rejectUnauthorized === false (line 118)
|
|
522
|
+
(0, vitest_1.expect)(result).toBe(opts);
|
|
523
|
+
(0, vitest_1.expect)(result.httpClient).toBeUndefined();
|
|
524
|
+
});
|
|
525
|
+
(0, vitest_1.test)('test sdkInit configures mTLS with client certs even when rejectUnauthorized is true', () => {
|
|
526
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
527
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
528
|
+
apiKey: 'test-key',
|
|
529
|
+
apiUrl: 'https://api.example.com',
|
|
530
|
+
clientCertPath,
|
|
531
|
+
clientKeyPath,
|
|
532
|
+
rejectUnauthorized: true,
|
|
533
|
+
});
|
|
534
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
535
|
+
const opts = { serverURL: 'https://api.example.com' };
|
|
536
|
+
const result = hook.sdkInit(opts);
|
|
537
|
+
// mTLS client certs should be configured regardless of rejectUnauthorized value
|
|
538
|
+
// rejectUnauthorized and custom certs are orthogonal concerns
|
|
539
|
+
(0, vitest_1.expect)(result.httpClient).toBeDefined();
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
(0, vitest_1.describe)('user hook preservation', () => {
|
|
543
|
+
(0, vitest_1.test)('test user-registered hooks are preserved when TLS is configured', async () => {
|
|
544
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
545
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
546
|
+
apiKey: 'test-key',
|
|
547
|
+
apiUrl: 'https://api.example.com',
|
|
548
|
+
caCertPath,
|
|
549
|
+
});
|
|
550
|
+
let userHookCalled = false;
|
|
551
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response('OK'));
|
|
552
|
+
const userClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
553
|
+
userClient.addHook('beforeRequest', (req) => {
|
|
554
|
+
userHookCalled = true;
|
|
555
|
+
// User hook can modify headers
|
|
556
|
+
const newReq = new Request(req.url, {
|
|
557
|
+
method: req.method,
|
|
558
|
+
headers: req.headers,
|
|
559
|
+
body: req.body,
|
|
560
|
+
});
|
|
561
|
+
newReq.headers.set('X-Custom-Header', 'user-value');
|
|
562
|
+
return newReq;
|
|
563
|
+
});
|
|
564
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
565
|
+
const opts = { httpClient: userClient };
|
|
566
|
+
const result = hook.sdkInit(opts);
|
|
567
|
+
const request = new Request('https://api.example.com/test', {
|
|
568
|
+
method: 'GET',
|
|
569
|
+
});
|
|
570
|
+
await result.httpClient?.request(request);
|
|
571
|
+
// Verify user hook was called
|
|
572
|
+
(0, vitest_1.expect)(userHookCalled).toBe(true);
|
|
573
|
+
// Verify the custom fetcher was called
|
|
574
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
575
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
576
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
577
|
+
if (!callArgs)
|
|
578
|
+
throw new Error('unreachable');
|
|
579
|
+
const [calledReq] = callArgs;
|
|
580
|
+
// Verify user's header was preserved in the final request
|
|
581
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
582
|
+
(0, vitest_1.expect)(calledReq.headers.get('X-Custom-Header')).toBe('user-value');
|
|
583
|
+
});
|
|
584
|
+
(0, vitest_1.test)('test TLS hook runs after user hooks', async () => {
|
|
585
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
586
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
587
|
+
apiKey: 'test-key',
|
|
588
|
+
apiUrl: 'https://api.example.com',
|
|
589
|
+
caCertPath,
|
|
590
|
+
});
|
|
591
|
+
const callOrder = [];
|
|
592
|
+
const userClient = new http_js_1.HTTPClient();
|
|
593
|
+
userClient.addHook('beforeRequest', (req) => {
|
|
594
|
+
callOrder.push('user-hook');
|
|
595
|
+
return req;
|
|
596
|
+
});
|
|
597
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
598
|
+
const opts = { httpClient: userClient };
|
|
599
|
+
const result = hook.sdkInit(opts);
|
|
600
|
+
// Mock fetch to capture when it's called
|
|
601
|
+
const fetchSpy = vitest_1.vi.spyOn(globalThis, 'fetch').mockImplementation(async () => {
|
|
602
|
+
callOrder.push('fetch');
|
|
603
|
+
return new Response('OK');
|
|
604
|
+
});
|
|
605
|
+
const request = new Request('https://api.example.com/test', {
|
|
606
|
+
method: 'GET',
|
|
607
|
+
});
|
|
608
|
+
await result.httpClient?.request(request);
|
|
609
|
+
// User hook should run before fetch (and before TLS hook which is closest to fetch)
|
|
610
|
+
(0, vitest_1.expect)(callOrder).toEqual(['user-hook', 'fetch']);
|
|
611
|
+
fetchSpy.mockRestore();
|
|
612
|
+
});
|
|
613
|
+
(0, vitest_1.test)('test multiple user hooks are all executed with TLS', async () => {
|
|
614
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
615
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
616
|
+
apiKey: 'test-key',
|
|
617
|
+
apiUrl: 'https://api.example.com',
|
|
618
|
+
caCertPath,
|
|
619
|
+
});
|
|
620
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response('OK'));
|
|
621
|
+
const userClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
622
|
+
const calls = [];
|
|
623
|
+
userClient.addHook('beforeRequest', (req) => {
|
|
624
|
+
calls.push('hook1');
|
|
625
|
+
return req;
|
|
626
|
+
});
|
|
627
|
+
userClient.addHook('beforeRequest', (req) => {
|
|
628
|
+
calls.push('hook2');
|
|
629
|
+
return req;
|
|
630
|
+
});
|
|
631
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
632
|
+
const opts = { httpClient: userClient };
|
|
633
|
+
const result = hook.sdkInit(opts);
|
|
634
|
+
const request = new Request('https://api.example.com/test', {
|
|
635
|
+
method: 'GET',
|
|
636
|
+
});
|
|
637
|
+
await result.httpClient?.request(request);
|
|
638
|
+
// Both user hooks should be called
|
|
639
|
+
(0, vitest_1.expect)(calls).toContain('hook1');
|
|
640
|
+
(0, vitest_1.expect)(calls).toContain('hook2');
|
|
641
|
+
// And the fetcher should be called with a request
|
|
642
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalled();
|
|
643
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
644
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
645
|
+
if (!callArgs)
|
|
646
|
+
throw new Error('unreachable');
|
|
647
|
+
const [calledReq] = callArgs;
|
|
648
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
(0, vitest_1.describe)('request body handling', () => {
|
|
652
|
+
(0, vitest_1.test)('test TLS hook preserves request headers and url', async () => {
|
|
653
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
654
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
655
|
+
apiKey: 'test-key',
|
|
656
|
+
apiUrl: 'https://api.example.com',
|
|
657
|
+
caCertPath,
|
|
658
|
+
});
|
|
659
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
660
|
+
const opts = {};
|
|
661
|
+
const result = hook.sdkInit(opts);
|
|
662
|
+
const fetchSpy = vitest_1.vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response('OK'));
|
|
663
|
+
const request = new Request('https://api.example.com/test', {
|
|
664
|
+
method: 'GET',
|
|
665
|
+
headers: { 'X-Custom': 'value', 'Content-Type': 'application/json' },
|
|
666
|
+
});
|
|
667
|
+
await result.httpClient?.request(request);
|
|
668
|
+
(0, vitest_1.expect)(fetchSpy).toHaveBeenCalledTimes(1);
|
|
669
|
+
const callArgs = fetchSpy.mock.calls[0];
|
|
670
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
671
|
+
if (!callArgs)
|
|
672
|
+
throw new Error('unreachable');
|
|
673
|
+
const [calledReq] = callArgs;
|
|
674
|
+
(0, vitest_1.expect)(calledReq.url).toBe('https://api.example.com/test');
|
|
675
|
+
(0, vitest_1.expect)(calledReq.headers.get('X-Custom')).toBe('value');
|
|
676
|
+
(0, vitest_1.expect)(calledReq.headers.get('Content-Type')).toBe('application/json');
|
|
677
|
+
fetchSpy.mockRestore();
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
(0, vitest_1.describe)('runtime version detection and warnings', () => {
|
|
681
|
+
(0, vitest_1.test)('test version detection correctly identifies supported Node.js versions', () => {
|
|
682
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
683
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
684
|
+
apiKey: 'test-key',
|
|
685
|
+
apiUrl: 'https://api.example.com',
|
|
686
|
+
caCertPath,
|
|
687
|
+
});
|
|
688
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
689
|
+
// Access the private method via type casting for testing
|
|
690
|
+
const hookAny = hook;
|
|
691
|
+
// Test various version strings
|
|
692
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20.18.0')).toBe(false); // Minor < 18
|
|
693
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20.18.1')).toBe(true); // Exact minimum
|
|
694
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20.19.0')).toBe(true); // Minor > 18
|
|
695
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('21.0.0')).toBe(true); // Major > 20
|
|
696
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('22.5.0')).toBe(true); // Much newer
|
|
697
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('19.10.0')).toBe(false); // Too old
|
|
698
|
+
});
|
|
699
|
+
(0, vitest_1.test)('test version string parsing handles various formats', () => {
|
|
700
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
701
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
702
|
+
apiKey: 'test-key',
|
|
703
|
+
apiUrl: 'https://api.example.com',
|
|
704
|
+
caCertPath,
|
|
705
|
+
});
|
|
706
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
707
|
+
const hookAny = hook;
|
|
708
|
+
// Test edge cases
|
|
709
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20')).toBe(false); // No minor version (defaults to 0)
|
|
710
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20.18')).toBe(false); // No patch version (defaults to 0, which is < 1)
|
|
711
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('20.19')).toBe(true); // Minor > 18
|
|
712
|
+
// Note: parseInt('invalid') returns NaN, but parts[0] would be NaN which !== undefined
|
|
713
|
+
// so the check major === undefined won't catch it. It would return false.
|
|
714
|
+
// For truly invalid versions, they'd fail the >= check anyway
|
|
715
|
+
(0, vitest_1.expect)(hookAny.isNodeVersionSupported('')).toBe(true); // Empty string → optimistic
|
|
716
|
+
});
|
|
717
|
+
(0, vitest_1.test)('test Node.js version extraction from process.versions', () => {
|
|
718
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
719
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
720
|
+
apiKey: 'test-key',
|
|
721
|
+
apiUrl: 'https://api.example.com',
|
|
722
|
+
caCertPath,
|
|
723
|
+
});
|
|
724
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
725
|
+
const hookAny = hook;
|
|
726
|
+
// Get the actual Node version
|
|
727
|
+
const version = hookAny.getNodeVersion();
|
|
728
|
+
// Verify we got a version string (or null in non-Node environments)
|
|
729
|
+
if (version !== null) {
|
|
730
|
+
(0, vitest_1.expect)(typeof version).toBe('string');
|
|
731
|
+
(0, vitest_1.expect)(version.length).toBeGreaterThan(0);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
});
|
|
735
|
+
(0, vitest_1.describe)('dispatcher integration', () => {
|
|
736
|
+
(0, vitest_1.test)('test dispatcher is passed correctly through the request chain', async () => {
|
|
737
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
738
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
739
|
+
apiKey: 'test-key',
|
|
740
|
+
apiUrl: 'https://api.example.com',
|
|
741
|
+
caCertPath,
|
|
742
|
+
});
|
|
743
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
744
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response('OK'));
|
|
745
|
+
const httpClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
746
|
+
const opts = { httpClient };
|
|
747
|
+
const result = hook.sdkInit(opts);
|
|
748
|
+
const request = new Request('https://api.example.com/test', {
|
|
749
|
+
method: 'GET',
|
|
750
|
+
});
|
|
751
|
+
await result.httpClient?.request(request);
|
|
752
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
753
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
754
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
755
|
+
if (!callArgs)
|
|
756
|
+
throw new Error('unreachable');
|
|
757
|
+
const [calledReq] = callArgs;
|
|
758
|
+
// Dispatcher should be attached to the request object
|
|
759
|
+
// (In a real Node.js environment with undici, this would be used by fetch)
|
|
760
|
+
(0, vitest_1.expect)(calledReq).toBeInstanceOf(Request);
|
|
761
|
+
// Verify it's a proper Request with all properties
|
|
762
|
+
(0, vitest_1.expect)(calledReq.url).toBeDefined();
|
|
763
|
+
(0, vitest_1.expect)(calledReq.method).toBeDefined();
|
|
764
|
+
(0, vitest_1.expect)(calledReq.headers).toBeDefined();
|
|
765
|
+
});
|
|
766
|
+
(0, vitest_1.test)('test TLS hook creates new Request instances', async () => {
|
|
767
|
+
galileo_config_js_1.GalileoConfig.reset();
|
|
768
|
+
galileo_config_js_1.GalileoConfig.get({
|
|
769
|
+
apiKey: 'test-key',
|
|
770
|
+
apiUrl: 'https://api.example.com',
|
|
771
|
+
caCertPath,
|
|
772
|
+
});
|
|
773
|
+
const hook = new cert_management_js_1.CertManagementHook();
|
|
774
|
+
const mockFetcher = vitest_1.vi.fn().mockResolvedValue(new Response('OK'));
|
|
775
|
+
const httpClient = new http_js_1.HTTPClient({ fetcher: mockFetcher });
|
|
776
|
+
const opts = { httpClient };
|
|
777
|
+
const result = hook.sdkInit(opts);
|
|
778
|
+
const originalRequest = new Request('https://api.example.com/test', {
|
|
779
|
+
method: 'GET',
|
|
780
|
+
});
|
|
781
|
+
await result.httpClient?.request(originalRequest);
|
|
782
|
+
(0, vitest_1.expect)(mockFetcher).toHaveBeenCalledTimes(1);
|
|
783
|
+
const callArgs = mockFetcher.mock.calls[0];
|
|
784
|
+
(0, vitest_1.expect)(callArgs).toBeDefined();
|
|
785
|
+
if (!callArgs)
|
|
786
|
+
throw new Error('unreachable');
|
|
787
|
+
const [calledReq] = callArgs;
|
|
788
|
+
// The request passed to the fetcher should be a new instance
|
|
789
|
+
// (Request objects are immutable, so the hook creates a new one)
|
|
790
|
+
(0, vitest_1.expect)(calledReq).not.toBe(originalRequest);
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
//# sourceMappingURL=cert-management.test.js.map
|