@robosystems/client 0.2.0 → 0.2.1

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.
@@ -0,0 +1,267 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * Graph Management Client
5
+ * Provides high-level graph management operations with automatic operation monitoring
6
+ */
7
+
8
+ import { createGraph, getGraphs, getOperationStatus } from '../sdk.gen'
9
+ import type { GraphMetadata, InitialEntityData } from '../types.gen'
10
+ import { OperationClient } from './OperationClient'
11
+
12
+ // API Response Types
13
+ interface GraphCreateResponse {
14
+ graph_id?: string
15
+ operation_id?: string
16
+ }
17
+
18
+ interface OperationStatusResponse {
19
+ status?: 'pending' | 'completed' | 'failed' | string
20
+ result?: {
21
+ graph_id?: string
22
+ }
23
+ error?: string
24
+ message?: string
25
+ }
26
+
27
+ interface GraphApiData {
28
+ graph_id?: string
29
+ id?: string
30
+ graph_name?: string
31
+ name?: string
32
+ description?: string
33
+ schema_extensions?: string[]
34
+ tags?: string[]
35
+ created_at?: string
36
+ status?: string
37
+ }
38
+
39
+ interface GetGraphsResponse {
40
+ graphs?: GraphApiData[]
41
+ }
42
+
43
+ export interface GraphMetadataInput {
44
+ graphName: string
45
+ description?: string
46
+ schemaExtensions?: string[]
47
+ tags?: string[]
48
+ }
49
+
50
+ export interface InitialEntityInput {
51
+ name: string
52
+ uri: string
53
+ category?: string
54
+ sic?: string
55
+ sicDescription?: string
56
+ }
57
+
58
+ export interface GraphInfo {
59
+ graphId: string
60
+ graphName: string
61
+ description?: string
62
+ schemaExtensions?: string[]
63
+ tags?: string[]
64
+ createdAt?: string
65
+ status?: string
66
+ }
67
+
68
+ export interface CreateGraphOptions {
69
+ timeout?: number
70
+ pollInterval?: number
71
+ onProgress?: (message: string) => void
72
+ }
73
+
74
+ export class GraphClient {
75
+ private operationClient: OperationClient
76
+ private config: {
77
+ baseUrl: string
78
+ credentials?: 'include' | 'same-origin' | 'omit'
79
+ headers?: Record<string, string>
80
+ token?: string
81
+ }
82
+
83
+ constructor(config: {
84
+ baseUrl: string
85
+ credentials?: 'include' | 'same-origin' | 'omit'
86
+ headers?: Record<string, string>
87
+ token?: string
88
+ }) {
89
+ this.config = config
90
+ this.operationClient = new OperationClient(config)
91
+ }
92
+
93
+ /**
94
+ * Create a graph and wait for completion
95
+ */
96
+ async createGraphAndWait(
97
+ metadata: GraphMetadataInput,
98
+ initialEntity?: InitialEntityInput,
99
+ options: CreateGraphOptions = {}
100
+ ): Promise<string> {
101
+ const { timeout = 60000, pollInterval = 2000, onProgress } = options
102
+
103
+ if (!this.config.token) {
104
+ throw new Error('No API key provided. Set token in config.')
105
+ }
106
+
107
+ // Build initial entity if provided
108
+ let initialEntityData: InitialEntityData | undefined
109
+ if (initialEntity) {
110
+ initialEntityData = {
111
+ name: initialEntity.name,
112
+ uri: initialEntity.uri,
113
+ category: initialEntity.category,
114
+ sic: initialEntity.sic,
115
+ sic_description: initialEntity.sicDescription,
116
+ }
117
+ }
118
+
119
+ // Build API metadata
120
+ const apiMetadata: GraphMetadata = {
121
+ graph_name: metadata.graphName,
122
+ description: metadata.description,
123
+ schema_extensions: metadata.schemaExtensions || [],
124
+ tags: metadata.tags || [],
125
+ }
126
+
127
+ if (onProgress) {
128
+ onProgress(`Creating graph: ${metadata.graphName}`)
129
+ }
130
+
131
+ // Create graph request - SDK expects options format, not data format
132
+ const response = await createGraph({
133
+ body: {
134
+ metadata: apiMetadata,
135
+ initial_entity: initialEntityData || null,
136
+ },
137
+ })
138
+
139
+ // Check if we got immediate graph_id
140
+ const responseData = response.data as GraphCreateResponse
141
+ if (responseData?.graph_id) {
142
+ if (onProgress) {
143
+ onProgress(`Graph created: ${responseData.graph_id}`)
144
+ }
145
+ return responseData.graph_id
146
+ }
147
+
148
+ // Otherwise, we have an operation_id to monitor
149
+ if (responseData?.operation_id) {
150
+ const operationId = responseData.operation_id
151
+
152
+ if (onProgress) {
153
+ onProgress(`Graph creation queued (operation: ${operationId})`)
154
+ }
155
+
156
+ // Poll operation status
157
+ const maxAttempts = Math.floor(timeout / pollInterval)
158
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
159
+ await new Promise((resolve) => setTimeout(resolve, pollInterval))
160
+
161
+ const statusResponse = await getOperationStatus({
162
+ path: { operation_id: operationId },
163
+ })
164
+
165
+ const statusData = statusResponse.data as OperationStatusResponse
166
+ const status = statusData?.status
167
+
168
+ if (onProgress) {
169
+ onProgress(`Status: ${status} (attempt ${attempt + 1}/${maxAttempts})`)
170
+ }
171
+
172
+ if (status === 'completed') {
173
+ const result = statusData?.result
174
+ const graphId = result?.graph_id
175
+
176
+ if (graphId) {
177
+ if (onProgress) {
178
+ onProgress(`Graph created: ${graphId}`)
179
+ }
180
+ return graphId
181
+ } else {
182
+ throw new Error('Operation completed but no graph_id in result')
183
+ }
184
+ } else if (status === 'failed') {
185
+ const error = statusData?.error || statusData?.message || 'Unknown error'
186
+ throw new Error(`Graph creation failed: ${error}`)
187
+ }
188
+ }
189
+
190
+ throw new Error(`Graph creation timed out after ${timeout}ms`)
191
+ }
192
+
193
+ throw new Error('No graph_id or operation_id in response')
194
+ }
195
+
196
+ /**
197
+ * Get information about a graph
198
+ */
199
+ async getGraphInfo(graphId: string): Promise<GraphInfo> {
200
+ if (!this.config.token) {
201
+ throw new Error('No API key provided. Set token in config.')
202
+ }
203
+
204
+ // Use getGraphs to list all graphs and find the one we want
205
+ // Note: This is a workaround since there's no dedicated getGraph endpoint yet
206
+ const response = await getGraphs()
207
+ const graphs = (response.data as GetGraphsResponse)?.graphs || []
208
+
209
+ const graph = graphs.find((g) => g.graph_id === graphId || g.id === graphId)
210
+
211
+ if (!graph) {
212
+ throw new Error(`Graph not found: ${graphId}`)
213
+ }
214
+
215
+ return {
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
+ /**
227
+ * List all graphs
228
+ */
229
+ async listGraphs(): Promise<GraphInfo[]> {
230
+ if (!this.config.token) {
231
+ throw new Error('No API key provided. Set token in config.')
232
+ }
233
+
234
+ const response = await getGraphs()
235
+ const graphs = (response.data as GetGraphsResponse)?.graphs || []
236
+
237
+ return graphs.map((graph) => ({
238
+ graphId: graph.graph_id || graph.id,
239
+ graphName: graph.graph_name || graph.name,
240
+ description: graph.description,
241
+ schemaExtensions: graph.schema_extensions,
242
+ tags: graph.tags,
243
+ createdAt: graph.created_at,
244
+ status: graph.status,
245
+ }))
246
+ }
247
+
248
+ /**
249
+ * Delete a graph
250
+ * Note: This will be implemented when the deleteGraph endpoint is available in the SDK
251
+ */
252
+ async deleteGraph(graphId: string): Promise<void> {
253
+ throw new Error('deleteGraph is not yet implemented - waiting for SDK endpoint to be generated')
254
+ // TODO: Implement when deleteGraph endpoint is available
255
+ // const response = await deleteGraph({ path: { graph_id: graphId } })
256
+ // if (response.status !== 200 && response.status !== 204) {
257
+ // throw new Error(`Failed to delete graph: ${response.status}`)
258
+ // }
259
+ }
260
+
261
+ /**
262
+ * Clean up resources
263
+ */
264
+ close(): void {
265
+ this.operationClient.closeAll()
266
+ }
267
+ }
@@ -63,7 +63,7 @@ export declare function useStreamingQuery(graphId: string): {
63
63
  export declare function useOperation<T = any>(operationId?: string): {
64
64
  monitor: (id: string, timeout?: number) => Promise<OperationResult<T> | null>;
65
65
  cancel: (id: string) => Promise<void>;
66
- status: "error" | "idle" | "running" | "completed";
66
+ status: "error" | "completed" | "idle" | "running";
67
67
  progress: OperationProgress;
68
68
  error: Error;
69
69
  result: OperationResult<T>;
@@ -6,6 +6,7 @@ import { OperationClient } from './OperationClient';
6
6
  import { QueryClient } from './QueryClient';
7
7
  import { SSEClient } from './SSEClient';
8
8
  import { TableIngestClient } from './TableIngestClient';
9
+ import { GraphClient } from './GraphClient';
9
10
  export interface RoboSystemsExtensionConfig {
10
11
  baseUrl?: string;
11
12
  credentials?: 'include' | 'same-origin' | 'omit';
@@ -18,6 +19,7 @@ export declare class RoboSystemsExtensions {
18
19
  readonly query: QueryClient;
19
20
  readonly operations: OperationClient;
20
21
  readonly tables: TableIngestClient;
22
+ readonly graphs: GraphClient;
21
23
  private config;
22
24
  constructor(config?: RoboSystemsExtensionConfig);
23
25
  /**
@@ -37,11 +39,13 @@ export * from './OperationClient';
37
39
  export * from './QueryClient';
38
40
  export * from './SSEClient';
39
41
  export * from './TableIngestClient';
40
- export { OperationClient, QueryClient, SSEClient, TableIngestClient };
42
+ export * from './GraphClient';
43
+ export { OperationClient, QueryClient, SSEClient, TableIngestClient, GraphClient };
41
44
  export { useMultipleOperations, useOperation, useQuery, useSDKClients, useStreamingQuery, useTableUpload, } from './hooks';
42
45
  export declare const extensions: {
43
46
  readonly query: QueryClient;
44
47
  readonly operations: OperationClient;
48
+ readonly graphs: GraphClient;
45
49
  monitorOperation: (operationId: string, onProgress?: (progress: any) => void) => Promise<any>;
46
50
  createSSEClient: () => SSEClient;
47
51
  close: () => void;
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.streamQuery = exports.executeQuery = exports.monitorOperation = exports.extensions = exports.useTableUpload = exports.useStreamingQuery = exports.useSDKClients = exports.useQuery = exports.useOperation = exports.useMultipleOperations = exports.TableIngestClient = exports.SSEClient = exports.QueryClient = exports.OperationClient = exports.RoboSystemsExtensions = void 0;
21
+ exports.streamQuery = exports.executeQuery = exports.monitorOperation = exports.extensions = exports.useTableUpload = exports.useStreamingQuery = exports.useSDKClients = exports.useQuery = exports.useOperation = exports.useMultipleOperations = exports.GraphClient = exports.TableIngestClient = exports.SSEClient = exports.QueryClient = exports.OperationClient = exports.RoboSystemsExtensions = void 0;
22
22
  const client_gen_1 = require("../client.gen");
23
23
  const config_1 = require("./config");
24
24
  const OperationClient_1 = require("./OperationClient");
@@ -29,6 +29,8 @@ const SSEClient_1 = require("./SSEClient");
29
29
  Object.defineProperty(exports, "SSEClient", { enumerable: true, get: function () { return SSEClient_1.SSEClient; } });
30
30
  const TableIngestClient_1 = require("./TableIngestClient");
31
31
  Object.defineProperty(exports, "TableIngestClient", { enumerable: true, get: function () { return TableIngestClient_1.TableIngestClient; } });
32
+ const GraphClient_1 = require("./GraphClient");
33
+ Object.defineProperty(exports, "GraphClient", { enumerable: true, get: function () { return GraphClient_1.GraphClient; } });
32
34
  class RoboSystemsExtensions {
33
35
  constructor(config = {}) {
34
36
  // Get base URL from SDK client config or use provided/default
@@ -62,6 +64,12 @@ class RoboSystemsExtensions {
62
64
  token: this.config.token,
63
65
  headers: this.config.headers,
64
66
  });
67
+ this.graphs = new GraphClient_1.GraphClient({
68
+ baseUrl: this.config.baseUrl,
69
+ credentials: this.config.credentials,
70
+ token: this.config.token,
71
+ headers: this.config.headers,
72
+ });
65
73
  }
66
74
  /**
67
75
  * Convenience method to monitor any operation
@@ -88,6 +96,7 @@ class RoboSystemsExtensions {
88
96
  close() {
89
97
  this.query.close();
90
98
  this.operations.closeAll();
99
+ this.graphs.close();
91
100
  }
92
101
  }
93
102
  exports.RoboSystemsExtensions = RoboSystemsExtensions;
@@ -96,6 +105,7 @@ __exportStar(require("./OperationClient"), exports);
96
105
  __exportStar(require("./QueryClient"), exports);
97
106
  __exportStar(require("./SSEClient"), exports);
98
107
  __exportStar(require("./TableIngestClient"), exports);
108
+ __exportStar(require("./GraphClient"), exports);
99
109
  // Export React hooks
100
110
  var hooks_1 = require("./hooks");
101
111
  Object.defineProperty(exports, "useMultipleOperations", { enumerable: true, get: function () { return hooks_1.useMultipleOperations; } });
@@ -119,6 +129,9 @@ exports.extensions = {
119
129
  get operations() {
120
130
  return getExtensions().operations;
121
131
  },
132
+ get graphs() {
133
+ return getExtensions().graphs;
134
+ },
122
135
  monitorOperation: (operationId, onProgress) => getExtensions().monitorOperation(operationId, onProgress),
123
136
  createSSEClient: () => getExtensions().createSSEClient(),
124
137
  close: () => getExtensions().close(),
@@ -24,10 +24,12 @@ describe('RoboSystemsExtensions', () => {
24
24
  expect(extensions.query).toBeDefined()
25
25
  expect(extensions.operations).toBeDefined()
26
26
  expect(extensions.tables).toBeDefined()
27
+ expect(extensions.graphs).toBeDefined()
27
28
  // Verify clients have expected methods
28
29
  expect(typeof extensions.query.executeQuery).toBe('function')
29
30
  expect(typeof extensions.operations.monitorOperation).toBe('function')
30
31
  expect(typeof extensions.tables.uploadParquetFile).toBe('function')
32
+ expect(typeof extensions.graphs.createGraphAndWait).toBe('function')
31
33
  })
32
34
 
33
35
  it('should create instance with custom baseUrl', () => {
@@ -38,6 +40,7 @@ describe('RoboSystemsExtensions', () => {
38
40
  expect(extensions.query).toBeDefined()
39
41
  expect(extensions.operations).toBeDefined()
40
42
  expect(extensions.tables).toBeDefined()
43
+ expect(extensions.graphs).toBeDefined()
41
44
  })
42
45
 
43
46
  it('should create instance with JWT token', () => {
@@ -88,6 +91,7 @@ describe('RoboSystemsExtensions', () => {
88
91
  expect(extensions.query).toBeDefined()
89
92
  expect(extensions.operations).toBeDefined()
90
93
  expect(extensions.tables).toBeDefined()
94
+ expect(extensions.graphs).toBeDefined()
91
95
  })
92
96
  })
93
97
 
@@ -152,11 +156,13 @@ describe('RoboSystemsExtensions', () => {
152
156
 
153
157
  const queryCloseSpy = vi.spyOn(extensions.query, 'close')
154
158
  const operationsCloseSpy = vi.spyOn(extensions.operations, 'closeAll')
159
+ const graphsCloseSpy = vi.spyOn(extensions.graphs, 'close')
155
160
 
156
161
  extensions.close()
157
162
 
158
163
  expect(queryCloseSpy).toHaveBeenCalled()
159
164
  expect(operationsCloseSpy).toHaveBeenCalled()
165
+ expect(graphsCloseSpy).toHaveBeenCalled()
160
166
  })
161
167
 
162
168
  it('should not throw when called multiple times', () => {
@@ -188,9 +194,11 @@ describe('RoboSystemsExtensions', () => {
188
194
  expect(extensions.query).toBeDefined()
189
195
  expect(extensions.operations).toBeDefined()
190
196
  expect(extensions.tables).toBeDefined()
197
+ expect(extensions.graphs).toBeDefined()
191
198
  expect(typeof extensions.query.executeQuery).toBe('function')
192
199
  expect(typeof extensions.operations.monitorOperation).toBe('function')
193
200
  expect(typeof extensions.tables.uploadParquetFile).toBe('function')
201
+ expect(typeof extensions.graphs.createGraphAndWait).toBe('function')
194
202
  })
195
203
 
196
204
  it('should use SDK client baseUrl when no baseUrl provided', () => {
@@ -200,6 +208,20 @@ describe('RoboSystemsExtensions', () => {
200
208
  expect(extensions.query).toBeDefined()
201
209
  expect(extensions.operations).toBeDefined()
202
210
  expect(extensions.tables).toBeDefined()
211
+ expect(extensions.graphs).toBeDefined()
212
+ })
213
+ })
214
+
215
+ describe('graphs client', () => {
216
+ it('should have graphs client with all methods', () => {
217
+ const extensions = new RoboSystemsExtensions()
218
+
219
+ expect(extensions.graphs).toBeDefined()
220
+ expect(typeof extensions.graphs.createGraphAndWait).toBe('function')
221
+ expect(typeof extensions.graphs.getGraphInfo).toBe('function')
222
+ expect(typeof extensions.graphs.listGraphs).toBe('function')
223
+ expect(typeof extensions.graphs.deleteGraph).toBe('function')
224
+ expect(typeof extensions.graphs.close).toBe('function')
203
225
  })
204
226
  })
205
227
  })
@@ -9,6 +9,7 @@ import { OperationClient } from './OperationClient'
9
9
  import { QueryClient } from './QueryClient'
10
10
  import { SSEClient } from './SSEClient'
11
11
  import { TableIngestClient } from './TableIngestClient'
12
+ import { GraphClient } from './GraphClient'
12
13
 
13
14
  export interface RoboSystemsExtensionConfig {
14
15
  baseUrl?: string
@@ -33,6 +34,7 @@ export class RoboSystemsExtensions {
33
34
  public readonly query: QueryClient
34
35
  public readonly operations: OperationClient
35
36
  public readonly tables: TableIngestClient
37
+ public readonly graphs: GraphClient
36
38
  private config: ResolvedConfig
37
39
 
38
40
  constructor(config: RoboSystemsExtensionConfig = {}) {
@@ -72,6 +74,13 @@ export class RoboSystemsExtensions {
72
74
  token: this.config.token,
73
75
  headers: this.config.headers,
74
76
  })
77
+
78
+ this.graphs = new GraphClient({
79
+ baseUrl: this.config.baseUrl,
80
+ credentials: this.config.credentials,
81
+ token: this.config.token,
82
+ headers: this.config.headers,
83
+ })
75
84
  }
76
85
 
77
86
  /**
@@ -101,6 +110,7 @@ export class RoboSystemsExtensions {
101
110
  close(): void {
102
111
  this.query.close()
103
112
  this.operations.closeAll()
113
+ this.graphs.close()
104
114
  }
105
115
  }
106
116
 
@@ -109,7 +119,8 @@ export * from './OperationClient'
109
119
  export * from './QueryClient'
110
120
  export * from './SSEClient'
111
121
  export * from './TableIngestClient'
112
- export { OperationClient, QueryClient, SSEClient, TableIngestClient }
122
+ export * from './GraphClient'
123
+ export { OperationClient, QueryClient, SSEClient, TableIngestClient, GraphClient }
113
124
 
114
125
  // Export React hooks
115
126
  export {
@@ -138,6 +149,9 @@ export const extensions = {
138
149
  get operations() {
139
150
  return getExtensions().operations
140
151
  },
152
+ get graphs() {
153
+ return getExtensions().graphs
154
+ },
141
155
  monitorOperation: (operationId: string, onProgress?: (progress: any) => void) =>
142
156
  getExtensions().monitorOperation(operationId, onProgress),
143
157
  createSSEClient: () => getExtensions().createSSEClient(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/client",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "TypeScript client library for RoboSystems Financial Knowledge Graph API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -0,0 +1,58 @@
1
+ export interface GraphMetadataInput {
2
+ graphName: string;
3
+ description?: string;
4
+ schemaExtensions?: string[];
5
+ tags?: string[];
6
+ }
7
+ export interface InitialEntityInput {
8
+ name: string;
9
+ uri: string;
10
+ category?: string;
11
+ sic?: string;
12
+ sicDescription?: string;
13
+ }
14
+ export interface GraphInfo {
15
+ graphId: string;
16
+ graphName: string;
17
+ description?: string;
18
+ schemaExtensions?: string[];
19
+ tags?: string[];
20
+ createdAt?: string;
21
+ status?: string;
22
+ }
23
+ export interface CreateGraphOptions {
24
+ timeout?: number;
25
+ pollInterval?: number;
26
+ onProgress?: (message: string) => void;
27
+ }
28
+ export declare class GraphClient {
29
+ private operationClient;
30
+ private config;
31
+ constructor(config: {
32
+ baseUrl: string;
33
+ credentials?: 'include' | 'same-origin' | 'omit';
34
+ headers?: Record<string, string>;
35
+ token?: string;
36
+ });
37
+ /**
38
+ * Create a graph and wait for completion
39
+ */
40
+ createGraphAndWait(metadata: GraphMetadataInput, initialEntity?: InitialEntityInput, options?: CreateGraphOptions): Promise<string>;
41
+ /**
42
+ * Get information about a graph
43
+ */
44
+ getGraphInfo(graphId: string): Promise<GraphInfo>;
45
+ /**
46
+ * List all graphs
47
+ */
48
+ listGraphs(): Promise<GraphInfo[]>;
49
+ /**
50
+ * Delete a graph
51
+ * Note: This will be implemented when the deleteGraph endpoint is available in the SDK
52
+ */
53
+ deleteGraph(graphId: string): Promise<void>;
54
+ /**
55
+ * Clean up resources
56
+ */
57
+ close(): void;
58
+ }