@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,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
|
-
})
|