@robosystems/client 0.2.5 → 0.2.7

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.
@@ -36,6 +36,7 @@ export declare class QueryClient {
36
36
  token?: string;
37
37
  });
38
38
  executeQuery(graphId: string, request: QueryRequest, options?: QueryOptions): Promise<QueryResult | AsyncIterableIterator<any>>;
39
+ private parseNDJSONResponse;
39
40
  private streamQueryResults;
40
41
  private waitForQueryCompletion;
41
42
  query(graphId: string, cypher: string, parameters?: Record<string, any>): Promise<QueryResult>;
@@ -27,6 +27,15 @@ class QueryClient {
27
27
  };
28
28
  // Execute the query
29
29
  const response = await (0, sdk_gen_1.executeCypherQuery)(data);
30
+ // Check if this is an NDJSON streaming response
31
+ // The SDK returns the response object which includes the raw Response
32
+ if (response.response) {
33
+ const contentType = response.response.headers.get('content-type') || '';
34
+ const streamFormat = response.response.headers.get('x-stream-format');
35
+ if (contentType.includes('application/x-ndjson') || streamFormat === 'ndjson') {
36
+ return this.parseNDJSONResponse(response.response, graphId);
37
+ }
38
+ }
30
39
  const responseData = response.data;
31
40
  // Check if this is an immediate response
32
41
  if (responseData?.data !== undefined && responseData?.columns) {
@@ -59,6 +68,51 @@ class QueryClient {
59
68
  // Unexpected response format
60
69
  throw new Error('Unexpected response format from query endpoint');
61
70
  }
71
+ async parseNDJSONResponse(response, graphId) {
72
+ const allData = [];
73
+ let columns = null;
74
+ let totalRows = 0;
75
+ let executionTimeMs = 0;
76
+ // Parse NDJSON line by line
77
+ const text = await response.text();
78
+ const lines = text.trim().split('\n');
79
+ for (const line of lines) {
80
+ if (!line.trim())
81
+ continue;
82
+ try {
83
+ const chunk = JSON.parse(line);
84
+ // Extract columns from first chunk
85
+ if (columns === null && chunk.columns) {
86
+ columns = chunk.columns;
87
+ }
88
+ // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
89
+ if (chunk.rows) {
90
+ allData.push(...chunk.rows);
91
+ totalRows += chunk.rows.length;
92
+ }
93
+ else if (chunk.data) {
94
+ allData.push(...chunk.data);
95
+ totalRows += chunk.data.length;
96
+ }
97
+ // Track execution time (use max from all chunks)
98
+ if (chunk.execution_time_ms) {
99
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms);
100
+ }
101
+ }
102
+ catch (error) {
103
+ throw new Error(`Failed to parse NDJSON line: ${error}`);
104
+ }
105
+ }
106
+ // Return aggregated result
107
+ return {
108
+ data: allData,
109
+ columns: columns || [],
110
+ row_count: totalRows,
111
+ execution_time_ms: executionTimeMs,
112
+ graph_id: graphId,
113
+ timestamp: new Date().toISOString(),
114
+ };
115
+ }
62
116
  async *streamQueryResults(operationId, options) {
63
117
  const buffer = [];
64
118
  let completed = false;
@@ -79,6 +79,18 @@ export class QueryClient {
79
79
 
80
80
  // Execute the query
81
81
  const response = await executeCypherQuery(data)
82
+
83
+ // Check if this is an NDJSON streaming response
84
+ // The SDK returns the response object which includes the raw Response
85
+ if (response.response) {
86
+ const contentType = response.response.headers.get('content-type') || ''
87
+ const streamFormat = response.response.headers.get('x-stream-format')
88
+
89
+ if (contentType.includes('application/x-ndjson') || streamFormat === 'ndjson') {
90
+ return this.parseNDJSONResponse(response.response, graphId)
91
+ }
92
+ }
93
+
82
94
  const responseData = response.data as any
83
95
 
84
96
  // Check if this is an immediate response
@@ -117,6 +129,56 @@ export class QueryClient {
117
129
  throw new Error('Unexpected response format from query endpoint')
118
130
  }
119
131
 
132
+ private async parseNDJSONResponse(response: Response, graphId: string): Promise<QueryResult> {
133
+ const allData: any[] = []
134
+ let columns: string[] | null = null
135
+ let totalRows = 0
136
+ let executionTimeMs = 0
137
+
138
+ // Parse NDJSON line by line
139
+ const text = await response.text()
140
+ const lines = text.trim().split('\n')
141
+
142
+ for (const line of lines) {
143
+ if (!line.trim()) continue
144
+
145
+ try {
146
+ const chunk = JSON.parse(line)
147
+
148
+ // Extract columns from first chunk
149
+ if (columns === null && chunk.columns) {
150
+ columns = chunk.columns
151
+ }
152
+
153
+ // Aggregate data rows (NDJSON uses "rows", regular JSON uses "data")
154
+ if (chunk.rows) {
155
+ allData.push(...chunk.rows)
156
+ totalRows += chunk.rows.length
157
+ } else if (chunk.data) {
158
+ allData.push(...chunk.data)
159
+ totalRows += chunk.data.length
160
+ }
161
+
162
+ // Track execution time (use max from all chunks)
163
+ if (chunk.execution_time_ms) {
164
+ executionTimeMs = Math.max(executionTimeMs, chunk.execution_time_ms)
165
+ }
166
+ } catch (error) {
167
+ throw new Error(`Failed to parse NDJSON line: ${error}`)
168
+ }
169
+ }
170
+
171
+ // Return aggregated result
172
+ return {
173
+ data: allData,
174
+ columns: columns || [],
175
+ row_count: totalRows,
176
+ execution_time_ms: executionTimeMs,
177
+ graph_id: graphId,
178
+ timestamp: new Date().toISOString(),
179
+ }
180
+ }
181
+
120
182
  private async *streamQueryResults(
121
183
  operationId: string,
122
184
  options: QueryOptions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/client",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "TypeScript client library for RoboSystems Financial Knowledge Graph API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",