@robosystems/client 0.2.42 → 0.2.44

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 (73) hide show
  1. package/extensions/LedgerClient.d.ts +88 -0
  2. package/extensions/LedgerClient.js +143 -0
  3. package/extensions/LedgerClient.ts +267 -0
  4. package/extensions/ReportClient.d.ts +14 -6
  5. package/extensions/ReportClient.js +19 -15
  6. package/extensions/ReportClient.ts +37 -21
  7. package/extensions/hooks.d.ts +1 -40
  8. package/extensions/hooks.js +0 -134
  9. package/extensions/hooks.ts +0 -156
  10. package/extensions/index.d.ts +2 -24
  11. package/extensions/index.js +1 -65
  12. package/extensions/index.test.ts +4 -38
  13. package/extensions/index.ts +0 -78
  14. package/index.ts +2 -2
  15. package/package.json +1 -1
  16. package/sdk/index.d.ts +2 -2
  17. package/sdk/index.js +11 -4
  18. package/sdk/index.ts +2 -2
  19. package/sdk/sdk.gen.d.ts +51 -9
  20. package/sdk/sdk.gen.js +105 -16
  21. package/sdk/sdk.gen.ts +101 -12
  22. package/sdk/types.gen.d.ts +812 -146
  23. package/sdk/types.gen.ts +844 -128
  24. package/sdk-extensions/LedgerClient.d.ts +88 -0
  25. package/sdk-extensions/LedgerClient.js +143 -0
  26. package/sdk-extensions/LedgerClient.ts +267 -0
  27. package/sdk-extensions/ReportClient.d.ts +14 -6
  28. package/sdk-extensions/ReportClient.js +19 -15
  29. package/sdk-extensions/ReportClient.ts +37 -21
  30. package/sdk-extensions/hooks.d.ts +1 -40
  31. package/sdk-extensions/hooks.js +0 -134
  32. package/sdk-extensions/hooks.ts +0 -156
  33. package/sdk-extensions/index.d.ts +2 -24
  34. package/sdk-extensions/index.js +1 -65
  35. package/sdk-extensions/index.test.ts +4 -38
  36. package/sdk-extensions/index.ts +0 -78
  37. package/sdk.gen.d.ts +51 -9
  38. package/sdk.gen.js +105 -16
  39. package/sdk.gen.ts +101 -12
  40. package/types.gen.d.ts +812 -146
  41. package/types.gen.ts +844 -128
  42. package/extensions/DocumentClient.d.ts +0 -77
  43. package/extensions/DocumentClient.js +0 -136
  44. package/extensions/DocumentClient.ts +0 -232
  45. package/extensions/FileClient.d.ts +0 -57
  46. package/extensions/FileClient.js +0 -246
  47. package/extensions/FileClient.ts +0 -330
  48. package/extensions/GraphClient.d.ts +0 -91
  49. package/extensions/GraphClient.js +0 -244
  50. package/extensions/GraphClient.test.ts +0 -455
  51. package/extensions/GraphClient.ts +0 -371
  52. package/extensions/MaterializationClient.d.ts +0 -61
  53. package/extensions/MaterializationClient.js +0 -157
  54. package/extensions/MaterializationClient.ts +0 -223
  55. package/extensions/TableClient.d.ts +0 -38
  56. package/extensions/TableClient.js +0 -92
  57. package/extensions/TableClient.ts +0 -132
  58. package/sdk-extensions/DocumentClient.d.ts +0 -77
  59. package/sdk-extensions/DocumentClient.js +0 -136
  60. package/sdk-extensions/DocumentClient.ts +0 -232
  61. package/sdk-extensions/FileClient.d.ts +0 -57
  62. package/sdk-extensions/FileClient.js +0 -246
  63. package/sdk-extensions/FileClient.ts +0 -330
  64. package/sdk-extensions/GraphClient.d.ts +0 -91
  65. package/sdk-extensions/GraphClient.js +0 -244
  66. package/sdk-extensions/GraphClient.test.ts +0 -455
  67. package/sdk-extensions/GraphClient.ts +0 -371
  68. package/sdk-extensions/MaterializationClient.d.ts +0 -61
  69. package/sdk-extensions/MaterializationClient.js +0 -157
  70. package/sdk-extensions/MaterializationClient.ts +0 -223
  71. package/sdk-extensions/TableClient.d.ts +0 -38
  72. package/sdk-extensions/TableClient.js +0 -92
  73. package/sdk-extensions/TableClient.ts +0 -132
@@ -1,244 +0,0 @@
1
- 'use client';
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.GraphClient = exports.GraphOperationError = void 0;
5
- /**
6
- * Graph Management Client
7
- * Provides high-level graph management operations with automatic operation monitoring.
8
- * Supports SSE (Server-Sent Events) for real-time updates with polling fallback.
9
- */
10
- const sdk_gen_1 = require("../sdk.gen");
11
- const OperationClient_1 = require("./OperationClient");
12
- /**
13
- * Error thrown when a graph operation fails (as reported by the server)
14
- * This is distinct from connection/SSE errors
15
- */
16
- class GraphOperationError extends Error {
17
- constructor(message) {
18
- super(message);
19
- this.name = 'GraphOperationError';
20
- }
21
- }
22
- exports.GraphOperationError = GraphOperationError;
23
- class GraphClient {
24
- constructor(config) {
25
- this.config = config;
26
- this.operationClient = new OperationClient_1.OperationClient(config);
27
- }
28
- /**
29
- * Create a graph and wait for completion
30
- *
31
- * Uses SSE (Server-Sent Events) for real-time progress updates with
32
- * automatic fallback to polling if SSE connection fails.
33
- *
34
- * @param metadata - Graph metadata (name, description, etc.)
35
- * @param initialEntity - Optional initial entity to create
36
- * @param options - Additional options including:
37
- * - createEntity: Whether to create the entity node and upload initial data.
38
- * Only applies when initialEntity is provided. Set to false to
39
- * create graph without populating entity data (useful for file-based ingestion).
40
- * Defaults to true.
41
- * - timeout: Maximum time to wait in milliseconds (default: 60000)
42
- * - pollInterval: Time between status checks in milliseconds (default: 2000, for polling fallback)
43
- * - onProgress: Callback for progress updates
44
- * - useSSE: Whether to try SSE first (default: true). Falls back to polling on failure.
45
- * @returns The graph ID when creation completes
46
- */
47
- async createGraphAndWait(metadata, initialEntity, options = {}) {
48
- const { createEntity = true, timeout = 60000, pollInterval = 2000, onProgress, useSSE = true, } = options;
49
- if (!this.config.token) {
50
- throw new Error('No API key provided. Set token in config.');
51
- }
52
- // Build initial entity if provided
53
- let initialEntityData;
54
- if (initialEntity) {
55
- initialEntityData = {
56
- name: initialEntity.name,
57
- uri: initialEntity.uri,
58
- category: initialEntity.category,
59
- sic: initialEntity.sic,
60
- sic_description: initialEntity.sicDescription,
61
- };
62
- }
63
- // Build API metadata
64
- const apiMetadata = {
65
- graph_name: metadata.graphName,
66
- description: metadata.description,
67
- schema_extensions: metadata.schemaExtensions || [],
68
- tags: metadata.tags || [],
69
- };
70
- if (onProgress) {
71
- onProgress(`Creating graph: ${metadata.graphName}`);
72
- }
73
- // Create graph request - SDK expects options format, not data format
74
- const response = await (0, sdk_gen_1.createGraph)({
75
- body: {
76
- metadata: apiMetadata,
77
- initial_entity: initialEntityData || null,
78
- create_entity: createEntity,
79
- },
80
- });
81
- // Check if we got immediate graph_id
82
- const responseData = response.data;
83
- if (responseData?.graph_id) {
84
- if (onProgress) {
85
- onProgress(`Graph created: ${responseData.graph_id}`);
86
- }
87
- return responseData.graph_id;
88
- }
89
- // Otherwise, we have an operation_id to monitor
90
- if (!responseData?.operation_id) {
91
- throw new Error('No graph_id or operation_id in response');
92
- }
93
- const operationId = responseData.operation_id;
94
- if (onProgress) {
95
- onProgress(`Graph creation queued (operation: ${operationId})`);
96
- }
97
- // Try SSE first, fall back to polling
98
- if (useSSE) {
99
- try {
100
- return await this.waitWithSSE(operationId, timeout, onProgress);
101
- }
102
- catch (error) {
103
- // Only fall back to polling for SSE connection failures
104
- // If it's a GraphOperationError, the operation actually failed - don't retry with polling
105
- if (error instanceof GraphOperationError) {
106
- throw error;
107
- }
108
- // SSE connection failed, fall back to polling
109
- if (onProgress) {
110
- onProgress('SSE unavailable, using polling...');
111
- }
112
- }
113
- }
114
- // Fallback to polling
115
- return await this.waitWithPolling(operationId, timeout, pollInterval, onProgress);
116
- }
117
- /**
118
- * Wait for operation completion using SSE stream
119
- */
120
- async waitWithSSE(operationId, timeout, onProgress) {
121
- const result = await this.operationClient.monitorOperation(operationId, {
122
- timeout,
123
- onProgress: (progress) => {
124
- if (onProgress) {
125
- if (progress.progressPercent !== undefined) {
126
- onProgress(`${progress.message} (${Math.round(progress.progressPercent)}%)`);
127
- }
128
- else {
129
- onProgress(progress.message);
130
- }
131
- }
132
- },
133
- });
134
- if (!result.success) {
135
- throw new GraphOperationError(result.error || 'Graph creation failed');
136
- }
137
- const graphId = result.result?.graph_id;
138
- if (!graphId) {
139
- throw new GraphOperationError('Operation completed but no graph_id in result');
140
- }
141
- if (onProgress) {
142
- onProgress(`Graph created: ${graphId}`);
143
- }
144
- return graphId;
145
- }
146
- /**
147
- * Wait for operation completion using polling
148
- */
149
- async waitWithPolling(operationId, timeout, pollInterval, onProgress) {
150
- const maxAttempts = Math.floor(timeout / pollInterval);
151
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
152
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
153
- const statusResponse = await (0, sdk_gen_1.getOperationStatus)({
154
- path: { operation_id: operationId },
155
- });
156
- const statusData = statusResponse.data;
157
- const status = statusData?.status;
158
- if (onProgress) {
159
- onProgress(`Status: ${status} (attempt ${attempt + 1}/${maxAttempts})`);
160
- }
161
- if (status === 'completed') {
162
- const result = statusData?.result;
163
- const graphId = result?.graph_id;
164
- if (graphId) {
165
- if (onProgress) {
166
- onProgress(`Graph created: ${graphId}`);
167
- }
168
- return graphId;
169
- }
170
- else {
171
- throw new GraphOperationError('Operation completed but no graph_id in result');
172
- }
173
- }
174
- else if (status === 'failed') {
175
- const error = statusData?.error || statusData?.message || 'Unknown error';
176
- throw new GraphOperationError(`Graph creation failed: ${error}`);
177
- }
178
- }
179
- throw new GraphOperationError(`Graph creation timed out after ${timeout}ms`);
180
- }
181
- /**
182
- * Get information about a graph
183
- */
184
- async getGraphInfo(graphId) {
185
- if (!this.config.token) {
186
- throw new Error('No API key provided. Set token in config.');
187
- }
188
- // Use getGraphs to list all graphs and find the one we want
189
- // Note: This is a workaround since there's no dedicated getGraph endpoint yet
190
- const response = await (0, sdk_gen_1.getGraphs)();
191
- const graphs = response.data?.graphs || [];
192
- const graph = graphs.find((g) => g.graph_id === graphId || g.id === graphId);
193
- if (!graph) {
194
- throw new Error(`Graph not found: ${graphId}`);
195
- }
196
- return {
197
- graphId: graph.graph_id || graph.id,
198
- graphName: graph.graph_name || graph.name,
199
- description: graph.description,
200
- schemaExtensions: graph.schema_extensions,
201
- tags: graph.tags,
202
- createdAt: graph.created_at,
203
- status: graph.status,
204
- };
205
- }
206
- /**
207
- * List all graphs
208
- */
209
- async listGraphs() {
210
- if (!this.config.token) {
211
- throw new Error('No API key provided. Set token in config.');
212
- }
213
- const response = await (0, sdk_gen_1.getGraphs)();
214
- const graphs = response.data?.graphs || [];
215
- return graphs.map((graph) => ({
216
- graphId: graph.graph_id || graph.id,
217
- graphName: graph.graph_name || graph.name,
218
- description: graph.description,
219
- schemaExtensions: graph.schema_extensions,
220
- tags: graph.tags,
221
- createdAt: graph.created_at,
222
- status: graph.status,
223
- }));
224
- }
225
- /**
226
- * Delete a graph
227
- * Note: This will be implemented when the deleteGraph endpoint is available in the SDK
228
- */
229
- async deleteGraph(_graphId) {
230
- throw new Error('deleteGraph is not yet implemented - waiting for SDK endpoint to be generated');
231
- // TODO: Implement when deleteGraph endpoint is available
232
- // const response = await deleteGraph({ path: { graph_id: _graphId } })
233
- // if (response.status !== 200 && response.status !== 204) {
234
- // throw new Error(`Failed to delete graph: ${response.status}`)
235
- // }
236
- }
237
- /**
238
- * Clean up resources
239
- */
240
- close() {
241
- this.operationClient.closeAll();
242
- }
243
- }
244
- exports.GraphClient = GraphClient;
@@ -1,455 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest'
2
- import type { GraphMetadataInput, InitialEntityInput } from './GraphClient'
3
- import { GraphClient } from './GraphClient'
4
-
5
- // Helper to create proper mock Response objects
6
- function createMockResponse(data: any, options: { ok?: boolean; status?: number } = {}) {
7
- return {
8
- ok: options.ok ?? true,
9
- status: options.status ?? 200,
10
- statusText: options.status === 200 ? 'OK' : 'Error',
11
- headers: new Headers({ 'content-type': 'application/json' }),
12
- json: async () => data,
13
- text: async () => JSON.stringify(data),
14
- blob: async () => new Blob([JSON.stringify(data)]),
15
- arrayBuffer: async () => new TextEncoder().encode(JSON.stringify(data)).buffer,
16
- }
17
- }
18
-
19
- describe('GraphClient', () => {
20
- let graphClient: GraphClient
21
- let mockFetch: any
22
- let mockMonitorOperation: MockInstance
23
- let mockCloseAll: MockInstance
24
-
25
- beforeEach(() => {
26
- // Mock global fetch first
27
- mockFetch = vi.fn()
28
- global.fetch = mockFetch
29
-
30
- // Create graphClient
31
- graphClient = new GraphClient({
32
- baseUrl: 'http://localhost:8000',
33
- token: 'test-api-key',
34
- headers: { 'X-API-Key': 'test-api-key' },
35
- })
36
-
37
- // Access the internal operationClient and spy on its methods
38
- const internalOperationClient = (graphClient as any).operationClient
39
- mockMonitorOperation = vi.spyOn(internalOperationClient, 'monitorOperation')
40
- mockCloseAll = vi.spyOn(internalOperationClient, 'closeAll').mockImplementation(() => {})
41
- })
42
-
43
- afterEach(() => {
44
- vi.restoreAllMocks()
45
- })
46
-
47
- describe('createGraphAndWait', () => {
48
- const mockMetadata: GraphMetadataInput = {
49
- graphName: 'Test Graph',
50
- description: 'A test graph',
51
- schemaExtensions: ['custom_prop'],
52
- tags: ['test'],
53
- }
54
-
55
- it('should create graph with immediate response', async () => {
56
- mockFetch.mockResolvedValueOnce(
57
- createMockResponse({
58
- graph_id: 'graph_123',
59
- })
60
- )
61
-
62
- const graphId = await graphClient.createGraphAndWait(mockMetadata)
63
-
64
- expect(graphId).toBe('graph_123')
65
- expect(mockFetch).toHaveBeenCalled()
66
- })
67
-
68
- it('should create graph with initial entity', async () => {
69
- const mockInitialEntity: InitialEntityInput = {
70
- name: 'ACME Corp',
71
- uri: 'https://example.com/acme',
72
- category: 'Technology',
73
- sic: '7372',
74
- sicDescription: 'Prepackaged Software',
75
- }
76
-
77
- mockFetch.mockResolvedValueOnce(
78
- createMockResponse({
79
- graph_id: 'graph_456',
80
- })
81
- )
82
-
83
- const graphId = await graphClient.createGraphAndWait(mockMetadata, mockInitialEntity)
84
-
85
- expect(graphId).toBe('graph_456')
86
- expect(mockFetch).toHaveBeenCalled()
87
- })
88
-
89
- it('should poll operation status when queued', async () => {
90
- // First call: createGraph returns operation_id
91
- mockFetch.mockResolvedValueOnce(
92
- createMockResponse({
93
- operation_id: 'op_789',
94
- })
95
- )
96
-
97
- // Second call: getOperationStatus returns pending
98
- mockFetch.mockResolvedValueOnce(
99
- createMockResponse({
100
- status: 'pending',
101
- })
102
- )
103
-
104
- // Third call: getOperationStatus returns completed
105
- mockFetch.mockResolvedValueOnce(
106
- createMockResponse({
107
- status: 'completed',
108
- result: {
109
- graph_id: 'graph_completed',
110
- },
111
- })
112
- )
113
-
114
- const graphId = await graphClient.createGraphAndWait(mockMetadata, undefined, {
115
- pollInterval: 100,
116
- })
117
-
118
- expect(graphId).toBe('graph_completed')
119
- expect(mockFetch).toHaveBeenCalledTimes(3)
120
- })
121
-
122
- it('should handle operation failure', async () => {
123
- mockFetch
124
- .mockResolvedValueOnce(
125
- createMockResponse({
126
- operation_id: 'op_fail',
127
- })
128
- )
129
- .mockResolvedValueOnce(
130
- createMockResponse({
131
- status: 'failed',
132
- error: 'Graph creation failed',
133
- })
134
- )
135
-
136
- await expect(
137
- graphClient.createGraphAndWait(mockMetadata, undefined, { pollInterval: 100 })
138
- ).rejects.toThrow('Graph creation failed')
139
- })
140
-
141
- it('should timeout if operation takes too long', async () => {
142
- mockFetch
143
- .mockResolvedValueOnce(
144
- createMockResponse({
145
- operation_id: 'op_timeout',
146
- })
147
- )
148
- .mockResolvedValue(
149
- createMockResponse({
150
- status: 'pending',
151
- })
152
- )
153
-
154
- await expect(
155
- graphClient.createGraphAndWait(mockMetadata, undefined, {
156
- timeout: 500,
157
- pollInterval: 100,
158
- })
159
- ).rejects.toThrow('timed out')
160
- })
161
-
162
- it('should call onProgress callback', async () => {
163
- mockFetch.mockResolvedValueOnce(
164
- createMockResponse({
165
- graph_id: 'graph_progress',
166
- })
167
- )
168
-
169
- const onProgress = vi.fn()
170
-
171
- await graphClient.createGraphAndWait(mockMetadata, undefined, { onProgress })
172
-
173
- expect(onProgress).toHaveBeenCalledWith(expect.stringContaining('Creating graph'))
174
- expect(onProgress).toHaveBeenCalledWith(expect.stringContaining('Graph created'))
175
- })
176
-
177
- it('should throw error if no token provided', async () => {
178
- const clientNoToken = new GraphClient({
179
- baseUrl: 'http://localhost:8000',
180
- })
181
-
182
- await expect(clientNoToken.createGraphAndWait(mockMetadata)).rejects.toThrow(
183
- 'No API key provided'
184
- )
185
- })
186
-
187
- describe('SSE mode', () => {
188
- it('should use SSE when operation_id is returned and SSE succeeds', async () => {
189
- // createGraph returns operation_id
190
- mockFetch.mockResolvedValueOnce(
191
- createMockResponse({
192
- operation_id: 'op_sse_success',
193
- })
194
- )
195
-
196
- mockMonitorOperation.mockResolvedValueOnce({
197
- success: true,
198
- result: { graph_id: 'graph_from_sse' },
199
- })
200
-
201
- const graphId = await graphClient.createGraphAndWait(mockMetadata)
202
-
203
- expect(graphId).toBe('graph_from_sse')
204
- expect(mockMonitorOperation).toHaveBeenCalledWith(
205
- 'op_sse_success',
206
- expect.objectContaining({ timeout: 60000 })
207
- )
208
- // Should only call fetch once (createGraph), no polling calls
209
- expect(mockFetch).toHaveBeenCalledTimes(1)
210
- })
211
-
212
- it('should format SSE progress with percentage', async () => {
213
- mockFetch.mockResolvedValueOnce(
214
- createMockResponse({
215
- operation_id: 'op_progress',
216
- })
217
- )
218
-
219
- mockMonitorOperation.mockImplementationOnce(
220
- async (_opId: string, options: { onProgress?: (p: any) => void }) => {
221
- // Simulate progress callback with percentage
222
- if (options.onProgress) {
223
- options.onProgress({ message: 'Processing', progressPercent: 50 })
224
- }
225
- return { success: true, result: { graph_id: 'graph_progress' } }
226
- }
227
- )
228
-
229
- const onProgress = vi.fn()
230
- await graphClient.createGraphAndWait(mockMetadata, undefined, { onProgress })
231
-
232
- expect(onProgress).toHaveBeenCalledWith('Processing (50%)')
233
- })
234
-
235
- it('should format SSE progress without percentage', async () => {
236
- mockFetch.mockResolvedValueOnce(
237
- createMockResponse({
238
- operation_id: 'op_no_percent',
239
- })
240
- )
241
-
242
- mockMonitorOperation.mockImplementationOnce(
243
- async (_opId: string, options: { onProgress?: (p: any) => void }) => {
244
- if (options.onProgress) {
245
- options.onProgress({ message: 'Initializing' })
246
- }
247
- return { success: true, result: { graph_id: 'graph_init' } }
248
- }
249
- )
250
-
251
- const onProgress = vi.fn()
252
- await graphClient.createGraphAndWait(mockMetadata, undefined, { onProgress })
253
-
254
- expect(onProgress).toHaveBeenCalledWith('Initializing')
255
- })
256
-
257
- it('should fall back to polling when SSE fails', async () => {
258
- // createGraph returns operation_id
259
- mockFetch.mockResolvedValueOnce(
260
- createMockResponse({
261
- operation_id: 'op_sse_fail',
262
- })
263
- )
264
-
265
- // SSE fails
266
- mockMonitorOperation.mockRejectedValueOnce(new Error('SSE connection failed'))
267
-
268
- // Polling succeeds
269
- mockFetch.mockResolvedValueOnce(
270
- createMockResponse({
271
- status: 'completed',
272
- result: { graph_id: 'graph_from_polling' },
273
- })
274
- )
275
-
276
- const onProgress = vi.fn()
277
- const graphId = await graphClient.createGraphAndWait(mockMetadata, undefined, {
278
- pollInterval: 100,
279
- onProgress,
280
- })
281
-
282
- expect(graphId).toBe('graph_from_polling')
283
- expect(onProgress).toHaveBeenCalledWith('SSE unavailable, using polling...')
284
- // createGraph + 1 polling call
285
- expect(mockFetch).toHaveBeenCalledTimes(2)
286
- })
287
-
288
- it('should skip SSE when useSSE is false', async () => {
289
- mockFetch.mockResolvedValueOnce(
290
- createMockResponse({
291
- operation_id: 'op_no_sse',
292
- })
293
- )
294
-
295
- // Polling succeeds
296
- mockFetch.mockResolvedValueOnce(
297
- createMockResponse({
298
- status: 'completed',
299
- result: { graph_id: 'graph_polling_only' },
300
- })
301
- )
302
-
303
- const graphId = await graphClient.createGraphAndWait(mockMetadata, undefined, {
304
- useSSE: false,
305
- pollInterval: 100,
306
- })
307
-
308
- expect(graphId).toBe('graph_polling_only')
309
- // SSE should never be called
310
- expect(mockMonitorOperation).not.toHaveBeenCalled()
311
- })
312
-
313
- it('should throw error when SSE operation fails', async () => {
314
- mockFetch.mockResolvedValueOnce(
315
- createMockResponse({
316
- operation_id: 'op_sse_error',
317
- })
318
- )
319
-
320
- mockMonitorOperation.mockResolvedValueOnce({
321
- success: false,
322
- error: 'Operation failed on server',
323
- })
324
-
325
- await expect(
326
- graphClient.createGraphAndWait(mockMetadata, undefined, { useSSE: true })
327
- ).rejects.toThrow('Operation failed on server')
328
- })
329
-
330
- it('should throw error when SSE completes but no graph_id in result', async () => {
331
- mockFetch.mockResolvedValueOnce(
332
- createMockResponse({
333
- operation_id: 'op_no_graph_id',
334
- })
335
- )
336
-
337
- mockMonitorOperation.mockResolvedValueOnce({
338
- success: true,
339
- result: {}, // No graph_id
340
- })
341
-
342
- await expect(graphClient.createGraphAndWait(mockMetadata)).rejects.toThrow(
343
- 'Operation completed but no graph_id in result'
344
- )
345
- })
346
- })
347
- })
348
-
349
- describe('getGraphInfo', () => {
350
- it('should get graph info by ID', async () => {
351
- mockFetch.mockResolvedValueOnce(
352
- createMockResponse({
353
- graphs: [
354
- {
355
- graph_id: 'graph_123',
356
- graph_name: 'Test Graph',
357
- description: 'Test description',
358
- schema_extensions: ['prop1'],
359
- tags: ['test'],
360
- created_at: '2024-01-01T00:00:00Z',
361
- status: 'active',
362
- },
363
- {
364
- graph_id: 'graph_456',
365
- graph_name: 'Other Graph',
366
- },
367
- ],
368
- })
369
- )
370
-
371
- const info = await graphClient.getGraphInfo('graph_123')
372
-
373
- expect(info.graphId).toBe('graph_123')
374
- expect(info.graphName).toBe('Test Graph')
375
- expect(info.description).toBe('Test description')
376
- expect(info.tags).toEqual(['test'])
377
- })
378
-
379
- it('should throw error if graph not found', async () => {
380
- mockFetch.mockResolvedValueOnce(
381
- createMockResponse({
382
- graphs: [
383
- {
384
- graph_id: 'graph_other',
385
- graph_name: 'Other Graph',
386
- },
387
- ],
388
- })
389
- )
390
-
391
- await expect(graphClient.getGraphInfo('graph_notfound')).rejects.toThrow('Graph not found')
392
- })
393
-
394
- it('should throw error if no token provided', async () => {
395
- const clientNoToken = new GraphClient({
396
- baseUrl: 'http://localhost:8000',
397
- })
398
-
399
- await expect(clientNoToken.getGraphInfo('graph_123')).rejects.toThrow('No API key provided')
400
- })
401
- })
402
-
403
- describe('listGraphs', () => {
404
- it('should list all graphs', async () => {
405
- mockFetch.mockResolvedValueOnce(
406
- createMockResponse({
407
- graphs: [
408
- {
409
- graph_id: 'graph_1',
410
- graph_name: 'Graph 1',
411
- description: 'First graph',
412
- },
413
- {
414
- graph_id: 'graph_2',
415
- graph_name: 'Graph 2',
416
- tags: ['production'],
417
- },
418
- ],
419
- })
420
- )
421
-
422
- const graphs = await graphClient.listGraphs()
423
-
424
- expect(graphs).toHaveLength(2)
425
- expect(graphs[0].graphId).toBe('graph_1')
426
- expect(graphs[0].graphName).toBe('Graph 1')
427
- expect(graphs[1].graphId).toBe('graph_2')
428
- expect(graphs[1].tags).toEqual(['production'])
429
- })
430
-
431
- it('should return empty array if no graphs', async () => {
432
- mockFetch.mockResolvedValueOnce(
433
- createMockResponse({
434
- graphs: [],
435
- })
436
- )
437
-
438
- const graphs = await graphClient.listGraphs()
439
-
440
- expect(graphs).toEqual([])
441
- })
442
- })
443
-
444
- describe('deleteGraph', () => {
445
- it('should throw not implemented error', async () => {
446
- await expect(graphClient.deleteGraph('graph_123')).rejects.toThrow('not yet implemented')
447
- })
448
- })
449
-
450
- describe('close', () => {
451
- it('should close without errors', () => {
452
- expect(() => graphClient.close()).not.toThrow()
453
- })
454
- })
455
- })