@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.
Files changed (190) hide show
  1. package/extensions/InvestorClient.d.ts +91 -0
  2. package/extensions/InvestorClient.js +223 -0
  3. package/extensions/InvestorClient.ts +501 -0
  4. package/extensions/LedgerClient.d.ts +213 -165
  5. package/extensions/LedgerClient.js +315 -393
  6. package/extensions/LedgerClient.ts +887 -564
  7. package/extensions/ReportClient.d.ts +77 -115
  8. package/extensions/ReportClient.js +124 -211
  9. package/extensions/ReportClient.ts +298 -358
  10. package/extensions/config.js +1 -1
  11. package/extensions/config.ts +1 -1
  12. package/extensions/graphql/client.d.ts +46 -0
  13. package/extensions/graphql/client.js +75 -0
  14. package/extensions/graphql/client.ts +82 -0
  15. package/extensions/graphql/generated/graphql.d.ts +1786 -0
  16. package/extensions/graphql/generated/graphql.js +2671 -0
  17. package/extensions/graphql/generated/graphql.ts +4491 -0
  18. package/extensions/graphql/queries/investor/holdings.d.ts +8 -0
  19. package/extensions/graphql/queries/investor/holdings.js +36 -0
  20. package/extensions/graphql/queries/investor/holdings.ts +34 -0
  21. package/extensions/graphql/queries/investor/portfolio.d.ts +4 -0
  22. package/extensions/graphql/queries/investor/portfolio.js +21 -0
  23. package/extensions/graphql/queries/investor/portfolio.ts +19 -0
  24. package/extensions/graphql/queries/investor/portfolios.d.ts +4 -0
  25. package/extensions/graphql/queries/investor/portfolios.js +29 -0
  26. package/extensions/graphql/queries/investor/portfolios.ts +27 -0
  27. package/extensions/graphql/queries/investor/position.d.ts +4 -0
  28. package/extensions/graphql/queries/investor/position.js +33 -0
  29. package/extensions/graphql/queries/investor/position.ts +31 -0
  30. package/extensions/graphql/queries/investor/positions.d.ts +8 -0
  31. package/extensions/graphql/queries/investor/positions.js +57 -0
  32. package/extensions/graphql/queries/investor/positions.ts +55 -0
  33. package/extensions/graphql/queries/investor/securities.d.ts +8 -0
  34. package/extensions/graphql/queries/investor/securities.js +50 -0
  35. package/extensions/graphql/queries/investor/securities.ts +48 -0
  36. package/extensions/graphql/queries/investor/security.d.ts +4 -0
  37. package/extensions/graphql/queries/investor/security.js +26 -0
  38. package/extensions/graphql/queries/investor/security.ts +24 -0
  39. package/extensions/graphql/queries/ledger/accountRollups.d.ts +7 -0
  40. package/extensions/graphql/queries/ledger/accountRollups.js +36 -0
  41. package/extensions/graphql/queries/ledger/accountRollups.ts +34 -0
  42. package/extensions/graphql/queries/ledger/accountTree.d.ts +11 -0
  43. package/extensions/graphql/queries/ledger/accountTree.js +61 -0
  44. package/extensions/graphql/queries/ledger/accountTree.ts +59 -0
  45. package/extensions/graphql/queries/ledger/accounts.d.ts +8 -0
  46. package/extensions/graphql/queries/ledger/accounts.js +45 -0
  47. package/extensions/graphql/queries/ledger/accounts.ts +43 -0
  48. package/extensions/graphql/queries/ledger/closingBookStructures.d.ts +6 -0
  49. package/extensions/graphql/queries/ledger/closingBookStructures.js +27 -0
  50. package/extensions/graphql/queries/ledger/closingBookStructures.ts +25 -0
  51. package/extensions/graphql/queries/ledger/elements.d.ts +6 -0
  52. package/extensions/graphql/queries/ledger/elements.js +56 -0
  53. package/extensions/graphql/queries/ledger/elements.ts +54 -0
  54. package/extensions/graphql/queries/ledger/entities.d.ts +7 -0
  55. package/extensions/graphql/queries/ledger/entities.js +31 -0
  56. package/extensions/graphql/queries/ledger/entities.ts +29 -0
  57. package/extensions/graphql/queries/ledger/entity.d.ts +14 -0
  58. package/extensions/graphql/queries/ledger/entity.js +55 -0
  59. package/extensions/graphql/queries/ledger/entity.ts +54 -0
  60. package/extensions/graphql/queries/ledger/fiscalCalendar.d.ts +8 -0
  61. package/extensions/graphql/queries/ledger/fiscalCalendar.js +35 -0
  62. package/extensions/graphql/queries/ledger/fiscalCalendar.ts +33 -0
  63. package/extensions/graphql/queries/ledger/mappedTrialBalance.d.ts +9 -0
  64. package/extensions/graphql/queries/ledger/mappedTrialBalance.js +29 -0
  65. package/extensions/graphql/queries/ledger/mappedTrialBalance.ts +27 -0
  66. package/extensions/graphql/queries/ledger/mapping.d.ts +5 -0
  67. package/extensions/graphql/queries/ledger/mapping.js +35 -0
  68. package/extensions/graphql/queries/ledger/mapping.ts +33 -0
  69. package/extensions/graphql/queries/ledger/mappingCoverage.d.ts +5 -0
  70. package/extensions/graphql/queries/ledger/mappingCoverage.js +22 -0
  71. package/extensions/graphql/queries/ledger/mappingCoverage.ts +20 -0
  72. package/extensions/graphql/queries/ledger/mappings.d.ts +6 -0
  73. package/extensions/graphql/queries/ledger/mappings.js +23 -0
  74. package/extensions/graphql/queries/ledger/mappings.ts +21 -0
  75. package/extensions/graphql/queries/ledger/periodCloseStatus.d.ts +6 -0
  76. package/extensions/graphql/queries/ledger/periodCloseStatus.js +29 -0
  77. package/extensions/graphql/queries/ledger/periodCloseStatus.ts +27 -0
  78. package/extensions/graphql/queries/ledger/periodDrafts.d.ts +8 -0
  79. package/extensions/graphql/queries/ledger/periodDrafts.js +45 -0
  80. package/extensions/graphql/queries/ledger/periodDrafts.ts +43 -0
  81. package/extensions/graphql/queries/ledger/publishList.d.ts +5 -0
  82. package/extensions/graphql/queries/ledger/publishList.js +29 -0
  83. package/extensions/graphql/queries/ledger/publishList.ts +27 -0
  84. package/extensions/graphql/queries/ledger/publishLists.d.ts +5 -0
  85. package/extensions/graphql/queries/ledger/publishLists.js +29 -0
  86. package/extensions/graphql/queries/ledger/publishLists.ts +27 -0
  87. package/extensions/graphql/queries/ledger/report.d.ts +5 -0
  88. package/extensions/graphql/queries/ledger/report.js +40 -0
  89. package/extensions/graphql/queries/ledger/report.ts +38 -0
  90. package/extensions/graphql/queries/ledger/reportingTaxonomy.d.ts +6 -0
  91. package/extensions/graphql/queries/ledger/reportingTaxonomy.js +27 -0
  92. package/extensions/graphql/queries/ledger/reportingTaxonomy.ts +25 -0
  93. package/extensions/graphql/queries/ledger/reports.d.ts +8 -0
  94. package/extensions/graphql/queries/ledger/reports.js +45 -0
  95. package/extensions/graphql/queries/ledger/reports.ts +43 -0
  96. package/extensions/graphql/queries/ledger/scheduleFacts.d.ts +7 -0
  97. package/extensions/graphql/queries/ledger/scheduleFacts.js +24 -0
  98. package/extensions/graphql/queries/ledger/scheduleFacts.ts +22 -0
  99. package/extensions/graphql/queries/ledger/schedules.d.ts +6 -0
  100. package/extensions/graphql/queries/ledger/schedules.js +24 -0
  101. package/extensions/graphql/queries/ledger/schedules.ts +22 -0
  102. package/extensions/graphql/queries/ledger/statement.d.ts +9 -0
  103. package/extensions/graphql/queries/ledger/statement.js +43 -0
  104. package/extensions/graphql/queries/ledger/statement.ts +41 -0
  105. package/extensions/graphql/queries/ledger/structures.d.ts +5 -0
  106. package/extensions/graphql/queries/ledger/structures.js +22 -0
  107. package/extensions/graphql/queries/ledger/structures.ts +20 -0
  108. package/extensions/graphql/queries/ledger/summary.d.ts +7 -0
  109. package/extensions/graphql/queries/ledger/summary.js +25 -0
  110. package/extensions/graphql/queries/ledger/summary.ts +23 -0
  111. package/extensions/graphql/queries/ledger/taxonomies.d.ts +5 -0
  112. package/extensions/graphql/queries/ledger/taxonomies.js +28 -0
  113. package/extensions/graphql/queries/ledger/taxonomies.ts +26 -0
  114. package/extensions/graphql/queries/ledger/transaction.d.ts +6 -0
  115. package/extensions/graphql/queries/ledger/transaction.js +49 -0
  116. package/extensions/graphql/queries/ledger/transaction.ts +47 -0
  117. package/extensions/graphql/queries/ledger/transactions.d.ts +7 -0
  118. package/extensions/graphql/queries/ledger/transactions.js +49 -0
  119. package/extensions/graphql/queries/ledger/transactions.ts +47 -0
  120. package/extensions/graphql/queries/ledger/trialBalance.d.ts +7 -0
  121. package/extensions/graphql/queries/ledger/trialBalance.js +28 -0
  122. package/extensions/graphql/queries/ledger/trialBalance.ts +26 -0
  123. package/extensions/graphql/queries/ledger/unmappedElements.d.ts +8 -0
  124. package/extensions/graphql/queries/ledger/unmappedElements.js +29 -0
  125. package/extensions/graphql/queries/ledger/unmappedElements.ts +27 -0
  126. package/extensions/hooks.d.ts +1 -1
  127. package/extensions/index.d.ts +5 -1
  128. package/extensions/index.js +13 -1
  129. package/extensions/index.ts +14 -0
  130. package/index.ts +2 -2
  131. package/package.json +14 -5
  132. package/sdk/index.d.ts +2 -2
  133. package/sdk/index.js +38 -65
  134. package/sdk/index.ts +2 -2
  135. package/sdk/sdk.gen.d.ts +101 -220
  136. package/sdk/sdk.gen.js +251 -445
  137. package/sdk/sdk.gen.ts +216 -409
  138. package/sdk/types.gen.d.ts +4586 -7045
  139. package/sdk/types.gen.ts +4702 -7334
  140. package/sdk.gen.d.ts +101 -220
  141. package/sdk.gen.js +251 -445
  142. package/sdk.gen.ts +216 -409
  143. package/types.gen.d.ts +4586 -7045
  144. package/types.gen.ts +4702 -7334
  145. package/extensions/AgentClient.test.ts +0 -403
  146. package/extensions/LedgerClient.test.ts +0 -1138
  147. package/extensions/OperationClient.test.ts +0 -365
  148. package/extensions/QueryClient.test.ts +0 -432
  149. package/extensions/ReportClient.test.ts +0 -828
  150. package/extensions/SSEClient.test.ts +0 -375
  151. package/extensions/config.test.ts +0 -199
  152. package/extensions/hooks.test.ts +0 -373
  153. package/extensions/index.test.ts +0 -420
  154. package/sdk-extensions/AgentClient.d.ts +0 -82
  155. package/sdk-extensions/AgentClient.js +0 -218
  156. package/sdk-extensions/AgentClient.test.ts +0 -403
  157. package/sdk-extensions/AgentClient.ts +0 -321
  158. package/sdk-extensions/LedgerClient.d.ts +0 -242
  159. package/sdk-extensions/LedgerClient.js +0 -496
  160. package/sdk-extensions/LedgerClient.test.ts +0 -1138
  161. package/sdk-extensions/LedgerClient.ts +0 -800
  162. package/sdk-extensions/OperationClient.d.ts +0 -65
  163. package/sdk-extensions/OperationClient.js +0 -251
  164. package/sdk-extensions/OperationClient.test.ts +0 -365
  165. package/sdk-extensions/OperationClient.ts +0 -324
  166. package/sdk-extensions/QueryClient.d.ts +0 -52
  167. package/sdk-extensions/QueryClient.js +0 -313
  168. package/sdk-extensions/QueryClient.test.ts +0 -432
  169. package/sdk-extensions/QueryClient.ts +0 -420
  170. package/sdk-extensions/README.md +0 -901
  171. package/sdk-extensions/ReportClient.d.ts +0 -151
  172. package/sdk-extensions/ReportClient.js +0 -278
  173. package/sdk-extensions/ReportClient.test.ts +0 -828
  174. package/sdk-extensions/ReportClient.ts +0 -486
  175. package/sdk-extensions/SSEClient.d.ts +0 -62
  176. package/sdk-extensions/SSEClient.js +0 -154
  177. package/sdk-extensions/SSEClient.test.ts +0 -375
  178. package/sdk-extensions/SSEClient.ts +0 -210
  179. package/sdk-extensions/config.d.ts +0 -57
  180. package/sdk-extensions/config.js +0 -152
  181. package/sdk-extensions/config.test.ts +0 -199
  182. package/sdk-extensions/config.ts +0 -175
  183. package/sdk-extensions/hooks.d.ts +0 -110
  184. package/sdk-extensions/hooks.js +0 -384
  185. package/sdk-extensions/hooks.test.ts +0 -373
  186. package/sdk-extensions/hooks.ts +0 -459
  187. package/sdk-extensions/index.d.ts +0 -63
  188. package/sdk-extensions/index.js +0 -164
  189. package/sdk-extensions/index.test.ts +0 -420
  190. package/sdk-extensions/index.ts +0 -203
@@ -1,65 +0,0 @@
1
- export interface OperationProgress {
2
- message: string;
3
- progressPercent?: number;
4
- details?: Record<string, any>;
5
- }
6
- export interface OperationResult<T = any> {
7
- success: boolean;
8
- result?: T;
9
- error?: string;
10
- metadata?: Record<string, any>;
11
- }
12
- export interface OperationMonitorOptions {
13
- onProgress?: (progress: OperationProgress) => void;
14
- onQueueUpdate?: (position: number, estimatedWait: number) => void;
15
- timeout?: number;
16
- }
17
- export declare class OperationClient {
18
- private sseClients;
19
- private cleanupTimeouts;
20
- private config;
21
- private cleanupIntervalMs;
22
- private cleanupInterval?;
23
- constructor(config: {
24
- baseUrl: string;
25
- credentials?: 'include' | 'same-origin' | 'omit';
26
- headers?: Record<string, string>;
27
- token?: string;
28
- maxRetries?: number;
29
- retryDelay?: number;
30
- });
31
- monitorOperation<T = any>(operationId: string, options?: OperationMonitorOptions): Promise<OperationResult<T>>;
32
- /**
33
- * Monitor multiple operations concurrently
34
- */
35
- monitorMultiple<T = any>(operationIds: string[], options?: OperationMonitorOptions): Promise<Map<string, OperationResult<T>>>;
36
- /**
37
- * Get the current status of an operation (point-in-time check)
38
- */
39
- getStatus(operationId: string): Promise<any>;
40
- /**
41
- * Cancel a pending or running operation
42
- */
43
- cancelOperation(operationId: string): Promise<void>;
44
- /**
45
- * Wait for an operation with a simple promise interface
46
- */
47
- waitForOperation<T = any>(operationId: string, timeoutMs?: number): Promise<T>;
48
- /**
49
- * Monitor operation with async iterator for progress updates
50
- */
51
- monitorWithProgress<T = any>(operationId: string): AsyncIterableIterator<OperationProgress | OperationResult<T>>;
52
- private cleanupClient;
53
- /**
54
- * Schedule automatic cleanup of SSE client after a delay
55
- */
56
- private scheduleCleanup;
57
- /**
58
- * Perform periodic cleanup of stale SSE connections
59
- */
60
- private performPeriodicCleanup;
61
- /**
62
- * Close all active SSE connections and clean up resources
63
- */
64
- closeAll(): void;
65
- }
@@ -1,251 +0,0 @@
1
- 'use client';
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.OperationClient = void 0;
5
- /**
6
- * General Operations Client for monitoring async operations
7
- * Handles graph creation, backups, imports, and other long-running tasks
8
- */
9
- const sdk_gen_1 = require("../sdk/sdk.gen");
10
- const SSEClient_1 = require("./SSEClient");
11
- class OperationClient {
12
- constructor(config) {
13
- this.sseClients = new Map();
14
- this.cleanupTimeouts = new Map();
15
- this.cleanupIntervalMs = 300000; // 5 minutes
16
- this.config = config;
17
- // Start periodic cleanup check every 5 minutes
18
- this.cleanupInterval = setInterval(() => {
19
- this.performPeriodicCleanup();
20
- }, this.cleanupIntervalMs);
21
- }
22
- async monitorOperation(operationId, options = {}) {
23
- return new Promise((resolve, reject) => {
24
- const sseClient = new SSEClient_1.SSEClient(this.config);
25
- this.sseClients.set(operationId, sseClient);
26
- const timeoutHandle = options.timeout
27
- ? setTimeout(() => {
28
- this.cleanupClient(operationId);
29
- reject(new Error(`Operation timeout after ${options.timeout}ms`));
30
- }, options.timeout)
31
- : undefined;
32
- sseClient
33
- .connect(operationId)
34
- .then(() => {
35
- let result = { success: false };
36
- // Track queue updates
37
- if (options.onQueueUpdate) {
38
- sseClient.on(SSEClient_1.EventType.QUEUE_UPDATE, (data) => {
39
- options.onQueueUpdate(data.position || data.queue_position, data.estimated_wait_seconds || 0);
40
- });
41
- }
42
- // Track progress
43
- if (options.onProgress) {
44
- sseClient.on(SSEClient_1.EventType.OPERATION_PROGRESS, (data) => {
45
- options.onProgress({
46
- message: data.message || data.status || 'Processing...',
47
- progressPercent: data.progress_percent || data.progress,
48
- details: data,
49
- });
50
- });
51
- }
52
- // Handle completion
53
- sseClient.on(SSEClient_1.EventType.OPERATION_COMPLETED, (data) => {
54
- if (timeoutHandle)
55
- clearTimeout(timeoutHandle);
56
- result = {
57
- success: true,
58
- result: data.result || data,
59
- metadata: data.metadata,
60
- };
61
- // Schedule cleanup after a short delay to ensure all data is received
62
- this.scheduleCleanup(operationId, 5000);
63
- resolve(result);
64
- });
65
- // Handle errors
66
- sseClient.on(SSEClient_1.EventType.OPERATION_ERROR, (error) => {
67
- if (timeoutHandle)
68
- clearTimeout(timeoutHandle);
69
- result = {
70
- success: false,
71
- error: error.message || error.error || 'Operation failed',
72
- metadata: error.metadata,
73
- };
74
- // Schedule cleanup after a short delay
75
- this.scheduleCleanup(operationId, 5000);
76
- resolve(result); // Resolve with error result, not reject
77
- });
78
- // Handle cancellation
79
- sseClient.on(SSEClient_1.EventType.OPERATION_CANCELLED, (data) => {
80
- if (timeoutHandle)
81
- clearTimeout(timeoutHandle);
82
- result = {
83
- success: false,
84
- error: 'Operation cancelled',
85
- metadata: data,
86
- };
87
- // Schedule cleanup after a short delay
88
- this.scheduleCleanup(operationId, 5000);
89
- resolve(result);
90
- });
91
- })
92
- .catch((error) => {
93
- if (timeoutHandle)
94
- clearTimeout(timeoutHandle);
95
- this.cleanupClient(operationId);
96
- reject(error);
97
- });
98
- });
99
- }
100
- /**
101
- * Monitor multiple operations concurrently
102
- */
103
- async monitorMultiple(operationIds, options = {}) {
104
- const results = await Promise.all(operationIds.map(async (id) => {
105
- const result = await this.monitorOperation(id, options);
106
- return [id, result];
107
- }));
108
- return new Map(results);
109
- }
110
- /**
111
- * Get the current status of an operation (point-in-time check)
112
- */
113
- async getStatus(operationId) {
114
- const response = await (0, sdk_gen_1.getOperationStatus)({
115
- path: { operation_id: operationId },
116
- });
117
- return response.data;
118
- }
119
- /**
120
- * Cancel a pending or running operation
121
- */
122
- async cancelOperation(operationId) {
123
- // First close any active SSE connection
124
- this.cleanupClient(operationId);
125
- // Then cancel the operation
126
- await (0, sdk_gen_1.cancelOperation)({
127
- path: { operation_id: operationId },
128
- });
129
- }
130
- /**
131
- * Wait for an operation with a simple promise interface
132
- */
133
- async waitForOperation(operationId, timeoutMs) {
134
- const result = await this.monitorOperation(operationId, {
135
- timeout: timeoutMs,
136
- });
137
- if (!result.success) {
138
- throw new Error(result.error || 'Operation failed');
139
- }
140
- return result.result;
141
- }
142
- /**
143
- * Monitor operation with async iterator for progress updates
144
- */
145
- async *monitorWithProgress(operationId) {
146
- const progressQueue = [];
147
- let completed = false;
148
- let finalResult = null;
149
- // Start monitoring in background
150
- const monitorPromise = this.monitorOperation(operationId, {
151
- onProgress: (progress) => {
152
- progressQueue.push(progress);
153
- },
154
- onQueueUpdate: (position, estimatedWait) => {
155
- progressQueue.push({
156
- message: `Queue position: ${position}`,
157
- progressPercent: 0,
158
- details: { position, estimatedWait },
159
- });
160
- },
161
- });
162
- // Handle completion
163
- monitorPromise
164
- .then((result) => {
165
- finalResult = result;
166
- completed = true;
167
- })
168
- .catch((error) => {
169
- finalResult = {
170
- success: false,
171
- error: error.message,
172
- };
173
- completed = true;
174
- });
175
- // Yield progress updates as they come
176
- while (!completed || progressQueue.length > 0) {
177
- if (progressQueue.length > 0) {
178
- yield progressQueue.shift();
179
- }
180
- else if (!completed) {
181
- // Wait for more progress
182
- await new Promise((resolve) => setTimeout(resolve, 100));
183
- }
184
- }
185
- // Yield final result
186
- if (finalResult) {
187
- yield finalResult;
188
- }
189
- }
190
- cleanupClient(operationId) {
191
- const client = this.sseClients.get(operationId);
192
- if (client) {
193
- client.close();
194
- this.sseClients.delete(operationId);
195
- }
196
- // Clear any cleanup timeout for this operation
197
- const timeout = this.cleanupTimeouts.get(operationId);
198
- if (timeout) {
199
- clearTimeout(timeout);
200
- this.cleanupTimeouts.delete(operationId);
201
- }
202
- }
203
- /**
204
- * Schedule automatic cleanup of SSE client after a delay
205
- */
206
- scheduleCleanup(operationId, delayMs = 60000) {
207
- // Clear any existing timeout
208
- const existingTimeout = this.cleanupTimeouts.get(operationId);
209
- if (existingTimeout) {
210
- clearTimeout(existingTimeout);
211
- }
212
- // Schedule new cleanup
213
- const timeout = setTimeout(() => {
214
- this.cleanupClient(operationId);
215
- this.cleanupTimeouts.delete(operationId);
216
- }, delayMs);
217
- this.cleanupTimeouts.set(operationId, timeout);
218
- }
219
- /**
220
- * Perform periodic cleanup of stale SSE connections
221
- */
222
- performPeriodicCleanup() {
223
- // Check each SSE client for staleness
224
- this.sseClients.forEach((client, operationId) => {
225
- if (!client.isConnected()) {
226
- // Clean up disconnected clients immediately
227
- this.cleanupClient(operationId);
228
- }
229
- });
230
- }
231
- /**
232
- * Close all active SSE connections and clean up resources
233
- */
234
- closeAll() {
235
- // Clear periodic cleanup interval
236
- if (this.cleanupInterval) {
237
- clearInterval(this.cleanupInterval);
238
- this.cleanupInterval = undefined;
239
- }
240
- // Clear all cleanup timeouts
241
- this.cleanupTimeouts.forEach((timeout) => {
242
- clearTimeout(timeout);
243
- });
244
- this.cleanupTimeouts.clear();
245
- // Close all SSE clients
246
- this.sseClients.forEach((client, operationId) => {
247
- this.cleanupClient(operationId);
248
- });
249
- }
250
- }
251
- exports.OperationClient = OperationClient;
@@ -1,365 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
- import { OperationClient } from './OperationClient'
3
- import { EventType } from './SSEClient'
4
-
5
- // Mock EventSource for SSE tests
6
- class MockEventSource {
7
- url: string
8
- withCredentials: boolean
9
- readyState: number = 0
10
- onopen: ((event: any) => void) | null = null
11
- onerror: ((event: any) => void) | null = null
12
- onmessage: ((event: any) => void) | null = null
13
- private eventListeners: Map<string, Set<(event: any) => void>> = new Map()
14
-
15
- static CONNECTING = 0
16
- static OPEN = 1
17
- static CLOSED = 2
18
-
19
- constructor(url: string, options?: { withCredentials?: boolean }) {
20
- this.url = url
21
- this.withCredentials = options?.withCredentials ?? false
22
- setTimeout(() => {
23
- this.readyState = MockEventSource.OPEN
24
- if (this.onopen) {
25
- this.onopen({ type: 'open' })
26
- }
27
- }, 0)
28
- }
29
-
30
- addEventListener(event: string, listener: (event: any) => void) {
31
- if (!this.eventListeners.has(event)) {
32
- this.eventListeners.set(event, new Set())
33
- }
34
- this.eventListeners.get(event)!.add(listener)
35
- }
36
-
37
- removeEventListener(event: string, listener: (event: any) => void) {
38
- const listeners = this.eventListeners.get(event)
39
- if (listeners) listeners.delete(listener)
40
- }
41
-
42
- dispatchEvent(event: any) {
43
- const listeners = this.eventListeners.get(event.type)
44
- if (listeners) listeners.forEach((l) => l(event))
45
- return true
46
- }
47
-
48
- close() {
49
- this.readyState = MockEventSource.CLOSED
50
- }
51
-
52
- simulateMessage(eventType: string, data: any) {
53
- const event = { type: eventType, data: JSON.stringify(data), lastEventId: '' }
54
- const listeners = this.eventListeners.get(eventType)
55
- if (listeners) listeners.forEach((l) => l(event))
56
- }
57
- }
58
-
59
- // Helper to create proper mock Response objects
60
- function createMockResponse(data: any, options: { ok?: boolean; status?: number } = {}) {
61
- return {
62
- ok: options.ok ?? true,
63
- status: options.status ?? 200,
64
- statusText: options.status === 200 ? 'OK' : 'Error',
65
- headers: new Headers({ 'content-type': 'application/json' }),
66
- json: async () => data,
67
- text: async () => JSON.stringify(data),
68
- blob: async () => new Blob([JSON.stringify(data)]),
69
- arrayBuffer: async () => new TextEncoder().encode(JSON.stringify(data)).buffer,
70
- }
71
- }
72
-
73
- describe('OperationClient', () => {
74
- let operationClient: OperationClient
75
- let mockFetch: any
76
-
77
- beforeEach(() => {
78
- operationClient = new OperationClient({
79
- baseUrl: 'http://localhost:8000',
80
- headers: { 'X-API-Key': 'test-key' },
81
- })
82
-
83
- // Mock global fetch
84
- mockFetch = vi.fn()
85
- global.fetch = mockFetch
86
-
87
- // Reset all mocks
88
- vi.clearAllMocks()
89
- })
90
-
91
- afterEach(() => {
92
- // Clean up any active operations
93
- operationClient.closeAll()
94
- })
95
-
96
- describe('constructor', () => {
97
- it('should create an OperationClient with config', () => {
98
- const client = new OperationClient({
99
- baseUrl: 'https://api.example.com',
100
- token: 'test-token',
101
- maxRetries: 5,
102
- retryDelay: 2000,
103
- })
104
-
105
- expect(client).toBeInstanceOf(OperationClient)
106
- })
107
- })
108
-
109
- describe('getStatus', () => {
110
- it('should get operation status', async () => {
111
- mockFetch.mockResolvedValueOnce(
112
- createMockResponse({
113
- operation_id: 'op_123',
114
- status: 'running',
115
- progress_percent: 50,
116
- message: 'Processing...',
117
- })
118
- )
119
-
120
- const status = await operationClient.getStatus('op_123')
121
-
122
- expect(status.operation_id).toBe('op_123')
123
- expect(status.status).toBe('running')
124
- expect(status.progress_percent).toBe(50)
125
- })
126
-
127
- it('should handle errors when getting status', async () => {
128
- mockFetch.mockResolvedValueOnce(
129
- createMockResponse({ detail: 'Operation not found' }, { ok: false, status: 404 })
130
- )
131
-
132
- const status = await operationClient.getStatus('op_nonexistent')
133
-
134
- // The SDK might return undefined for error responses
135
- // We just need to verify the call doesn't throw
136
- expect(mockFetch).toHaveBeenCalledTimes(1)
137
- })
138
- })
139
-
140
- describe('cancelOperation', () => {
141
- it('should cancel an operation', async () => {
142
- mockFetch.mockResolvedValueOnce(
143
- createMockResponse({
144
- operation_id: 'op_123',
145
- status: 'cancelled',
146
- })
147
- )
148
-
149
- await expect(operationClient.cancelOperation('op_123')).resolves.toBeUndefined()
150
- })
151
- })
152
-
153
- describe('closeAll', () => {
154
- it('should close all active connections', () => {
155
- // Create a client
156
- const client = new OperationClient({
157
- baseUrl: 'http://localhost:8000',
158
- })
159
-
160
- // closeAll should complete without error
161
- expect(() => client.closeAll()).not.toThrow()
162
- })
163
-
164
- it('should be safe to call closeAll multiple times', () => {
165
- const client = new OperationClient({
166
- baseUrl: 'http://localhost:8000',
167
- })
168
-
169
- client.closeAll()
170
- expect(() => client.closeAll()).not.toThrow()
171
- })
172
- })
173
-
174
- describe('monitorMultiple', () => {
175
- it('should reject if no operation IDs provided', async () => {
176
- const results = await operationClient.monitorMultiple([])
177
- expect(results.size).toBe(0)
178
- })
179
- })
180
-
181
- describe('monitorOperation', () => {
182
- beforeEach(() => {
183
- global.EventSource = MockEventSource as any
184
- })
185
-
186
- it('should resolve with success on OPERATION_COMPLETED', async () => {
187
- const resultPromise = operationClient.monitorOperation('op_sse_1')
188
-
189
- // Wait for SSE connection to establish
190
- await new Promise((r) => setTimeout(r, 20))
191
-
192
- // Get the SSE client and simulate completion
193
- const sseClients = (operationClient as any).sseClients as Map<string, any>
194
- const sseClient = sseClients.get('op_sse_1')
195
- const eventSource = (sseClient as any).eventSource as MockEventSource
196
- eventSource.simulateMessage(EventType.OPERATION_COMPLETED, {
197
- result: { graph_id: 'graph_done' },
198
- metadata: { took: 5000 },
199
- })
200
-
201
- const result = await resultPromise
202
-
203
- expect(result.success).toBe(true)
204
- expect(result.result).toEqual({ graph_id: 'graph_done' })
205
- })
206
-
207
- it('should resolve with error on OPERATION_ERROR', async () => {
208
- const resultPromise = operationClient.monitorOperation('op_sse_err')
209
-
210
- await new Promise((r) => setTimeout(r, 20))
211
-
212
- const sseClients = (operationClient as any).sseClients as Map<string, any>
213
- const sseClient = sseClients.get('op_sse_err')
214
- const eventSource = (sseClient as any).eventSource as MockEventSource
215
- eventSource.simulateMessage(EventType.OPERATION_ERROR, {
216
- message: 'Processing failed',
217
- })
218
-
219
- const result = await resultPromise
220
-
221
- expect(result.success).toBe(false)
222
- expect(result.error).toBe('Processing failed')
223
- })
224
-
225
- it('should resolve with cancelled on OPERATION_CANCELLED', async () => {
226
- const resultPromise = operationClient.monitorOperation('op_sse_cancel')
227
-
228
- await new Promise((r) => setTimeout(r, 20))
229
-
230
- const sseClients = (operationClient as any).sseClients as Map<string, any>
231
- const sseClient = sseClients.get('op_sse_cancel')
232
- const eventSource = (sseClient as any).eventSource as MockEventSource
233
- eventSource.simulateMessage(EventType.OPERATION_CANCELLED, {})
234
-
235
- const result = await resultPromise
236
-
237
- expect(result.success).toBe(false)
238
- expect(result.error).toBe('Operation cancelled')
239
- })
240
-
241
- it('should call onProgress callback', async () => {
242
- const progressUpdates: any[] = []
243
-
244
- const resultPromise = operationClient.monitorOperation('op_progress', {
245
- onProgress: (p) => progressUpdates.push(p),
246
- })
247
-
248
- await new Promise((r) => setTimeout(r, 20))
249
-
250
- const sseClients = (operationClient as any).sseClients as Map<string, any>
251
- const sseClient = sseClients.get('op_progress')
252
- const eventSource = (sseClient as any).eventSource as MockEventSource
253
-
254
- // Send progress then completion
255
- eventSource.simulateMessage(EventType.OPERATION_PROGRESS, {
256
- message: 'Step 1 of 3',
257
- progress_percent: 33,
258
- })
259
-
260
- eventSource.simulateMessage(EventType.OPERATION_COMPLETED, {
261
- result: { done: true },
262
- })
263
-
264
- await resultPromise
265
-
266
- expect(progressUpdates).toHaveLength(1)
267
- expect(progressUpdates[0].message).toBe('Step 1 of 3')
268
- expect(progressUpdates[0].progressPercent).toBe(33)
269
- })
270
-
271
- it('should timeout after specified duration', async () => {
272
- const resultPromise = operationClient.monitorOperation('op_timeout', {
273
- timeout: 100,
274
- })
275
-
276
- await expect(resultPromise).rejects.toThrow('Operation timeout after 100ms')
277
- })
278
- })
279
-
280
- describe('waitForOperation', () => {
281
- beforeEach(() => {
282
- global.EventSource = MockEventSource as any
283
- })
284
-
285
- it('should return result on success', async () => {
286
- const resultPromise = operationClient.waitForOperation('op_wait')
287
-
288
- await new Promise((r) => setTimeout(r, 20))
289
-
290
- const sseClients = (operationClient as any).sseClients as Map<string, any>
291
- const sseClient = sseClients.get('op_wait')
292
- const eventSource = (sseClient as any).eventSource as MockEventSource
293
- eventSource.simulateMessage(EventType.OPERATION_COMPLETED, {
294
- result: { data: 'done' },
295
- })
296
-
297
- const result = await resultPromise
298
-
299
- expect(result).toEqual({ data: 'done' })
300
- })
301
-
302
- it('should throw on failure', async () => {
303
- const resultPromise = operationClient.waitForOperation('op_wait_fail')
304
-
305
- await new Promise((r) => setTimeout(r, 20))
306
-
307
- const sseClients = (operationClient as any).sseClients as Map<string, any>
308
- const sseClient = sseClients.get('op_wait_fail')
309
- const eventSource = (sseClient as any).eventSource as MockEventSource
310
- eventSource.simulateMessage(EventType.OPERATION_ERROR, {
311
- message: 'Server error',
312
- })
313
-
314
- await expect(resultPromise).rejects.toThrow('Server error')
315
- })
316
-
317
- it('should timeout with specified duration', async () => {
318
- await expect(operationClient.waitForOperation('op_wait_timeout', 100)).rejects.toThrow(
319
- 'Operation timeout'
320
- )
321
- })
322
- })
323
-
324
- describe('configuration', () => {
325
- it('should accept JWT token in config', () => {
326
- const client = new OperationClient({
327
- baseUrl: 'http://localhost:8000',
328
- token: 'eyJhbGc.eyJzdWI.SflKxw',
329
- })
330
-
331
- expect(client).toBeInstanceOf(OperationClient)
332
- })
333
-
334
- it('should accept credentials option', () => {
335
- const client = new OperationClient({
336
- baseUrl: 'http://localhost:8000',
337
- credentials: 'include',
338
- })
339
-
340
- expect(client).toBeInstanceOf(OperationClient)
341
- })
342
-
343
- it('should accept custom headers', () => {
344
- const client = new OperationClient({
345
- baseUrl: 'http://localhost:8000',
346
- headers: {
347
- 'X-Custom-Header': 'test-value',
348
- 'X-API-Key': 'my-key',
349
- },
350
- })
351
-
352
- expect(client).toBeInstanceOf(OperationClient)
353
- })
354
-
355
- it('should accept retry configuration', () => {
356
- const client = new OperationClient({
357
- baseUrl: 'http://localhost:8000',
358
- maxRetries: 10,
359
- retryDelay: 5000,
360
- })
361
-
362
- expect(client).toBeInstanceOf(OperationClient)
363
- })
364
- })
365
- })