galileo-generated 0.2.10 → 0.2.12

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/commonjs/hooks/sdk-identifier.js +3 -3
  3. package/dist/commonjs/hooks/sdk-identifier.js.map +1 -1
  4. package/dist/commonjs/lib/config.d.ts.map +1 -1
  5. package/dist/commonjs/lib/config.js +5 -3
  6. package/dist/commonjs/lib/config.js.map +1 -1
  7. package/dist/commonjs/lib/galileo-config.d.ts +11 -2
  8. package/dist/commonjs/lib/galileo-config.d.ts.map +1 -1
  9. package/dist/commonjs/lib/galileo-config.js +24 -5
  10. package/dist/commonjs/lib/galileo-config.js.map +1 -1
  11. package/dist/commonjs/models/errors/responsevalidationerror.d.ts +2 -2
  12. package/dist/commonjs/models/errors/responsevalidationerror.d.ts.map +1 -1
  13. package/dist/commonjs/models/errors/responsevalidationerror.js +9 -9
  14. package/dist/commonjs/models/errors/responsevalidationerror.js.map +1 -1
  15. package/dist/commonjs/models/errors/sdkvalidationerror.d.ts +2 -2
  16. package/dist/commonjs/models/errors/sdkvalidationerror.d.ts.map +1 -1
  17. package/dist/commonjs/models/errors/sdkvalidationerror.js +18 -10
  18. package/dist/commonjs/models/errors/sdkvalidationerror.js.map +1 -1
  19. package/dist/commonjs/tests/integration/env-auth-ingestion.test.d.ts +2 -0
  20. package/dist/commonjs/tests/integration/env-auth-ingestion.test.d.ts.map +1 -0
  21. package/dist/commonjs/tests/integration/env-auth-ingestion.test.js +185 -0
  22. package/dist/commonjs/tests/integration/env-auth-ingestion.test.js.map +1 -0
  23. package/dist/esm/hooks/sdk-identifier.js +3 -3
  24. package/dist/esm/hooks/sdk-identifier.js.map +1 -1
  25. package/dist/esm/lib/config.d.ts.map +1 -1
  26. package/dist/esm/lib/config.js +5 -3
  27. package/dist/esm/lib/config.js.map +1 -1
  28. package/dist/esm/lib/galileo-config.d.ts +11 -2
  29. package/dist/esm/lib/galileo-config.d.ts.map +1 -1
  30. package/dist/esm/lib/galileo-config.js +24 -5
  31. package/dist/esm/lib/galileo-config.js.map +1 -1
  32. package/dist/esm/models/errors/responsevalidationerror.d.ts +2 -2
  33. package/dist/esm/models/errors/responsevalidationerror.d.ts.map +1 -1
  34. package/dist/esm/models/errors/responsevalidationerror.js +9 -9
  35. package/dist/esm/models/errors/responsevalidationerror.js.map +1 -1
  36. package/dist/esm/models/errors/sdkvalidationerror.d.ts +2 -2
  37. package/dist/esm/models/errors/sdkvalidationerror.d.ts.map +1 -1
  38. package/dist/esm/models/errors/sdkvalidationerror.js +18 -10
  39. package/dist/esm/models/errors/sdkvalidationerror.js.map +1 -1
  40. package/dist/esm/tests/integration/env-auth-ingestion.test.d.ts +2 -0
  41. package/dist/esm/tests/integration/env-auth-ingestion.test.d.ts.map +1 -0
  42. package/dist/esm/tests/integration/env-auth-ingestion.test.js +183 -0
  43. package/dist/esm/tests/integration/env-auth-ingestion.test.js.map +1 -0
  44. package/package.json +1 -1
  45. package/src/hooks/sdk-identifier.ts +3 -3
  46. package/src/lib/config.ts +6 -4
  47. package/src/lib/galileo-config.ts +26 -5
  48. package/src/models/errors/responsevalidationerror.ts +14 -10
  49. package/src/models/errors/sdkvalidationerror.ts +20 -11
  50. package/src/tests/integration/env-auth-ingestion.test.ts +254 -0
@@ -0,0 +1,254 @@
1
+ import { http, HttpResponse } from 'msw';
2
+ import { setupServer } from 'msw/node';
3
+ import { describe, test, expect, beforeAll, afterAll, afterEach, beforeEach } from 'vitest';
4
+ import { GalileoConfig } from '../../lib/galileo-config.js';
5
+ import { BaseEntity } from '../../entities/base-entity.js';
6
+ import { GalileoGenerated } from '../../sdk/sdk.js';
7
+
8
+ const TEST_HOST = 'http://localhost:8088';
9
+ const MOCK_API_KEY = 'test-api-key-for-env-auth';
10
+ const MOCK_ACCESS_TOKEN = 'mock-access-token-from-login';
11
+ const MOCK_PROJECT_ID = 'proj-00000000-0000-0000-0000-000000000001';
12
+
13
+ /**
14
+ * Captured request data from MSW handlers, used to assert that env vars
15
+ * propagate correctly through the auth and hook chain.
16
+ */
17
+ let capturedLoginBody: { api_key?: string } | null = null;
18
+ let capturedTraceHeaders: Record<string, string> = {};
19
+ let capturedTraceBody: Record<string, unknown> | null = null;
20
+
21
+ const loginApiKeyHandler = http.post(
22
+ `${TEST_HOST}/login/api_key`,
23
+ async ({ request }) => {
24
+ capturedLoginBody = (await request.json()) as { api_key?: string };
25
+ if (capturedLoginBody?.['api_key'] !== MOCK_API_KEY) {
26
+ return HttpResponse.json(
27
+ { detail: 'Invalid API key' },
28
+ { status: 401 },
29
+ );
30
+ }
31
+ return HttpResponse.json({
32
+ access_token: MOCK_ACCESS_TOKEN,
33
+ token_type: 'bearer',
34
+ });
35
+ },
36
+ );
37
+
38
+ const traceIngestionHandler = http.post(
39
+ `${TEST_HOST}/projects/${MOCK_PROJECT_ID}/traces`,
40
+ async ({ request }) => {
41
+ capturedTraceHeaders = Object.fromEntries(request.headers.entries());
42
+ capturedTraceBody = (await request.json()) as Record<string, unknown>;
43
+ return HttpResponse.json({
44
+ project_id: MOCK_PROJECT_ID,
45
+ project_name: 'test-project',
46
+ records_count: 1,
47
+ traces_count: 1,
48
+ });
49
+ },
50
+ );
51
+
52
+ const server = setupServer(loginApiKeyHandler, traceIngestionHandler);
53
+
54
+ const ENV_KEYS = [
55
+ 'GALILEO_API_KEY',
56
+ 'GALILEO_CONSOLE_URL',
57
+ 'GALILEO_API_URL',
58
+ 'GALILEO_USERNAME',
59
+ 'GALILEO_PASSWORD',
60
+ 'GALILEO_PROJECT',
61
+ 'GALILEO_LOG_STREAM',
62
+ ] as const;
63
+
64
+ function clearGalileoEnv(): void {
65
+ for (const key of ENV_KEYS) {
66
+ delete process.env[key];
67
+ }
68
+ }
69
+
70
+ describe('env vars → auth → trace ingestion', () => {
71
+ beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }));
72
+ afterAll(() => server.close());
73
+
74
+ beforeEach(() => {
75
+ capturedLoginBody = null;
76
+ capturedTraceHeaders = {};
77
+ capturedTraceBody = null;
78
+ GalileoConfig.reset();
79
+ BaseEntity.resetForTesting();
80
+ });
81
+
82
+ afterEach(() => {
83
+ server.resetHandlers();
84
+ clearGalileoEnv();
85
+ });
86
+
87
+ test('test GALILEO_API_KEY from env reaches the login endpoint', async () => {
88
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
89
+ process.env['GALILEO_API_KEY'] = MOCK_API_KEY;
90
+
91
+ const token = await BaseEntity.getToken();
92
+
93
+ expect(capturedLoginBody).not.toBeNull();
94
+ expect(capturedLoginBody?.['api_key']).toBe(MOCK_API_KEY);
95
+ expect(token).toBe(MOCK_ACCESS_TOKEN);
96
+ });
97
+
98
+ test('test auth token is injected into trace ingestion request via hook', async () => {
99
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
100
+ process.env['GALILEO_API_KEY'] = MOCK_API_KEY;
101
+
102
+ // Authenticate — populates BaseEntity.token via the hook chain
103
+ await BaseEntity.getToken();
104
+
105
+ // Create a fresh SDK client that reads from GalileoConfig (which got TEST_HOST)
106
+ const client = new GalileoGenerated({ serverURL: TEST_HOST });
107
+
108
+ // Call trace ingestion through the SDK
109
+ await client.trace.logTracesProjectsProjectIdTracesPost(
110
+ {}, // security — empty: let the TokenManagementHook inject the Bearer token
111
+ {
112
+ projectId: MOCK_PROJECT_ID,
113
+ body: {
114
+ traces: [{ input: 'hello', output: 'world', name: 'test-trace' }],
115
+ logStreamId: 'ls-test',
116
+ },
117
+ },
118
+ );
119
+
120
+ // The TokenManagementHook should have added the Bearer token
121
+ expect(capturedTraceHeaders['authorization']).toBe(
122
+ `Bearer ${MOCK_ACCESS_TOKEN}`,
123
+ );
124
+ });
125
+
126
+ test('test trace ingestion receives correct payload', async () => {
127
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
128
+ process.env['GALILEO_API_KEY'] = MOCK_API_KEY;
129
+
130
+ await BaseEntity.getToken();
131
+
132
+ const client = new GalileoGenerated({ serverURL: TEST_HOST });
133
+
134
+ await client.trace.logTracesProjectsProjectIdTracesPost(
135
+ {},
136
+ {
137
+ projectId: MOCK_PROJECT_ID,
138
+ body: {
139
+ traces: [{ input: 'test-input', output: 'test-output', name: 'trace-1' }],
140
+ logStreamId: 'ls-abc',
141
+ isComplete: true,
142
+ },
143
+ },
144
+ );
145
+
146
+ expect(capturedTraceBody).not.toBeNull();
147
+ expect(capturedTraceBody?.['log_stream_id']).toBe('ls-abc');
148
+ expect(capturedTraceBody?.['is_complete']).toBe(true);
149
+
150
+ const traces = capturedTraceBody?.['traces'] as Array<Record<string, unknown>>;
151
+ expect(traces).toHaveLength(1);
152
+ expect(traces[0]?.['input']).toBe('test-input');
153
+ expect(traces[0]?.['output']).toBe('test-output');
154
+ expect(traces[0]?.['name']).toBe('trace-1');
155
+ });
156
+
157
+ test('test SDK identifier header is present on trace ingestion', async () => {
158
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
159
+ process.env['GALILEO_API_KEY'] = MOCK_API_KEY;
160
+
161
+ await BaseEntity.getToken();
162
+
163
+ const client = new GalileoGenerated({ serverURL: TEST_HOST });
164
+
165
+ await client.trace.logTracesProjectsProjectIdTracesPost(
166
+ {},
167
+ {
168
+ projectId: MOCK_PROJECT_ID,
169
+ body: {
170
+ traces: [{ input: 'x', output: 'y', name: 'n' }],
171
+ logStreamId: 'ls-test',
172
+ },
173
+ },
174
+ );
175
+
176
+ expect(capturedTraceHeaders['x-galileo-sdk']).toMatch(
177
+ /^galileo-generated\/\d+\.\d+\.\d+$/,
178
+ );
179
+ });
180
+
181
+ test('test wrong GALILEO_API_KEY causes authentication error', async () => {
182
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
183
+ process.env['GALILEO_API_KEY'] = 'wrong-api-key';
184
+
185
+ await expect(BaseEntity.getToken()).rejects.toThrow();
186
+
187
+ // Login was attempted with the wrong key
188
+ expect(capturedLoginBody?.['api_key']).toBe('wrong-api-key');
189
+ // No token was cached — trace requests would have no auth header
190
+ BaseEntity.resetForTesting();
191
+ const token = await BaseEntity.getToken().catch(() => null);
192
+ expect(token).toBeNull();
193
+ });
194
+
195
+ test('test no credentials in env means no auth header on request', async () => {
196
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
197
+ // No GALILEO_API_KEY, no USERNAME/PASSWORD
198
+
199
+ const token = await BaseEntity.getToken();
200
+ expect(token).toBeNull();
201
+
202
+ const client = new GalileoGenerated({ serverURL: TEST_HOST });
203
+
204
+ await client.trace.logTracesProjectsProjectIdTracesPost(
205
+ {},
206
+ {
207
+ projectId: MOCK_PROJECT_ID,
208
+ body: {
209
+ traces: [{ input: 'a', output: 'b', name: 'c' }],
210
+ logStreamId: 'ls-test',
211
+ },
212
+ },
213
+ );
214
+
215
+ // TokenManagementHook skips injection when token is null
216
+ expect(capturedTraceHeaders['authorization']).toBeUndefined();
217
+ });
218
+
219
+ test('test full chain: env var set after config reset is picked up', async () => {
220
+ // Simulate late env loading (e.g. dotenv.config() called after first import)
221
+ const configBefore = GalileoConfig.get();
222
+ expect(configBefore.apiKey).toBeUndefined();
223
+
224
+ // Now "load" the env vars (as dotenv would)
225
+ process.env['GALILEO_CONSOLE_URL'] = TEST_HOST;
226
+ process.env['GALILEO_API_KEY'] = MOCK_API_KEY;
227
+
228
+ // GalileoConfig.get() re-reads env when instance has no external config
229
+ // (isMissingExternalConfig returns true → singleton is rebuilt)
230
+ const configAfter = GalileoConfig.get();
231
+ expect(configAfter.apiKey).toBe(MOCK_API_KEY);
232
+
233
+ // Auth picks up the new config
234
+ const token = await BaseEntity.getToken();
235
+ expect(token).toBe(MOCK_ACCESS_TOKEN);
236
+
237
+ // And the token flows through to the request
238
+ const client = new GalileoGenerated({ serverURL: TEST_HOST });
239
+ await client.trace.logTracesProjectsProjectIdTracesPost(
240
+ {},
241
+ {
242
+ projectId: MOCK_PROJECT_ID,
243
+ body: {
244
+ traces: [{ input: 'late', output: 'load', name: 'dotenv-test' }],
245
+ logStreamId: 'ls-test',
246
+ },
247
+ },
248
+ );
249
+
250
+ expect(capturedTraceHeaders['authorization']).toBe(
251
+ `Bearer ${MOCK_ACCESS_TOKEN}`,
252
+ );
253
+ });
254
+ });