@illuma-ai/observability-core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/__tests__/core-client.test.d.ts +8 -0
  2. package/dist/__tests__/core-client.test.d.ts.map +1 -0
  3. package/dist/__tests__/core-client.test.js +844 -0
  4. package/dist/__tests__/core-client.test.js.map +1 -0
  5. package/dist/__tests__/generation-client.test.d.ts +8 -0
  6. package/dist/__tests__/generation-client.test.d.ts.map +1 -0
  7. package/dist/__tests__/generation-client.test.js +117 -0
  8. package/dist/__tests__/generation-client.test.js.map +1 -0
  9. package/dist/__tests__/span-client.test.d.ts +9 -0
  10. package/dist/__tests__/span-client.test.d.ts.map +1 -0
  11. package/dist/__tests__/span-client.test.js +272 -0
  12. package/dist/__tests__/span-client.test.js.map +1 -0
  13. package/dist/__tests__/trace-client.test.d.ts +9 -0
  14. package/dist/__tests__/trace-client.test.d.ts.map +1 -0
  15. package/dist/__tests__/trace-client.test.js +260 -0
  16. package/dist/__tests__/trace-client.test.js.map +1 -0
  17. package/dist/__tests__/types.test.d.ts +9 -0
  18. package/dist/__tests__/types.test.d.ts.map +1 -0
  19. package/dist/__tests__/types.test.js +453 -0
  20. package/dist/__tests__/types.test.js.map +1 -0
  21. package/dist/__tests__/utils.test.d.ts +7 -0
  22. package/dist/__tests__/utils.test.d.ts.map +1 -0
  23. package/dist/__tests__/utils.test.js +164 -0
  24. package/dist/__tests__/utils.test.js.map +1 -0
  25. package/dist/core-client.d.ts +1 -0
  26. package/dist/core-client.d.ts.map +1 -1
  27. package/dist/core-client.js +4 -0
  28. package/dist/core-client.js.map +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/span-client.d.ts +28 -0
  34. package/dist/span-client.d.ts.map +1 -1
  35. package/dist/span-client.js +92 -0
  36. package/dist/span-client.js.map +1 -1
  37. package/dist/trace-client.d.ts +35 -0
  38. package/dist/trace-client.d.ts.map +1 -1
  39. package/dist/trace-client.js +110 -0
  40. package/dist/trace-client.js.map +1 -1
  41. package/dist/types.d.ts +109 -7
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js +40 -2
  44. package/dist/types.js.map +1 -1
  45. package/package.json +5 -2
@@ -0,0 +1,453 @@
1
+ /**
2
+ * Unit tests for the observability type system.
3
+ *
4
+ * Validates enum values, ingestion event type constants, and structural
5
+ * compatibility of all parameter interfaces (TraceParams, GenerationParams,
6
+ * SpanParams, ScoreParams, ErrorInfo, etc.).
7
+ */
8
+ import { describe, it, expect } from 'vitest';
9
+ import { ObservationType, ObservationLevel, IngestionEventType, } from '../index.js';
10
+ // ---------------------------------------------------------------------------
11
+ // ObservationType enum
12
+ // ---------------------------------------------------------------------------
13
+ describe('ObservationType', () => {
14
+ it('should have exactly 10 values', () => {
15
+ const values = Object.values(ObservationType);
16
+ expect(values).toHaveLength(10);
17
+ });
18
+ it.each([
19
+ ['SPAN', 'SPAN'],
20
+ ['GENERATION', 'GENERATION'],
21
+ ['EVENT', 'EVENT'],
22
+ ['AGENT', 'AGENT'],
23
+ ['TOOL', 'TOOL'],
24
+ ['CHAIN', 'CHAIN'],
25
+ ['RETRIEVER', 'RETRIEVER'],
26
+ ['EVALUATOR', 'EVALUATOR'],
27
+ ['EMBEDDING', 'EMBEDDING'],
28
+ ['GUARDRAIL', 'GUARDRAIL'],
29
+ ])('should have %s = "%s"', (key, expected) => {
30
+ expect(ObservationType[key]).toBe(expected);
31
+ });
32
+ it('should use string values matching the key names', () => {
33
+ // All values should equal their keys (uppercase pattern)
34
+ for (const [key, value] of Object.entries(ObservationType)) {
35
+ expect(value).toBe(key);
36
+ }
37
+ });
38
+ });
39
+ // ---------------------------------------------------------------------------
40
+ // ObservationLevel enum
41
+ // ---------------------------------------------------------------------------
42
+ describe('ObservationLevel', () => {
43
+ it('should have exactly 4 values', () => {
44
+ const values = Object.values(ObservationLevel);
45
+ expect(values).toHaveLength(4);
46
+ });
47
+ it.each([
48
+ ['DEBUG', 'DEBUG'],
49
+ ['DEFAULT', 'DEFAULT'],
50
+ ['WARNING', 'WARNING'],
51
+ ['ERROR', 'ERROR'],
52
+ ])('should have %s = "%s"', (key, expected) => {
53
+ expect(ObservationLevel[key]).toBe(expected);
54
+ });
55
+ });
56
+ // ---------------------------------------------------------------------------
57
+ // IngestionEventType constants
58
+ // ---------------------------------------------------------------------------
59
+ describe('IngestionEventType', () => {
60
+ it('should have all core event types', () => {
61
+ expect(IngestionEventType.TRACE_CREATE).toBe('trace-create');
62
+ expect(IngestionEventType.SPAN_CREATE).toBe('span-create');
63
+ expect(IngestionEventType.SPAN_UPDATE).toBe('span-update');
64
+ expect(IngestionEventType.GENERATION_CREATE).toBe('generation-create');
65
+ expect(IngestionEventType.GENERATION_UPDATE).toBe('generation-update');
66
+ expect(IngestionEventType.EVENT_CREATE).toBe('event-create');
67
+ expect(IngestionEventType.SCORE_CREATE).toBe('score-create');
68
+ expect(IngestionEventType.SDK_LOG).toBe('sdk-log');
69
+ });
70
+ it('should have all new typed observation event types', () => {
71
+ expect(IngestionEventType.AGENT_CREATE).toBe('agent-create');
72
+ expect(IngestionEventType.TOOL_CREATE).toBe('tool-create');
73
+ expect(IngestionEventType.CHAIN_CREATE).toBe('chain-create');
74
+ expect(IngestionEventType.RETRIEVER_CREATE).toBe('retriever-create');
75
+ expect(IngestionEventType.EVALUATOR_CREATE).toBe('evaluator-create');
76
+ expect(IngestionEventType.EMBEDDING_CREATE).toBe('embedding-create');
77
+ expect(IngestionEventType.GUARDRAIL_CREATE).toBe('guardrail-create');
78
+ });
79
+ it('should have the dataset-run-item-create event type', () => {
80
+ expect(IngestionEventType.DATASET_RUN_ITEM_CREATE).toBe('dataset-run-item-create');
81
+ });
82
+ it('should have exactly 16 event type constants', () => {
83
+ const keys = Object.keys(IngestionEventType);
84
+ expect(keys).toHaveLength(16);
85
+ });
86
+ it('should use kebab-case string values', () => {
87
+ for (const value of Object.values(IngestionEventType)) {
88
+ expect(value).toMatch(/^[a-z]+-[a-z]+(-[a-z]+)*$/);
89
+ }
90
+ });
91
+ });
92
+ // ---------------------------------------------------------------------------
93
+ // ErrorInfo interface
94
+ // ---------------------------------------------------------------------------
95
+ describe('ErrorInfo', () => {
96
+ it('should accept required fields (exceptionType, traceback)', () => {
97
+ const error = {
98
+ exceptionType: 'ValueError',
99
+ traceback: 'Traceback (most recent call last):\n File "main.py", line 42',
100
+ };
101
+ expect(error.exceptionType).toBe('ValueError');
102
+ expect(error.traceback).toContain('Traceback');
103
+ });
104
+ it('should accept the optional message field', () => {
105
+ const error = {
106
+ exceptionType: 'TypeError',
107
+ message: 'cannot read property of undefined',
108
+ traceback: 'at Object.<anonymous> (index.js:1:1)',
109
+ };
110
+ expect(error.message).toBe('cannot read property of undefined');
111
+ });
112
+ it('should not require message', () => {
113
+ const error = {
114
+ exceptionType: 'RuntimeError',
115
+ traceback: 'stack trace here',
116
+ };
117
+ expect(error.message).toBeUndefined();
118
+ });
119
+ });
120
+ // ---------------------------------------------------------------------------
121
+ // TraceParams type compatibility
122
+ // ---------------------------------------------------------------------------
123
+ describe('TraceParams', () => {
124
+ it('should accept all base fields', () => {
125
+ const params = {
126
+ id: 'trace-1',
127
+ name: 'my-trace',
128
+ userId: 'user-1',
129
+ sessionId: 'session-1',
130
+ input: { prompt: 'hello' },
131
+ output: { response: 'world' },
132
+ metadata: { key: 'value' },
133
+ tags: ['tag1', 'tag2'],
134
+ public: true,
135
+ version: '1.0.0',
136
+ timestamp: '2024-01-01T00:00:00.000Z',
137
+ };
138
+ expect(params.name).toBe('my-trace');
139
+ expect(params.tags).toHaveLength(2);
140
+ });
141
+ it('should accept the new release field', () => {
142
+ const params = { release: 'v2.3.1' };
143
+ expect(params.release).toBe('v2.3.1');
144
+ });
145
+ it('should accept the new environment field', () => {
146
+ const params = { environment: 'production' };
147
+ expect(params.environment).toBe('production');
148
+ });
149
+ it('should accept the new externalId field', () => {
150
+ const params = { externalId: 'ext-abc-123' };
151
+ expect(params.externalId).toBe('ext-abc-123');
152
+ });
153
+ it('should accept the new threadId field', () => {
154
+ const params = { threadId: 'thread-conv-456' };
155
+ expect(params.threadId).toBe('thread-conv-456');
156
+ });
157
+ it('should accept the new errorInfo field', () => {
158
+ const params = {
159
+ errorInfo: {
160
+ exceptionType: 'TimeoutError',
161
+ message: 'Request timed out',
162
+ traceback: 'at Timer.setTimeout (node:internal/timers:1:1)',
163
+ },
164
+ };
165
+ expect(params.errorInfo).toBeDefined();
166
+ expect(params.errorInfo.exceptionType).toBe('TimeoutError');
167
+ expect(params.errorInfo.message).toBe('Request timed out');
168
+ expect(params.errorInfo.traceback).toContain('Timer');
169
+ });
170
+ it('should accept all new fields together', () => {
171
+ const params = {
172
+ name: 'full-trace',
173
+ release: 'abc123',
174
+ environment: 'staging',
175
+ externalId: 'jira-PROJ-999',
176
+ threadId: 'thread-multi-turn',
177
+ errorInfo: {
178
+ exceptionType: 'Error',
179
+ traceback: 'stack',
180
+ },
181
+ };
182
+ expect(params.release).toBe('abc123');
183
+ expect(params.environment).toBe('staging');
184
+ expect(params.externalId).toBe('jira-PROJ-999');
185
+ expect(params.threadId).toBe('thread-multi-turn');
186
+ expect(params.errorInfo).toBeDefined();
187
+ });
188
+ });
189
+ // ---------------------------------------------------------------------------
190
+ // GenerationParams type compatibility
191
+ // ---------------------------------------------------------------------------
192
+ describe('GenerationParams', () => {
193
+ it('should accept the provider field', () => {
194
+ const params = {
195
+ model: 'gpt-4o',
196
+ provider: 'openai',
197
+ };
198
+ expect(params.provider).toBe('openai');
199
+ });
200
+ it('should accept the costDetails field', () => {
201
+ const params = {
202
+ costDetails: { input: 0.015, output: 0.06, cached: 0.0075 },
203
+ };
204
+ expect(params.costDetails.input).toBe(0.015);
205
+ expect(params.costDetails.cached).toBe(0.0075);
206
+ });
207
+ it('should accept the usageDetails field', () => {
208
+ const params = {
209
+ usageDetails: { cachedTokens: 200, audioTokens: 50, reasoningTokens: 1024 },
210
+ };
211
+ expect(params.usageDetails.cachedTokens).toBe(200);
212
+ expect(params.usageDetails.reasoningTokens).toBe(1024);
213
+ });
214
+ it('should accept the errorInfo field', () => {
215
+ const params = {
216
+ errorInfo: {
217
+ exceptionType: 'RateLimitError',
218
+ message: '429 Too Many Requests',
219
+ traceback: 'at OpenAI.request (openai.js:100:1)',
220
+ },
221
+ };
222
+ expect(params.errorInfo.exceptionType).toBe('RateLimitError');
223
+ });
224
+ it('should accept the environment field', () => {
225
+ const params = { environment: 'development' };
226
+ expect(params.environment).toBe('development');
227
+ });
228
+ it('should accept all generation-specific fields together', () => {
229
+ const params = {
230
+ id: 'gen-1',
231
+ name: 'completion',
232
+ model: 'claude-sonnet-4-20250514',
233
+ provider: 'anthropic',
234
+ input: [{ role: 'user', content: 'Hi' }],
235
+ output: { role: 'assistant', content: 'Hello!' },
236
+ usage: { input: 10, output: 5, total: 15, unit: 'TOKENS' },
237
+ usageDetails: { cachedTokens: 3 },
238
+ costDetails: { input: 0.01, output: 0.02 },
239
+ environment: 'production',
240
+ errorInfo: {
241
+ exceptionType: 'None',
242
+ traceback: '',
243
+ },
244
+ level: ObservationLevel.DEFAULT,
245
+ promptName: 'chat-prompt',
246
+ promptVersion: 2,
247
+ modelParameters: { temperature: 0.7 },
248
+ };
249
+ expect(params.provider).toBe('anthropic');
250
+ expect(params.usageDetails.cachedTokens).toBe(3);
251
+ expect(params.costDetails.input).toBe(0.01);
252
+ });
253
+ });
254
+ // ---------------------------------------------------------------------------
255
+ // SpanParams type compatibility
256
+ // ---------------------------------------------------------------------------
257
+ describe('SpanParams', () => {
258
+ it('should accept the type field with ObservationType values', () => {
259
+ const agentSpan = {
260
+ name: 'agent-run',
261
+ type: ObservationType.AGENT,
262
+ };
263
+ expect(agentSpan.type).toBe('AGENT');
264
+ const toolSpan = {
265
+ name: 'tool-call',
266
+ type: ObservationType.TOOL,
267
+ };
268
+ expect(toolSpan.type).toBe('TOOL');
269
+ });
270
+ it('should accept all ObservationType values for the type field', () => {
271
+ const allTypes = Object.values(ObservationType);
272
+ for (const obsType of allTypes) {
273
+ const params = { type: obsType };
274
+ expect(params.type).toBe(obsType);
275
+ }
276
+ });
277
+ it('should accept the model field', () => {
278
+ const params = { model: 'gpt-4o-mini' };
279
+ expect(params.model).toBe('gpt-4o-mini');
280
+ });
281
+ it('should accept the provider field', () => {
282
+ const params = { provider: 'aws_bedrock' };
283
+ expect(params.provider).toBe('aws_bedrock');
284
+ });
285
+ it('should accept the usage field', () => {
286
+ const params = {
287
+ usage: { input: 100, output: 50, total: 150, unit: 'TOKENS' },
288
+ };
289
+ expect(params.usage.total).toBe(150);
290
+ });
291
+ it('should accept the environment field', () => {
292
+ const params = { environment: 'staging' };
293
+ expect(params.environment).toBe('staging');
294
+ });
295
+ it('should accept the errorInfo field', () => {
296
+ const params = {
297
+ errorInfo: {
298
+ exceptionType: 'ConnectionError',
299
+ message: 'Vector DB unreachable',
300
+ traceback: 'at Retriever.search (retriever.ts:55:3)',
301
+ },
302
+ };
303
+ expect(params.errorInfo.exceptionType).toBe('ConnectionError');
304
+ });
305
+ it('should accept all new fields together for a retriever span', () => {
306
+ const params = {
307
+ name: 'vector-search',
308
+ type: ObservationType.RETRIEVER,
309
+ model: 'text-embedding-3-small',
310
+ provider: 'openai',
311
+ usage: { input: 50, total: 50 },
312
+ environment: 'production',
313
+ errorInfo: {
314
+ exceptionType: 'None',
315
+ traceback: '',
316
+ },
317
+ };
318
+ expect(params.type).toBe('RETRIEVER');
319
+ expect(params.model).toBe('text-embedding-3-small');
320
+ expect(params.provider).toBe('openai');
321
+ });
322
+ });
323
+ // ---------------------------------------------------------------------------
324
+ // ScoreParams type compatibility
325
+ // ---------------------------------------------------------------------------
326
+ describe('ScoreParams', () => {
327
+ it('should require traceId, name, and value', () => {
328
+ const params = {
329
+ traceId: 'trace-1',
330
+ name: 'accuracy',
331
+ value: 0.95,
332
+ };
333
+ expect(params.traceId).toBe('trace-1');
334
+ expect(params.name).toBe('accuracy');
335
+ expect(params.value).toBe(0.95);
336
+ });
337
+ describe('dataType', () => {
338
+ it.each(['NUMERIC', 'BOOLEAN', 'CATEGORICAL', 'CORRECTION'])('should accept dataType = "%s"', (dataType) => {
339
+ const params = {
340
+ traceId: 'trace-1',
341
+ name: 'metric',
342
+ value: 1,
343
+ dataType,
344
+ };
345
+ expect(params.dataType).toBe(dataType);
346
+ });
347
+ });
348
+ describe('source', () => {
349
+ it.each(['API', 'EVAL', 'ANNOTATION'])('should accept source = "%s"', (source) => {
350
+ const params = {
351
+ traceId: 'trace-1',
352
+ name: 'metric',
353
+ value: 1,
354
+ source,
355
+ };
356
+ expect(params.source).toBe(source);
357
+ });
358
+ });
359
+ it('should accept the metadata field', () => {
360
+ const params = {
361
+ traceId: 'trace-1',
362
+ name: 'quality',
363
+ value: 0.8,
364
+ metadata: { evaluatorVersion: '2.0', runId: 'eval-run-42' },
365
+ };
366
+ expect(params.metadata.evaluatorVersion).toBe('2.0');
367
+ });
368
+ it('should accept the sessionId field', () => {
369
+ const params = {
370
+ traceId: 'trace-1',
371
+ name: 'session-quality',
372
+ value: 4,
373
+ sessionId: 'session-abc',
374
+ };
375
+ expect(params.sessionId).toBe('session-abc');
376
+ });
377
+ it('should accept the stringValue field', () => {
378
+ const params = {
379
+ traceId: 'trace-1',
380
+ name: 'sentiment',
381
+ value: 1,
382
+ dataType: 'CATEGORICAL',
383
+ stringValue: 'positive',
384
+ };
385
+ expect(params.stringValue).toBe('positive');
386
+ });
387
+ it('should accept the environment field', () => {
388
+ const params = {
389
+ traceId: 'trace-1',
390
+ name: 'metric',
391
+ value: 1,
392
+ environment: 'production',
393
+ };
394
+ expect(params.environment).toBe('production');
395
+ });
396
+ it('should accept all optional fields together', () => {
397
+ const params = {
398
+ id: 'score-1',
399
+ traceId: 'trace-1',
400
+ observationId: 'gen-1',
401
+ sessionId: 'session-1',
402
+ name: 'comprehensive-score',
403
+ value: 0.75,
404
+ stringValue: 'good',
405
+ comment: 'Mostly correct but missed edge case',
406
+ dataType: 'CATEGORICAL',
407
+ source: 'ANNOTATION',
408
+ metadata: { annotatorId: 'user-5', round: 2 },
409
+ configId: 'config-abc',
410
+ environment: 'staging',
411
+ };
412
+ expect(params.dataType).toBe('CATEGORICAL');
413
+ expect(params.source).toBe('ANNOTATION');
414
+ expect(params.stringValue).toBe('good');
415
+ expect(params.metadata.round).toBe(2);
416
+ });
417
+ });
418
+ // ---------------------------------------------------------------------------
419
+ // UsageParams and UsageDetailsParams
420
+ // ---------------------------------------------------------------------------
421
+ describe('UsageParams', () => {
422
+ it('should accept all standard usage fields', () => {
423
+ const usage = {
424
+ input: 100,
425
+ output: 50,
426
+ total: 150,
427
+ unit: 'TOKENS',
428
+ inputCost: 0.01,
429
+ outputCost: 0.02,
430
+ totalCost: 0.03,
431
+ };
432
+ expect(usage.total).toBe(150);
433
+ expect(usage.totalCost).toBe(0.03);
434
+ });
435
+ it('should allow partial usage (all fields optional)', () => {
436
+ const usage = { total: 42 };
437
+ expect(usage.total).toBe(42);
438
+ expect(usage.input).toBeUndefined();
439
+ });
440
+ });
441
+ describe('UsageDetailsParams', () => {
442
+ it('should accept arbitrary string keys with numeric values', () => {
443
+ const details = {
444
+ cachedTokens: 200,
445
+ audioTokens: 50,
446
+ reasoningTokens: 1024,
447
+ imageTokens: 0,
448
+ };
449
+ expect(details.cachedTokens).toBe(200);
450
+ expect(Object.keys(details)).toHaveLength(4);
451
+ });
452
+ });
453
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Unit tests for observability SDK utility functions.
3
+ *
4
+ * Covers: generateId, currentISOTimestamp, safeStringify, encodeBasicAuth, backoffDelay.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Unit tests for observability SDK utility functions.
3
+ *
4
+ * Covers: generateId, currentISOTimestamp, safeStringify, encodeBasicAuth, backoffDelay.
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ import { generateId, currentISOTimestamp, safeStringify, encodeBasicAuth, backoffDelay, } from '../utils.js';
8
+ // ---------------------------------------------------------------------------
9
+ // generateId
10
+ // ---------------------------------------------------------------------------
11
+ describe('generateId', () => {
12
+ it('should return a string', () => {
13
+ expect(typeof generateId()).toBe('string');
14
+ });
15
+ it('should return unique values on consecutive calls', () => {
16
+ const ids = new Set(Array.from({ length: 100 }, () => generateId()));
17
+ expect(ids.size).toBe(100);
18
+ });
19
+ it('should return a valid UUID format', () => {
20
+ const id = generateId();
21
+ // Standard UUID v4 pattern: 8-4-4-4-12 hex chars
22
+ expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
23
+ });
24
+ });
25
+ // ---------------------------------------------------------------------------
26
+ // currentISOTimestamp
27
+ // ---------------------------------------------------------------------------
28
+ describe('currentISOTimestamp', () => {
29
+ it('should return a valid ISO-8601 string', () => {
30
+ const ts = currentISOTimestamp();
31
+ // ISO format: YYYY-MM-DDTHH:MM:SS.sssZ
32
+ expect(ts).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
33
+ });
34
+ it('should return the current time', () => {
35
+ const before = Date.now();
36
+ const ts = currentISOTimestamp();
37
+ const after = Date.now();
38
+ const parsed = new Date(ts).getTime();
39
+ expect(parsed).toBeGreaterThanOrEqual(before);
40
+ expect(parsed).toBeLessThanOrEqual(after);
41
+ });
42
+ it('should return a parseable Date string', () => {
43
+ const ts = currentISOTimestamp();
44
+ const date = new Date(ts);
45
+ expect(date.toISOString()).toBe(ts);
46
+ });
47
+ });
48
+ // ---------------------------------------------------------------------------
49
+ // safeStringify
50
+ // ---------------------------------------------------------------------------
51
+ describe('safeStringify', () => {
52
+ it('should stringify plain objects', () => {
53
+ const result = safeStringify({ a: 1, b: 'two' });
54
+ expect(JSON.parse(result)).toEqual({ a: 1, b: 'two' });
55
+ });
56
+ it('should handle circular references without throwing', () => {
57
+ const obj = { name: 'root' };
58
+ obj.self = obj;
59
+ const result = safeStringify(obj);
60
+ expect(result).toContain('"name":"root"');
61
+ expect(result).toContain('[Circular]');
62
+ });
63
+ it('should handle nested circular references', () => {
64
+ const a = { label: 'a' };
65
+ const b = { label: 'b', parent: a };
66
+ a.child = b;
67
+ b.grandchild = a; // circular back to a
68
+ const result = safeStringify(a);
69
+ expect(result).toContain('[Circular]');
70
+ expect(result).toContain('"label":"a"');
71
+ });
72
+ it('should handle BigInt values by converting to string', () => {
73
+ const result = safeStringify({ big: BigInt(9007199254740991) });
74
+ const parsed = JSON.parse(result);
75
+ expect(parsed.big).toBe('9007199254740991');
76
+ });
77
+ it('should handle null and undefined', () => {
78
+ expect(safeStringify(null)).toBe('null');
79
+ // undefined at top level is converted via String()
80
+ expect(safeStringify(undefined)).toBe(undefined);
81
+ });
82
+ it('should support indent parameter', () => {
83
+ const result = safeStringify({ a: 1 }, 2);
84
+ expect(result).toContain('\n');
85
+ expect(result).toContain(' ');
86
+ });
87
+ it('should stringify arrays', () => {
88
+ const result = safeStringify([1, 2, 3]);
89
+ expect(JSON.parse(result)).toEqual([1, 2, 3]);
90
+ });
91
+ it('should stringify nested objects', () => {
92
+ const result = safeStringify({ a: { b: { c: 42 } } });
93
+ expect(JSON.parse(result)).toEqual({ a: { b: { c: 42 } } });
94
+ });
95
+ });
96
+ // ---------------------------------------------------------------------------
97
+ // encodeBasicAuth
98
+ // ---------------------------------------------------------------------------
99
+ describe('encodeBasicAuth', () => {
100
+ it('should produce a Basic auth header string', () => {
101
+ const result = encodeBasicAuth('public', 'secret');
102
+ expect(result).toMatch(/^Basic .+$/);
103
+ });
104
+ it('should encode credentials as base64', () => {
105
+ const result = encodeBasicAuth('pk-abc', 'sk-xyz');
106
+ const expected = `Basic ${Buffer.from('pk-abc:sk-xyz').toString('base64')}`;
107
+ expect(result).toBe(expected);
108
+ });
109
+ it('should handle special characters in keys', () => {
110
+ const result = encodeBasicAuth('pk+special/key=', 'sk:pass@word!');
111
+ const expected = `Basic ${Buffer.from('pk+special/key=:sk:pass@word!').toString('base64')}`;
112
+ expect(result).toBe(expected);
113
+ });
114
+ it('should handle empty strings', () => {
115
+ const result = encodeBasicAuth('', '');
116
+ const expected = `Basic ${Buffer.from(':').toString('base64')}`;
117
+ expect(result).toBe(expected);
118
+ });
119
+ });
120
+ // ---------------------------------------------------------------------------
121
+ // backoffDelay
122
+ // ---------------------------------------------------------------------------
123
+ describe('backoffDelay', () => {
124
+ it('should return a number', () => {
125
+ expect(typeof backoffDelay(0)).toBe('number');
126
+ });
127
+ it('should increase with attempt number on average', () => {
128
+ // Run many samples to account for jitter
129
+ const samples = 50;
130
+ const avgAttempt0 = Array.from({ length: samples }, () => backoffDelay(0)).reduce((a, b) => a + b, 0) / samples;
131
+ const avgAttempt3 = Array.from({ length: samples }, () => backoffDelay(3)).reduce((a, b) => a + b, 0) / samples;
132
+ expect(avgAttempt3).toBeGreaterThan(avgAttempt0);
133
+ });
134
+ it('should respect the 30 second cap', () => {
135
+ // Very high attempt number should still be capped
136
+ for (let i = 0; i < 20; i++) {
137
+ const delay = backoffDelay(20);
138
+ expect(delay).toBeLessThanOrEqual(30_000);
139
+ }
140
+ });
141
+ it('should use exponential growth (base * 2^attempt)', () => {
142
+ // With jitter of up to 25%, the delay should be between base*2^n and base*2^n*1.25
143
+ const baseMs = 1000;
144
+ for (let attempt = 0; attempt < 4; attempt++) {
145
+ const exponential = baseMs * Math.pow(2, attempt);
146
+ const delay = backoffDelay(attempt, baseMs);
147
+ expect(delay).toBeGreaterThanOrEqual(exponential);
148
+ expect(delay).toBeLessThanOrEqual(exponential * 1.25);
149
+ }
150
+ });
151
+ it('should accept a custom base delay', () => {
152
+ const delay = backoffDelay(0, 500);
153
+ // Attempt 0 with base 500: 500 + jitter (up to 125)
154
+ expect(delay).toBeGreaterThanOrEqual(500);
155
+ expect(delay).toBeLessThanOrEqual(625);
156
+ });
157
+ it('should add jitter (non-deterministic within range)', () => {
158
+ // Two calls with the same attempt should very likely produce different values
159
+ // (only fails with probability ~1/2^52)
160
+ const delays = new Set(Array.from({ length: 10 }, () => backoffDelay(2)));
161
+ expect(delays.size).toBeGreaterThan(1);
162
+ });
163
+ });
164
+ //# sourceMappingURL=utils.test.js.map