@aerostack/sdk-node 0.8.8 → 0.8.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/package.json +9 -2
- package/FUNCTIONS.md +0 -95
- package/RUNTIMES.md +0 -48
- package/examples/aiAIChat.example.ts +0 -31
- package/examples/databaseDbQuery.example.ts +0 -34
- package/examples/e2e/__tests__/e2e.test.ts +0 -118
- package/examples/e2e/package.json +0 -15
- package/examples/e2e/vitest.config.ts +0 -8
- package/examples/express-integration.ts +0 -67
- package/examples/next-api-route.ts +0 -46
- package/examples/package.json +0 -18
- package/examples/standalone-auth.ts +0 -44
- package/jsr.json +0 -27
- package/src/__tests__/realtime.test.ts +0 -430
- package/src/__tests__/sdk.test.ts +0 -412
- package/src/_generated/apis/AIApi.ts +0 -477
- package/src/_generated/apis/AuthenticationApi.ts +0 -121
- package/src/_generated/apis/CacheApi.ts +0 -551
- package/src/_generated/apis/DatabaseApi.ts +0 -138
- package/src/_generated/apis/GatewayApi.ts +0 -204
- package/src/_generated/apis/QueueApi.ts +0 -218
- package/src/_generated/apis/ServicesApi.ts +0 -74
- package/src/_generated/apis/StorageApi.ts +0 -476
- package/src/_generated/apis/index.ts +0 -10
- package/src/_generated/index.ts +0 -5
- package/src/_generated/models/AuthResponse.ts +0 -88
- package/src/_generated/models/AuthSigninRequest.ts +0 -75
- package/src/_generated/models/AuthSignupRequest.ts +0 -91
- package/src/_generated/models/CacheDeleteMany200Response.ts +0 -81
- package/src/_generated/models/CacheDeleteManyRequest.ts +0 -66
- package/src/_generated/models/CacheExpireRequest.ts +0 -75
- package/src/_generated/models/CacheFlush200Response.ts +0 -73
- package/src/_generated/models/CacheFlushRequest.ts +0 -65
- package/src/_generated/models/CacheGet200Response.ts +0 -73
- package/src/_generated/models/CacheGetMany200Response.ts +0 -72
- package/src/_generated/models/CacheGetManyEntry.ts +0 -81
- package/src/_generated/models/CacheGetManyRequest.ts +0 -66
- package/src/_generated/models/CacheGetRequest.ts +0 -66
- package/src/_generated/models/CacheIncrement200Response.ts +0 -65
- package/src/_generated/models/CacheIncrementRequest.ts +0 -90
- package/src/_generated/models/CacheKeyEntry.ts +0 -73
- package/src/_generated/models/CacheKeys200Response.ts +0 -73
- package/src/_generated/models/CacheKeysRequest.ts +0 -65
- package/src/_generated/models/CacheListRequest.ts +0 -81
- package/src/_generated/models/CacheListResult.ts +0 -88
- package/src/_generated/models/CacheSet200Response.ts +0 -65
- package/src/_generated/models/CacheSetEntry.ts +0 -83
- package/src/_generated/models/CacheSetMany200Response.ts +0 -73
- package/src/_generated/models/CacheSetManyRequest.ts +0 -73
- package/src/_generated/models/CacheSetRequest.ts +0 -83
- package/src/_generated/models/ChatCompletionRequest.ts +0 -130
- package/src/_generated/models/ChatCompletionRequestStreamOptions.ts +0 -67
- package/src/_generated/models/ChatCompletionResponse.ts +0 -128
- package/src/_generated/models/ChatCompletionResponseChoicesInner.ts +0 -100
- package/src/_generated/models/ChatMessage.ts +0 -87
- package/src/_generated/models/ConfigureRequest.ts +0 -77
- package/src/_generated/models/DbBatchRequest.ts +0 -73
- package/src/_generated/models/DbBatchRequestQueriesInner.ts +0 -74
- package/src/_generated/models/DbBatchResult.ts +0 -80
- package/src/_generated/models/DbBatchResultResultsInner.ts +0 -81
- package/src/_generated/models/DbQueryRequest.ts +0 -74
- package/src/_generated/models/DbQueryResult.ts +0 -73
- package/src/_generated/models/DeleteByTypeRequest.ts +0 -66
- package/src/_generated/models/DeleteRequest.ts +0 -66
- package/src/_generated/models/ErrorResponse.ts +0 -99
- package/src/_generated/models/GatewayBillingLog200Response.ts +0 -73
- package/src/_generated/models/GatewayBillingLogRequest.ts +0 -92
- package/src/_generated/models/GatewayGetWallet200Response.ts +0 -72
- package/src/_generated/models/IngestRequest.ts +0 -91
- package/src/_generated/models/JobRecord.ts +0 -119
- package/src/_generated/models/ListTypes200Response.ts +0 -72
- package/src/_generated/models/Query200Response.ts +0 -72
- package/src/_generated/models/QueryRequest.ts +0 -90
- package/src/_generated/models/QueueCancelJob200Response.ts +0 -73
- package/src/_generated/models/QueueEnqueue201Response.ts +0 -73
- package/src/_generated/models/QueueEnqueueRequest.ts +0 -83
- package/src/_generated/models/QueueGetJob200Response.ts +0 -80
- package/src/_generated/models/QueueGetJobRequest.ts +0 -66
- package/src/_generated/models/QueueListJobs200Response.ts +0 -88
- package/src/_generated/models/QueueListJobsRequest.ts +0 -103
- package/src/_generated/models/SearchCount200Response.ts +0 -65
- package/src/_generated/models/SearchCountRequest.ts +0 -65
- package/src/_generated/models/SearchGet200Response.ts +0 -80
- package/src/_generated/models/SearchGetRequest.ts +0 -66
- package/src/_generated/models/SearchResult.ts +0 -97
- package/src/_generated/models/SearchUpdateRequest.ts +0 -91
- package/src/_generated/models/ServicesInvoke200Response.ts +0 -73
- package/src/_generated/models/ServicesInvokeRequest.ts +0 -75
- package/src/_generated/models/StorageCopy200Response.ts +0 -73
- package/src/_generated/models/StorageCopyRequest.ts +0 -75
- package/src/_generated/models/StorageExists200Response.ts +0 -65
- package/src/_generated/models/StorageGetRequest.ts +0 -66
- package/src/_generated/models/StorageListRequest.ts +0 -81
- package/src/_generated/models/StorageListResult.ts +0 -88
- package/src/_generated/models/StorageMetadata.ts +0 -97
- package/src/_generated/models/StorageMove200Response.ts +0 -73
- package/src/_generated/models/StorageMoveRequest.ts +0 -75
- package/src/_generated/models/StorageObject.ts +0 -97
- package/src/_generated/models/StorageUpload200Response.ts +0 -65
- package/src/_generated/models/TokenUsage.ts +0 -81
- package/src/_generated/models/TokenWallet.ts +0 -73
- package/src/_generated/models/TypeStats.ts +0 -73
- package/src/_generated/models/User.ts +0 -97
- package/src/_generated/models/index.ts +0 -80
- package/src/_generated/runtime.ts +0 -431
- package/src/index.ts +0 -3
- package/src/realtime.ts +0 -439
- package/src/sdk.ts +0 -317
- package/test_sdk.ts +0 -19
- package/tsconfig.json +0 -43
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
|
|
3
|
-
// Mock the generated APIs and realtime
|
|
4
|
-
vi.mock('../_generated/index.js', () => {
|
|
5
|
-
const createMockApi = () => ({});
|
|
6
|
-
class MockConfiguration {
|
|
7
|
-
basePath: string;
|
|
8
|
-
headers: Record<string, string>;
|
|
9
|
-
apiKey?: string;
|
|
10
|
-
constructor(opts: any = {}) {
|
|
11
|
-
this.basePath = opts.basePath || '';
|
|
12
|
-
this.headers = opts.headers || {};
|
|
13
|
-
this.apiKey = opts.apiKey;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return {
|
|
17
|
-
Configuration: MockConfiguration,
|
|
18
|
-
AuthenticationApi: vi.fn().mockImplementation(() => ({ auth: true })),
|
|
19
|
-
CacheApi: vi.fn().mockImplementation(() => ({
|
|
20
|
-
cacheGet: vi.fn().mockResolvedValue({ _exists: true, value: 'cached' }),
|
|
21
|
-
cacheSet: vi.fn().mockResolvedValue({}),
|
|
22
|
-
cacheDelete: vi.fn().mockResolvedValue({}),
|
|
23
|
-
cacheList: vi.fn().mockResolvedValue({ keys: [], cursor: null }),
|
|
24
|
-
cacheKeys: vi.fn().mockResolvedValue({ keys: ['k1', 'k2'] }),
|
|
25
|
-
cacheGetMany: vi.fn().mockResolvedValue({ results: [] }),
|
|
26
|
-
cacheSetMany: vi.fn().mockResolvedValue({}),
|
|
27
|
-
cacheDeleteMany: vi.fn().mockResolvedValue({}),
|
|
28
|
-
cacheFlush: vi.fn().mockResolvedValue({}),
|
|
29
|
-
cacheExpire: vi.fn().mockResolvedValue({}),
|
|
30
|
-
cacheIncrement: vi.fn().mockResolvedValue({ value: 5 }),
|
|
31
|
-
})),
|
|
32
|
-
DatabaseApi: vi.fn().mockImplementation(() => ({
|
|
33
|
-
dbQuery: vi.fn().mockResolvedValue({ results: [] }),
|
|
34
|
-
})),
|
|
35
|
-
QueueApi: vi.fn().mockImplementation(() => ({ queue: true })),
|
|
36
|
-
StorageApi: vi.fn().mockImplementation(() => ({ storage: true })),
|
|
37
|
-
AIApi: vi.fn().mockImplementation(() => ({ ai: true })),
|
|
38
|
-
ServicesApi: vi.fn().mockImplementation(() => ({ services: true })),
|
|
39
|
-
GatewayApi: vi.fn().mockImplementation(() => ({ gateway: true })),
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
vi.mock('../realtime.js', () => {
|
|
44
|
-
return {
|
|
45
|
-
NodeRealtimeClient: vi.fn().mockImplementation(() => ({
|
|
46
|
-
connect: vi.fn(),
|
|
47
|
-
disconnect: vi.fn(),
|
|
48
|
-
channel: vi.fn(),
|
|
49
|
-
})),
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
vi.mock('@aerostack/core', () => {
|
|
54
|
-
return {
|
|
55
|
-
AerostackClient: vi.fn().mockImplementation(() => ({
|
|
56
|
-
db: { query: vi.fn() },
|
|
57
|
-
cache: { get: vi.fn() },
|
|
58
|
-
})),
|
|
59
|
-
};
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
import { SDK, Aerostack, createClient } from '../sdk.js';
|
|
63
|
-
|
|
64
|
-
describe('SDK', () => {
|
|
65
|
-
describe('constructor', () => {
|
|
66
|
-
it('should initialize with default options', () => {
|
|
67
|
-
const sdk = new SDK();
|
|
68
|
-
expect(sdk).toBeDefined();
|
|
69
|
-
expect(sdk.database).toBeDefined();
|
|
70
|
-
expect(sdk.auth).toBeDefined();
|
|
71
|
-
expect(sdk.cache).toBeDefined();
|
|
72
|
-
expect(sdk.queue).toBeDefined();
|
|
73
|
-
expect(sdk.storage).toBeDefined();
|
|
74
|
-
expect(sdk.ai).toBeDefined();
|
|
75
|
-
expect(sdk.services).toBeDefined();
|
|
76
|
-
expect(sdk.gateway).toBeDefined();
|
|
77
|
-
expect(sdk.realtime).toBeDefined();
|
|
78
|
-
expect(sdk.rpc).toBeDefined();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('should accept apiKey option', () => {
|
|
82
|
-
const sdk = new SDK({ apiKey: 'my-key' });
|
|
83
|
-
expect(sdk).toBeDefined();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should accept apiKeyAuth alias', () => {
|
|
87
|
-
const sdk = new SDK({ apiKeyAuth: 'my-key' });
|
|
88
|
-
expect(sdk).toBeDefined();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should accept serverUrl option', () => {
|
|
92
|
-
const sdk = new SDK({ serverUrl: 'https://custom.com/v1' });
|
|
93
|
-
expect(sdk).toBeDefined();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should accept serverURL alias', () => {
|
|
97
|
-
const sdk = new SDK({ serverURL: 'https://custom.com/v1' });
|
|
98
|
-
expect(sdk).toBeDefined();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should accept projectId', () => {
|
|
102
|
-
const sdk = new SDK({ projectId: 'proj-1' });
|
|
103
|
-
expect(sdk).toBeDefined();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should accept maxReconnectAttempts', () => {
|
|
107
|
-
const sdk = new SDK({ maxReconnectAttempts: 5 });
|
|
108
|
-
expect(sdk).toBeDefined();
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
describe('CacheFacade', () => {
|
|
113
|
-
it('should get a cached value', async () => {
|
|
114
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
115
|
-
const result = await sdk.cache.get('test-key');
|
|
116
|
-
expect(result).toBe('cached');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should return null when key not found', async () => {
|
|
120
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
121
|
-
// Override the mock for this test
|
|
122
|
-
const cacheApi = (sdk.cache as any).api;
|
|
123
|
-
cacheApi.cacheGet.mockResolvedValueOnce({ _exists: false });
|
|
124
|
-
const result = await sdk.cache.get('missing');
|
|
125
|
-
expect(result).toBeNull();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should set a value', async () => {
|
|
129
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
130
|
-
await sdk.cache.set('key', 'value');
|
|
131
|
-
const cacheApi = (sdk.cache as any).api;
|
|
132
|
-
expect(cacheApi.cacheSet).toHaveBeenCalled();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should set a value with TTL', async () => {
|
|
136
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
137
|
-
await sdk.cache.set('key', 'value', 3600);
|
|
138
|
-
const cacheApi = (sdk.cache as any).api;
|
|
139
|
-
const call = cacheApi.cacheSet.mock.calls[0][0];
|
|
140
|
-
expect(call.cacheSetRequest.ttl).toBe(3600);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should delete a key', async () => {
|
|
144
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
145
|
-
await sdk.cache.delete('key');
|
|
146
|
-
const cacheApi = (sdk.cache as any).api;
|
|
147
|
-
expect(cacheApi.cacheDelete).toHaveBeenCalled();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should check if key exists', async () => {
|
|
151
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
152
|
-
const result = await sdk.cache.exists('key');
|
|
153
|
-
expect(result).toBe(true);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should list keys', async () => {
|
|
157
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
158
|
-
await sdk.cache.list('prefix:', 10, 'cursor');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should get all keys', async () => {
|
|
162
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
163
|
-
const keys = await sdk.cache.keys('prefix:');
|
|
164
|
-
expect(keys).toEqual(['k1', 'k2']);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should get many keys', async () => {
|
|
168
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
169
|
-
const result = await sdk.cache.getMany(['k1', 'k2']);
|
|
170
|
-
expect(result).toEqual([]);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should set many entries', async () => {
|
|
174
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
175
|
-
await sdk.cache.setMany([{ key: 'k1', value: 'v1' }]);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should delete many keys', async () => {
|
|
179
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
180
|
-
await sdk.cache.deleteMany(['k1', 'k2']);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should flush cache', async () => {
|
|
184
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
185
|
-
await sdk.cache.flush('prefix:');
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('should expire a key', async () => {
|
|
189
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
190
|
-
await sdk.cache.expire('key', 300);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should increment a counter', async () => {
|
|
194
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
195
|
-
const result = await sdk.cache.increment('counter', 1, 0, 3600);
|
|
196
|
-
expect(result).toBe(5);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
describe('DatabaseFacade', () => {
|
|
201
|
-
it('should execute a query', async () => {
|
|
202
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
203
|
-
const result = await sdk.database.dbQuery({
|
|
204
|
-
dbQueryRequest: { sql: 'SELECT 1', params: [] },
|
|
205
|
-
});
|
|
206
|
-
expect(result).toEqual({ results: [] });
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('should accept requestBody alias', async () => {
|
|
210
|
-
const sdk = new SDK({ apiKey: 'key' });
|
|
211
|
-
await sdk.database.dbQuery({
|
|
212
|
-
requestBody: { sql: 'SELECT 1', params: [] },
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
describe('setApiKey', () => {
|
|
218
|
-
it('should update all service instances', () => {
|
|
219
|
-
const sdk = new SDK({ apiKey: 'old-key' });
|
|
220
|
-
sdk.setApiKey('new-key');
|
|
221
|
-
// After setApiKey, all services should be recreated
|
|
222
|
-
expect(sdk.database).toBeDefined();
|
|
223
|
-
expect(sdk.auth).toBeDefined();
|
|
224
|
-
expect(sdk.cache).toBeDefined();
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe('streamGateway', () => {
|
|
229
|
-
it('should make POST request to gateway endpoint', async () => {
|
|
230
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
231
|
-
ok: true,
|
|
232
|
-
body: createMockStream('data: {"choices":[{"delta":{"content":"Hello"}}]}\n\ndata: [DONE]\n\n'),
|
|
233
|
-
});
|
|
234
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
235
|
-
|
|
236
|
-
const sdk = new SDK({ apiKey: 'key', serverUrl: 'https://api.test.com/v1' });
|
|
237
|
-
const result = await sdk.streamGateway({
|
|
238
|
-
apiSlug: 'my-chatbot',
|
|
239
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
240
|
-
consumerKey: 'ask_live_123',
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
expect(result.text).toBe('Hello');
|
|
244
|
-
expect(mockFetch).toHaveBeenCalledOnce();
|
|
245
|
-
const [url, opts] = mockFetch.mock.calls[0];
|
|
246
|
-
expect(url).toBe('https://api.test.com/api/gateway/my-chatbot/v1/chat/completions');
|
|
247
|
-
expect(opts.headers.Authorization).toBe('Bearer ask_live_123');
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should use token when consumerKey not provided', async () => {
|
|
251
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
252
|
-
ok: true,
|
|
253
|
-
body: createMockStream('data: [DONE]\n\n'),
|
|
254
|
-
});
|
|
255
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
256
|
-
|
|
257
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
258
|
-
await sdk.streamGateway({
|
|
259
|
-
apiSlug: 'bot',
|
|
260
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
261
|
-
token: 'jwt-token',
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
expect(mockFetch.mock.calls[0][1].headers.Authorization).toBe('Bearer jwt-token');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('should prepend system prompt', async () => {
|
|
268
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
269
|
-
ok: true,
|
|
270
|
-
body: createMockStream('data: [DONE]\n\n'),
|
|
271
|
-
});
|
|
272
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
273
|
-
|
|
274
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
275
|
-
await sdk.streamGateway({
|
|
276
|
-
apiSlug: 'bot',
|
|
277
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
278
|
-
systemPrompt: 'You are helpful',
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
const body = JSON.parse(mockFetch.mock.calls[0][1].body);
|
|
282
|
-
expect(body.messages[0]).toEqual({ role: 'system', content: 'You are helpful' });
|
|
283
|
-
expect(body.messages[1]).toEqual({ role: 'user', content: 'Hi' });
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('should call onToken callback', async () => {
|
|
287
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
288
|
-
ok: true,
|
|
289
|
-
body: createMockStream('data: {"choices":[{"delta":{"content":"Hi"}}]}\n\ndata: {"choices":[{"delta":{"content":" there"}}]}\n\ndata: [DONE]\n\n'),
|
|
290
|
-
});
|
|
291
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
292
|
-
|
|
293
|
-
const tokens: string[] = [];
|
|
294
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
295
|
-
await sdk.streamGateway({
|
|
296
|
-
apiSlug: 'bot',
|
|
297
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
298
|
-
onToken: (delta: string) => tokens.push(delta),
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
expect(tokens).toEqual(['Hi', ' there']);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('should call onDone callback', async () => {
|
|
305
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
306
|
-
ok: true,
|
|
307
|
-
body: createMockStream('data: {"choices":[{"delta":{"content":"Hi"}}],"usage":{"total_tokens":10}}\n\ndata: [DONE]\n\n'),
|
|
308
|
-
});
|
|
309
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
310
|
-
|
|
311
|
-
let doneResult: any;
|
|
312
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
313
|
-
await sdk.streamGateway({
|
|
314
|
-
apiSlug: 'bot',
|
|
315
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
316
|
-
onDone: (result: any) => { doneResult = result; },
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
expect(doneResult.tokensUsed).toBe(10);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it('should throw on non-OK response', async () => {
|
|
323
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
324
|
-
ok: false,
|
|
325
|
-
status: 500,
|
|
326
|
-
json: vi.fn().mockResolvedValue({ error: 'Server error' }),
|
|
327
|
-
});
|
|
328
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
329
|
-
|
|
330
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
331
|
-
await expect(sdk.streamGateway({
|
|
332
|
-
apiSlug: 'bot',
|
|
333
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
334
|
-
})).rejects.toThrow('Server error');
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('should call onError on failure', async () => {
|
|
338
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
339
|
-
ok: false,
|
|
340
|
-
status: 500,
|
|
341
|
-
json: vi.fn().mockResolvedValue({ error: 'boom' }),
|
|
342
|
-
});
|
|
343
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
344
|
-
|
|
345
|
-
let capturedError: Error | null = null;
|
|
346
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
await sdk.streamGateway({
|
|
350
|
-
apiSlug: 'bot',
|
|
351
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
352
|
-
onError: (err: Error) => { capturedError = err; },
|
|
353
|
-
});
|
|
354
|
-
} catch {
|
|
355
|
-
// Expected
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
expect(capturedError).not.toBeNull();
|
|
359
|
-
expect(capturedError!.message).toBe('boom');
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('should handle abort gracefully', async () => {
|
|
363
|
-
const abortController = new AbortController();
|
|
364
|
-
const mockFetch = vi.fn().mockRejectedValue(
|
|
365
|
-
Object.assign(new Error('Aborted'), { name: 'AbortError' })
|
|
366
|
-
);
|
|
367
|
-
vi.stubGlobal('fetch', mockFetch);
|
|
368
|
-
|
|
369
|
-
const sdk = new SDK({ serverUrl: 'https://api.test.com/v1' });
|
|
370
|
-
const result = await sdk.streamGateway({
|
|
371
|
-
apiSlug: 'bot',
|
|
372
|
-
messages: [{ role: 'user', content: 'Hi' }],
|
|
373
|
-
signal: abortController.signal,
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
expect(result.text).toBe('');
|
|
377
|
-
expect(result.tokensUsed).toBe(0);
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
describe('Aerostack alias', () => {
|
|
382
|
-
it('should be the same as SDK', () => {
|
|
383
|
-
expect(Aerostack).toBe(SDK);
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
describe('createClient', () => {
|
|
388
|
-
it('should return an SDK instance', () => {
|
|
389
|
-
const client = createClient({ apiKey: 'key' });
|
|
390
|
-
expect(client).toBeInstanceOf(SDK);
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
// Helper to create a mock ReadableStream
|
|
396
|
-
function createMockStream(text: string) {
|
|
397
|
-
const encoder = new TextEncoder();
|
|
398
|
-
const data = encoder.encode(text);
|
|
399
|
-
let read = false;
|
|
400
|
-
return {
|
|
401
|
-
getReader: () => ({
|
|
402
|
-
read: async () => {
|
|
403
|
-
if (!read) {
|
|
404
|
-
read = true;
|
|
405
|
-
return { done: false, value: data };
|
|
406
|
-
}
|
|
407
|
-
return { done: true, value: undefined };
|
|
408
|
-
},
|
|
409
|
-
cancel: vi.fn(),
|
|
410
|
-
}),
|
|
411
|
-
};
|
|
412
|
-
}
|