@eyepop.ai/eyepop 3.19.0 → 3.19.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/README.md CHANGED
@@ -6,7 +6,7 @@ The EyePop.ai Node SDK provides JavaScript and TypeScript access to EyePop worke
6
6
 
7
7
  ### Node
8
8
 
9
- The SDK is tested with Node 20 LTS and newer.
9
+ Requires Node.js 18 or newer. CI validates Node.js 22.
10
10
 
11
11
  ```shell
12
12
  npm install --save @eyepop.ai/eyepop
@@ -1251,12 +1251,21 @@ declare class EvaluateDatasetJob {
1251
1251
  cancel(): void;
1252
1252
  }
1253
1253
 
1254
+ declare class EyePopDataWebSocketError extends Error {
1255
+ readonly code = "DATA_WEBSOCKET_CONNECTION_FAILED";
1256
+ readonly endpoint: string;
1257
+ readonly sourceError: unknown;
1258
+ constructor(url: string, event: unknown);
1259
+ }
1254
1260
  declare class DataEndpoint extends Endpoint<DataEndpoint> {
1255
1261
  private datasetApiUrl;
1256
1262
  private vlmApiUrl;
1257
1263
  private _accountId;
1258
1264
  private _ws;
1259
1265
  private _ws_current_reconnect_delay;
1266
+ private _ws_reconnect_timeout;
1267
+ private _ws_reconnect_enabled;
1268
+ private _ws_connecting;
1260
1269
  private _account_event_handlers;
1261
1270
  private _dataset_uuid_to_event_handlers;
1262
1271
  constructor(options: DataOptions);
@@ -1264,6 +1273,9 @@ declare class DataEndpoint extends Endpoint<DataEndpoint> {
1264
1273
  disconnect(wait?: boolean): Promise<void>;
1265
1274
  protected reconnect(): Promise<DataEndpoint>;
1266
1275
  private reconnect_ws;
1276
+ private open_ws;
1277
+ private close_ws;
1278
+ private schedule_ws_reconnect;
1267
1279
  private options;
1268
1280
  private request;
1269
1281
  listDatasets(include_stats?: boolean, modifiable_version_only?: boolean): Promise<Dataset[]>;
@@ -1551,4 +1563,4 @@ declare namespace EyePop {
1551
1563
  function dataEndpoint(opts?: DataOptions): DataEndpoint;
1552
1564
  }
1553
1565
 
1554
- export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, type ChangeEvent, ChangeType, type ClassificationTask, type ComponentFinderComponent, type ComponentParams, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, type PathSource, type PlatformSupport, type Point2d, type Point3d, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopForward, type PopForwardOperator, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, type QcAiHubExportParams, type RectangleArea, type ResultStream, type Roi, Semaphore, type Session, type SessionAuth, type Source, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, WorkerEndpoint, type WorkerOptions, type WorkerSession, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, decodeDepthMap, EyePop as default, encodeMultipartFormData, getBaseUrl, randomMultipartBoundary, readableStreamFromString, resolveAuth };
1566
+ export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, type ChangeEvent, ChangeType, type ClassificationTask, type ComponentFinderComponent, type ComponentParams, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, type PathSource, type PlatformSupport, type Point2d, type Point3d, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopForward, type PopForwardOperator, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, type QcAiHubExportParams, type RectangleArea, type ResultStream, type Roi, Semaphore, type Session, type SessionAuth, type Source, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, WorkerEndpoint, type WorkerOptions, type WorkerSession, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, decodeDepthMap, EyePop as default, encodeMultipartFormData, getBaseUrl, randomMultipartBoundary, readableStreamFromString, resolveAuth };
@@ -1251,12 +1251,21 @@ declare class EvaluateDatasetJob {
1251
1251
  cancel(): void;
1252
1252
  }
1253
1253
 
1254
+ declare class EyePopDataWebSocketError extends Error {
1255
+ readonly code = "DATA_WEBSOCKET_CONNECTION_FAILED";
1256
+ readonly endpoint: string;
1257
+ readonly sourceError: unknown;
1258
+ constructor(url: string, event: unknown);
1259
+ }
1254
1260
  declare class DataEndpoint extends Endpoint<DataEndpoint> {
1255
1261
  private datasetApiUrl;
1256
1262
  private vlmApiUrl;
1257
1263
  private _accountId;
1258
1264
  private _ws;
1259
1265
  private _ws_current_reconnect_delay;
1266
+ private _ws_reconnect_timeout;
1267
+ private _ws_reconnect_enabled;
1268
+ private _ws_connecting;
1260
1269
  private _account_event_handlers;
1261
1270
  private _dataset_uuid_to_event_handlers;
1262
1271
  constructor(options: DataOptions);
@@ -1264,6 +1273,9 @@ declare class DataEndpoint extends Endpoint<DataEndpoint> {
1264
1273
  disconnect(wait?: boolean): Promise<void>;
1265
1274
  protected reconnect(): Promise<DataEndpoint>;
1266
1275
  private reconnect_ws;
1276
+ private open_ws;
1277
+ private close_ws;
1278
+ private schedule_ws_reconnect;
1267
1279
  private options;
1268
1280
  private request;
1269
1281
  listDatasets(include_stats?: boolean, modifiable_version_only?: boolean): Promise<Dataset[]>;
@@ -1551,4 +1563,4 @@ declare namespace EyePop {
1551
1563
  function dataEndpoint(opts?: DataOptions): DataEndpoint;
1552
1564
  }
1553
1565
 
1554
- export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, type ChangeEvent, ChangeType, type ClassificationTask, type ComponentFinderComponent, type ComponentParams, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, type PathSource, type PlatformSupport, type Point2d, type Point3d, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopForward, type PopForwardOperator, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, type QcAiHubExportParams, type RectangleArea, type ResultStream, type Roi, Semaphore, type Session, type SessionAuth, type Source, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, WorkerEndpoint, type WorkerOptions, type WorkerSession, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, decodeDepthMap, EyePop as default, encodeMultipartFormData, getBaseUrl, randomMultipartBoundary, readableStreamFromString, resolveAuth };
1566
+ export { type AbilityAliasEntry, AbstractJob, type AccessTokenAuth, type AliasResolution, type Annotation, AnnotationInclusionMode, AnnotationType, type ApiKeyAuth, type Area, AreaType, ArtifactType, type Asset, type AssetImport, AssetInclusionMode, AssetStatus, AssetUrlType, type AssetUuidSource, type Auth0Options, type Authentication, type AutoAnnotate, type AutoAnnotateParams, type AutoAnnotatePrompt, AutoAnnotateStatus, AutoAnnotateTask, type AutoPromptConfig, type AutoTask, type BaseArea, type BaseComponent, type BaseTask, type Box, type ChangeEvent, ChangeType, type ClassificationTask, type ComponentFinderComponent, type ComponentParams, type Contour, type ContourArea, type ContourFinderComponent, ContourType, type CreateWorkflow, type CreateWorkflowConfig, DEFAULT_PREDICTION_VERSION, DataApiType, DataEndpoint, type DataOptions, type DataSession, type Dataset, type DatasetAutoAnnotate, type DatasetAutoAnnotateCreate, type DatasetAutoAnnotateUpdate, type DatasetCreate, type DatasetHeroAssetUpdate, type DatasetParent, type DatasetUpdate, type DatasetVersion, type DatasetVersionAssetStats, type Depth, DepthMap, type DownloadResponse, Endpoint, EndpointState, type EvaluateConfig, type EvaluateFilter, type EvaluateRequest, type EvaluateResponse, type EvaluateRunInfo, EvaluationStatus, ExportedBy, EyePop, EyePopDataWebSocketError, EyepopLineDecoder, type FileSource, type ForwardComponent, ForwardOperatorType, type HttpClient, type InferRequest, type InferRunInfo, type InferRuntimeConfig, type InferenceComponent, InferenceType, type ListWorkFlowItem, type ListWorkFlowItemMetadata, type ListWorkflowItemMetadataLabels, LoadFromAssetUuidJob, LoadFromGroupJob, LoadFromJob, LoadMediaStreamJob, type LocalAuth, type Mask, type MediaStreamSource, type Model, type ModelCreate, type ModelExport, ModelExportStatus, ModelFormat, type ModelMetrics, ModelPrecisionType, type ModelSample, ModelStatus, ModelTask, type ModelTrainingProgress, ModelTrainingStage, ModelType, type ModelUpdate, type MotionDetectConfig, MotionModel, type MultipartContent, type MultipartPart, type OAuth2Auth, type OnChangeEvent, type Options, type PathSource, type PlatformSupport, type Point2d, type Point3d, type Pop, type PopComponent, PopComponentType, type PopCrop, type PopForward, type PopForwardOperator, type PredictedClass, type PredictedEmbedding, type PredictedKeyPoint, type PredictedKeyPoints, type PredictedMesh, type PredictedMotion, type PredictedObject, type PredictedText, type Prediction, PredictionVersion, type ProcessParams, type ProcessRequest, type QcAiHubExportParams, type RectangleArea, type ResultStream, type Roi, Semaphore, type Session, type SessionAuth, type Source, Stream, type StreamEvent, type StreamSource, type StreamTime, TaskMode, TaskType, type TimeSpan, type TrackingComponent, TranscodeMode, type TransformInto, TransientPopId, UploadGroupJob, UploadJob, type UploadSource, type UrlSource, UserReview, VideoMode, type VlmAbility, type VlmAbilityCreate, type VlmAbilityGroup, type VlmAbilityGroupCreate, type VlmAbilityGroupUpdate, VlmAbilityStatus, type VlmAbilityUpdate, WebrtcBase, WebrtcWhep, WebrtcWhip, WorkerEndpoint, type WorkerOptions, type WorkerSession, type Workflow, WorkflowPhase, accessTokenCredential, apiKeyCredential, decodeDepthMap, EyePop as default, encodeMultipartFormData, getBaseUrl, randomMultipartBoundary, readableStreamFromString, resolveAuth };
@@ -8677,6 +8677,7 @@ __export(index_exports, {
8677
8677
  EvaluationStatus: () => EvaluationStatus,
8678
8678
  ExportedBy: () => ExportedBy,
8679
8679
  EyePop: () => EyePop,
8680
+ EyePopDataWebSocketError: () => EyePopDataWebSocketError,
8680
8681
  EyepopLineDecoder: () => EyepopLineDecoder,
8681
8682
  ForwardOperatorType: () => ForwardOperatorType,
8682
8683
  InferenceType: () => InferenceType,
@@ -11522,57 +11523,8 @@ if ("document" in globalThis && "implementation" in globalThis.document) {
11522
11523
  };
11523
11524
  }
11524
11525
 
11525
- // ../../node_modules/url-join/lib/url-join.js
11526
- function normalize(strArray) {
11527
- var resultArray = [];
11528
- if (strArray.length === 0) {
11529
- return "";
11530
- }
11531
- if (typeof strArray[0] !== "string") {
11532
- throw new TypeError("Url must be a string. Received " + strArray[0]);
11533
- }
11534
- if (strArray[0].match(/^[^/:]+:\/*$/) && strArray.length > 1) {
11535
- var first = strArray.shift();
11536
- strArray[0] = first + strArray[0];
11537
- }
11538
- if (strArray[0].match(/^file:\/\/\//)) {
11539
- strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1:///");
11540
- } else {
11541
- strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1://");
11542
- }
11543
- for (var i = 0; i < strArray.length; i++) {
11544
- var component = strArray[i];
11545
- if (typeof component !== "string") {
11546
- throw new TypeError("Url must be a string. Received " + component);
11547
- }
11548
- if (component === "") {
11549
- continue;
11550
- }
11551
- if (i > 0) {
11552
- component = component.replace(/^[\/]+/, "");
11553
- }
11554
- if (i < strArray.length - 1) {
11555
- component = component.replace(/[\/]+$/, "");
11556
- } else {
11557
- component = component.replace(/[\/]+$/, "/");
11558
- }
11559
- resultArray.push(component);
11560
- }
11561
- var str = resultArray.join("/");
11562
- str = str.replace(/\/(\?|&|#[^!])/g, "$1");
11563
- var parts = str.split("?");
11564
- str = parts.shift() + (parts.length > 0 ? "?" : "") + parts.join("&");
11565
- return str;
11566
- }
11567
- function urlJoin() {
11568
- var input;
11569
- if (typeof arguments[0] === "object") {
11570
- input = arguments[0];
11571
- } else {
11572
- input = [].slice.call(arguments);
11573
- }
11574
- return normalize(input);
11575
- }
11526
+ // data/data_endpoint.ts
11527
+ var import_url_join = __toESM(require("url-join"));
11576
11528
 
11577
11529
  // data/data_types.ts
11578
11530
  var DataApiType = /* @__PURE__ */ ((DataApiType2) => {
@@ -11925,6 +11877,33 @@ var EvaluateDatasetJob = class {
11925
11877
  // data/data_endpoint.ts
11926
11878
  var WS_INITIAL_RECONNECT_DELAY = 1e3;
11927
11879
  var WS_MAX_RECONNECT_DELAY = 6e4;
11880
+ function ws_origin(url) {
11881
+ try {
11882
+ return new URL(url).origin;
11883
+ } catch {
11884
+ return url;
11885
+ }
11886
+ }
11887
+ function ws_failure_reason(event, sourceError) {
11888
+ if (sourceError instanceof Error) {
11889
+ return sourceError.message;
11890
+ }
11891
+ if (typeof sourceError === "string") {
11892
+ return sourceError;
11893
+ }
11894
+ return event?.message ?? "";
11895
+ }
11896
+ var EyePopDataWebSocketError = class extends Error {
11897
+ constructor(url, event) {
11898
+ const sourceError = event?.error ?? event;
11899
+ const reason = ws_failure_reason(event, sourceError);
11900
+ super(reason ? `EyePop Dataset event WebSocket connection failed: ${reason}` : "EyePop Dataset event WebSocket connection failed");
11901
+ this.code = "DATA_WEBSOCKET_CONNECTION_FAILED";
11902
+ this.name = "EyePopDataWebSocketError";
11903
+ this.endpoint = ws_origin(url);
11904
+ this.sourceError = sourceError;
11905
+ }
11906
+ };
11928
11907
  function omit_nulls(_, value) {
11929
11908
  if (value === null) {
11930
11909
  return void 0;
@@ -11938,6 +11917,9 @@ var DataEndpoint = class extends Endpoint {
11938
11917
  this.vlmApiUrl = null;
11939
11918
  this._ws = null;
11940
11919
  this._ws_current_reconnect_delay = null;
11920
+ this._ws_reconnect_timeout = null;
11921
+ this._ws_reconnect_enabled = false;
11922
+ this._ws_connecting = null;
11941
11923
  this._accountId = options.accountId || null;
11942
11924
  this._account_event_handlers = [];
11943
11925
  this._dataset_uuid_to_event_handlers = /* @__PURE__ */ new Map();
@@ -11961,14 +11943,15 @@ var DataEndpoint = class extends Endpoint {
11961
11943
  };
11962
11944
  }
11963
11945
  async disconnect(wait = true) {
11946
+ this._ws_reconnect_enabled = false;
11947
+ if (this._ws_reconnect_timeout) {
11948
+ clearTimeout(this._ws_reconnect_timeout);
11949
+ this._ws_reconnect_timeout = null;
11950
+ }
11964
11951
  this.datasetApiUrl = null;
11965
11952
  this.vlmApiUrl = null;
11966
11953
  if (this._ws) {
11967
- try {
11968
- this._ws.close();
11969
- } catch (e) {
11970
- this._logger.warn("ignored exception", e);
11971
- }
11954
+ this.close_ws(this._ws, "unsubscribe");
11972
11955
  this._ws = null;
11973
11956
  }
11974
11957
  await super.disconnect(wait);
@@ -12006,13 +11989,14 @@ var DataEndpoint = class extends Endpoint {
12006
11989
  const vlmApiUrl = new URL(config.vlm_api_url, this.eyepopUrl());
12007
11990
  this.vlmApiUrl = vlmApiUrl.toString();
12008
11991
  if (this.options().disableWs) {
11992
+ this._ws_reconnect_enabled = false;
12009
11993
  this._logger.info("disabled ws connection");
12010
11994
  } else {
12011
11995
  await this.reconnect_ws();
12012
11996
  }
12013
11997
  if (this.options().useCookie) {
12014
11998
  const client = this._client;
12015
- const url = urlJoin(this.datasetApiUrl, "security", "check?set_cookie=true");
11999
+ const url = (0, import_url_join.default)(this.datasetApiUrl, "security", "check?set_cookie=true");
12016
12000
  const headers2 = {
12017
12001
  Authorization: await this.authorizationHeader()
12018
12002
  };
@@ -12029,37 +12013,68 @@ var DataEndpoint = class extends Endpoint {
12029
12013
  return Promise.resolve(this);
12030
12014
  }
12031
12015
  async reconnect_ws() {
12016
+ if (this._ws_connecting) {
12017
+ return this._ws_connecting;
12018
+ }
12019
+ const connecting = this.open_ws();
12020
+ this._ws_connecting = connecting;
12021
+ try {
12022
+ await connecting;
12023
+ } finally {
12024
+ this._ws_connecting = null;
12025
+ }
12026
+ }
12027
+ async open_ws() {
12032
12028
  if (this._ws) {
12033
- this._ws.close();
12029
+ this.close_ws(this._ws, "unsubscribe");
12034
12030
  this._ws = null;
12035
12031
  }
12036
12032
  const baseUrl = this.datasetApiUrl?.replace("https://", "wss://").replace("http://", "ws://");
12037
12033
  if (!baseUrl) {
12038
12034
  return;
12039
12035
  }
12040
- const ws_url = urlJoin(baseUrl, "events");
12036
+ const ws_url = (0, import_url_join.default)(baseUrl, "events");
12041
12037
  this._requestLogger.debug("about to connect ws to: %s", ws_url);
12042
12038
  return new Promise((resolve, reject) => {
12039
+ let settled = false;
12040
+ const settle_ok = () => {
12041
+ settled = true;
12042
+ resolve();
12043
+ };
12044
+ const settle_err = (error) => {
12045
+ settled = true;
12046
+ reject(error);
12047
+ };
12043
12048
  const ws = createWebSocket(ws_url);
12044
12049
  if (!ws) {
12045
- return resolve();
12050
+ return settle_ok();
12046
12051
  }
12047
12052
  this._ws = ws;
12048
- ws.onopen = async () => {
12049
- const auth_header = await this.authorizationHeader();
12050
- let msg = JSON.stringify({ authorization: auth_header });
12051
- this._requestLogger.debug("ws send: %s", msg);
12052
- ws.send(msg);
12053
- msg = JSON.stringify({ subscribe: { account_uuid: this._accountId } });
12054
- this._requestLogger.debug("ws send: %s", msg);
12055
- ws.send(msg);
12056
- for (let dataset_uuid in this._dataset_uuid_to_event_handlers.keys()) {
12057
- const msg2 = JSON.stringify({ subscribe: { dataset_uuid } });
12058
- this._requestLogger.debug("ws send: %s", msg2);
12059
- ws.send(msg2);
12060
- }
12061
- this._ws_current_reconnect_delay = WS_INITIAL_RECONNECT_DELAY;
12062
- resolve();
12053
+ ws.onopen = () => {
12054
+ void this.authorizationHeader().then((auth_header) => {
12055
+ if (this._ws !== ws) {
12056
+ this.close_ws(ws, "unsubscribe");
12057
+ settle_ok();
12058
+ return;
12059
+ }
12060
+ let msg = JSON.stringify({ authorization: auth_header });
12061
+ this._requestLogger.debug("ws send: %s", msg);
12062
+ ws.send(msg);
12063
+ msg = JSON.stringify({ subscribe: { account_uuid: this._accountId } });
12064
+ this._requestLogger.debug("ws send: %s", msg);
12065
+ ws.send(msg);
12066
+ for (const dataset_uuid of this._dataset_uuid_to_event_handlers.keys()) {
12067
+ const msg2 = JSON.stringify({ subscribe: { dataset_uuid } });
12068
+ this._requestLogger.debug("ws send: %s", msg2);
12069
+ ws.send(msg2);
12070
+ }
12071
+ this._ws_current_reconnect_delay = WS_INITIAL_RECONNECT_DELAY;
12072
+ this._ws_reconnect_enabled = true;
12073
+ settle_ok();
12074
+ }).catch((error) => {
12075
+ this.close_ws(ws, "authorization failed", 1011);
12076
+ settle_err(error);
12077
+ });
12063
12078
  };
12064
12079
  ws.onmessage = (event) => {
12065
12080
  const data = JSON.parse(event.data);
@@ -12070,24 +12085,54 @@ var DataEndpoint = class extends Endpoint {
12070
12085
  ws.onclose = (event) => {
12071
12086
  const { code, reason } = event;
12072
12087
  this._requestLogger.debug("ws closed: %d %s", code, reason);
12073
- if (reason !== "unsubscribe") {
12074
- if (!this._ws_current_reconnect_delay) {
12075
- this._ws_current_reconnect_delay = WS_INITIAL_RECONNECT_DELAY;
12076
- } else if (this._ws_current_reconnect_delay < WS_MAX_RECONNECT_DELAY) {
12077
- this._ws_current_reconnect_delay *= 1.5;
12078
- }
12079
- setTimeout(async () => {
12080
- await this.reconnect_ws();
12081
- }, this._ws_current_reconnect_delay);
12088
+ if (!settled) {
12089
+ settle_err(new EyePopDataWebSocketError(ws_url, new Error(`closed before the connection was established: ${code} ${reason}`)));
12090
+ }
12091
+ if (this._ws !== ws) {
12092
+ return;
12082
12093
  }
12094
+ this._ws = null;
12095
+ this.schedule_ws_reconnect();
12083
12096
  };
12084
12097
  ws.onerror = (event) => {
12085
- this._logger.error(event);
12086
- reject(event);
12098
+ const error = new EyePopDataWebSocketError(ws_url, event);
12099
+ this._logger.error({ err: error }, "dataset event WebSocket connection failed");
12100
+ settle_err(error);
12087
12101
  return null;
12088
12102
  };
12089
12103
  });
12090
12104
  }
12105
+ close_ws(ws, reason, code = 1e3) {
12106
+ try {
12107
+ ws.close(code, reason);
12108
+ } catch (e) {
12109
+ this._logger.warn({ err: e }, "ignored exception closing the dataset event WebSocket");
12110
+ }
12111
+ }
12112
+ schedule_ws_reconnect() {
12113
+ if (!this._ws_reconnect_enabled || this._ws_reconnect_timeout) {
12114
+ return;
12115
+ }
12116
+ if (!this._ws_current_reconnect_delay) {
12117
+ this._ws_current_reconnect_delay = WS_INITIAL_RECONNECT_DELAY;
12118
+ } else if (this._ws_current_reconnect_delay < WS_MAX_RECONNECT_DELAY) {
12119
+ this._ws_current_reconnect_delay *= 1.5;
12120
+ }
12121
+ this._ws_reconnect_timeout = setTimeout(() => {
12122
+ if (!this._ws_reconnect_enabled) {
12123
+ this._ws_reconnect_timeout = null;
12124
+ return;
12125
+ }
12126
+ void this.reconnect_ws().catch((error) => {
12127
+ this._requestLogger.debug("dataset event WebSocket reconnect failed: %s", error);
12128
+ }).finally(() => {
12129
+ this._ws_reconnect_timeout = null;
12130
+ if (!this._ws) {
12131
+ this.schedule_ws_reconnect();
12132
+ }
12133
+ });
12134
+ }, this._ws_current_reconnect_delay);
12135
+ }
12091
12136
  options() {
12092
12137
  return this._options;
12093
12138
  }
@@ -12112,7 +12157,7 @@ var DataEndpoint = class extends Endpoint {
12112
12157
  body: options.body
12113
12158
  };
12114
12159
  this._requestLogger.debug("Request - " + ri.method + " " + path2 + " BODY: " + (ri.body ? ri.body : ""));
12115
- return await client.fetch(urlJoin(baseUrl ?? "", path2), ri);
12160
+ return await client.fetch((0, import_url_join.default)(baseUrl ?? "", path2), ri);
12116
12161
  });
12117
12162
  if (response.status === 204) {
12118
12163
  return null;
@@ -13090,6 +13135,7 @@ var index_default = EyePop;
13090
13135
  EvaluationStatus,
13091
13136
  ExportedBy,
13092
13137
  EyePop,
13138
+ EyePopDataWebSocketError,
13093
13139
  EyepopLineDecoder,
13094
13140
  ForwardOperatorType,
13095
13141
  InferenceType,