flowscale 1.2.0 → 1.3.1
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/CHANGELOG.md +2 -0
- package/CLAUDE.md +2 -7
- package/Makefile +1 -10
- package/README.md +42 -127
- package/dist/index.d.ts +17 -27
- package/dist/index.js +517 -189
- package/dist/types.d.ts +22 -18
- package/examples/backend-proxy-example.js +1 -12
- package/package.json +1 -1
- package/examples/node-websocket-example.js +0 -173
- package/examples/websocket-example.html +0 -157
package/dist/index.js
CHANGED
|
@@ -78,12 +78,9 @@ var axios_1 = __importDefault(require("axios"));
|
|
|
78
78
|
var FlowscaleAPI = /** @class */ (function () {
|
|
79
79
|
function FlowscaleAPI(config) {
|
|
80
80
|
var _this = this;
|
|
81
|
-
this.ws = null;
|
|
82
|
-
this.wsConnected = false;
|
|
83
|
-
this.reconnectAttempts = 0;
|
|
84
|
-
this.reconnectTimeout = null;
|
|
85
81
|
this.proxyMode = false;
|
|
86
82
|
this.customHeaders = {};
|
|
83
|
+
this.fetchImpl = null;
|
|
87
84
|
// Validate required configuration
|
|
88
85
|
if (!config) {
|
|
89
86
|
throw new Error('FlowscaleAPI configuration is required');
|
|
@@ -123,7 +120,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
123
120
|
this.baseUrl = config.baseUrl.trim();
|
|
124
121
|
this.maxRetries = config.maxRetries || 3;
|
|
125
122
|
this.retryDelay = config.retryDelay || 1000;
|
|
126
|
-
this.
|
|
123
|
+
this.fetchImpl = config.fetchImpl || this.resolveGlobalFetch();
|
|
127
124
|
this.client = axios_1.default.create({
|
|
128
125
|
baseURL: this.baseUrl,
|
|
129
126
|
timeout: config.timeout || 6000000, // Default 6000s timeout instead of Axios default 0 (no timeout)
|
|
@@ -239,13 +236,13 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
239
236
|
*/
|
|
240
237
|
FlowscaleAPI.prototype.executeWorkflowAsync = function (workflowId_1, data_1, groupId_1) {
|
|
241
238
|
return __awaiter(this, arguments, void 0, function (workflowId, data, groupId, pollIntervalMs, timeoutMs, returnAllOutputsOrOptions) {
|
|
242
|
-
var _a, returnAllOutputs, onIntermediateResponse, startTime, executeResponse, runId, resolvedWorkflowId, run_status, output_names, runResponse, attempts, outputPromises, outputResults, successfulOutputs, pendingOutputs, hasErrors, _i, outputResults_1, result, deprecationWarning, legacyResponse, allOutputsResponse, error_1;
|
|
239
|
+
var _a, returnAllOutputs, onIntermediateResponse, startTime, executeResponse, runId, resolvedWorkflowId, run_status, output_names, runResponse, attempts, runResponse, latestOutputNames, outputPromises, outputResults, successfulOutputs, pendingOutputs, hasErrors, _i, outputResults_1, result, deprecationWarning, legacyResponse, allOutputsResponse, error_1;
|
|
243
240
|
var _this = this;
|
|
244
|
-
var _b, _c, _d, _e, _f;
|
|
241
|
+
var _b, _c, _d, _e, _f, _g, _h, _j;
|
|
245
242
|
if (pollIntervalMs === void 0) { pollIntervalMs = 2000; }
|
|
246
243
|
if (timeoutMs === void 0) { timeoutMs = 600000; }
|
|
247
|
-
return __generator(this, function (
|
|
248
|
-
switch (
|
|
244
|
+
return __generator(this, function (_k) {
|
|
245
|
+
switch (_k.label) {
|
|
249
246
|
case 0:
|
|
250
247
|
// Validate inputs
|
|
251
248
|
if (!workflowId || typeof workflowId !== 'string' || workflowId.trim() === '') {
|
|
@@ -264,7 +261,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
264
261
|
startTime = Date.now();
|
|
265
262
|
return [4 /*yield*/, this.executeWorkflow(workflowId, data, groupId)];
|
|
266
263
|
case 1:
|
|
267
|
-
executeResponse =
|
|
264
|
+
executeResponse = _k.sent();
|
|
268
265
|
if (!((_b = executeResponse === null || executeResponse === void 0 ? void 0 : executeResponse.data) === null || _b === void 0 ? void 0 : _b.run_id)) {
|
|
269
266
|
throw new Error('No run ID returned from workflow execution');
|
|
270
267
|
}
|
|
@@ -281,10 +278,10 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
281
278
|
response: executeResponse,
|
|
282
279
|
})];
|
|
283
280
|
case 2:
|
|
284
|
-
|
|
281
|
+
_k.sent();
|
|
285
282
|
run_status = "queued";
|
|
286
283
|
output_names = [];
|
|
287
|
-
|
|
284
|
+
_k.label = 3;
|
|
288
285
|
case 3:
|
|
289
286
|
if (!(output_names.length === 0)) return [3 /*break*/, 8];
|
|
290
287
|
if (Date.now() - startTime > timeoutMs) {
|
|
@@ -292,7 +289,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
292
289
|
}
|
|
293
290
|
return [4 /*yield*/, this.getRun(runId)];
|
|
294
291
|
case 4:
|
|
295
|
-
runResponse =
|
|
292
|
+
runResponse = _k.sent();
|
|
296
293
|
run_status = ((_d = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _d === void 0 ? void 0 : _d.status) || "queued";
|
|
297
294
|
output_names = ((_e = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _e === void 0 ? void 0 : _e.output_names) || [];
|
|
298
295
|
return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
|
|
@@ -306,15 +303,15 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
306
303
|
response: runResponse,
|
|
307
304
|
})];
|
|
308
305
|
case 5:
|
|
309
|
-
|
|
306
|
+
_k.sent();
|
|
310
307
|
if (run_status === 'failed' || run_status === 'cancelled') {
|
|
311
308
|
throw new Error("Run ".concat(runId, " failed with status: ").concat(run_status));
|
|
312
309
|
}
|
|
313
310
|
if (!(output_names.length === 0)) return [3 /*break*/, 7];
|
|
314
311
|
return [4 /*yield*/, this.sleep(pollIntervalMs)];
|
|
315
312
|
case 6:
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
_k.sent();
|
|
314
|
+
_k.label = 7;
|
|
318
315
|
case 7: return [3 /*break*/, 3];
|
|
319
316
|
case 8:
|
|
320
317
|
if (!output_names || output_names.length === 0) {
|
|
@@ -322,15 +319,39 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
322
319
|
}
|
|
323
320
|
this.logInfo("Found ".concat(output_names.length, " outputs to wait for: ").concat(output_names.join(', ')));
|
|
324
321
|
attempts = 0;
|
|
325
|
-
|
|
322
|
+
_k.label = 9;
|
|
326
323
|
case 9:
|
|
327
|
-
if (!true) return [3 /*break*/,
|
|
324
|
+
if (!true) return [3 /*break*/, 23];
|
|
328
325
|
if (Date.now() - startTime > timeoutMs) {
|
|
329
326
|
throw new Error("Workflow execution timed out after ".concat(timeoutMs, "ms"));
|
|
330
327
|
}
|
|
331
|
-
|
|
328
|
+
_k.label = 10;
|
|
332
329
|
case 10:
|
|
333
|
-
|
|
330
|
+
_k.trys.push([10, 19, , 22]);
|
|
331
|
+
return [4 /*yield*/, this.getRun(runId)];
|
|
332
|
+
case 11:
|
|
333
|
+
runResponse = _k.sent();
|
|
334
|
+
run_status = ((_g = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _g === void 0 ? void 0 : _g.status) || run_status;
|
|
335
|
+
latestOutputNames = ((_h = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _h === void 0 ? void 0 : _h.output_names) || [];
|
|
336
|
+
if (latestOutputNames.length > 0) {
|
|
337
|
+
output_names = latestOutputNames;
|
|
338
|
+
}
|
|
339
|
+
return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
|
|
340
|
+
type: 'run_status',
|
|
341
|
+
timestamp: new Date().toISOString(),
|
|
342
|
+
run_id: runId,
|
|
343
|
+
workflow_id: resolvedWorkflowId,
|
|
344
|
+
attempt: attempts,
|
|
345
|
+
run_status: run_status,
|
|
346
|
+
output_names: output_names,
|
|
347
|
+
progress: ((_j = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _j === void 0 ? void 0 : _j.progress) || undefined,
|
|
348
|
+
response: runResponse,
|
|
349
|
+
})];
|
|
350
|
+
case 12:
|
|
351
|
+
_k.sent();
|
|
352
|
+
if (run_status === 'failed' || run_status === 'cancelled') {
|
|
353
|
+
throw new Error("Run ".concat(runId, " failed with status: ").concat(run_status));
|
|
354
|
+
}
|
|
334
355
|
outputPromises = output_names.map(function (outputName) { return __awaiter(_this, void 0, void 0, function () {
|
|
335
356
|
var output, error_2;
|
|
336
357
|
var _a;
|
|
@@ -375,8 +396,8 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
375
396
|
});
|
|
376
397
|
}); });
|
|
377
398
|
return [4 /*yield*/, Promise.all(outputPromises)];
|
|
378
|
-
case
|
|
379
|
-
outputResults =
|
|
399
|
+
case 13:
|
|
400
|
+
outputResults = _k.sent();
|
|
380
401
|
successfulOutputs = [];
|
|
381
402
|
pendingOutputs = [];
|
|
382
403
|
hasErrors = false;
|
|
@@ -416,9 +437,9 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
416
437
|
if (hasErrors) {
|
|
417
438
|
throw new Error('One or more workflow outputs failed');
|
|
418
439
|
}
|
|
419
|
-
if (!(pendingOutputs.length === 0)) return [3 /*break*/,
|
|
440
|
+
if (!(pendingOutputs.length === 0)) return [3 /*break*/, 17];
|
|
420
441
|
this.logInfo("All ".concat(successfulOutputs.length, " outputs completed successfully"));
|
|
421
|
-
if (!(returnAllOutputs === false || (returnAllOutputs === undefined && successfulOutputs.length === 1))) return [3 /*break*/,
|
|
442
|
+
if (!(returnAllOutputs === false || (returnAllOutputs === undefined && successfulOutputs.length === 1))) return [3 /*break*/, 15];
|
|
422
443
|
deprecationWarning = {
|
|
423
444
|
message: successfulOutputs.length > 1
|
|
424
445
|
? 'Single output format is deprecated. This workflow returned multiple outputs but only the first is shown.'
|
|
@@ -446,10 +467,10 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
446
467
|
completed_outputs: successfulOutputs.map(function (output) { return output.filename; }),
|
|
447
468
|
response: legacyResponse,
|
|
448
469
|
})];
|
|
449
|
-
case
|
|
450
|
-
|
|
470
|
+
case 14:
|
|
471
|
+
_k.sent();
|
|
451
472
|
return [2 /*return*/, legacyResponse];
|
|
452
|
-
case
|
|
473
|
+
case 15:
|
|
453
474
|
allOutputsResponse = {
|
|
454
475
|
status: 'success',
|
|
455
476
|
data: successfulOutputs
|
|
@@ -463,18 +484,18 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
463
484
|
completed_outputs: successfulOutputs.map(function (output) { return output.filename; }),
|
|
464
485
|
response: allOutputsResponse,
|
|
465
486
|
})];
|
|
466
|
-
case
|
|
467
|
-
|
|
487
|
+
case 16:
|
|
488
|
+
_k.sent();
|
|
468
489
|
return [2 /*return*/, allOutputsResponse];
|
|
469
|
-
case
|
|
490
|
+
case 17:
|
|
470
491
|
// If some outputs are still pending, continue polling
|
|
471
492
|
this.logDebug("".concat(pendingOutputs.length, " outputs still pending: ").concat(pendingOutputs.join(', ')));
|
|
472
493
|
return [4 /*yield*/, this.sleep(pollIntervalMs)];
|
|
473
|
-
case
|
|
474
|
-
|
|
475
|
-
return [3 /*break*/,
|
|
476
|
-
case
|
|
477
|
-
error_1 =
|
|
494
|
+
case 18:
|
|
495
|
+
_k.sent();
|
|
496
|
+
return [3 /*break*/, 22];
|
|
497
|
+
case 19:
|
|
498
|
+
error_1 = _k.sent();
|
|
478
499
|
// Log the error but continue polling
|
|
479
500
|
this.logWarn("Error polling for outputs (attempt ".concat(attempts, "):"), error_1);
|
|
480
501
|
return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
|
|
@@ -486,22 +507,22 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
486
507
|
output_names: output_names,
|
|
487
508
|
error: this.formatUnknownError(error_1),
|
|
488
509
|
})];
|
|
489
|
-
case
|
|
490
|
-
|
|
510
|
+
case 20:
|
|
511
|
+
_k.sent();
|
|
491
512
|
// After several failures, increase polling interval to avoid excessive requests
|
|
492
513
|
if (attempts > 5) {
|
|
493
514
|
pollIntervalMs = Math.min(pollIntervalMs * 1.5, 10000); // Increase interval, max 10s
|
|
494
515
|
}
|
|
495
516
|
// Wait before retrying
|
|
496
517
|
return [4 /*yield*/, this.sleep(pollIntervalMs)];
|
|
497
|
-
case
|
|
518
|
+
case 21:
|
|
498
519
|
// Wait before retrying
|
|
499
|
-
|
|
500
|
-
return [3 /*break*/,
|
|
501
|
-
case
|
|
520
|
+
_k.sent();
|
|
521
|
+
return [3 /*break*/, 22];
|
|
522
|
+
case 22:
|
|
502
523
|
attempts++;
|
|
503
524
|
return [3 /*break*/, 9];
|
|
504
|
-
case
|
|
525
|
+
case 23: return [2 /*return*/];
|
|
505
526
|
}
|
|
506
527
|
});
|
|
507
528
|
});
|
|
@@ -512,7 +533,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
512
533
|
*/
|
|
513
534
|
FlowscaleAPI.prototype.getOutput = function (filename) {
|
|
514
535
|
return __awaiter(this, void 0, void 0, function () {
|
|
515
|
-
var error_3, axiosError;
|
|
536
|
+
var response, error_3, axiosError;
|
|
516
537
|
return __generator(this, function (_a) {
|
|
517
538
|
switch (_a.label) {
|
|
518
539
|
case 0:
|
|
@@ -523,21 +544,35 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
523
544
|
_a.label = 1;
|
|
524
545
|
case 1:
|
|
525
546
|
_a.trys.push([1, 3, , 4]);
|
|
526
|
-
return [4 /*yield*/, this.
|
|
547
|
+
return [4 /*yield*/, this.client.get('/api/v1/runs/output', {
|
|
527
548
|
params: { filename: filename },
|
|
549
|
+
// We need to inspect HTTP status directly (204 is a valid "not ready" response).
|
|
550
|
+
validateStatus: function () { return true; },
|
|
528
551
|
})];
|
|
529
|
-
case 2:
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
axiosError = error_3;
|
|
533
|
-
if (axiosError.response && axiosError.response.status === 204) {
|
|
552
|
+
case 2:
|
|
553
|
+
response = _a.sent();
|
|
554
|
+
if (response.status === 204) {
|
|
534
555
|
return [2 /*return*/, null]; // No output found
|
|
535
556
|
}
|
|
536
|
-
else if (
|
|
557
|
+
else if (response.status === 504) {
|
|
537
558
|
this.logWarn('Received 504 Gateway Timeout, retrying...');
|
|
538
559
|
// For 504 errors specifically, we'll return null to allow the polling to continue
|
|
539
560
|
return [2 /*return*/, null];
|
|
540
561
|
}
|
|
562
|
+
else if (response.status === 408) {
|
|
563
|
+
throw new Error('Run Timeout');
|
|
564
|
+
}
|
|
565
|
+
if (response.status < 200 || response.status >= 300) {
|
|
566
|
+
throw new Error("Error: ".concat(response.status, " ").concat(response.statusText, " - ").concat(JSON.stringify(response.data)));
|
|
567
|
+
}
|
|
568
|
+
return [2 /*return*/, this.normalizeGetOutputResponse(response.data)];
|
|
569
|
+
case 3:
|
|
570
|
+
error_3 = _a.sent();
|
|
571
|
+
axiosError = error_3;
|
|
572
|
+
if (axiosError.response && axiosError.response.status === 504) {
|
|
573
|
+
this.logWarn('Received 504 Gateway Timeout, retrying...');
|
|
574
|
+
return [2 /*return*/, null];
|
|
575
|
+
}
|
|
541
576
|
else if (axiosError.response && axiosError.response.status === 408) {
|
|
542
577
|
throw new Error('Run Timeout');
|
|
543
578
|
}
|
|
@@ -594,6 +629,39 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
594
629
|
});
|
|
595
630
|
});
|
|
596
631
|
};
|
|
632
|
+
/**
|
|
633
|
+
* Subscribes to run events from the SSE endpoint.
|
|
634
|
+
* @param runId - The run ID to stream events for.
|
|
635
|
+
* @param options - SSE subscription options and callbacks.
|
|
636
|
+
* @returns Connection handle with `close()` and `done` promise.
|
|
637
|
+
*/
|
|
638
|
+
FlowscaleAPI.prototype.subscribeRunEvents = function (runId, options) {
|
|
639
|
+
if (options === void 0) { options = {}; }
|
|
640
|
+
if (!runId || typeof runId !== 'string' || runId.trim() === '') {
|
|
641
|
+
throw new Error('Run ID is required and must be a non-empty string');
|
|
642
|
+
}
|
|
643
|
+
if (options.fromSeq !== undefined && options.fromSeq < 0) {
|
|
644
|
+
throw new Error('fromSeq must be greater than or equal to 0');
|
|
645
|
+
}
|
|
646
|
+
if (!this.fetchImpl) {
|
|
647
|
+
throw new Error('SSE streaming requires a fetch implementation. ' +
|
|
648
|
+
'In Node.js < 18, pass `fetchImpl` in FlowscaleAPI config.');
|
|
649
|
+
}
|
|
650
|
+
var abortController = new AbortController();
|
|
651
|
+
if (options.signal) {
|
|
652
|
+
if (options.signal.aborted) {
|
|
653
|
+
abortController.abort();
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
options.signal.addEventListener('abort', function () { return abortController.abort(); }, { once: true });
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
var done = this.consumeRunEventsStream(runId, options, abortController.signal);
|
|
660
|
+
return {
|
|
661
|
+
close: function () { return abortController.abort(); },
|
|
662
|
+
done: done,
|
|
663
|
+
};
|
|
664
|
+
};
|
|
597
665
|
FlowscaleAPI.prototype.resolveExecuteWorkflowAsyncOptions = function (returnAllOutputsOrOptions) {
|
|
598
666
|
if (returnAllOutputsOrOptions == null ||
|
|
599
667
|
typeof returnAllOutputsOrOptions === 'boolean') {
|
|
@@ -655,6 +723,400 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
655
723
|
});
|
|
656
724
|
});
|
|
657
725
|
};
|
|
726
|
+
FlowscaleAPI.prototype.normalizeGetOutputResponse = function (payload) {
|
|
727
|
+
if (!payload || typeof payload !== 'object') {
|
|
728
|
+
return null;
|
|
729
|
+
}
|
|
730
|
+
if (typeof payload.status === 'string') {
|
|
731
|
+
return payload;
|
|
732
|
+
}
|
|
733
|
+
// Handle payloads that omit top-level status but still contain useful output data.
|
|
734
|
+
if (payload.data && typeof payload.data === 'object') {
|
|
735
|
+
if (payload.data.errors) {
|
|
736
|
+
return {
|
|
737
|
+
status: 'error',
|
|
738
|
+
data: {
|
|
739
|
+
errors: payload.data.errors,
|
|
740
|
+
},
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
if (payload.data.progress) {
|
|
744
|
+
return {
|
|
745
|
+
status: 'in_progress',
|
|
746
|
+
data: payload.data,
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
if (payload.data.download_url ||
|
|
750
|
+
payload.data.file_content ||
|
|
751
|
+
payload.data.generation_status) {
|
|
752
|
+
return {
|
|
753
|
+
status: 'success',
|
|
754
|
+
data: payload.data,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
// Legacy shape fallback: response data returned directly without wrapping.
|
|
759
|
+
if (payload.download_url || payload.file_content || payload.generation_status) {
|
|
760
|
+
return {
|
|
761
|
+
status: 'success',
|
|
762
|
+
data: payload,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
if (payload.errors) {
|
|
766
|
+
return {
|
|
767
|
+
status: 'error',
|
|
768
|
+
data: {
|
|
769
|
+
errors: payload.errors,
|
|
770
|
+
},
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
return null;
|
|
774
|
+
};
|
|
775
|
+
FlowscaleAPI.prototype.resolveGlobalFetch = function () {
|
|
776
|
+
var globalScope = typeof globalThis !== 'undefined'
|
|
777
|
+
? globalThis
|
|
778
|
+
: (typeof window !== 'undefined' ? window : undefined);
|
|
779
|
+
if (globalScope && typeof globalScope.fetch === 'function') {
|
|
780
|
+
return globalScope.fetch.bind(globalScope);
|
|
781
|
+
}
|
|
782
|
+
return null;
|
|
783
|
+
};
|
|
784
|
+
FlowscaleAPI.prototype.consumeRunEventsStream = function (runId, options, signal) {
|
|
785
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
786
|
+
var url, headers_1, response, contentType, errorText, error_5, normalizedError;
|
|
787
|
+
var _this = this;
|
|
788
|
+
var _a, _b;
|
|
789
|
+
return __generator(this, function (_c) {
|
|
790
|
+
switch (_c.label) {
|
|
791
|
+
case 0:
|
|
792
|
+
_c.trys.push([0, 8, 10, 12]);
|
|
793
|
+
url = new URL("/api/v1/runs/".concat(encodeURIComponent(runId), "/events"), this.baseUrl);
|
|
794
|
+
if (options.fromSeq !== undefined) {
|
|
795
|
+
url.searchParams.set('from_seq', String(options.fromSeq));
|
|
796
|
+
}
|
|
797
|
+
headers_1 = {
|
|
798
|
+
Accept: 'text/event-stream',
|
|
799
|
+
};
|
|
800
|
+
if (!this.proxyMode && this.apiKey) {
|
|
801
|
+
headers_1['X-API-KEY'] = this.apiKey;
|
|
802
|
+
}
|
|
803
|
+
Object.keys(this.customHeaders).forEach(function (key) {
|
|
804
|
+
headers_1[key] = _this.customHeaders[key];
|
|
805
|
+
});
|
|
806
|
+
return [4 /*yield*/, this.fetchImpl(url.toString(), {
|
|
807
|
+
method: 'GET',
|
|
808
|
+
headers: headers_1,
|
|
809
|
+
signal: signal,
|
|
810
|
+
})];
|
|
811
|
+
case 1:
|
|
812
|
+
response = _c.sent();
|
|
813
|
+
contentType = ((_b = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, 'content-type')) || null;
|
|
814
|
+
return [4 /*yield*/, this.invokeRunEventsCallback(options.onOpen, {
|
|
815
|
+
status: response.status,
|
|
816
|
+
contentType: contentType,
|
|
817
|
+
})];
|
|
818
|
+
case 2:
|
|
819
|
+
_c.sent();
|
|
820
|
+
if (!!response.ok) return [3 /*break*/, 4];
|
|
821
|
+
return [4 /*yield*/, this.safeReadResponseText(response)];
|
|
822
|
+
case 3:
|
|
823
|
+
errorText = _c.sent();
|
|
824
|
+
throw new Error("Failed to stream run events: ".concat(response.status, " ").concat(response.statusText) +
|
|
825
|
+
(errorText ? " - ".concat(errorText) : ''));
|
|
826
|
+
case 4:
|
|
827
|
+
if (!(contentType && contentType.includes('application/json'))) return [3 /*break*/, 6];
|
|
828
|
+
return [4 /*yield*/, this.consumeRunEventsSnapshotResponse(response, options)];
|
|
829
|
+
case 5:
|
|
830
|
+
_c.sent();
|
|
831
|
+
return [2 /*return*/];
|
|
832
|
+
case 6:
|
|
833
|
+
if (!response.body || typeof response.body.getReader !== 'function') {
|
|
834
|
+
throw new Error('SSE response body is not readable in this environment');
|
|
835
|
+
}
|
|
836
|
+
return [4 /*yield*/, this.consumeSSEReadableStream(response.body.getReader(), options, signal)];
|
|
837
|
+
case 7:
|
|
838
|
+
_c.sent();
|
|
839
|
+
return [3 /*break*/, 12];
|
|
840
|
+
case 8:
|
|
841
|
+
error_5 = _c.sent();
|
|
842
|
+
if (signal.aborted) {
|
|
843
|
+
return [2 /*return*/];
|
|
844
|
+
}
|
|
845
|
+
normalizedError = error_5 instanceof Error ? error_5 : new Error(this.formatUnknownError(error_5));
|
|
846
|
+
return [4 /*yield*/, this.invokeRunEventsCallback(options.onError, normalizedError)];
|
|
847
|
+
case 9:
|
|
848
|
+
_c.sent();
|
|
849
|
+
if (!options.onError) {
|
|
850
|
+
throw normalizedError;
|
|
851
|
+
}
|
|
852
|
+
return [3 /*break*/, 12];
|
|
853
|
+
case 10: return [4 /*yield*/, this.invokeRunEventsCallback(options.onClose)];
|
|
854
|
+
case 11:
|
|
855
|
+
_c.sent();
|
|
856
|
+
return [7 /*endfinally*/];
|
|
857
|
+
case 12: return [2 /*return*/];
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
};
|
|
862
|
+
FlowscaleAPI.prototype.safeReadResponseText = function (response) {
|
|
863
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
864
|
+
var _1;
|
|
865
|
+
return __generator(this, function (_a) {
|
|
866
|
+
switch (_a.label) {
|
|
867
|
+
case 0:
|
|
868
|
+
_a.trys.push([0, 2, , 3]);
|
|
869
|
+
return [4 /*yield*/, response.text()];
|
|
870
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
871
|
+
case 2:
|
|
872
|
+
_1 = _a.sent();
|
|
873
|
+
return [2 /*return*/, ''];
|
|
874
|
+
case 3: return [2 /*return*/];
|
|
875
|
+
}
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
};
|
|
879
|
+
FlowscaleAPI.prototype.consumeRunEventsSnapshotResponse = function (response, options) {
|
|
880
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
881
|
+
var snapshot, _2, events, _i, events_1, event_1, payload;
|
|
882
|
+
return __generator(this, function (_a) {
|
|
883
|
+
switch (_a.label) {
|
|
884
|
+
case 0:
|
|
885
|
+
snapshot = null;
|
|
886
|
+
_a.label = 1;
|
|
887
|
+
case 1:
|
|
888
|
+
_a.trys.push([1, 3, , 4]);
|
|
889
|
+
return [4 /*yield*/, response.json()];
|
|
890
|
+
case 2:
|
|
891
|
+
snapshot = _a.sent();
|
|
892
|
+
return [3 /*break*/, 4];
|
|
893
|
+
case 3:
|
|
894
|
+
_2 = _a.sent();
|
|
895
|
+
return [2 /*return*/];
|
|
896
|
+
case 4:
|
|
897
|
+
events = snapshot === null || snapshot === void 0 ? void 0 : snapshot.events;
|
|
898
|
+
if (!Array.isArray(events)) {
|
|
899
|
+
return [2 /*return*/];
|
|
900
|
+
}
|
|
901
|
+
_i = 0, events_1 = events;
|
|
902
|
+
_a.label = 5;
|
|
903
|
+
case 5:
|
|
904
|
+
if (!(_i < events_1.length)) return [3 /*break*/, 8];
|
|
905
|
+
event_1 = events_1[_i];
|
|
906
|
+
payload = event_1 === null || event_1 === void 0 ? void 0 : event_1.payload;
|
|
907
|
+
return [4 /*yield*/, this.invokeRunEventsCallback(options.onEvent, {
|
|
908
|
+
id: event_1 === null || event_1 === void 0 ? void 0 : event_1.sequence,
|
|
909
|
+
data: payload,
|
|
910
|
+
raw: JSON.stringify(payload !== null && payload !== void 0 ? payload : null),
|
|
911
|
+
})];
|
|
912
|
+
case 6:
|
|
913
|
+
_a.sent();
|
|
914
|
+
_a.label = 7;
|
|
915
|
+
case 7:
|
|
916
|
+
_i++;
|
|
917
|
+
return [3 /*break*/, 5];
|
|
918
|
+
case 8: return [2 /*return*/];
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
};
|
|
923
|
+
FlowscaleAPI.prototype.consumeSSEReadableStream = function (reader, options, signal) {
|
|
924
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
925
|
+
var decoder, buffer, eventId, eventType, dataLines, emitEvent, processLine, processBuffer, _a, done, value;
|
|
926
|
+
var _this = this;
|
|
927
|
+
return __generator(this, function (_b) {
|
|
928
|
+
switch (_b.label) {
|
|
929
|
+
case 0:
|
|
930
|
+
decoder = new TextDecoder();
|
|
931
|
+
buffer = '';
|
|
932
|
+
dataLines = [];
|
|
933
|
+
emitEvent = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
934
|
+
var raw, parsedData, id, eventPayload;
|
|
935
|
+
return __generator(this, function (_a) {
|
|
936
|
+
switch (_a.label) {
|
|
937
|
+
case 0:
|
|
938
|
+
if (dataLines.length === 0) {
|
|
939
|
+
eventId = undefined;
|
|
940
|
+
eventType = undefined;
|
|
941
|
+
return [2 /*return*/];
|
|
942
|
+
}
|
|
943
|
+
raw = dataLines.join('\n');
|
|
944
|
+
parsedData = raw;
|
|
945
|
+
try {
|
|
946
|
+
parsedData = JSON.parse(raw);
|
|
947
|
+
}
|
|
948
|
+
catch (_) {
|
|
949
|
+
// Keep raw text when payload is not JSON.
|
|
950
|
+
}
|
|
951
|
+
id = this.parseSSEEventId(eventId);
|
|
952
|
+
eventPayload = {
|
|
953
|
+
id: id,
|
|
954
|
+
event: eventType,
|
|
955
|
+
data: parsedData,
|
|
956
|
+
raw: raw,
|
|
957
|
+
};
|
|
958
|
+
return [4 /*yield*/, this.invokeRunEventsCallback(options.onEvent, eventPayload)];
|
|
959
|
+
case 1:
|
|
960
|
+
_a.sent();
|
|
961
|
+
eventId = undefined;
|
|
962
|
+
eventType = undefined;
|
|
963
|
+
dataLines = [];
|
|
964
|
+
return [2 /*return*/];
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
}); };
|
|
968
|
+
processLine = function (line) { return __awaiter(_this, void 0, void 0, function () {
|
|
969
|
+
var separatorIndex, field, value;
|
|
970
|
+
return __generator(this, function (_a) {
|
|
971
|
+
switch (_a.label) {
|
|
972
|
+
case 0:
|
|
973
|
+
if (!(line === '')) return [3 /*break*/, 2];
|
|
974
|
+
return [4 /*yield*/, emitEvent()];
|
|
975
|
+
case 1:
|
|
976
|
+
_a.sent();
|
|
977
|
+
return [2 /*return*/];
|
|
978
|
+
case 2:
|
|
979
|
+
if (line.startsWith(':')) {
|
|
980
|
+
return [2 /*return*/];
|
|
981
|
+
}
|
|
982
|
+
separatorIndex = line.indexOf(':');
|
|
983
|
+
field = line;
|
|
984
|
+
value = '';
|
|
985
|
+
if (separatorIndex >= 0) {
|
|
986
|
+
field = line.slice(0, separatorIndex);
|
|
987
|
+
value = line.slice(separatorIndex + 1);
|
|
988
|
+
if (value.startsWith(' ')) {
|
|
989
|
+
value = value.slice(1);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
switch (field) {
|
|
993
|
+
case 'id':
|
|
994
|
+
eventId = value;
|
|
995
|
+
break;
|
|
996
|
+
case 'event':
|
|
997
|
+
eventType = value;
|
|
998
|
+
break;
|
|
999
|
+
case 'data':
|
|
1000
|
+
dataLines.push(value);
|
|
1001
|
+
break;
|
|
1002
|
+
default:
|
|
1003
|
+
break;
|
|
1004
|
+
}
|
|
1005
|
+
return [2 /*return*/];
|
|
1006
|
+
}
|
|
1007
|
+
});
|
|
1008
|
+
}); };
|
|
1009
|
+
processBuffer = function () {
|
|
1010
|
+
var args_1 = [];
|
|
1011
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1012
|
+
args_1[_i] = arguments[_i];
|
|
1013
|
+
}
|
|
1014
|
+
return __awaiter(_this, __spreadArray([], args_1, true), void 0, function (flushFinalLine) {
|
|
1015
|
+
var newlineIndex, line, line;
|
|
1016
|
+
if (flushFinalLine === void 0) { flushFinalLine = false; }
|
|
1017
|
+
return __generator(this, function (_a) {
|
|
1018
|
+
switch (_a.label) {
|
|
1019
|
+
case 0:
|
|
1020
|
+
if (!true) return [3 /*break*/, 2];
|
|
1021
|
+
newlineIndex = buffer.indexOf('\n');
|
|
1022
|
+
if (newlineIndex < 0) {
|
|
1023
|
+
return [3 /*break*/, 2];
|
|
1024
|
+
}
|
|
1025
|
+
line = buffer.slice(0, newlineIndex);
|
|
1026
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
1027
|
+
if (line.endsWith('\r')) {
|
|
1028
|
+
line = line.slice(0, -1);
|
|
1029
|
+
}
|
|
1030
|
+
return [4 /*yield*/, processLine(line)];
|
|
1031
|
+
case 1:
|
|
1032
|
+
_a.sent();
|
|
1033
|
+
return [3 /*break*/, 0];
|
|
1034
|
+
case 2:
|
|
1035
|
+
if (!(flushFinalLine && buffer.length > 0)) return [3 /*break*/, 4];
|
|
1036
|
+
line = buffer;
|
|
1037
|
+
buffer = '';
|
|
1038
|
+
if (line.endsWith('\r')) {
|
|
1039
|
+
line = line.slice(0, -1);
|
|
1040
|
+
}
|
|
1041
|
+
return [4 /*yield*/, processLine(line)];
|
|
1042
|
+
case 3:
|
|
1043
|
+
_a.sent();
|
|
1044
|
+
_a.label = 4;
|
|
1045
|
+
case 4: return [2 /*return*/];
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
});
|
|
1049
|
+
};
|
|
1050
|
+
_b.label = 1;
|
|
1051
|
+
case 1:
|
|
1052
|
+
if (!!signal.aborted) return [3 /*break*/, 5];
|
|
1053
|
+
return [4 /*yield*/, reader.read()];
|
|
1054
|
+
case 2:
|
|
1055
|
+
_a = _b.sent(), done = _a.done, value = _a.value;
|
|
1056
|
+
if (done) {
|
|
1057
|
+
return [3 /*break*/, 5];
|
|
1058
|
+
}
|
|
1059
|
+
if (!value) return [3 /*break*/, 4];
|
|
1060
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1061
|
+
return [4 /*yield*/, processBuffer()];
|
|
1062
|
+
case 3:
|
|
1063
|
+
_b.sent();
|
|
1064
|
+
_b.label = 4;
|
|
1065
|
+
case 4: return [3 /*break*/, 1];
|
|
1066
|
+
case 5:
|
|
1067
|
+
buffer += decoder.decode();
|
|
1068
|
+
return [4 /*yield*/, processBuffer(true)];
|
|
1069
|
+
case 6:
|
|
1070
|
+
_b.sent();
|
|
1071
|
+
return [4 /*yield*/, emitEvent()];
|
|
1072
|
+
case 7:
|
|
1073
|
+
_b.sent();
|
|
1074
|
+
return [2 /*return*/];
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
};
|
|
1079
|
+
FlowscaleAPI.prototype.parseSSEEventId = function (eventId) {
|
|
1080
|
+
if (eventId === undefined || eventId === '') {
|
|
1081
|
+
return undefined;
|
|
1082
|
+
}
|
|
1083
|
+
var numeric = Number(eventId);
|
|
1084
|
+
if (!Number.isNaN(numeric) && Number.isFinite(numeric)) {
|
|
1085
|
+
return numeric;
|
|
1086
|
+
}
|
|
1087
|
+
return eventId;
|
|
1088
|
+
};
|
|
1089
|
+
FlowscaleAPI.prototype.invokeRunEventsCallback = function (callback, payload) {
|
|
1090
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1091
|
+
var error_6;
|
|
1092
|
+
return __generator(this, function (_a) {
|
|
1093
|
+
switch (_a.label) {
|
|
1094
|
+
case 0:
|
|
1095
|
+
if (!callback) {
|
|
1096
|
+
return [2 /*return*/];
|
|
1097
|
+
}
|
|
1098
|
+
_a.label = 1;
|
|
1099
|
+
case 1:
|
|
1100
|
+
_a.trys.push([1, 6, , 7]);
|
|
1101
|
+
if (!(payload === undefined)) return [3 /*break*/, 3];
|
|
1102
|
+
return [4 /*yield*/, callback()];
|
|
1103
|
+
case 2:
|
|
1104
|
+
_a.sent();
|
|
1105
|
+
return [3 /*break*/, 5];
|
|
1106
|
+
case 3: return [4 /*yield*/, callback(payload)];
|
|
1107
|
+
case 4:
|
|
1108
|
+
_a.sent();
|
|
1109
|
+
_a.label = 5;
|
|
1110
|
+
case 5: return [3 /*break*/, 7];
|
|
1111
|
+
case 6:
|
|
1112
|
+
error_6 = _a.sent();
|
|
1113
|
+
this.logWarn('Run events callback failed:', error_6);
|
|
1114
|
+
return [3 /*break*/, 7];
|
|
1115
|
+
case 7: return [2 /*return*/];
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
});
|
|
1119
|
+
};
|
|
658
1120
|
/**
|
|
659
1121
|
* Helper method to append data to FormData.
|
|
660
1122
|
*/
|
|
@@ -759,7 +1221,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
759
1221
|
case 0:
|
|
760
1222
|
retries = 0;
|
|
761
1223
|
_loop_2 = function () {
|
|
762
|
-
var response, _b,
|
|
1224
|
+
var response, _b, error_7, axiosError, isTimeout, delay_1;
|
|
763
1225
|
return __generator(this, function (_c) {
|
|
764
1226
|
switch (_c.label) {
|
|
765
1227
|
case 0:
|
|
@@ -777,13 +1239,13 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
777
1239
|
response = _b;
|
|
778
1240
|
return [2 /*return*/, { value: response.data }];
|
|
779
1241
|
case 5:
|
|
780
|
-
|
|
781
|
-
axiosError =
|
|
1242
|
+
error_7 = _c.sent();
|
|
1243
|
+
axiosError = error_7;
|
|
782
1244
|
isTimeout = axiosError.code === 'ECONNABORTED' ||
|
|
783
1245
|
(axiosError.response && axiosError.response.status === 504);
|
|
784
1246
|
// Only retry on timeout errors or if we're in the browser (not Node.js)
|
|
785
1247
|
if (!isTimeout && this_2.isNode) {
|
|
786
|
-
this_2.handleError(
|
|
1248
|
+
this_2.handleError(error_7);
|
|
787
1249
|
}
|
|
788
1250
|
retries++;
|
|
789
1251
|
// If we've tried max times, handle the error
|
|
@@ -793,7 +1255,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
793
1255
|
return [2 /*return*/, { value: { status: "success", data: {} } }];
|
|
794
1256
|
}
|
|
795
1257
|
else {
|
|
796
|
-
this_2.handleError(
|
|
1258
|
+
this_2.handleError(error_7);
|
|
797
1259
|
}
|
|
798
1260
|
}
|
|
799
1261
|
this_2.logWarn("Attempt ".concat(retries, "/").concat(this_2.maxRetries, " failed, retrying in ").concat(this_2.retryDelay * Math.pow(2, retries - 1), "ms..."));
|
|
@@ -823,127 +1285,6 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
823
1285
|
});
|
|
824
1286
|
});
|
|
825
1287
|
};
|
|
826
|
-
/**
|
|
827
|
-
* Connects to the WebSocket API endpoint and sets up event handlers.
|
|
828
|
-
* @param options - Configuration options for the WebSocket connection
|
|
829
|
-
* @returns A function that can be called to disconnect the WebSocket
|
|
830
|
-
*/
|
|
831
|
-
FlowscaleAPI.prototype.connectWebSocket = function (options) {
|
|
832
|
-
var _this = this;
|
|
833
|
-
var _a, _b, _c;
|
|
834
|
-
if (options === void 0) { options = {}; }
|
|
835
|
-
if (!this.WebSocketImpl) {
|
|
836
|
-
throw new Error('WebSocket functionality is not available. ' +
|
|
837
|
-
(this.isNode ?
|
|
838
|
-
'For Node.js environments, install the "ws" library and pass it as WebSocketImpl in the config:\n' +
|
|
839
|
-
'npm install ws\n' +
|
|
840
|
-
'const WebSocket = require("ws");\n' +
|
|
841
|
-
'new FlowscaleAPI({ ..., WebSocketImpl: WebSocket })' :
|
|
842
|
-
'WebSocket is not supported in this environment.'));
|
|
843
|
-
}
|
|
844
|
-
// Default options
|
|
845
|
-
var reconnect = (_a = options.reconnect) !== null && _a !== void 0 ? _a : true;
|
|
846
|
-
var reconnectInterval = (_b = options.reconnectInterval) !== null && _b !== void 0 ? _b : 5000;
|
|
847
|
-
var maxReconnectAttempts = (_c = options.maxReconnectAttempts) !== null && _c !== void 0 ? _c : 5;
|
|
848
|
-
// Close any existing connection and clear reconnection timeout
|
|
849
|
-
this.disconnectWebSocket();
|
|
850
|
-
// Format the WebSocket URL
|
|
851
|
-
var wsUrl = new URL('/api/v1/ws/subscribe', this.baseUrl);
|
|
852
|
-
wsUrl.protocol = wsUrl.protocol.replace('https', 'wss');
|
|
853
|
-
// Add API key only if not in proxy mode
|
|
854
|
-
if (!this.proxyMode && this.apiKey) {
|
|
855
|
-
wsUrl.searchParams.append('api_key', this.apiKey);
|
|
856
|
-
}
|
|
857
|
-
// Note: In proxy mode, authentication should be handled by the proxy server
|
|
858
|
-
// Create a new WebSocket connection
|
|
859
|
-
this.ws = new this.WebSocketImpl(wsUrl.toString());
|
|
860
|
-
this.reconnectAttempts = 0;
|
|
861
|
-
// Set up event handlers
|
|
862
|
-
if (this.ws) {
|
|
863
|
-
this.ws.onopen = function () {
|
|
864
|
-
_this.logInfo('WebSocket connection established');
|
|
865
|
-
_this.wsConnected = true;
|
|
866
|
-
_this.reconnectAttempts = 0;
|
|
867
|
-
if (options.onOpen)
|
|
868
|
-
options.onOpen();
|
|
869
|
-
};
|
|
870
|
-
this.ws.onmessage = function (event) {
|
|
871
|
-
try {
|
|
872
|
-
var message = JSON.parse(event.data);
|
|
873
|
-
if (options.onMessage)
|
|
874
|
-
options.onMessage(message);
|
|
875
|
-
}
|
|
876
|
-
catch (error) {
|
|
877
|
-
_this.logError('Failed to parse WebSocket message:', error);
|
|
878
|
-
if (options.onError)
|
|
879
|
-
options.onError(new ErrorEvent('error', { error: error }));
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
this.ws.onclose = function (event) {
|
|
883
|
-
_this.logInfo("WebSocket connection closed: ".concat(event.code, " ").concat(event.reason));
|
|
884
|
-
_this.wsConnected = false;
|
|
885
|
-
// Attempt to reconnect if enabled and not already reconnecting
|
|
886
|
-
if (reconnect && _this.reconnectAttempts < maxReconnectAttempts && !_this.reconnectTimeout) {
|
|
887
|
-
_this.reconnectAttempts++;
|
|
888
|
-
_this.logInfo("Attempting to reconnect (".concat(_this.reconnectAttempts, "/").concat(maxReconnectAttempts, ")..."));
|
|
889
|
-
_this.reconnectTimeout = setTimeout(function () {
|
|
890
|
-
_this.reconnectTimeout = null;
|
|
891
|
-
_this.connectWebSocket(options);
|
|
892
|
-
}, reconnectInterval);
|
|
893
|
-
}
|
|
894
|
-
if (options.onClose)
|
|
895
|
-
options.onClose(event);
|
|
896
|
-
};
|
|
897
|
-
this.ws.onerror = function (error) {
|
|
898
|
-
_this.logError('WebSocket error:', error);
|
|
899
|
-
if (options.onError)
|
|
900
|
-
options.onError(error);
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
// Return a function to disconnect
|
|
904
|
-
return function () { return _this.disconnectWebSocket(); };
|
|
905
|
-
};
|
|
906
|
-
/**
|
|
907
|
-
* Disconnects the WebSocket connection if it exists.
|
|
908
|
-
*/
|
|
909
|
-
FlowscaleAPI.prototype.disconnectWebSocket = function () {
|
|
910
|
-
// Clear any pending reconnection timeout
|
|
911
|
-
if (this.reconnectTimeout) {
|
|
912
|
-
clearTimeout(this.reconnectTimeout);
|
|
913
|
-
this.reconnectTimeout = null;
|
|
914
|
-
}
|
|
915
|
-
if (this.ws) {
|
|
916
|
-
this.ws.close();
|
|
917
|
-
this.ws = null;
|
|
918
|
-
this.wsConnected = false;
|
|
919
|
-
}
|
|
920
|
-
// Reset reconnection attempts
|
|
921
|
-
this.reconnectAttempts = 0;
|
|
922
|
-
};
|
|
923
|
-
/**
|
|
924
|
-
* Sends a message through the WebSocket connection.
|
|
925
|
-
* @param message - The message to send
|
|
926
|
-
* @returns Whether the message was sent successfully
|
|
927
|
-
*/
|
|
928
|
-
FlowscaleAPI.prototype.sendWebSocketMessage = function (message) {
|
|
929
|
-
if (message === undefined || message === null) {
|
|
930
|
-
this.logError('Message cannot be null or undefined');
|
|
931
|
-
return false;
|
|
932
|
-
}
|
|
933
|
-
if (!this.ws || !this.wsConnected) {
|
|
934
|
-
this.logError('WebSocket is not connected');
|
|
935
|
-
return false;
|
|
936
|
-
}
|
|
937
|
-
try {
|
|
938
|
-
var messageString = typeof message === 'string' ? message : JSON.stringify(message);
|
|
939
|
-
this.ws.send(messageString);
|
|
940
|
-
return true;
|
|
941
|
-
}
|
|
942
|
-
catch (error) {
|
|
943
|
-
this.logError('Error sending WebSocket message:', error);
|
|
944
|
-
return false;
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
1288
|
/**
|
|
948
1289
|
* Updates custom headers for authentication (useful for refreshing JWT tokens)
|
|
949
1290
|
* @param headers - Object containing header key-value pairs
|
|
@@ -964,19 +1305,6 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
964
1305
|
FlowscaleAPI.prototype.getCustomHeaders = function () {
|
|
965
1306
|
return __assign({}, this.customHeaders);
|
|
966
1307
|
};
|
|
967
|
-
/**
|
|
968
|
-
* Checks if the WebSocket connection is currently open.
|
|
969
|
-
* @returns True if the WebSocket is connected, false otherwise
|
|
970
|
-
*/
|
|
971
|
-
FlowscaleAPI.prototype.isWebSocketConnected = function () {
|
|
972
|
-
var _a;
|
|
973
|
-
if (!this.ws || !this.wsConnected) {
|
|
974
|
-
return false;
|
|
975
|
-
}
|
|
976
|
-
// Handle both browser WebSocket and Node.js 'ws' library
|
|
977
|
-
var OPEN_STATE = ((_a = this.WebSocketImpl) === null || _a === void 0 ? void 0 : _a.OPEN) || 1; // WebSocket.OPEN = 1
|
|
978
|
-
return this.ws.readyState === OPEN_STATE;
|
|
979
|
-
};
|
|
980
1308
|
return FlowscaleAPI;
|
|
981
1309
|
}());
|
|
982
1310
|
exports.FlowscaleAPI = FlowscaleAPI;
|