@robosystems/client 0.3.11 → 0.3.12

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.
@@ -88,6 +88,20 @@ class OperationClient {
88
88
  this.scheduleCleanup(operationId, 5000);
89
89
  resolve(result);
90
90
  });
91
+ // Handle transport-level failures after the stream was initially
92
+ // opened (server drop, network blip exhausting retries). Without
93
+ // this, max_retries_exceeded closes the SSE client but leaves the
94
+ // monitorOperation promise pending until options.timeout fires.
95
+ sseClient.on('max_retries_exceeded', (err) => {
96
+ if (timeoutHandle)
97
+ clearTimeout(timeoutHandle);
98
+ result = {
99
+ success: false,
100
+ error: (err && (err.message || err.error)) || 'SSE connection lost (max retries exceeded)',
101
+ };
102
+ this.scheduleCleanup(operationId, 5000);
103
+ resolve(result);
104
+ });
91
105
  })
92
106
  .catch((error) => {
93
107
  if (timeoutHandle)
@@ -136,6 +136,21 @@ export class OperationClient {
136
136
  this.scheduleCleanup(operationId, 5000)
137
137
  resolve(result)
138
138
  })
139
+
140
+ // Handle transport-level failures after the stream was initially
141
+ // opened (server drop, network blip exhausting retries). Without
142
+ // this, max_retries_exceeded closes the SSE client but leaves the
143
+ // monitorOperation promise pending until options.timeout fires.
144
+ sseClient.on('max_retries_exceeded', (err) => {
145
+ if (timeoutHandle) clearTimeout(timeoutHandle)
146
+ result = {
147
+ success: false,
148
+ error:
149
+ (err && (err.message || err.error)) || 'SSE connection lost (max retries exceeded)',
150
+ }
151
+ this.scheduleCleanup(operationId, 5000)
152
+ resolve(result)
153
+ })
139
154
  })
140
155
  .catch((error) => {
141
156
  if (timeoutHandle) clearTimeout(timeoutHandle)
@@ -38,18 +38,36 @@ class SSEClient {
38
38
  this.eventSource = new EventSource(url, {
39
39
  withCredentials: this.config.credentials === 'include',
40
40
  });
41
+ let opened = false;
41
42
  const connectionTimeout = setTimeout(() => {
42
- reject(new Error('Connection timeout'));
43
- this.close();
43
+ if (!opened) {
44
+ reject(new Error('SSE connection timed out before opening'));
45
+ this.close();
46
+ }
44
47
  }, 10000);
45
48
  this.eventSource.onopen = () => {
49
+ opened = true;
46
50
  clearTimeout(connectionTimeout);
47
51
  this.reconnectAttempts = 0;
48
52
  this.emit('connected', null);
49
53
  resolve();
50
54
  };
51
55
  this.eventSource.onerror = (error) => {
52
- clearTimeout(connectionTimeout);
56
+ if (!opened) {
57
+ // Failed before the stream ever opened. Browser EventSource doesn't
58
+ // expose the HTTP status, but a CLOSED readyState at this point
59
+ // means a non-retryable response (commonly 401/403/404). Reject
60
+ // the initial promise so callers surface a clear error instead of
61
+ // waiting out the 10s connectionTimeout or spinning retries that
62
+ // can never satisfy this promise.
63
+ clearTimeout(connectionTimeout);
64
+ const nonRetryable = this.eventSource?.readyState === EventSource.CLOSED;
65
+ this.close();
66
+ reject(new Error(nonRetryable
67
+ ? 'SSE connection failed before open (likely auth/not-found; EventSource hides the HTTP status)'
68
+ : 'SSE connection error before open'));
69
+ return;
70
+ }
53
71
  if (!this.closed) {
54
72
  this.handleError(error, operationId, fromSequence);
55
73
  }
@@ -80,12 +80,17 @@ export class SSEClient {
80
80
  withCredentials: this.config.credentials === 'include',
81
81
  } as any)
82
82
 
83
+ let opened = false
84
+
83
85
  const connectionTimeout = setTimeout(() => {
84
- reject(new Error('Connection timeout'))
85
- this.close()
86
+ if (!opened) {
87
+ reject(new Error('SSE connection timed out before opening'))
88
+ this.close()
89
+ }
86
90
  }, 10000)
87
91
 
88
92
  this.eventSource.onopen = () => {
93
+ opened = true
89
94
  clearTimeout(connectionTimeout)
90
95
  this.reconnectAttempts = 0
91
96
  this.emit('connected', null)
@@ -93,7 +98,25 @@ export class SSEClient {
93
98
  }
94
99
 
95
100
  this.eventSource.onerror = (error) => {
96
- clearTimeout(connectionTimeout)
101
+ if (!opened) {
102
+ // Failed before the stream ever opened. Browser EventSource doesn't
103
+ // expose the HTTP status, but a CLOSED readyState at this point
104
+ // means a non-retryable response (commonly 401/403/404). Reject
105
+ // the initial promise so callers surface a clear error instead of
106
+ // waiting out the 10s connectionTimeout or spinning retries that
107
+ // can never satisfy this promise.
108
+ clearTimeout(connectionTimeout)
109
+ const nonRetryable = this.eventSource?.readyState === EventSource.CLOSED
110
+ this.close()
111
+ reject(
112
+ new Error(
113
+ nonRetryable
114
+ ? 'SSE connection failed before open (likely auth/not-found; EventSource hides the HTTP status)'
115
+ : 'SSE connection error before open'
116
+ )
117
+ )
118
+ return
119
+ }
97
120
  if (!this.closed) {
98
121
  this.handleError(error, operationId, fromSequence)
99
122
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/client",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "description": "TypeScript client library for RoboSystems Financial Knowledge Graph API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -1507,7 +1507,7 @@ export type CreateEventHandlerRequest = {
1507
1507
  /**
1508
1508
  * Match Metadata Expression
1509
1509
  *
1510
- * JSONPath-style equality map, e.g. {"metadata.category": "payroll"}
1510
+ * JSONPath-style equality map against event.metadata, e.g. {"category": "payroll"} or {"metadata.category": "payroll"}
1511
1511
  */
1512
1512
  match_metadata_expression?: {
1513
1513
  [key: string]: unknown;
package/sdk/types.gen.ts CHANGED
@@ -1552,7 +1552,7 @@ export type CreateEventHandlerRequest = {
1552
1552
  /**
1553
1553
  * Match Metadata Expression
1554
1554
  *
1555
- * JSONPath-style equality map, e.g. {"metadata.category": "payroll"}
1555
+ * JSONPath-style equality map against event.metadata, e.g. {"category": "payroll"} or {"metadata.category": "payroll"}
1556
1556
  */
1557
1557
  match_metadata_expression?: {
1558
1558
  [key: string]: unknown;
package/types.gen.d.ts CHANGED
@@ -1507,7 +1507,7 @@ export type CreateEventHandlerRequest = {
1507
1507
  /**
1508
1508
  * Match Metadata Expression
1509
1509
  *
1510
- * JSONPath-style equality map, e.g. {"metadata.category": "payroll"}
1510
+ * JSONPath-style equality map against event.metadata, e.g. {"category": "payroll"} or {"metadata.category": "payroll"}
1511
1511
  */
1512
1512
  match_metadata_expression?: {
1513
1513
  [key: string]: unknown;
package/types.gen.ts CHANGED
@@ -1552,7 +1552,7 @@ export type CreateEventHandlerRequest = {
1552
1552
  /**
1553
1553
  * Match Metadata Expression
1554
1554
  *
1555
- * JSONPath-style equality map, e.g. {"metadata.category": "payroll"}
1555
+ * JSONPath-style equality map against event.metadata, e.g. {"category": "payroll"} or {"metadata.category": "payroll"}
1556
1556
  */
1557
1557
  match_metadata_expression?: {
1558
1558
  [key: string]: unknown;