galileo-generated 0.2.6 → 0.2.8
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-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/error-cleaner.d.ts.map +1 -1
- package/dist/commonjs/hooks/error-cleaner.js +0 -4
- package/dist/commonjs/hooks/error-cleaner.js.map +1 -1
- package/dist/commonjs/hooks/registration.d.ts.map +1 -1
- package/dist/commonjs/hooks/registration.js +4 -0
- package/dist/commonjs/hooks/registration.js.map +1 -1
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/lib/galileo-config.d.ts +105 -14
- package/dist/commonjs/lib/galileo-config.d.ts.map +1 -1
- package/dist/commonjs/lib/galileo-config.js +168 -12
- package/dist/commonjs/lib/galileo-config.js.map +1 -1
- package/dist/commonjs/lib/sdk-logger.d.ts +26 -0
- package/dist/commonjs/lib/sdk-logger.d.ts.map +1 -0
- package/dist/commonjs/lib/sdk-logger.js +85 -0
- package/dist/commonjs/lib/sdk-logger.js.map +1 -0
- 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/lib/galileo-config.test.js +101 -0
- package/dist/commonjs/tests/lib/galileo-config.test.js.map +1 -1
- package/dist/commonjs/tests/lib/sdk-logger.test.d.ts +2 -0
- package/dist/commonjs/tests/lib/sdk-logger.test.d.ts.map +1 -0
- package/dist/commonjs/tests/lib/sdk-logger.test.js +401 -0
- package/dist/commonjs/tests/lib/sdk-logger.test.js.map +1 -0
- package/dist/commonjs/types/sdk-logger.types.d.ts +35 -0
- package/dist/commonjs/types/sdk-logger.types.d.ts.map +1 -0
- package/dist/commonjs/types/sdk-logger.types.js +17 -0
- package/dist/commonjs/types/sdk-logger.types.js.map +1 -0
- 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/error-cleaner.d.ts.map +1 -1
- package/dist/esm/hooks/error-cleaner.js +0 -4
- package/dist/esm/hooks/error-cleaner.js.map +1 -1
- package/dist/esm/hooks/registration.d.ts.map +1 -1
- package/dist/esm/hooks/registration.js +4 -0
- package/dist/esm/hooks/registration.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/galileo-config.d.ts +105 -14
- package/dist/esm/lib/galileo-config.d.ts.map +1 -1
- package/dist/esm/lib/galileo-config.js +167 -12
- package/dist/esm/lib/galileo-config.js.map +1 -1
- package/dist/esm/lib/sdk-logger.d.ts +26 -0
- package/dist/esm/lib/sdk-logger.d.ts.map +1 -0
- package/dist/esm/lib/sdk-logger.js +78 -0
- package/dist/esm/lib/sdk-logger.js.map +1 -0
- 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/lib/galileo-config.test.js +101 -0
- package/dist/esm/tests/lib/galileo-config.test.js.map +1 -1
- package/dist/esm/tests/lib/sdk-logger.test.d.ts +2 -0
- package/dist/esm/tests/lib/sdk-logger.test.d.ts.map +1 -0
- package/dist/esm/tests/lib/sdk-logger.test.js +399 -0
- package/dist/esm/tests/lib/sdk-logger.test.js.map +1 -0
- package/dist/esm/types/sdk-logger.types.d.ts +35 -0
- package/dist/esm/types/sdk-logger.types.d.ts.map +1 -0
- package/dist/esm/types/sdk-logger.types.js +14 -0
- package/dist/esm/types/sdk-logger.types.js.map +1 -0
- package/package.json +5 -3
- package/src/hooks/cert-management.ts +288 -0
- package/src/hooks/error-cleaner.ts +0 -7
- package/src/hooks/registration.ts +5 -0
- package/src/index.ts +2 -1
- package/src/lib/galileo-config.ts +232 -17
- package/src/lib/sdk-logger.ts +91 -0
- package/src/tests/hooks/cert-management.test.ts +958 -0
- package/src/tests/lib/galileo-config.test.ts +110 -0
- package/src/tests/lib/sdk-logger.test.ts +518 -0
- package/src/types/sdk-logger.types.ts +43 -0
|
@@ -13,6 +13,11 @@ const ENV_KEYS = [
|
|
|
13
13
|
'GALILEO_PROJECT_NAME',
|
|
14
14
|
'GALILEO_LOG_STREAM',
|
|
15
15
|
'GALILEO_LOG_STREAM_NAME',
|
|
16
|
+
'GALILEO_CA_CERT_PATH',
|
|
17
|
+
'GALILEO_CA_CERT_CONTENT',
|
|
18
|
+
'GALILEO_CLIENT_CERT_PATH',
|
|
19
|
+
'GALILEO_CLIENT_KEY_PATH',
|
|
20
|
+
'GALILEO_REJECT_UNAUTHORIZED',
|
|
16
21
|
] as const;
|
|
17
22
|
|
|
18
23
|
function clearGalileoEnv(): void {
|
|
@@ -233,4 +238,109 @@ describe('GalileoConfig', () => {
|
|
|
233
238
|
expect(() => config.logConfig()).not.toThrow();
|
|
234
239
|
spy.mockRestore();
|
|
235
240
|
});
|
|
241
|
+
|
|
242
|
+
test('test getCertConfig returns cert fields from overrides', () => {
|
|
243
|
+
GalileoConfig.reset();
|
|
244
|
+
const config = GalileoConfig.get({
|
|
245
|
+
apiKey: 'key',
|
|
246
|
+
apiUrl: 'https://api.example.com',
|
|
247
|
+
caCertPath: '/path/to/ca.pem',
|
|
248
|
+
caCertContent: '-----BEGIN CERTIFICATE-----',
|
|
249
|
+
clientCertPath: '/path/to/client.pem',
|
|
250
|
+
clientKeyPath: '/path/to/key.pem',
|
|
251
|
+
rejectUnauthorized: false,
|
|
252
|
+
});
|
|
253
|
+
const cert = config.getCertConfig();
|
|
254
|
+
expect(cert).not.toBeNull();
|
|
255
|
+
if (!cert) throw new Error("unreachable");
|
|
256
|
+
expect(cert.caCertPath).toBe('/path/to/ca.pem');
|
|
257
|
+
expect(cert.caCertContent).toBe('-----BEGIN CERTIFICATE-----');
|
|
258
|
+
expect(cert.clientCertPath).toBe('/path/to/client.pem');
|
|
259
|
+
expect(cert.clientKeyPath).toBe('/path/to/key.pem');
|
|
260
|
+
expect(cert.rejectUnauthorized).toBe(false);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('test getCertConfig empty when no cert set', () => {
|
|
264
|
+
GalileoConfig.reset();
|
|
265
|
+
const config = GalileoConfig.get({
|
|
266
|
+
apiKey: 'key',
|
|
267
|
+
apiUrl: 'https://api.example.com',
|
|
268
|
+
});
|
|
269
|
+
const cert = config.getCertConfig();
|
|
270
|
+
expect(cert).toBeNull();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('test snapshot includes cert when set', () => {
|
|
274
|
+
GalileoConfig.reset();
|
|
275
|
+
const config = GalileoConfig.get({
|
|
276
|
+
apiKey: 'key',
|
|
277
|
+
apiUrl: 'https://api.example.com',
|
|
278
|
+
caCertPath: '/ca.pem',
|
|
279
|
+
rejectUnauthorized: true,
|
|
280
|
+
});
|
|
281
|
+
expect(config.snapshot.cert).toEqual({
|
|
282
|
+
caCertPath: '/ca.pem',
|
|
283
|
+
rejectUnauthorized: true,
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('test cert from env', () => {
|
|
288
|
+
GalileoConfig.reset();
|
|
289
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
290
|
+
process.env['GALILEO_CA_CERT_PATH'] = '/env/ca.pem';
|
|
291
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = 'false';
|
|
292
|
+
const config = GalileoConfig.get({});
|
|
293
|
+
const cert = config.getCertConfig();
|
|
294
|
+
expect(cert).not.toBeNull();
|
|
295
|
+
if (!cert) throw new Error("unreachable");
|
|
296
|
+
expect(cert.caCertPath).toBe('/env/ca.pem');
|
|
297
|
+
expect(cert.rejectUnauthorized).toBe(false);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test('test empty GALILEO_REJECT_UNAUTHORIZED treated as undefined', () => {
|
|
301
|
+
GalileoConfig.reset();
|
|
302
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
303
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = '';
|
|
304
|
+
const config = GalileoConfig.get({});
|
|
305
|
+
const cert = config.getCertConfig();
|
|
306
|
+
expect(cert).toBeNull();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test('test empty NODE_TLS_REJECT_UNAUTHORIZED treated as undefined', () => {
|
|
310
|
+
GalileoConfig.reset();
|
|
311
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
312
|
+
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '';
|
|
313
|
+
const config = GalileoConfig.get({});
|
|
314
|
+
const cert = config.getCertConfig();
|
|
315
|
+
expect(cert).toBeNull();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('test explicit rejectUnauthorized values', () => {
|
|
319
|
+
GalileoConfig.reset();
|
|
320
|
+
process.env['GALILEO_API_KEY'] = 'env-key';
|
|
321
|
+
|
|
322
|
+
// Test "true" string
|
|
323
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = 'true';
|
|
324
|
+
let config = GalileoConfig.get({});
|
|
325
|
+
let cert = config.getCertConfig();
|
|
326
|
+
expect(cert?.rejectUnauthorized).toBe(true);
|
|
327
|
+
|
|
328
|
+
GalileoConfig.reset();
|
|
329
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = '1';
|
|
330
|
+
config = GalileoConfig.get({});
|
|
331
|
+
cert = config.getCertConfig();
|
|
332
|
+
expect(cert?.rejectUnauthorized).toBe(true);
|
|
333
|
+
|
|
334
|
+
GalileoConfig.reset();
|
|
335
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = 'false';
|
|
336
|
+
config = GalileoConfig.get({});
|
|
337
|
+
cert = config.getCertConfig();
|
|
338
|
+
expect(cert?.rejectUnauthorized).toBe(false);
|
|
339
|
+
|
|
340
|
+
GalileoConfig.reset();
|
|
341
|
+
process.env['GALILEO_REJECT_UNAUTHORIZED'] = '0';
|
|
342
|
+
config = GalileoConfig.get({});
|
|
343
|
+
cert = config.getCertConfig();
|
|
344
|
+
expect(cert?.rejectUnauthorized).toBe(false);
|
|
345
|
+
});
|
|
236
346
|
});
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach, vi } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
getSdkLogger,
|
|
4
|
+
enableLogging,
|
|
5
|
+
disableLogging,
|
|
6
|
+
setCustomLogger,
|
|
7
|
+
resetSdkLogger,
|
|
8
|
+
} from "../../lib/sdk-logger.js";
|
|
9
|
+
import { GalileoConfig } from "../../lib/galileo-config.js";
|
|
10
|
+
import type { GalileoSdkLogger } from "../../types/sdk-logger.types.js";
|
|
11
|
+
|
|
12
|
+
const GALILEO_LOG_LEVEL = "GALILEO_LOG_LEVEL";
|
|
13
|
+
|
|
14
|
+
function clearGalileoEnv(): void {
|
|
15
|
+
delete process.env[GALILEO_LOG_LEVEL];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("SdkLogger", () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
// Reset all singletons and environment to ensure clean test state
|
|
21
|
+
GalileoConfig.reset();
|
|
22
|
+
clearGalileoEnv();
|
|
23
|
+
setCustomLogger(undefined);
|
|
24
|
+
resetSdkLogger();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("initialization", () => {
|
|
28
|
+
test("default log level is silent", () => {
|
|
29
|
+
const logger = getSdkLogger();
|
|
30
|
+
// Debug should be silenced by default
|
|
31
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
32
|
+
logger.debug("test message");
|
|
33
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
34
|
+
debugSpy.mockRestore();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("respects GALILEO_LOG_LEVEL environment variable", () => {
|
|
38
|
+
process.env[GALILEO_LOG_LEVEL] = "debug";
|
|
39
|
+
// GalileoConfig requires at least one auth credential to process the config
|
|
40
|
+
process.env["GALILEO_API_KEY"] = "test-key";
|
|
41
|
+
GalileoConfig.reset();
|
|
42
|
+
resetSdkLogger();
|
|
43
|
+
const logger = getSdkLogger();
|
|
44
|
+
|
|
45
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
46
|
+
logger.debug("test message");
|
|
47
|
+
expect(debugSpy).toHaveBeenCalledWith("test message");
|
|
48
|
+
debugSpy.mockRestore();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("normalizes log level to lowercase", () => {
|
|
52
|
+
process.env[GALILEO_LOG_LEVEL] = "DEBUG";
|
|
53
|
+
// GalileoConfig requires at least one auth credential to process the config
|
|
54
|
+
process.env["GALILEO_API_KEY"] = "test-key";
|
|
55
|
+
GalileoConfig.reset();
|
|
56
|
+
resetSdkLogger();
|
|
57
|
+
const logger = getSdkLogger();
|
|
58
|
+
|
|
59
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
60
|
+
logger.debug("test message");
|
|
61
|
+
expect(debugSpy).toHaveBeenCalledWith("test message");
|
|
62
|
+
debugSpy.mockRestore();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("ignores invalid log levels", () => {
|
|
66
|
+
process.env[GALILEO_LOG_LEVEL] = "invalid";
|
|
67
|
+
GalileoConfig.reset();
|
|
68
|
+
resetSdkLogger();
|
|
69
|
+
const logger = getSdkLogger();
|
|
70
|
+
|
|
71
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
72
|
+
logger.debug("test message");
|
|
73
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
74
|
+
debugSpy.mockRestore();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("logging levels", () => {
|
|
79
|
+
test("silent level blocks all logs", () => {
|
|
80
|
+
const logger = getSdkLogger();
|
|
81
|
+
enableLogging("silent");
|
|
82
|
+
|
|
83
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
84
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
85
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
86
|
+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
87
|
+
|
|
88
|
+
logger.debug("debug");
|
|
89
|
+
logger.info("info");
|
|
90
|
+
logger.warn("warn");
|
|
91
|
+
logger.error("error");
|
|
92
|
+
|
|
93
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
94
|
+
expect(infoSpy).not.toHaveBeenCalled();
|
|
95
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
96
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
97
|
+
|
|
98
|
+
debugSpy.mockRestore();
|
|
99
|
+
infoSpy.mockRestore();
|
|
100
|
+
warnSpy.mockRestore();
|
|
101
|
+
errorSpy.mockRestore();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("error level only logs errors", () => {
|
|
105
|
+
const logger = getSdkLogger();
|
|
106
|
+
enableLogging("error");
|
|
107
|
+
|
|
108
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
109
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
110
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
111
|
+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
112
|
+
|
|
113
|
+
logger.debug("debug");
|
|
114
|
+
logger.info("info");
|
|
115
|
+
logger.warn("warn");
|
|
116
|
+
logger.error("error");
|
|
117
|
+
|
|
118
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
119
|
+
expect(infoSpy).not.toHaveBeenCalled();
|
|
120
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
121
|
+
expect(errorSpy).toHaveBeenCalledWith("error");
|
|
122
|
+
|
|
123
|
+
debugSpy.mockRestore();
|
|
124
|
+
infoSpy.mockRestore();
|
|
125
|
+
warnSpy.mockRestore();
|
|
126
|
+
errorSpy.mockRestore();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("warn level logs warn and error", () => {
|
|
130
|
+
const logger = getSdkLogger();
|
|
131
|
+
enableLogging("warn");
|
|
132
|
+
|
|
133
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
134
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
135
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
136
|
+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
137
|
+
|
|
138
|
+
logger.debug("debug");
|
|
139
|
+
logger.info("info");
|
|
140
|
+
logger.warn("warn");
|
|
141
|
+
logger.error("error");
|
|
142
|
+
|
|
143
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
144
|
+
expect(infoSpy).not.toHaveBeenCalled();
|
|
145
|
+
expect(warnSpy).toHaveBeenCalledWith("warn");
|
|
146
|
+
expect(errorSpy).toHaveBeenCalledWith("error");
|
|
147
|
+
|
|
148
|
+
debugSpy.mockRestore();
|
|
149
|
+
infoSpy.mockRestore();
|
|
150
|
+
warnSpy.mockRestore();
|
|
151
|
+
errorSpy.mockRestore();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("info level logs info, warn, and error", () => {
|
|
155
|
+
const logger = getSdkLogger();
|
|
156
|
+
enableLogging("info");
|
|
157
|
+
|
|
158
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
159
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
160
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
161
|
+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
162
|
+
|
|
163
|
+
logger.debug("debug");
|
|
164
|
+
logger.info("info");
|
|
165
|
+
logger.warn("warn");
|
|
166
|
+
logger.error("error");
|
|
167
|
+
|
|
168
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
169
|
+
expect(infoSpy).toHaveBeenCalledWith("info");
|
|
170
|
+
expect(warnSpy).toHaveBeenCalledWith("warn");
|
|
171
|
+
expect(errorSpy).toHaveBeenCalledWith("error");
|
|
172
|
+
|
|
173
|
+
debugSpy.mockRestore();
|
|
174
|
+
infoSpy.mockRestore();
|
|
175
|
+
warnSpy.mockRestore();
|
|
176
|
+
errorSpy.mockRestore();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("debug level logs all messages", () => {
|
|
180
|
+
const logger = getSdkLogger();
|
|
181
|
+
enableLogging("debug");
|
|
182
|
+
|
|
183
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
184
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
185
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
186
|
+
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
187
|
+
|
|
188
|
+
logger.debug("debug");
|
|
189
|
+
logger.info("info");
|
|
190
|
+
logger.warn("warn");
|
|
191
|
+
logger.error("error");
|
|
192
|
+
|
|
193
|
+
expect(debugSpy).toHaveBeenCalledWith("debug");
|
|
194
|
+
expect(infoSpy).toHaveBeenCalledWith("info");
|
|
195
|
+
expect(warnSpy).toHaveBeenCalledWith("warn");
|
|
196
|
+
expect(errorSpy).toHaveBeenCalledWith("error");
|
|
197
|
+
|
|
198
|
+
debugSpy.mockRestore();
|
|
199
|
+
infoSpy.mockRestore();
|
|
200
|
+
warnSpy.mockRestore();
|
|
201
|
+
errorSpy.mockRestore();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe("enableLogging and disableLogging", () => {
|
|
206
|
+
test("enableLogging sets the log level", () => {
|
|
207
|
+
const logger = getSdkLogger();
|
|
208
|
+
enableLogging("debug");
|
|
209
|
+
|
|
210
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
211
|
+
logger.debug("test");
|
|
212
|
+
expect(debugSpy).toHaveBeenCalledWith("test");
|
|
213
|
+
debugSpy.mockRestore();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test("enableLogging defaults to info level", () => {
|
|
217
|
+
const logger = getSdkLogger();
|
|
218
|
+
enableLogging();
|
|
219
|
+
|
|
220
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
221
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
222
|
+
|
|
223
|
+
logger.info("info");
|
|
224
|
+
logger.debug("debug");
|
|
225
|
+
|
|
226
|
+
expect(infoSpy).toHaveBeenCalledWith("info");
|
|
227
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
228
|
+
|
|
229
|
+
infoSpy.mockRestore();
|
|
230
|
+
debugSpy.mockRestore();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("disableLogging silences all output", () => {
|
|
234
|
+
const logger = getSdkLogger();
|
|
235
|
+
enableLogging("debug");
|
|
236
|
+
disableLogging();
|
|
237
|
+
|
|
238
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
239
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
240
|
+
|
|
241
|
+
logger.debug("debug");
|
|
242
|
+
logger.info("info");
|
|
243
|
+
|
|
244
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
245
|
+
expect(infoSpy).not.toHaveBeenCalled();
|
|
246
|
+
|
|
247
|
+
debugSpy.mockRestore();
|
|
248
|
+
infoSpy.mockRestore();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe("custom logger", () => {
|
|
253
|
+
test("routes logs to custom logger when set", () => {
|
|
254
|
+
const logger = getSdkLogger();
|
|
255
|
+
enableLogging("info");
|
|
256
|
+
|
|
257
|
+
const customLogger: GalileoSdkLogger = {
|
|
258
|
+
debug: vi.fn(),
|
|
259
|
+
info: vi.fn(),
|
|
260
|
+
warn: vi.fn(),
|
|
261
|
+
error: vi.fn(),
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
setCustomLogger(customLogger);
|
|
265
|
+
logger.info("test message");
|
|
266
|
+
|
|
267
|
+
expect(customLogger.info).toHaveBeenCalledWith("test message");
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("uses custom logger for all log levels", () => {
|
|
271
|
+
const logger = getSdkLogger();
|
|
272
|
+
enableLogging("debug");
|
|
273
|
+
|
|
274
|
+
const customLogger: GalileoSdkLogger = {
|
|
275
|
+
debug: vi.fn(),
|
|
276
|
+
info: vi.fn(),
|
|
277
|
+
warn: vi.fn(),
|
|
278
|
+
error: vi.fn(),
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
setCustomLogger(customLogger);
|
|
282
|
+
|
|
283
|
+
logger.debug("debug");
|
|
284
|
+
logger.info("info");
|
|
285
|
+
logger.warn("warn");
|
|
286
|
+
logger.error("error");
|
|
287
|
+
|
|
288
|
+
expect(customLogger.debug).toHaveBeenCalledWith("debug");
|
|
289
|
+
expect(customLogger.info).toHaveBeenCalledWith("info");
|
|
290
|
+
expect(customLogger.warn).toHaveBeenCalledWith("warn");
|
|
291
|
+
expect(customLogger.error).toHaveBeenCalledWith("error");
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test("respects log level filtering with custom logger", () => {
|
|
295
|
+
const logger = getSdkLogger();
|
|
296
|
+
enableLogging("warn");
|
|
297
|
+
|
|
298
|
+
const customLogger: GalileoSdkLogger = {
|
|
299
|
+
debug: vi.fn(),
|
|
300
|
+
info: vi.fn(),
|
|
301
|
+
warn: vi.fn(),
|
|
302
|
+
error: vi.fn(),
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
setCustomLogger(customLogger);
|
|
306
|
+
|
|
307
|
+
logger.debug("debug");
|
|
308
|
+
logger.info("info");
|
|
309
|
+
logger.warn("warn");
|
|
310
|
+
logger.error("error");
|
|
311
|
+
|
|
312
|
+
expect(customLogger.debug).not.toHaveBeenCalled();
|
|
313
|
+
expect(customLogger.info).not.toHaveBeenCalled();
|
|
314
|
+
expect(customLogger.warn).toHaveBeenCalledWith("warn");
|
|
315
|
+
expect(customLogger.error).toHaveBeenCalledWith("error");
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("clears custom logger when set to undefined", () => {
|
|
319
|
+
const logger = getSdkLogger();
|
|
320
|
+
enableLogging("info");
|
|
321
|
+
|
|
322
|
+
const customLogger: GalileoSdkLogger = {
|
|
323
|
+
debug: vi.fn(),
|
|
324
|
+
info: vi.fn(),
|
|
325
|
+
warn: vi.fn(),
|
|
326
|
+
error: vi.fn(),
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
setCustomLogger(customLogger);
|
|
330
|
+
logger.info("first");
|
|
331
|
+
expect(customLogger.info).toHaveBeenCalledWith("first");
|
|
332
|
+
|
|
333
|
+
setCustomLogger(undefined);
|
|
334
|
+
|
|
335
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
336
|
+
logger.info("second");
|
|
337
|
+
|
|
338
|
+
expect(infoSpy).toHaveBeenCalledWith("second");
|
|
339
|
+
expect(customLogger.info).toHaveBeenCalledTimes(1);
|
|
340
|
+
|
|
341
|
+
infoSpy.mockRestore();
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
test("falls back to console when custom logger not set", () => {
|
|
345
|
+
const logger = getSdkLogger();
|
|
346
|
+
enableLogging("info");
|
|
347
|
+
|
|
348
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
349
|
+
logger.info("console output");
|
|
350
|
+
|
|
351
|
+
expect(infoSpy).toHaveBeenCalledWith("console output");
|
|
352
|
+
infoSpy.mockRestore();
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
describe("logger with multiple arguments", () => {
|
|
357
|
+
test("passes all arguments to console log", () => {
|
|
358
|
+
const logger = getSdkLogger();
|
|
359
|
+
enableLogging("info");
|
|
360
|
+
|
|
361
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
362
|
+
logger.info("message", { key: "value" }, 123);
|
|
363
|
+
|
|
364
|
+
expect(infoSpy).toHaveBeenCalledWith("message", { key: "value" }, 123);
|
|
365
|
+
infoSpy.mockRestore();
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test("passes all arguments to custom logger", () => {
|
|
369
|
+
const logger = getSdkLogger();
|
|
370
|
+
enableLogging("info");
|
|
371
|
+
|
|
372
|
+
const customLogger: GalileoSdkLogger = {
|
|
373
|
+
debug: vi.fn(),
|
|
374
|
+
info: vi.fn(),
|
|
375
|
+
warn: vi.fn(),
|
|
376
|
+
error: vi.fn(),
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
setCustomLogger(customLogger);
|
|
380
|
+
logger.info("message", { key: "value" }, 123);
|
|
381
|
+
|
|
382
|
+
expect(customLogger.info).toHaveBeenCalledWith(
|
|
383
|
+
"message",
|
|
384
|
+
{ key: "value" },
|
|
385
|
+
123,
|
|
386
|
+
);
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
describe("environment variable integration", () => {
|
|
391
|
+
test("reads log level from GALILEO_LOG_LEVEL env var on startup", () => {
|
|
392
|
+
process.env[GALILEO_LOG_LEVEL] = "info";
|
|
393
|
+
// GalileoConfig requires at least one auth credential to process the config
|
|
394
|
+
process.env["GALILEO_API_KEY"] = "test-key";
|
|
395
|
+
GalileoConfig.reset();
|
|
396
|
+
resetSdkLogger();
|
|
397
|
+
const logger = getSdkLogger();
|
|
398
|
+
|
|
399
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
400
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
401
|
+
|
|
402
|
+
logger.info("info");
|
|
403
|
+
logger.debug("debug");
|
|
404
|
+
|
|
405
|
+
expect(infoSpy).toHaveBeenCalledWith("info");
|
|
406
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
407
|
+
|
|
408
|
+
infoSpy.mockRestore();
|
|
409
|
+
debugSpy.mockRestore();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test("handles mixed case env var value", () => {
|
|
413
|
+
process.env[GALILEO_LOG_LEVEL] = "DeBuG";
|
|
414
|
+
// GalileoConfig requires at least one auth credential to process the config
|
|
415
|
+
process.env["GALILEO_API_KEY"] = "test-key";
|
|
416
|
+
GalileoConfig.reset();
|
|
417
|
+
resetSdkLogger();
|
|
418
|
+
const logger = getSdkLogger();
|
|
419
|
+
|
|
420
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
421
|
+
logger.debug("test");
|
|
422
|
+
|
|
423
|
+
expect(debugSpy).toHaveBeenCalledWith("test");
|
|
424
|
+
debugSpy.mockRestore();
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
test("ignores invalid env var and defaults to silent", () => {
|
|
428
|
+
process.env[GALILEO_LOG_LEVEL] = "notarealevel";
|
|
429
|
+
GalileoConfig.reset();
|
|
430
|
+
resetSdkLogger();
|
|
431
|
+
const logger = getSdkLogger();
|
|
432
|
+
|
|
433
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
434
|
+
logger.debug("test");
|
|
435
|
+
|
|
436
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
437
|
+
debugSpy.mockRestore();
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
test("respects GalileoConfig override", () => {
|
|
441
|
+
GalileoConfig.reset();
|
|
442
|
+
GalileoConfig.get({ logLevel: "debug" });
|
|
443
|
+
resetSdkLogger();
|
|
444
|
+
const logger = getSdkLogger();
|
|
445
|
+
|
|
446
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
447
|
+
logger.debug("test");
|
|
448
|
+
|
|
449
|
+
expect(debugSpy).toHaveBeenCalledWith("test");
|
|
450
|
+
debugSpy.mockRestore();
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
describe("singleton behavior", () => {
|
|
455
|
+
test("getSdkLogger returns the same instance", () => {
|
|
456
|
+
const logger1 = getSdkLogger();
|
|
457
|
+
const logger2 = getSdkLogger();
|
|
458
|
+
expect(logger1).toBe(logger2);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
test("state persists across getSdkLogger calls", () => {
|
|
462
|
+
getSdkLogger();
|
|
463
|
+
enableLogging("debug");
|
|
464
|
+
|
|
465
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
466
|
+
|
|
467
|
+
const logger2 = getSdkLogger();
|
|
468
|
+
logger2.debug("test");
|
|
469
|
+
|
|
470
|
+
expect(debugSpy).toHaveBeenCalledWith("test");
|
|
471
|
+
debugSpy.mockRestore();
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
describe("edge cases", () => {
|
|
476
|
+
test("empty string log message works", () => {
|
|
477
|
+
const logger = getSdkLogger();
|
|
478
|
+
enableLogging("info");
|
|
479
|
+
|
|
480
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
481
|
+
logger.info("");
|
|
482
|
+
|
|
483
|
+
expect(infoSpy).toHaveBeenCalledWith("");
|
|
484
|
+
infoSpy.mockRestore();
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
test("null and undefined in args are passed through", () => {
|
|
488
|
+
const logger = getSdkLogger();
|
|
489
|
+
enableLogging("info");
|
|
490
|
+
|
|
491
|
+
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
|
|
492
|
+
logger.info("message", null, undefined);
|
|
493
|
+
|
|
494
|
+
expect(infoSpy).toHaveBeenCalledWith("message", null, undefined);
|
|
495
|
+
infoSpy.mockRestore();
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
test("changing level multiple times works correctly", () => {
|
|
499
|
+
const logger = getSdkLogger();
|
|
500
|
+
|
|
501
|
+
const debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
502
|
+
|
|
503
|
+
enableLogging("silent");
|
|
504
|
+
logger.debug("1");
|
|
505
|
+
expect(debugSpy).not.toHaveBeenCalled();
|
|
506
|
+
|
|
507
|
+
enableLogging("debug");
|
|
508
|
+
logger.debug("2");
|
|
509
|
+
expect(debugSpy).toHaveBeenCalledWith("2");
|
|
510
|
+
|
|
511
|
+
enableLogging("silent");
|
|
512
|
+
logger.debug("3");
|
|
513
|
+
expect(debugSpy).toHaveBeenCalledTimes(1);
|
|
514
|
+
|
|
515
|
+
debugSpy.mockRestore();
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log level for SDK logging output.
|
|
3
|
+
*
|
|
4
|
+
* - `silent`: Disables all logging
|
|
5
|
+
* - `error`: Only error messages
|
|
6
|
+
* - `warn`: Warnings and errors
|
|
7
|
+
* - `info`: Info, warnings, and errors (default when logging is enabled)
|
|
8
|
+
* - `debug`: All messages including debug information
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Log level priority mapping for filtering log output.
|
|
14
|
+
*
|
|
15
|
+
* Higher numbers indicate more verbose output. Used internally
|
|
16
|
+
* to determine which messages should be logged based on the current level.
|
|
17
|
+
*/
|
|
18
|
+
export const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
19
|
+
silent: -1,
|
|
20
|
+
error: 0,
|
|
21
|
+
warn: 1,
|
|
22
|
+
info: 2,
|
|
23
|
+
debug: 3,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Logger interface for SDK logging output.
|
|
28
|
+
*
|
|
29
|
+
* Used as:
|
|
30
|
+
* - The public contract for getSdkLogger() (what callers use for logging)
|
|
31
|
+
* - The interface that custom loggers must implement for setCustomLogger()
|
|
32
|
+
*
|
|
33
|
+
* Implement this interface to integrate SDK logging with custom loggers
|
|
34
|
+
* (e.g., Winston, Pino, or other structured logging libraries).
|
|
35
|
+
* Pass an implementation to setCustomLogger() to use it instead of console.
|
|
36
|
+
*/
|
|
37
|
+
export interface GalileoSdkLogger {
|
|
38
|
+
debug: (message: string, ...args: unknown[]) => void;
|
|
39
|
+
info: (message: string, ...args: unknown[]) => void;
|
|
40
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
41
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
42
|
+
}
|
|
43
|
+
|