@robosystems/client 0.2.6 → 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
|
@@ -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
|