@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.
- package/extensions/LedgerClient.d.ts +88 -0
- package/extensions/LedgerClient.js +143 -0
- package/extensions/LedgerClient.ts +267 -0
- package/extensions/ReportClient.d.ts +14 -6
- package/extensions/ReportClient.js +19 -15
- package/extensions/ReportClient.ts +37 -21
- package/extensions/hooks.d.ts +1 -40
- package/extensions/hooks.js +0 -134
- package/extensions/hooks.ts +0 -156
- package/extensions/index.d.ts +2 -24
- package/extensions/index.js +1 -65
- package/extensions/index.test.ts +4 -38
- package/extensions/index.ts +0 -78
- package/index.ts +2 -2
- package/package.json +1 -1
- package/sdk/index.d.ts +2 -2
- package/sdk/index.js +11 -4
- package/sdk/index.ts +2 -2
- package/sdk/sdk.gen.d.ts +51 -9
- package/sdk/sdk.gen.js +105 -16
- package/sdk/sdk.gen.ts +101 -12
- package/sdk/types.gen.d.ts +812 -146
- package/sdk/types.gen.ts +844 -128
- package/sdk-extensions/LedgerClient.d.ts +88 -0
- package/sdk-extensions/LedgerClient.js +143 -0
- package/sdk-extensions/LedgerClient.ts +267 -0
- package/sdk-extensions/ReportClient.d.ts +14 -6
- package/sdk-extensions/ReportClient.js +19 -15
- package/sdk-extensions/ReportClient.ts +37 -21
- package/sdk-extensions/hooks.d.ts +1 -40
- package/sdk-extensions/hooks.js +0 -134
- package/sdk-extensions/hooks.ts +0 -156
- package/sdk-extensions/index.d.ts +2 -24
- package/sdk-extensions/index.js +1 -65
- package/sdk-extensions/index.test.ts +4 -38
- package/sdk-extensions/index.ts +0 -78
- package/sdk.gen.d.ts +51 -9
- package/sdk.gen.js +105 -16
- package/sdk.gen.ts +101 -12
- package/types.gen.d.ts +812 -146
- package/types.gen.ts +844 -128
- package/extensions/DocumentClient.d.ts +0 -77
- package/extensions/DocumentClient.js +0 -136
- package/extensions/DocumentClient.ts +0 -232
- package/extensions/FileClient.d.ts +0 -57
- package/extensions/FileClient.js +0 -246
- package/extensions/FileClient.ts +0 -330
- package/extensions/GraphClient.d.ts +0 -91
- package/extensions/GraphClient.js +0 -244
- package/extensions/GraphClient.test.ts +0 -455
- package/extensions/GraphClient.ts +0 -371
- package/extensions/MaterializationClient.d.ts +0 -61
- package/extensions/MaterializationClient.js +0 -157
- package/extensions/MaterializationClient.ts +0 -223
- package/extensions/TableClient.d.ts +0 -38
- package/extensions/TableClient.js +0 -92
- package/extensions/TableClient.ts +0 -132
- package/sdk-extensions/DocumentClient.d.ts +0 -77
- package/sdk-extensions/DocumentClient.js +0 -136
- package/sdk-extensions/DocumentClient.ts +0 -232
- package/sdk-extensions/FileClient.d.ts +0 -57
- package/sdk-extensions/FileClient.js +0 -246
- package/sdk-extensions/FileClient.ts +0 -330
- package/sdk-extensions/GraphClient.d.ts +0 -91
- package/sdk-extensions/GraphClient.js +0 -244
- package/sdk-extensions/GraphClient.test.ts +0 -455
- package/sdk-extensions/GraphClient.ts +0 -371
- package/sdk-extensions/MaterializationClient.d.ts +0 -61
- package/sdk-extensions/MaterializationClient.js +0 -157
- package/sdk-extensions/MaterializationClient.ts +0 -223
- package/sdk-extensions/TableClient.d.ts +0 -38
- package/sdk-extensions/TableClient.js +0 -92
- package/sdk-extensions/TableClient.ts +0 -132
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* File Client for RoboSystems API
|
|
5
|
-
*
|
|
6
|
-
* Manages file upload operations including presigned URLs, S3 uploads,
|
|
7
|
-
* and file status tracking.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { createFileUpload, deleteFile, getFile, listFiles, updateFile } from '../sdk/sdk.gen'
|
|
11
|
-
import type { FileStatusUpdate, FileUploadRequest, FileUploadResponse } from '../sdk/types.gen'
|
|
12
|
-
|
|
13
|
-
export interface FileUploadOptions {
|
|
14
|
-
onProgress?: (message: string) => void
|
|
15
|
-
fileName?: string
|
|
16
|
-
ingestToGraph?: boolean
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface FileUploadResult {
|
|
20
|
-
fileId: string
|
|
21
|
-
fileSize: number
|
|
22
|
-
rowCount: number
|
|
23
|
-
tableName: string
|
|
24
|
-
fileName: string
|
|
25
|
-
success: boolean
|
|
26
|
-
error?: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface FileInfo {
|
|
30
|
-
fileId: string
|
|
31
|
-
fileName: string
|
|
32
|
-
tableName: string
|
|
33
|
-
status: string
|
|
34
|
-
fileSize: number
|
|
35
|
-
rowCount: number
|
|
36
|
-
createdAt: string
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type FileInput = File | Blob | Buffer | ReadableStream<Uint8Array>
|
|
40
|
-
|
|
41
|
-
export class FileClient {
|
|
42
|
-
private config: {
|
|
43
|
-
baseUrl: string
|
|
44
|
-
credentials?: 'include' | 'same-origin' | 'omit'
|
|
45
|
-
headers?: Record<string, string>
|
|
46
|
-
token?: string
|
|
47
|
-
s3EndpointUrl?: string // Override S3 endpoint (e.g., for LocalStack)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
constructor(config: {
|
|
51
|
-
baseUrl: string
|
|
52
|
-
credentials?: 'include' | 'same-origin' | 'omit'
|
|
53
|
-
headers?: Record<string, string>
|
|
54
|
-
token?: string
|
|
55
|
-
s3EndpointUrl?: string
|
|
56
|
-
}) {
|
|
57
|
-
this.config = config
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Upload a Parquet file to staging
|
|
62
|
-
*
|
|
63
|
-
* Handles the complete 3-step upload process:
|
|
64
|
-
* 1. Get presigned upload URL
|
|
65
|
-
* 2. Upload file to S3
|
|
66
|
-
* 3. Mark file as 'uploaded' (backend validates, calculates size/row count)
|
|
67
|
-
*/
|
|
68
|
-
async upload(
|
|
69
|
-
graphId: string,
|
|
70
|
-
tableName: string,
|
|
71
|
-
fileOrBuffer: FileInput,
|
|
72
|
-
options: FileUploadOptions = {}
|
|
73
|
-
): Promise<FileUploadResult> {
|
|
74
|
-
const fileName = this.getFileName(fileOrBuffer, options.fileName)
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
options.onProgress?.(`Getting upload URL for ${fileName} -> table '${tableName}'...`)
|
|
78
|
-
|
|
79
|
-
const uploadRequest: FileUploadRequest = {
|
|
80
|
-
file_name: fileName,
|
|
81
|
-
content_type: 'application/x-parquet',
|
|
82
|
-
table_name: tableName,
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const uploadUrlResponse = await createFileUpload({
|
|
86
|
-
path: { graph_id: graphId },
|
|
87
|
-
body: uploadRequest,
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
if (uploadUrlResponse.error || !uploadUrlResponse.data) {
|
|
91
|
-
return {
|
|
92
|
-
fileId: '',
|
|
93
|
-
fileSize: 0,
|
|
94
|
-
rowCount: 0,
|
|
95
|
-
tableName,
|
|
96
|
-
fileName,
|
|
97
|
-
success: false,
|
|
98
|
-
error: `Failed to get upload URL: ${uploadUrlResponse.error}`,
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const uploadData = uploadUrlResponse.data as FileUploadResponse
|
|
103
|
-
let uploadUrl = uploadData.upload_url
|
|
104
|
-
const fileId = uploadData.file_id
|
|
105
|
-
|
|
106
|
-
// Override S3 endpoint if configured (e.g., for LocalStack)
|
|
107
|
-
if (this.config.s3EndpointUrl) {
|
|
108
|
-
const originalUrl = new URL(uploadUrl)
|
|
109
|
-
const overrideUrl = new URL(this.config.s3EndpointUrl)
|
|
110
|
-
// Replace scheme, host, and port with the override endpoint
|
|
111
|
-
originalUrl.protocol = overrideUrl.protocol
|
|
112
|
-
originalUrl.host = overrideUrl.host
|
|
113
|
-
uploadUrl = originalUrl.toString()
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
options.onProgress?.(`Uploading ${fileName} to S3...`)
|
|
117
|
-
|
|
118
|
-
const fileContent = await this.getFileContent(fileOrBuffer)
|
|
119
|
-
const fileSize = fileContent.byteLength
|
|
120
|
-
|
|
121
|
-
const s3Response = await fetch(uploadUrl, {
|
|
122
|
-
method: 'PUT',
|
|
123
|
-
body: fileContent,
|
|
124
|
-
headers: {
|
|
125
|
-
'Content-Type': 'application/x-parquet',
|
|
126
|
-
},
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
if (!s3Response.ok) {
|
|
130
|
-
return {
|
|
131
|
-
fileId,
|
|
132
|
-
fileSize,
|
|
133
|
-
rowCount: 0,
|
|
134
|
-
tableName,
|
|
135
|
-
fileName,
|
|
136
|
-
success: false,
|
|
137
|
-
error: `S3 upload failed: ${s3Response.status} ${s3Response.statusText}`,
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
options.onProgress?.(`Marking ${fileName} as uploaded...`)
|
|
142
|
-
|
|
143
|
-
const statusUpdate: FileStatusUpdate = {
|
|
144
|
-
status: 'uploaded',
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const updateResponse = await updateFile({
|
|
148
|
-
path: { graph_id: graphId, file_id: fileId },
|
|
149
|
-
body: statusUpdate,
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
if (updateResponse.error || !updateResponse.data) {
|
|
153
|
-
return {
|
|
154
|
-
fileId,
|
|
155
|
-
fileSize,
|
|
156
|
-
rowCount: 0,
|
|
157
|
-
tableName,
|
|
158
|
-
fileName,
|
|
159
|
-
success: false,
|
|
160
|
-
error: 'Failed to complete file upload',
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const responseData = updateResponse.data as any
|
|
165
|
-
const actualFileSize = responseData.file_size_bytes || 0
|
|
166
|
-
const actualRowCount = responseData.row_count || 0
|
|
167
|
-
|
|
168
|
-
options.onProgress?.(
|
|
169
|
-
`✅ Uploaded ${fileName} (${actualFileSize.toLocaleString()} bytes, ${actualRowCount.toLocaleString()} rows)`
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
fileId,
|
|
174
|
-
fileSize: actualFileSize,
|
|
175
|
-
rowCount: actualRowCount,
|
|
176
|
-
tableName,
|
|
177
|
-
fileName,
|
|
178
|
-
success: true,
|
|
179
|
-
}
|
|
180
|
-
} catch (error) {
|
|
181
|
-
return {
|
|
182
|
-
fileId: '',
|
|
183
|
-
fileSize: 0,
|
|
184
|
-
rowCount: 0,
|
|
185
|
-
tableName,
|
|
186
|
-
fileName,
|
|
187
|
-
success: false,
|
|
188
|
-
error: error instanceof Error ? error.message : String(error),
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* List files in a graph
|
|
195
|
-
*/
|
|
196
|
-
async list(graphId: string, tableName?: string, status?: string): Promise<FileInfo[]> {
|
|
197
|
-
try {
|
|
198
|
-
const response = await listFiles({
|
|
199
|
-
path: { graph_id: graphId },
|
|
200
|
-
query: {
|
|
201
|
-
table_name: tableName,
|
|
202
|
-
status: status as any,
|
|
203
|
-
},
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
if (response.error || !response.data) {
|
|
207
|
-
console.error('Failed to list files:', response.error)
|
|
208
|
-
return []
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const fileData = response.data as any
|
|
212
|
-
|
|
213
|
-
return (
|
|
214
|
-
fileData.files?.map((file: any) => ({
|
|
215
|
-
fileId: file.file_id,
|
|
216
|
-
fileName: file.file_name,
|
|
217
|
-
tableName: file.table_name,
|
|
218
|
-
status: file.status,
|
|
219
|
-
fileSize: file.file_size_bytes || 0,
|
|
220
|
-
rowCount: file.row_count || 0,
|
|
221
|
-
createdAt: file.created_at,
|
|
222
|
-
})) || []
|
|
223
|
-
)
|
|
224
|
-
} catch (error) {
|
|
225
|
-
console.error('Failed to list files:', error)
|
|
226
|
-
return []
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Get file information
|
|
232
|
-
*/
|
|
233
|
-
async get(graphId: string, fileId: string): Promise<FileInfo | null> {
|
|
234
|
-
try {
|
|
235
|
-
const response = await getFile({
|
|
236
|
-
path: { graph_id: graphId, file_id: fileId },
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
if (response.error || !response.data) {
|
|
240
|
-
console.error('Failed to get file:', response.error)
|
|
241
|
-
return null
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const file = response.data as any
|
|
245
|
-
|
|
246
|
-
return {
|
|
247
|
-
fileId: file.file_id,
|
|
248
|
-
fileName: file.file_name,
|
|
249
|
-
tableName: file.table_name,
|
|
250
|
-
status: file.status,
|
|
251
|
-
fileSize: file.file_size_bytes || 0,
|
|
252
|
-
rowCount: file.row_count || 0,
|
|
253
|
-
createdAt: file.created_at,
|
|
254
|
-
}
|
|
255
|
-
} catch (error) {
|
|
256
|
-
console.error('Failed to get file:', error)
|
|
257
|
-
return null
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Delete a file
|
|
263
|
-
*/
|
|
264
|
-
async delete(graphId: string, fileId: string, cascade: boolean = false): Promise<boolean> {
|
|
265
|
-
try {
|
|
266
|
-
const response = await deleteFile({
|
|
267
|
-
path: { graph_id: graphId, file_id: fileId },
|
|
268
|
-
query: { cascade },
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
return !response.error
|
|
272
|
-
} catch (error) {
|
|
273
|
-
console.error('Failed to delete file:', error)
|
|
274
|
-
return false
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
private getFileName(fileOrBuffer: FileInput, override?: string): string {
|
|
279
|
-
if (override) return override
|
|
280
|
-
|
|
281
|
-
if ('name' in fileOrBuffer && typeof fileOrBuffer.name === 'string') {
|
|
282
|
-
return fileOrBuffer.name
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return 'data.parquet'
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
private async getFileContent(fileOrBuffer: FileInput): Promise<ArrayBuffer> {
|
|
289
|
-
if (fileOrBuffer instanceof Blob || fileOrBuffer instanceof File) {
|
|
290
|
-
return fileOrBuffer.arrayBuffer()
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (Buffer.isBuffer(fileOrBuffer)) {
|
|
294
|
-
const buffer = fileOrBuffer.buffer.slice(
|
|
295
|
-
fileOrBuffer.byteOffset,
|
|
296
|
-
fileOrBuffer.byteOffset + fileOrBuffer.byteLength
|
|
297
|
-
)
|
|
298
|
-
// Convert SharedArrayBuffer to ArrayBuffer if needed
|
|
299
|
-
if (buffer instanceof ArrayBuffer) {
|
|
300
|
-
return buffer
|
|
301
|
-
}
|
|
302
|
-
// Handle SharedArrayBuffer by copying to ArrayBuffer
|
|
303
|
-
const arrayBuffer = new ArrayBuffer(buffer.byteLength)
|
|
304
|
-
new Uint8Array(arrayBuffer).set(new Uint8Array(buffer))
|
|
305
|
-
return arrayBuffer
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if ('getReader' in fileOrBuffer) {
|
|
309
|
-
const reader = fileOrBuffer.getReader()
|
|
310
|
-
const chunks: Uint8Array[] = []
|
|
311
|
-
|
|
312
|
-
while (true) {
|
|
313
|
-
const { done, value } = await reader.read()
|
|
314
|
-
if (done) break
|
|
315
|
-
if (value) chunks.push(value)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
|
|
319
|
-
const result = new Uint8Array(totalLength)
|
|
320
|
-
let offset = 0
|
|
321
|
-
for (const chunk of chunks) {
|
|
322
|
-
result.set(chunk, offset)
|
|
323
|
-
offset += chunk.length
|
|
324
|
-
}
|
|
325
|
-
return result.buffer
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
throw new Error('Unsupported file input type')
|
|
329
|
-
}
|
|
330
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error thrown when a graph operation fails (as reported by the server)
|
|
3
|
-
* This is distinct from connection/SSE errors
|
|
4
|
-
*/
|
|
5
|
-
export declare class GraphOperationError extends Error {
|
|
6
|
-
constructor(message: string);
|
|
7
|
-
}
|
|
8
|
-
export interface GraphMetadataInput {
|
|
9
|
-
graphName: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
schemaExtensions?: string[];
|
|
12
|
-
tags?: string[];
|
|
13
|
-
}
|
|
14
|
-
export interface InitialEntityInput {
|
|
15
|
-
name: string;
|
|
16
|
-
uri: string;
|
|
17
|
-
category?: string;
|
|
18
|
-
sic?: string;
|
|
19
|
-
sicDescription?: string;
|
|
20
|
-
}
|
|
21
|
-
export interface GraphInfo {
|
|
22
|
-
graphId: string;
|
|
23
|
-
graphName: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
schemaExtensions?: string[];
|
|
26
|
-
tags?: string[];
|
|
27
|
-
createdAt?: string;
|
|
28
|
-
status?: string;
|
|
29
|
-
}
|
|
30
|
-
export interface CreateGraphOptions {
|
|
31
|
-
createEntity?: boolean;
|
|
32
|
-
timeout?: number;
|
|
33
|
-
pollInterval?: number;
|
|
34
|
-
onProgress?: (message: string) => void;
|
|
35
|
-
useSSE?: boolean;
|
|
36
|
-
}
|
|
37
|
-
export declare class GraphClient {
|
|
38
|
-
private operationClient;
|
|
39
|
-
private config;
|
|
40
|
-
constructor(config: {
|
|
41
|
-
baseUrl: string;
|
|
42
|
-
credentials?: 'include' | 'same-origin' | 'omit';
|
|
43
|
-
headers?: Record<string, string>;
|
|
44
|
-
token?: string;
|
|
45
|
-
});
|
|
46
|
-
/**
|
|
47
|
-
* Create a graph and wait for completion
|
|
48
|
-
*
|
|
49
|
-
* Uses SSE (Server-Sent Events) for real-time progress updates with
|
|
50
|
-
* automatic fallback to polling if SSE connection fails.
|
|
51
|
-
*
|
|
52
|
-
* @param metadata - Graph metadata (name, description, etc.)
|
|
53
|
-
* @param initialEntity - Optional initial entity to create
|
|
54
|
-
* @param options - Additional options including:
|
|
55
|
-
* - createEntity: Whether to create the entity node and upload initial data.
|
|
56
|
-
* Only applies when initialEntity is provided. Set to false to
|
|
57
|
-
* create graph without populating entity data (useful for file-based ingestion).
|
|
58
|
-
* Defaults to true.
|
|
59
|
-
* - timeout: Maximum time to wait in milliseconds (default: 60000)
|
|
60
|
-
* - pollInterval: Time between status checks in milliseconds (default: 2000, for polling fallback)
|
|
61
|
-
* - onProgress: Callback for progress updates
|
|
62
|
-
* - useSSE: Whether to try SSE first (default: true). Falls back to polling on failure.
|
|
63
|
-
* @returns The graph ID when creation completes
|
|
64
|
-
*/
|
|
65
|
-
createGraphAndWait(metadata: GraphMetadataInput, initialEntity?: InitialEntityInput, options?: CreateGraphOptions): Promise<string>;
|
|
66
|
-
/**
|
|
67
|
-
* Wait for operation completion using SSE stream
|
|
68
|
-
*/
|
|
69
|
-
private waitWithSSE;
|
|
70
|
-
/**
|
|
71
|
-
* Wait for operation completion using polling
|
|
72
|
-
*/
|
|
73
|
-
private waitWithPolling;
|
|
74
|
-
/**
|
|
75
|
-
* Get information about a graph
|
|
76
|
-
*/
|
|
77
|
-
getGraphInfo(graphId: string): Promise<GraphInfo>;
|
|
78
|
-
/**
|
|
79
|
-
* List all graphs
|
|
80
|
-
*/
|
|
81
|
-
listGraphs(): Promise<GraphInfo[]>;
|
|
82
|
-
/**
|
|
83
|
-
* Delete a graph
|
|
84
|
-
* Note: This will be implemented when the deleteGraph endpoint is available in the SDK
|
|
85
|
-
*/
|
|
86
|
-
deleteGraph(_graphId: string): Promise<void>;
|
|
87
|
-
/**
|
|
88
|
-
* Clean up resources
|
|
89
|
-
*/
|
|
90
|
-
close(): void;
|
|
91
|
-
}
|
|
@@ -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/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;
|