@robosystems/client 0.2.48 → 0.3.0
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/InvestorClient.d.ts +91 -0
- package/extensions/InvestorClient.js +223 -0
- package/extensions/InvestorClient.ts +501 -0
- package/extensions/LedgerClient.d.ts +213 -165
- package/extensions/LedgerClient.js +315 -393
- package/extensions/LedgerClient.ts +887 -564
- package/extensions/ReportClient.d.ts +77 -115
- package/extensions/ReportClient.js +124 -211
- package/extensions/ReportClient.ts +298 -358
- package/extensions/config.js +1 -1
- package/extensions/config.ts +1 -1
- package/extensions/graphql/client.d.ts +46 -0
- package/extensions/graphql/client.js +75 -0
- package/extensions/graphql/client.ts +82 -0
- package/extensions/graphql/generated/graphql.d.ts +1786 -0
- package/extensions/graphql/generated/graphql.js +2671 -0
- package/extensions/graphql/generated/graphql.ts +4491 -0
- package/extensions/graphql/queries/investor/holdings.d.ts +8 -0
- package/extensions/graphql/queries/investor/holdings.js +36 -0
- package/extensions/graphql/queries/investor/holdings.ts +34 -0
- package/extensions/graphql/queries/investor/portfolio.d.ts +4 -0
- package/extensions/graphql/queries/investor/portfolio.js +21 -0
- package/extensions/graphql/queries/investor/portfolio.ts +19 -0
- package/extensions/graphql/queries/investor/portfolios.d.ts +4 -0
- package/extensions/graphql/queries/investor/portfolios.js +29 -0
- package/extensions/graphql/queries/investor/portfolios.ts +27 -0
- package/extensions/graphql/queries/investor/position.d.ts +4 -0
- package/extensions/graphql/queries/investor/position.js +33 -0
- package/extensions/graphql/queries/investor/position.ts +31 -0
- package/extensions/graphql/queries/investor/positions.d.ts +8 -0
- package/extensions/graphql/queries/investor/positions.js +57 -0
- package/extensions/graphql/queries/investor/positions.ts +55 -0
- package/extensions/graphql/queries/investor/securities.d.ts +8 -0
- package/extensions/graphql/queries/investor/securities.js +50 -0
- package/extensions/graphql/queries/investor/securities.ts +48 -0
- package/extensions/graphql/queries/investor/security.d.ts +4 -0
- package/extensions/graphql/queries/investor/security.js +26 -0
- package/extensions/graphql/queries/investor/security.ts +24 -0
- package/extensions/graphql/queries/ledger/accountRollups.d.ts +7 -0
- package/extensions/graphql/queries/ledger/accountRollups.js +36 -0
- package/extensions/graphql/queries/ledger/accountRollups.ts +34 -0
- package/extensions/graphql/queries/ledger/accountTree.d.ts +11 -0
- package/extensions/graphql/queries/ledger/accountTree.js +61 -0
- package/extensions/graphql/queries/ledger/accountTree.ts +59 -0
- package/extensions/graphql/queries/ledger/accounts.d.ts +8 -0
- package/extensions/graphql/queries/ledger/accounts.js +45 -0
- package/extensions/graphql/queries/ledger/accounts.ts +43 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.d.ts +6 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.js +27 -0
- package/extensions/graphql/queries/ledger/closingBookStructures.ts +25 -0
- package/extensions/graphql/queries/ledger/elements.d.ts +6 -0
- package/extensions/graphql/queries/ledger/elements.js +56 -0
- package/extensions/graphql/queries/ledger/elements.ts +54 -0
- package/extensions/graphql/queries/ledger/entities.d.ts +7 -0
- package/extensions/graphql/queries/ledger/entities.js +31 -0
- package/extensions/graphql/queries/ledger/entities.ts +29 -0
- package/extensions/graphql/queries/ledger/entity.d.ts +14 -0
- package/extensions/graphql/queries/ledger/entity.js +55 -0
- package/extensions/graphql/queries/ledger/entity.ts +54 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.d.ts +8 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.js +35 -0
- package/extensions/graphql/queries/ledger/fiscalCalendar.ts +33 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.d.ts +9 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.js +29 -0
- package/extensions/graphql/queries/ledger/mappedTrialBalance.ts +27 -0
- package/extensions/graphql/queries/ledger/mapping.d.ts +5 -0
- package/extensions/graphql/queries/ledger/mapping.js +35 -0
- package/extensions/graphql/queries/ledger/mapping.ts +33 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.d.ts +5 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.js +22 -0
- package/extensions/graphql/queries/ledger/mappingCoverage.ts +20 -0
- package/extensions/graphql/queries/ledger/mappings.d.ts +6 -0
- package/extensions/graphql/queries/ledger/mappings.js +23 -0
- package/extensions/graphql/queries/ledger/mappings.ts +21 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.d.ts +6 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.js +29 -0
- package/extensions/graphql/queries/ledger/periodCloseStatus.ts +27 -0
- package/extensions/graphql/queries/ledger/periodDrafts.d.ts +8 -0
- package/extensions/graphql/queries/ledger/periodDrafts.js +45 -0
- package/extensions/graphql/queries/ledger/periodDrafts.ts +43 -0
- package/extensions/graphql/queries/ledger/publishList.d.ts +5 -0
- package/extensions/graphql/queries/ledger/publishList.js +29 -0
- package/extensions/graphql/queries/ledger/publishList.ts +27 -0
- package/extensions/graphql/queries/ledger/publishLists.d.ts +5 -0
- package/extensions/graphql/queries/ledger/publishLists.js +29 -0
- package/extensions/graphql/queries/ledger/publishLists.ts +27 -0
- package/extensions/graphql/queries/ledger/report.d.ts +5 -0
- package/extensions/graphql/queries/ledger/report.js +40 -0
- package/extensions/graphql/queries/ledger/report.ts +38 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.d.ts +6 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.js +27 -0
- package/extensions/graphql/queries/ledger/reportingTaxonomy.ts +25 -0
- package/extensions/graphql/queries/ledger/reports.d.ts +8 -0
- package/extensions/graphql/queries/ledger/reports.js +45 -0
- package/extensions/graphql/queries/ledger/reports.ts +43 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.d.ts +7 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.js +24 -0
- package/extensions/graphql/queries/ledger/scheduleFacts.ts +22 -0
- package/extensions/graphql/queries/ledger/schedules.d.ts +6 -0
- package/extensions/graphql/queries/ledger/schedules.js +24 -0
- package/extensions/graphql/queries/ledger/schedules.ts +22 -0
- package/extensions/graphql/queries/ledger/statement.d.ts +9 -0
- package/extensions/graphql/queries/ledger/statement.js +43 -0
- package/extensions/graphql/queries/ledger/statement.ts +41 -0
- package/extensions/graphql/queries/ledger/structures.d.ts +5 -0
- package/extensions/graphql/queries/ledger/structures.js +22 -0
- package/extensions/graphql/queries/ledger/structures.ts +20 -0
- package/extensions/graphql/queries/ledger/summary.d.ts +7 -0
- package/extensions/graphql/queries/ledger/summary.js +25 -0
- package/extensions/graphql/queries/ledger/summary.ts +23 -0
- package/extensions/graphql/queries/ledger/taxonomies.d.ts +5 -0
- package/extensions/graphql/queries/ledger/taxonomies.js +28 -0
- package/extensions/graphql/queries/ledger/taxonomies.ts +26 -0
- package/extensions/graphql/queries/ledger/transaction.d.ts +6 -0
- package/extensions/graphql/queries/ledger/transaction.js +49 -0
- package/extensions/graphql/queries/ledger/transaction.ts +47 -0
- package/extensions/graphql/queries/ledger/transactions.d.ts +7 -0
- package/extensions/graphql/queries/ledger/transactions.js +49 -0
- package/extensions/graphql/queries/ledger/transactions.ts +47 -0
- package/extensions/graphql/queries/ledger/trialBalance.d.ts +7 -0
- package/extensions/graphql/queries/ledger/trialBalance.js +28 -0
- package/extensions/graphql/queries/ledger/trialBalance.ts +26 -0
- package/extensions/graphql/queries/ledger/unmappedElements.d.ts +8 -0
- package/extensions/graphql/queries/ledger/unmappedElements.js +29 -0
- package/extensions/graphql/queries/ledger/unmappedElements.ts +27 -0
- package/extensions/hooks.d.ts +1 -1
- package/extensions/index.d.ts +5 -1
- package/extensions/index.js +13 -1
- package/extensions/index.ts +14 -0
- package/index.ts +2 -2
- package/package.json +14 -5
- package/sdk/index.d.ts +2 -2
- package/sdk/index.js +38 -65
- package/sdk/index.ts +2 -2
- package/sdk/sdk.gen.d.ts +101 -220
- package/sdk/sdk.gen.js +251 -445
- package/sdk/sdk.gen.ts +216 -409
- package/sdk/types.gen.d.ts +4586 -7045
- package/sdk/types.gen.ts +4702 -7334
- package/sdk.gen.d.ts +101 -220
- package/sdk.gen.js +251 -445
- package/sdk.gen.ts +216 -409
- package/types.gen.d.ts +4586 -7045
- package/types.gen.ts +4702 -7334
- package/extensions/AgentClient.test.ts +0 -403
- package/extensions/LedgerClient.test.ts +0 -1138
- package/extensions/OperationClient.test.ts +0 -365
- package/extensions/QueryClient.test.ts +0 -432
- package/extensions/ReportClient.test.ts +0 -828
- package/extensions/SSEClient.test.ts +0 -375
- package/extensions/config.test.ts +0 -199
- package/extensions/hooks.test.ts +0 -373
- package/extensions/index.test.ts +0 -420
- package/sdk-extensions/AgentClient.d.ts +0 -82
- package/sdk-extensions/AgentClient.js +0 -218
- package/sdk-extensions/AgentClient.test.ts +0 -403
- package/sdk-extensions/AgentClient.ts +0 -321
- package/sdk-extensions/LedgerClient.d.ts +0 -242
- package/sdk-extensions/LedgerClient.js +0 -496
- package/sdk-extensions/LedgerClient.test.ts +0 -1138
- package/sdk-extensions/LedgerClient.ts +0 -800
- package/sdk-extensions/OperationClient.d.ts +0 -65
- package/sdk-extensions/OperationClient.js +0 -251
- package/sdk-extensions/OperationClient.test.ts +0 -365
- package/sdk-extensions/OperationClient.ts +0 -324
- package/sdk-extensions/QueryClient.d.ts +0 -52
- package/sdk-extensions/QueryClient.js +0 -313
- package/sdk-extensions/QueryClient.test.ts +0 -432
- package/sdk-extensions/QueryClient.ts +0 -420
- package/sdk-extensions/README.md +0 -901
- package/sdk-extensions/ReportClient.d.ts +0 -151
- package/sdk-extensions/ReportClient.js +0 -278
- package/sdk-extensions/ReportClient.test.ts +0 -828
- package/sdk-extensions/ReportClient.ts +0 -486
- package/sdk-extensions/SSEClient.d.ts +0 -62
- package/sdk-extensions/SSEClient.js +0 -154
- package/sdk-extensions/SSEClient.test.ts +0 -375
- package/sdk-extensions/SSEClient.ts +0 -210
- package/sdk-extensions/config.d.ts +0 -57
- package/sdk-extensions/config.js +0 -152
- package/sdk-extensions/config.test.ts +0 -199
- package/sdk-extensions/config.ts +0 -175
- package/sdk-extensions/hooks.d.ts +0 -110
- package/sdk-extensions/hooks.js +0 -384
- package/sdk-extensions/hooks.test.ts +0 -373
- package/sdk-extensions/hooks.ts +0 -459
- package/sdk-extensions/index.d.ts +0 -63
- package/sdk-extensions/index.js +0 -164
- package/sdk-extensions/index.test.ts +0 -420
- package/sdk-extensions/index.ts +0 -203
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import { QueryClient, QueuedQueryError } from './QueryClient'
|
|
3
|
-
|
|
4
|
-
// Helper to create proper mock Response objects
|
|
5
|
-
function createMockResponse(data: any, options: { ok?: boolean; status?: number } = {}) {
|
|
6
|
-
return {
|
|
7
|
-
ok: options.ok ?? true,
|
|
8
|
-
status: options.status ?? 200,
|
|
9
|
-
statusText: options.status === 200 ? 'OK' : 'Error',
|
|
10
|
-
headers: new Headers({ 'content-type': 'application/json' }),
|
|
11
|
-
json: async () => data,
|
|
12
|
-
text: async () => JSON.stringify(data),
|
|
13
|
-
blob: async () => new Blob([JSON.stringify(data)]),
|
|
14
|
-
arrayBuffer: async () => new TextEncoder().encode(JSON.stringify(data)).buffer,
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe('QueryClient', () => {
|
|
19
|
-
let queryClient: QueryClient
|
|
20
|
-
let mockFetch: any
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
queryClient = new QueryClient({
|
|
24
|
-
baseUrl: 'http://localhost:8000',
|
|
25
|
-
headers: { 'X-API-Key': 'test-key' },
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
// Mock global fetch (also set globalThis for SDK client compatibility)
|
|
29
|
-
mockFetch = vi.fn()
|
|
30
|
-
global.fetch = mockFetch
|
|
31
|
-
globalThis.fetch = mockFetch
|
|
32
|
-
|
|
33
|
-
// Reset all mocks
|
|
34
|
-
vi.clearAllMocks()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
describe('executeQuery - immediate response', () => {
|
|
38
|
-
it('should execute a sync query successfully', async () => {
|
|
39
|
-
mockFetch.mockResolvedValueOnce(
|
|
40
|
-
createMockResponse({
|
|
41
|
-
data: [
|
|
42
|
-
{ name: 'Alice', age: 30 },
|
|
43
|
-
{ name: 'Bob', age: 25 },
|
|
44
|
-
],
|
|
45
|
-
columns: ['name', 'age'],
|
|
46
|
-
row_count: 2,
|
|
47
|
-
execution_time_ms: 45,
|
|
48
|
-
timestamp: '2025-01-01T00:00:00Z',
|
|
49
|
-
})
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const result = await queryClient.executeQuery('graph_123', {
|
|
53
|
-
query: 'MATCH (n:Person) RETURN n.name, n.age',
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
// Should be a QueryResult, not an iterator
|
|
57
|
-
expect(result).toHaveProperty('data')
|
|
58
|
-
expect(result).toHaveProperty('columns')
|
|
59
|
-
|
|
60
|
-
const queryResult = result as any
|
|
61
|
-
expect(queryResult.data).toHaveLength(2)
|
|
62
|
-
expect(queryResult.columns).toEqual(['name', 'age'])
|
|
63
|
-
expect(queryResult.row_count).toBe(2)
|
|
64
|
-
expect(queryResult.execution_time_ms).toBe(45)
|
|
65
|
-
expect(queryResult.graph_id).toBe('graph_123')
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('should handle query with parameters', async () => {
|
|
69
|
-
mockFetch.mockResolvedValueOnce(
|
|
70
|
-
createMockResponse({
|
|
71
|
-
data: [{ name: 'Alice' }],
|
|
72
|
-
columns: ['name'],
|
|
73
|
-
row_count: 1,
|
|
74
|
-
execution_time_ms: 20,
|
|
75
|
-
})
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
const result = await queryClient.executeQuery(
|
|
79
|
-
'graph_123',
|
|
80
|
-
{
|
|
81
|
-
query: 'MATCH (n:Person {age: $age}) RETURN n.name',
|
|
82
|
-
parameters: { age: 30 },
|
|
83
|
-
},
|
|
84
|
-
{ mode: 'sync' }
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
const queryResult = result as any
|
|
88
|
-
expect(queryResult.data).toHaveLength(1)
|
|
89
|
-
expect(queryResult.data[0].name).toBe('Alice')
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should default row_count if not provided', async () => {
|
|
93
|
-
mockFetch.mockResolvedValueOnce(
|
|
94
|
-
createMockResponse({
|
|
95
|
-
data: [{ a: 1 }, { b: 2 }, { c: 3 }],
|
|
96
|
-
columns: ['value'],
|
|
97
|
-
})
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
const result = await queryClient.executeQuery('graph_123', {
|
|
101
|
-
query: 'RETURN 1',
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
const queryResult = result as any
|
|
105
|
-
expect(queryResult.row_count).toBe(3) // Should default to data.length
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('should default execution_time_ms if not provided', async () => {
|
|
109
|
-
mockFetch.mockResolvedValueOnce(
|
|
110
|
-
createMockResponse({
|
|
111
|
-
data: [],
|
|
112
|
-
columns: [],
|
|
113
|
-
})
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
const result = await queryClient.executeQuery('graph_123', {
|
|
117
|
-
query: 'RETURN 1',
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
const queryResult = result as any
|
|
121
|
-
expect(queryResult.execution_time_ms).toBe(0)
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
describe('executeQuery - queued response', () => {
|
|
126
|
-
it('should throw QueuedQueryError when maxWait is 0', async () => {
|
|
127
|
-
mockFetch.mockResolvedValueOnce(
|
|
128
|
-
createMockResponse({
|
|
129
|
-
status: 'queued',
|
|
130
|
-
operation_id: 'op_123',
|
|
131
|
-
queue_position: 5,
|
|
132
|
-
estimated_wait_seconds: 30,
|
|
133
|
-
message: 'Query queued',
|
|
134
|
-
})
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
await expect(
|
|
138
|
-
queryClient.executeQuery(
|
|
139
|
-
'graph_123',
|
|
140
|
-
{ query: 'RETURN 1' },
|
|
141
|
-
{ maxWait: 0 } // Don't wait for queued queries
|
|
142
|
-
)
|
|
143
|
-
).rejects.toThrow(QueuedQueryError)
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
it('should call onQueueUpdate when query is queued', async () => {
|
|
147
|
-
mockFetch.mockResolvedValueOnce(
|
|
148
|
-
createMockResponse({
|
|
149
|
-
status: 'queued',
|
|
150
|
-
operation_id: 'op_123',
|
|
151
|
-
queue_position: 3,
|
|
152
|
-
estimated_wait_seconds: 15,
|
|
153
|
-
message: 'Query queued',
|
|
154
|
-
})
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
const queueUpdates: Array<{ position: number; wait: number }> = []
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
await queryClient.executeQuery(
|
|
161
|
-
'graph_123',
|
|
162
|
-
{ query: 'RETURN 1' },
|
|
163
|
-
{
|
|
164
|
-
maxWait: 0,
|
|
165
|
-
onQueueUpdate: (position, estimatedWait) => {
|
|
166
|
-
queueUpdates.push({ position, wait: estimatedWait })
|
|
167
|
-
},
|
|
168
|
-
}
|
|
169
|
-
)
|
|
170
|
-
} catch (error) {
|
|
171
|
-
// Expected to throw QueuedQueryError
|
|
172
|
-
expect(error).toBeInstanceOf(QueuedQueryError)
|
|
173
|
-
expect((error as QueuedQueryError).queueInfo.queue_position).toBe(3)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
expect(queueUpdates).toHaveLength(1)
|
|
177
|
-
expect(queueUpdates[0].position).toBe(3)
|
|
178
|
-
expect(queueUpdates[0].wait).toBe(15)
|
|
179
|
-
})
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
describe('executeQuery - error handling', () => {
|
|
183
|
-
it('should throw error for unexpected response format', async () => {
|
|
184
|
-
mockFetch.mockResolvedValueOnce(
|
|
185
|
-
createMockResponse({
|
|
186
|
-
unexpected: 'format',
|
|
187
|
-
})
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
await expect(queryClient.executeQuery('graph_123', { query: 'RETURN 1' })).rejects.toThrow(
|
|
191
|
-
'Unexpected response format'
|
|
192
|
-
)
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('should handle fetch errors', async () => {
|
|
196
|
-
mockFetch.mockRejectedValueOnce(new Error('Network error'))
|
|
197
|
-
|
|
198
|
-
await expect(queryClient.executeQuery('graph_123', { query: 'RETURN 1' })).rejects.toThrow(
|
|
199
|
-
'Network error'
|
|
200
|
-
)
|
|
201
|
-
})
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
describe('query (convenience method)', () => {
|
|
205
|
-
it('should execute a simple query', async () => {
|
|
206
|
-
mockFetch.mockResolvedValueOnce(
|
|
207
|
-
createMockResponse({
|
|
208
|
-
data: [{ result: 42 }],
|
|
209
|
-
columns: ['result'],
|
|
210
|
-
row_count: 1,
|
|
211
|
-
execution_time_ms: 10,
|
|
212
|
-
})
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
const result = await queryClient.query('graph_123', 'RETURN 42 as result')
|
|
216
|
-
|
|
217
|
-
expect(result.data).toHaveLength(1)
|
|
218
|
-
expect(result.data[0].result).toBe(42)
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('should execute query with parameters', async () => {
|
|
222
|
-
mockFetch.mockResolvedValueOnce(
|
|
223
|
-
createMockResponse({
|
|
224
|
-
data: [{ sum: 10 }],
|
|
225
|
-
columns: ['sum'],
|
|
226
|
-
row_count: 1,
|
|
227
|
-
execution_time_ms: 5,
|
|
228
|
-
})
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
const result = await queryClient.query('graph_123', 'RETURN $a + $b as sum', {
|
|
232
|
-
a: 3,
|
|
233
|
-
b: 7,
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
expect(result.data[0].sum).toBe(10)
|
|
237
|
-
})
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
describe('executeQuery - stream mode with NDJSON', () => {
|
|
241
|
-
it('should parse NDJSON streaming response', async () => {
|
|
242
|
-
const ndjsonBody = [
|
|
243
|
-
'{"columns":["name","age"],"rows":[["Alice",30],["Bob",25]]}',
|
|
244
|
-
'{"rows":[["Charlie",35]]}',
|
|
245
|
-
'',
|
|
246
|
-
].join('\n')
|
|
247
|
-
|
|
248
|
-
// Create a ReadableStream from the NDJSON string
|
|
249
|
-
const stream = new ReadableStream({
|
|
250
|
-
start(controller) {
|
|
251
|
-
controller.enqueue(new TextEncoder().encode(ndjsonBody))
|
|
252
|
-
controller.close()
|
|
253
|
-
},
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
const mockStreamResponse = {
|
|
257
|
-
data: undefined,
|
|
258
|
-
error: undefined,
|
|
259
|
-
response: {
|
|
260
|
-
ok: true,
|
|
261
|
-
status: 200,
|
|
262
|
-
headers: new Headers({ 'content-type': 'application/x-ndjson' }),
|
|
263
|
-
body: stream,
|
|
264
|
-
json: async () => ({}),
|
|
265
|
-
},
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Mock the SDK function via fetch
|
|
269
|
-
mockFetch.mockResolvedValueOnce({
|
|
270
|
-
ok: true,
|
|
271
|
-
status: 200,
|
|
272
|
-
headers: new Headers({ 'content-type': 'application/x-ndjson' }),
|
|
273
|
-
body: stream,
|
|
274
|
-
json: async () => mockStreamResponse,
|
|
275
|
-
text: async () => JSON.stringify(mockStreamResponse),
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
// We can't easily test the full stream mode through the SDK mock
|
|
279
|
-
// because the SDK parses the response. Test the NDJSON parser directly instead.
|
|
280
|
-
const parser = (queryClient as any).parseNDJSONResponse.bind(queryClient)
|
|
281
|
-
|
|
282
|
-
const ndjsonStream = new ReadableStream({
|
|
283
|
-
start(controller) {
|
|
284
|
-
controller.enqueue(
|
|
285
|
-
new TextEncoder().encode(
|
|
286
|
-
'{"columns":["name"],"rows":[["Alice"],["Bob"]]}\n{"rows":[["Charlie"]]}\n'
|
|
287
|
-
)
|
|
288
|
-
)
|
|
289
|
-
controller.close()
|
|
290
|
-
},
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
const mockResp = {
|
|
294
|
-
body: ndjsonStream,
|
|
295
|
-
headers: new Headers({ 'content-type': 'application/x-ndjson' }),
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const result = await parser(mockResp, 'graph_1')
|
|
299
|
-
|
|
300
|
-
expect(result.columns).toEqual(['name'])
|
|
301
|
-
expect(result.data).toEqual([['Alice'], ['Bob'], ['Charlie']])
|
|
302
|
-
expect(result.row_count).toBe(3)
|
|
303
|
-
expect(result.graph_id).toBe('graph_1')
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
it('should handle NDJSON with data key instead of rows', async () => {
|
|
307
|
-
const parser = (queryClient as any).parseNDJSONResponse.bind(queryClient)
|
|
308
|
-
|
|
309
|
-
const stream = new ReadableStream({
|
|
310
|
-
start(controller) {
|
|
311
|
-
controller.enqueue(
|
|
312
|
-
new TextEncoder().encode(
|
|
313
|
-
'{"columns":["id"],"data":[{"id":1},{"id":2}],"execution_time_ms":50}\n'
|
|
314
|
-
)
|
|
315
|
-
)
|
|
316
|
-
controller.close()
|
|
317
|
-
},
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
const result = await parser({ body: stream }, 'graph_1')
|
|
321
|
-
|
|
322
|
-
expect(result.data).toEqual([{ id: 1 }, { id: 2 }])
|
|
323
|
-
expect(result.row_count).toBe(2)
|
|
324
|
-
expect(result.execution_time_ms).toBe(50)
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
it('should throw on NDJSON parse errors', async () => {
|
|
328
|
-
const parser = (queryClient as any).parseNDJSONResponse.bind(queryClient)
|
|
329
|
-
|
|
330
|
-
const stream = new ReadableStream({
|
|
331
|
-
start(controller) {
|
|
332
|
-
controller.enqueue(new TextEncoder().encode('not valid json\n'))
|
|
333
|
-
controller.close()
|
|
334
|
-
},
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
await expect(parser({ body: stream }, 'graph_1')).rejects.toThrow('NDJSON parsing failed')
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
it('should throw when body is not readable', async () => {
|
|
341
|
-
const parser = (queryClient as any).parseNDJSONResponse.bind(queryClient)
|
|
342
|
-
|
|
343
|
-
await expect(parser({ body: null }, 'graph_1')).rejects.toThrow(
|
|
344
|
-
'Response body is not readable'
|
|
345
|
-
)
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
it('should track max execution_time_ms across chunks', async () => {
|
|
349
|
-
const parser = (queryClient as any).parseNDJSONResponse.bind(queryClient)
|
|
350
|
-
|
|
351
|
-
const stream = new ReadableStream({
|
|
352
|
-
start(controller) {
|
|
353
|
-
controller.enqueue(
|
|
354
|
-
new TextEncoder().encode(
|
|
355
|
-
'{"columns":["x"],"rows":[[1]],"execution_time_ms":10}\n' +
|
|
356
|
-
'{"rows":[[2]],"execution_time_ms":50}\n' +
|
|
357
|
-
'{"rows":[[3]],"execution_time_ms":25}\n'
|
|
358
|
-
)
|
|
359
|
-
)
|
|
360
|
-
controller.close()
|
|
361
|
-
},
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
const result = await parser({ body: stream }, 'graph_1')
|
|
365
|
-
|
|
366
|
-
expect(result.execution_time_ms).toBe(50) // max across chunks
|
|
367
|
-
expect(result.row_count).toBe(3)
|
|
368
|
-
})
|
|
369
|
-
})
|
|
370
|
-
|
|
371
|
-
describe('streamQuery', () => {
|
|
372
|
-
it('should yield all data items when result is non-streaming', async () => {
|
|
373
|
-
mockFetch.mockResolvedValueOnce(
|
|
374
|
-
createMockResponse({
|
|
375
|
-
data: [{ id: 1 }, { id: 2 }, { id: 3 }],
|
|
376
|
-
columns: ['id'],
|
|
377
|
-
row_count: 3,
|
|
378
|
-
execution_time_ms: 10,
|
|
379
|
-
})
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
const items: any[] = []
|
|
383
|
-
for await (const item of queryClient.streamQuery('graph_1', 'MATCH (n) RETURN n')) {
|
|
384
|
-
items.push(item)
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
expect(items).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }])
|
|
388
|
-
})
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
describe('close', () => {
|
|
392
|
-
it('should close without error when no SSE client exists', () => {
|
|
393
|
-
expect(() => queryClient.close()).not.toThrow()
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
it('should be safe to call multiple times', () => {
|
|
397
|
-
queryClient.close()
|
|
398
|
-
expect(() => queryClient.close()).not.toThrow()
|
|
399
|
-
})
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
describe('QueuedQueryError', () => {
|
|
403
|
-
it('should create error with queue info', () => {
|
|
404
|
-
const queueInfo = {
|
|
405
|
-
status: 'queued' as const,
|
|
406
|
-
operation_id: 'op_123',
|
|
407
|
-
queue_position: 5,
|
|
408
|
-
estimated_wait_seconds: 30,
|
|
409
|
-
message: 'Query queued',
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const error = new QueuedQueryError(queueInfo)
|
|
413
|
-
|
|
414
|
-
expect(error.message).toBe('Query was queued')
|
|
415
|
-
expect(error.name).toBe('QueuedQueryError')
|
|
416
|
-
expect(error.queueInfo).toEqual(queueInfo)
|
|
417
|
-
})
|
|
418
|
-
|
|
419
|
-
it('should be instanceof Error', () => {
|
|
420
|
-
const error = new QueuedQueryError({
|
|
421
|
-
status: 'queued',
|
|
422
|
-
operation_id: 'op_1',
|
|
423
|
-
queue_position: 1,
|
|
424
|
-
estimated_wait_seconds: 5,
|
|
425
|
-
message: 'Queued',
|
|
426
|
-
})
|
|
427
|
-
|
|
428
|
-
expect(error).toBeInstanceOf(Error)
|
|
429
|
-
expect(error).toBeInstanceOf(QueuedQueryError)
|
|
430
|
-
})
|
|
431
|
-
})
|
|
432
|
-
})
|