@robosystems/core 0.11.2 → 0.11.4
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/auth-components/AuthProvider.js +166 -27
- package/auth-components/SessionWarningDialog.js +2 -2
- package/auth-components/SignInForm.d.ts +2 -1
- package/auth-components/SignInForm.js +8 -2
- package/auth-components/SignUpForm.js +4 -1
- package/auth-core/client.d.ts +8 -1
- package/auth-core/client.js +142 -100
- package/auth-core/sso.d.ts +4 -9
- package/auth-core/sso.js +24 -75
- package/auth-core/token-storage.d.ts +12 -0
- package/auth-core/token-storage.js +42 -16
- package/auth-core/types.d.ts +1 -0
- package/components/console/ConsoleContent.js +30 -4
- package/components/console/graphAwareConfig.js +27 -17
- package/components/repositories/ActiveSubscriptions.js +18 -6
- package/components/repositories/BrowseRepositories.js +17 -5
- package/components/search/SearchContent.js +30 -4
- package/contexts/graph-context.js +23 -13
- package/hooks/use-streaming-query.js +43 -28
- package/index.d.ts +5 -2
- package/index.js +6 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/sdk-errors.d.ts +79 -0
- package/lib/sdk-errors.js +148 -0
- package/package.json +1 -1
- package/task-monitoring/hooks.js +23 -13
- package/task-monitoring/operationHooks.d.ts +21 -2
- package/task-monitoring/operationHooks.js +67 -17
- package/task-monitoring/operationMonitor.d.ts +10 -1
- package/task-monitoring/operationMonitor.js +109 -57
- package/task-monitoring/taskMonitor.d.ts +15 -1
- package/task-monitoring/taskMonitor.js +120 -73
- package/task-monitoring/types.d.ts +2 -1
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { changeSubscriptionPlan, client, createCheckoutSession, createGraph as createGraphAPI, createRepositorySubscription, getOrgBillingCustomer, } from '@robosystems/client';
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { toApiError } from '../lib/sdk-errors';
|
|
5
|
+
import { MONITORING_STOPPED, operationMonitor } from './operationMonitor';
|
|
6
|
+
/**
|
|
7
|
+
* Thrown by `startMonitoring` (and so by `createGraph`) when an operation
|
|
8
|
+
* ends in any state but `completed`. `status` is the terminal state;
|
|
9
|
+
* `'cancelled'` with `stopped: true` means monitoring was stopped locally
|
|
10
|
+
* and the operation may still be running.
|
|
11
|
+
*/
|
|
12
|
+
export class OperationOutcomeError extends Error {
|
|
13
|
+
constructor(result) {
|
|
14
|
+
const stopped = result.error === MONITORING_STOPPED;
|
|
15
|
+
super(stopped
|
|
16
|
+
? STOPPED_MESSAGE
|
|
17
|
+
: result.error ||
|
|
18
|
+
(result.status === 'cancelled'
|
|
19
|
+
? 'Operation was cancelled'
|
|
20
|
+
: 'Operation failed'));
|
|
21
|
+
this.name = 'OperationOutcomeError';
|
|
22
|
+
this.status = result.status;
|
|
23
|
+
this.operationId = result.operation_id;
|
|
24
|
+
this.stopped = stopped;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const STOPPED_MESSAGE = 'Stopped monitoring. The operation continues on the server.';
|
|
5
28
|
/**
|
|
6
29
|
* Hook for monitoring operations using SSE
|
|
7
30
|
*/
|
|
@@ -30,11 +53,13 @@ export function useOperationMonitoring() {
|
|
|
30
53
|
});
|
|
31
54
|
currentOperationId.current = null;
|
|
32
55
|
}, []);
|
|
56
|
+
// Stops watching; the server-side operation is not cancelled (graph
|
|
57
|
+
// creation, for one, cannot be cancelled mid-provision).
|
|
33
58
|
const cancelOperation = useCallback(async () => {
|
|
34
59
|
if (currentOperationId.current) {
|
|
35
60
|
try {
|
|
36
|
-
|
|
37
|
-
setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, isMonitoring: false, status: 'cancelled', error:
|
|
61
|
+
operationMonitor.cancelOperation(currentOperationId.current);
|
|
62
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, isMonitoring: false, status: 'cancelled', error: STOPPED_MESSAGE, result: null })));
|
|
38
63
|
}
|
|
39
64
|
catch (error) {
|
|
40
65
|
console.error('Failed to cancel operation:', error);
|
|
@@ -43,6 +68,10 @@ export function useOperationMonitoring() {
|
|
|
43
68
|
}
|
|
44
69
|
}, []);
|
|
45
70
|
const startMonitoring = useCallback(async (operationId, options) => {
|
|
71
|
+
if (currentOperationId.current &&
|
|
72
|
+
currentOperationId.current !== operationId) {
|
|
73
|
+
operationMonitor.cancelOperation(currentOperationId.current);
|
|
74
|
+
}
|
|
46
75
|
currentOperationId.current = operationId;
|
|
47
76
|
setState({
|
|
48
77
|
isLoading: true,
|
|
@@ -68,15 +97,20 @@ export function useOperationMonitoring() {
|
|
|
68
97
|
setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, isMonitoring: false, error: errorMsg, result: null, status: 'failed' })));
|
|
69
98
|
},
|
|
70
99
|
});
|
|
100
|
+
if (result.status !== 'completed') {
|
|
101
|
+
throw new OperationOutcomeError(result);
|
|
102
|
+
}
|
|
71
103
|
return result.result || result;
|
|
72
104
|
}
|
|
73
105
|
catch (error) {
|
|
74
106
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
75
|
-
setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, isMonitoring: false, error: errorMessage, result: null, status: 'failed' })));
|
|
107
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, isMonitoring: false, error: errorMessage, result: null, status: error instanceof OperationOutcomeError ? error.status : 'failed' })));
|
|
76
108
|
throw error;
|
|
77
109
|
}
|
|
78
110
|
finally {
|
|
79
|
-
|
|
111
|
+
// A newer run may have started meanwhile; leave its id in place.
|
|
112
|
+
if (currentOperationId.current === operationId)
|
|
113
|
+
currentOperationId.current = null;
|
|
80
114
|
}
|
|
81
115
|
}, []);
|
|
82
116
|
// Cleanup on unmount
|
|
@@ -91,6 +125,19 @@ export function useOperationMonitoring() {
|
|
|
91
125
|
cancelOperation, cancelMonitoring: cancelOperation, // Alias for consistency
|
|
92
126
|
reset });
|
|
93
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* The schema sent for a generic graph: the caller's, or an empty one named
|
|
130
|
+
* after the graph (a bare database the user fills in later).
|
|
131
|
+
*/
|
|
132
|
+
function genericSchema(graphData) {
|
|
133
|
+
if (graphData.custom_schema)
|
|
134
|
+
return graphData.custom_schema;
|
|
135
|
+
const name = graphData.graph_name
|
|
136
|
+
.toLowerCase()
|
|
137
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
138
|
+
.replace(/^_+|_+$/g, '') || 'custom_graph';
|
|
139
|
+
return { name, nodes: [], relationships: [] };
|
|
140
|
+
}
|
|
94
141
|
/**
|
|
95
142
|
* Hook for graph creation using the new unified endpoint
|
|
96
143
|
*/
|
|
@@ -98,7 +145,7 @@ export function useGraphCreation() {
|
|
|
98
145
|
const operationMonitoring = useOperationMonitoring();
|
|
99
146
|
const [isCreating, setIsCreating] = useState(false);
|
|
100
147
|
const createGraph = useCallback(async (graphData) => {
|
|
101
|
-
var _a, _b, _c;
|
|
148
|
+
var _a, _b, _c, _d;
|
|
102
149
|
setIsCreating(true);
|
|
103
150
|
try {
|
|
104
151
|
// Check if billing is enabled and user needs to complete checkout
|
|
@@ -129,6 +176,9 @@ export function useGraphCreation() {
|
|
|
129
176
|
description: graphData.description,
|
|
130
177
|
tags: graphData.tags,
|
|
131
178
|
schema_extensions: graphData.schema_extensions,
|
|
179
|
+
custom_schema: graphData.graph_type === 'generic'
|
|
180
|
+
? genericSchema(graphData)
|
|
181
|
+
: undefined,
|
|
132
182
|
create_entity: graphData.create_entity,
|
|
133
183
|
entity_name: graphData.entity_name,
|
|
134
184
|
entity_identifier: graphData.entity_identifier,
|
|
@@ -140,11 +190,7 @@ export function useGraphCreation() {
|
|
|
140
190
|
},
|
|
141
191
|
});
|
|
142
192
|
if (checkoutResponse.error) {
|
|
143
|
-
|
|
144
|
-
'detail' in checkoutResponse.error
|
|
145
|
-
? String(checkoutResponse.error.detail)
|
|
146
|
-
: 'Failed to create checkout session';
|
|
147
|
-
throw new Error(errorMsg);
|
|
193
|
+
throw toApiError(checkoutResponse.error, checkoutResponse.response);
|
|
148
194
|
}
|
|
149
195
|
// Check if billing is disabled on the backend
|
|
150
196
|
// @ts-ignore - billing_disabled field will be in next SDK release
|
|
@@ -173,11 +219,19 @@ export function useGraphCreation() {
|
|
|
173
219
|
tags: graphData.tags,
|
|
174
220
|
schema_extensions: graphData.schema_extensions || [],
|
|
175
221
|
},
|
|
222
|
+
// The API files tags from the top-level field; `metadata.tags` is
|
|
223
|
+
// kept for older servers.
|
|
224
|
+
tags: (_c = graphData.tags) !== null && _c !== void 0 ? _c : [],
|
|
176
225
|
instance_tier: graphData.instance_tier || 'ladybug-standard',
|
|
177
226
|
create_entity: graphData.graph_type === 'generic'
|
|
178
227
|
? false
|
|
179
|
-
: ((
|
|
228
|
+
: ((_d = graphData.create_entity) !== null && _d !== void 0 ? _d : true),
|
|
180
229
|
};
|
|
230
|
+
// A generic graph is defined by its schema; the API requires either
|
|
231
|
+
// a custom_schema or an initial_entity.
|
|
232
|
+
if (graphData.graph_type === 'generic') {
|
|
233
|
+
requestBody.custom_schema = genericSchema(graphData);
|
|
234
|
+
}
|
|
181
235
|
// Add initial_entity for entity or company graphs
|
|
182
236
|
if (graphData.graph_type === 'entity' && graphData.entity_name) {
|
|
183
237
|
requestBody.initial_entity = {
|
|
@@ -310,11 +364,7 @@ export function useRepositorySubscription() {
|
|
|
310
364
|
},
|
|
311
365
|
});
|
|
312
366
|
if (checkoutResponse.error) {
|
|
313
|
-
|
|
314
|
-
'detail' in checkoutResponse.error
|
|
315
|
-
? String(checkoutResponse.error.detail)
|
|
316
|
-
: 'Failed to create checkout session';
|
|
317
|
-
throw new Error(errorMsg);
|
|
367
|
+
throw toApiError(checkoutResponse.error, checkoutResponse.response);
|
|
318
368
|
}
|
|
319
369
|
// Check if billing is disabled on the backend
|
|
320
370
|
// @ts-ignore - billing_disabled field will be in next SDK release
|
|
@@ -31,8 +31,15 @@ export interface OperationMonitorOptions {
|
|
|
31
31
|
onComplete?: (result: any) => void;
|
|
32
32
|
onError?: (error: string) => void;
|
|
33
33
|
onEvent?: (event: OperationEvent) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Give up watching after this many milliseconds. No default: an operation
|
|
36
|
+
* runs as long as it runs (backups, large graph creations), and a monitor
|
|
37
|
+
* that times out reports a failure for work that is still succeeding.
|
|
38
|
+
*/
|
|
34
39
|
timeout?: number;
|
|
35
40
|
}
|
|
41
|
+
/** Error message on a result whose monitoring was stopped locally. */
|
|
42
|
+
export declare const MONITORING_STOPPED = "Monitoring stopped";
|
|
36
43
|
export declare class OperationMonitor {
|
|
37
44
|
private static instance;
|
|
38
45
|
private activeOperations;
|
|
@@ -43,7 +50,9 @@ export declare class OperationMonitor {
|
|
|
43
50
|
*/
|
|
44
51
|
monitorOperation({ operationId, onProgress, onComplete, onError, onEvent, timeout, }: OperationMonitorOptions): Promise<OperationResult>;
|
|
45
52
|
/**
|
|
46
|
-
*
|
|
53
|
+
* Stop monitoring an operation: closes its stream and settles its
|
|
54
|
+
* `monitorOperation` promise with `status: 'cancelled'` and
|
|
55
|
+
* `error: MONITORING_STOPPED`. Does not cancel the operation itself.
|
|
47
56
|
*/
|
|
48
57
|
cancelOperation(operationId: string): boolean;
|
|
49
58
|
/**
|
|
@@ -16,6 +16,30 @@ const getSDKExtensions = async () => {
|
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
+
/** Error message on a result whose monitoring was stopped locally. */
|
|
20
|
+
export const MONITORING_STOPPED = 'Monitoring stopped';
|
|
21
|
+
function createActiveOperation() {
|
|
22
|
+
let resolveStopped = () => undefined;
|
|
23
|
+
const entry = {
|
|
24
|
+
client: null,
|
|
25
|
+
stopped: false,
|
|
26
|
+
stoppedPromise: new Promise((resolve) => {
|
|
27
|
+
resolveStopped = resolve;
|
|
28
|
+
}),
|
|
29
|
+
stop: () => {
|
|
30
|
+
var _a;
|
|
31
|
+
entry.stopped = true;
|
|
32
|
+
resolveStopped(null);
|
|
33
|
+
(_a = entry.client) === null || _a === void 0 ? void 0 : _a.closeAll();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
return entry;
|
|
37
|
+
}
|
|
38
|
+
const stoppedResult = (operationId) => ({
|
|
39
|
+
operation_id: operationId,
|
|
40
|
+
status: 'cancelled',
|
|
41
|
+
error: MONITORING_STOPPED,
|
|
42
|
+
});
|
|
19
43
|
export class OperationMonitor {
|
|
20
44
|
constructor() {
|
|
21
45
|
this.activeOperations = new Map();
|
|
@@ -30,40 +54,55 @@ export class OperationMonitor {
|
|
|
30
54
|
/**
|
|
31
55
|
* Monitor an operation using SSE streaming
|
|
32
56
|
*/
|
|
33
|
-
async monitorOperation({ operationId, onProgress, onComplete, onError, onEvent, timeout
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
async monitorOperation({ operationId, onProgress, onComplete, onError, onEvent, timeout, }) {
|
|
58
|
+
// Registered before any await, so a stop issued while the SDK loads
|
|
59
|
+
// (an immediate cancel, an unmount, a StrictMode remount) is honoured.
|
|
60
|
+
if (this.activeOperations.has(operationId)) {
|
|
61
|
+
this.cancelOperation(operationId);
|
|
62
|
+
}
|
|
63
|
+
const entry = createActiveOperation();
|
|
64
|
+
this.activeOperations.set(operationId, entry);
|
|
65
|
+
try {
|
|
66
|
+
// Get SDK extensions at runtime
|
|
67
|
+
const sdkExtensions = await getSDKExtensions();
|
|
68
|
+
if (entry.stopped)
|
|
69
|
+
return stoppedResult(operationId);
|
|
70
|
+
// Require SDK extensions - fail fast if not available
|
|
71
|
+
if (!(sdkExtensions === null || sdkExtensions === void 0 ? void 0 : sdkExtensions.OperationClient)) {
|
|
72
|
+
throw new Error('SDK extensions not available. Please install @robosystems/client with extensions support.');
|
|
73
|
+
}
|
|
74
|
+
return await this.monitorWithSDKExtensions({
|
|
75
|
+
operationId,
|
|
76
|
+
onProgress,
|
|
77
|
+
onComplete,
|
|
78
|
+
onError,
|
|
79
|
+
onEvent,
|
|
80
|
+
timeout,
|
|
81
|
+
}, sdkExtensions, entry);
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
if (this.activeOperations.get(operationId) === entry) {
|
|
85
|
+
this.activeOperations.delete(operationId);
|
|
86
|
+
}
|
|
40
87
|
}
|
|
41
|
-
return this.monitorWithSDKExtensions({
|
|
42
|
-
operationId,
|
|
43
|
-
onProgress,
|
|
44
|
-
onComplete,
|
|
45
|
-
onError,
|
|
46
|
-
onEvent,
|
|
47
|
-
timeout,
|
|
48
|
-
}, sdkExtensions);
|
|
49
88
|
}
|
|
50
89
|
/**
|
|
51
|
-
*
|
|
90
|
+
* Stop monitoring an operation: closes its stream and settles its
|
|
91
|
+
* `monitorOperation` promise with `status: 'cancelled'` and
|
|
92
|
+
* `error: MONITORING_STOPPED`. Does not cancel the operation itself.
|
|
52
93
|
*/
|
|
53
94
|
cancelOperation(operationId) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (eventSource) {
|
|
57
|
-
eventSource.close();
|
|
58
|
-
this.activeOperations.delete(operationId);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
95
|
+
const active = this.activeOperations.get(operationId);
|
|
96
|
+
if (!active)
|
|
61
97
|
return false;
|
|
98
|
+
this.activeOperations.delete(operationId);
|
|
99
|
+
try {
|
|
100
|
+
active.stop();
|
|
62
101
|
}
|
|
63
102
|
catch (error) {
|
|
64
|
-
console.error('Failed to
|
|
65
|
-
return false;
|
|
103
|
+
console.error('Failed to stop operation monitoring:', error);
|
|
66
104
|
}
|
|
105
|
+
return true;
|
|
67
106
|
}
|
|
68
107
|
/**
|
|
69
108
|
* Get cached operation status/result
|
|
@@ -80,49 +119,63 @@ export class OperationMonitor {
|
|
|
80
119
|
* Clean up operation monitoring resources
|
|
81
120
|
*/
|
|
82
121
|
cleanupOperation(operationId) {
|
|
83
|
-
|
|
84
|
-
if (eventSource) {
|
|
85
|
-
eventSource.close();
|
|
86
|
-
this.activeOperations.delete(operationId);
|
|
87
|
-
}
|
|
122
|
+
this.cancelOperation(operationId);
|
|
88
123
|
}
|
|
89
124
|
/**
|
|
90
125
|
* Monitor operation using SDK extensions
|
|
91
126
|
*/
|
|
92
|
-
async monitorWithSDKExtensions(options, sdkExtensions) {
|
|
127
|
+
async monitorWithSDKExtensions(options, sdkExtensions, entry) {
|
|
93
128
|
var _a, _b, _c;
|
|
94
129
|
const { OperationClient, extractTokenFromSDKClient } = sdkExtensions;
|
|
95
|
-
const { getToken } = await import('../auth-core/token-storage');
|
|
130
|
+
const { getToken, getValidToken } = await import('../auth-core/token-storage');
|
|
131
|
+
if (entry.stopped)
|
|
132
|
+
return stoppedResult(options.operationId);
|
|
96
133
|
const config = client.getConfig();
|
|
97
|
-
|
|
98
|
-
//
|
|
134
|
+
// One client per operation, tracked so `cancelOperation` can close it.
|
|
135
|
+
// The credential is resolved per connect (`tokenProvider`), so a stream
|
|
136
|
+
// that reconnects after the JWT rotates presents the current token; the
|
|
137
|
+
// static `token` only serves SDK versions that predate the provider.
|
|
99
138
|
const operationClient = new OperationClient({
|
|
100
139
|
baseUrl: config.baseUrl || 'http://localhost:8000',
|
|
101
140
|
credentials: 'include',
|
|
102
|
-
token:
|
|
141
|
+
token: getToken() || (extractTokenFromSDKClient === null || extractTokenFromSDKClient === void 0 ? void 0 : extractTokenFromSDKClient()) || undefined,
|
|
142
|
+
tokenProvider: async () => { var _a; return (_a = (await getValidToken())) !== null && _a !== void 0 ? _a : null; },
|
|
103
143
|
maxRetries: 3,
|
|
104
144
|
retryDelay: 1000,
|
|
105
145
|
});
|
|
146
|
+
entry.client = operationClient;
|
|
147
|
+
const stopped = () => entry.stopped;
|
|
106
148
|
try {
|
|
107
|
-
const result = await
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
149
|
+
const result = await Promise.race([
|
|
150
|
+
operationClient.monitorOperation(options.operationId, {
|
|
151
|
+
onProgress: (progress) => {
|
|
152
|
+
var _a, _b, _c, _d;
|
|
153
|
+
if (stopped())
|
|
154
|
+
return;
|
|
155
|
+
(_a = options.onProgress) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
156
|
+
percent: progress.progressPercent || 0,
|
|
157
|
+
message: progress.message || '',
|
|
158
|
+
current_step: (_c = (_b = progress.details) === null || _b === void 0 ? void 0 : _b.current_step) === null || _c === void 0 ? void 0 : _c.toString(),
|
|
159
|
+
total_steps: (_d = progress.details) === null || _d === void 0 ? void 0 : _d.total_steps,
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
onEvent: (event) => {
|
|
163
|
+
var _a;
|
|
164
|
+
if (stopped())
|
|
165
|
+
return;
|
|
166
|
+
(_a = options.onEvent) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
167
|
+
event: event.type,
|
|
168
|
+
data: event.data,
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
timeout: options.timeout,
|
|
172
|
+
}),
|
|
173
|
+
entry.stoppedPromise,
|
|
174
|
+
]);
|
|
175
|
+
if (result === null) {
|
|
176
|
+
// Stopped locally: report it without firing the outcome callbacks.
|
|
177
|
+
return stoppedResult(options.operationId);
|
|
178
|
+
}
|
|
126
179
|
// Map OperationResult (success: boolean) to status string
|
|
127
180
|
const status = result.success
|
|
128
181
|
? 'completed'
|
|
@@ -158,10 +211,9 @@ export class OperationMonitor {
|
|
|
158
211
|
* Clean up all active operations
|
|
159
212
|
*/
|
|
160
213
|
cleanup() {
|
|
161
|
-
for (const
|
|
162
|
-
|
|
214
|
+
for (const operationId of Array.from(this.activeOperations.keys())) {
|
|
215
|
+
this.cancelOperation(operationId);
|
|
163
216
|
}
|
|
164
|
-
this.activeOperations.clear();
|
|
165
217
|
}
|
|
166
218
|
/**
|
|
167
219
|
* Get list of active operation IDs
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import type { TaskPollingOptions, TaskStatusResponse } from './types';
|
|
2
|
+
/** Rejection message when watching stopped locally (`stopPolling`). */
|
|
3
|
+
export declare const POLLING_CANCELLED = "Task polling was cancelled";
|
|
2
4
|
export declare class TaskMonitor {
|
|
3
5
|
private static instance;
|
|
4
6
|
private activeTasks;
|
|
5
7
|
static getInstance(): TaskMonitor;
|
|
6
|
-
pollTask({ taskId, onProgress, onComplete, onError, pollInterval, maxAttempts,
|
|
8
|
+
pollTask({ taskId, onProgress, onComplete, onError, pollInterval, maxAttempts, // 5 minutes at 2s intervals
|
|
9
|
+
maxConsecutiveErrors, }: TaskPollingOptions): Promise<TaskStatusResponse>;
|
|
10
|
+
/**
|
|
11
|
+
* Stop watching a task locally. The operation itself keeps running on the
|
|
12
|
+
* server — this is what leaving a page should do.
|
|
13
|
+
*/
|
|
14
|
+
stopPolling(taskId: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Cancel the operation on the server, then stop watching it. Only for an
|
|
17
|
+
* explicit user action. Returns false when the server refused — the task
|
|
18
|
+
* is then still being watched, and its real outcome still arrives.
|
|
19
|
+
*/
|
|
7
20
|
cancelTask(taskId: string): Promise<boolean>;
|
|
8
21
|
cancelAllTasks(): void;
|
|
9
22
|
getActiveTasks(): string[];
|
|
@@ -11,4 +24,5 @@ export declare class TaskMonitor {
|
|
|
11
24
|
export declare const taskMonitor: TaskMonitor;
|
|
12
25
|
export declare const pollTaskStatus: (options: TaskPollingOptions) => Promise<TaskStatusResponse>;
|
|
13
26
|
export declare const cancelTask: (taskId: string) => Promise<boolean>;
|
|
27
|
+
export declare const stopPollingTask: (taskId: string) => boolean;
|
|
14
28
|
export declare const getActiveTasks: () => string[];
|