@robosystems/client 0.1.12 → 0.1.13

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.
@@ -1,166 +1,148 @@
1
- 'use client'
2
-
3
- /**
4
- * Core SSE (Server-Sent Events) client for RoboSystems API
5
- * Provides automatic reconnection, event replay, and type-safe event handling
6
- */
7
-
8
-
9
-
10
-
11
-
12
- export enum EventType {
13
- OPERATION_STARTED = 'operation_started',
14
- OPERATION_PROGRESS = 'operation_progress',
15
- OPERATION_COMPLETED = 'operation_completed',
16
- OPERATION_ERROR = 'operation_error',
17
- OPERATION_CANCELLED = 'operation_cancelled',
18
- DATA_CHUNK = 'data_chunk',
19
- METADATA = 'metadata',
20
- HEARTBEAT = 'heartbeat',
21
- QUEUE_UPDATE = 'queue_update',
22
- }
23
-
24
- export class SSEClient {
25
- private config
26
- private eventSource?
27
- private reconnectAttempts = 0
28
- private lastEventId?
29
- private closed = false
30
- private listeners void>> = new Map()
31
-
32
- constructor(config) {
33
- this.config = {
34
- maxRetries,
35
- retryDelay,
36
- heartbeatInterval,
37
- ...config,
1
+ 'use client';
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.SSEClient = exports.EventType = void 0;
5
+ var EventType;
6
+ (function (EventType) {
7
+ EventType["OPERATION_STARTED"] = "operation_started";
8
+ EventType["OPERATION_PROGRESS"] = "operation_progress";
9
+ EventType["OPERATION_COMPLETED"] = "operation_completed";
10
+ EventType["OPERATION_ERROR"] = "operation_error";
11
+ EventType["OPERATION_CANCELLED"] = "operation_cancelled";
12
+ EventType["DATA_CHUNK"] = "data_chunk";
13
+ EventType["METADATA"] = "metadata";
14
+ EventType["HEARTBEAT"] = "heartbeat";
15
+ EventType["QUEUE_UPDATE"] = "queue_update";
16
+ })(EventType || (exports.EventType = EventType = {}));
17
+ class SSEClient {
18
+ constructor(config) {
19
+ this.reconnectAttempts = 0;
20
+ this.closed = false;
21
+ this.listeners = new Map();
22
+ this.config = {
23
+ maxRetries: 5,
24
+ retryDelay: 1000,
25
+ heartbeatInterval: 30000,
26
+ ...config,
27
+ };
28
+ }
29
+ async connect(operationId, fromSequence = 0) {
30
+ return new Promise((resolve, reject) => {
31
+ const url = `${this.config.baseUrl}/v1/operations/${operationId}/stream?from_sequence=${fromSequence}`;
32
+ this.eventSource = new EventSource(url, {
33
+ withCredentials: this.config.credentials === 'include',
34
+ });
35
+ const connectionTimeout = setTimeout(() => {
36
+ reject(new Error('Connection timeout'));
37
+ this.close();
38
+ }, 10000);
39
+ this.eventSource.onopen = () => {
40
+ clearTimeout(connectionTimeout);
41
+ this.reconnectAttempts = 0;
42
+ this.emit('connected', null);
43
+ resolve();
44
+ };
45
+ this.eventSource.onerror = (error) => {
46
+ clearTimeout(connectionTimeout);
47
+ if (!this.closed) {
48
+ this.handleError(error, operationId, fromSequence);
49
+ }
50
+ };
51
+ this.eventSource.onmessage = (event) => {
52
+ this.handleMessage(event);
53
+ };
54
+ // Set up specific event listeners
55
+ Object.values(EventType).forEach((eventType) => {
56
+ this.eventSource.addEventListener(eventType, (event) => {
57
+ this.handleTypedEvent(eventType, event);
58
+ });
59
+ });
60
+ });
61
+ }
62
+ handleMessage(event) {
63
+ try {
64
+ const data = JSON.parse(event.data);
65
+ const sseEvent = {
66
+ event: event.type || 'message',
67
+ data,
68
+ id: event.lastEventId,
69
+ timestamp: new Date(),
70
+ };
71
+ this.lastEventId = event.lastEventId;
72
+ this.emit('event', sseEvent);
73
+ }
74
+ catch (error) {
75
+ this.emit('parse_error', { error, rawData: event.data });
76
+ }
38
77
  }
39
- }
40
-
41
- async connect(operationId, fromSequence = 0) {
42
- return new Promise((resolve, reject) => {
43
- const url = `${this.config.baseUrl}/v1/operations/${operationId}/stream?from_sequence=${fromSequence}`
44
-
45
- this.eventSource = new EventSource(url, {
46
- withCredentials.config.credentials === 'include',
47
- })
48
-
49
- const connectionTimeout = setTimeout(() => {
50
- reject(new Error('Connection timeout'))
51
- this.close()
52
- }, 10000)
53
-
54
- this.eventSource.onopen = () => {
55
- clearTimeout(connectionTimeout)
56
- this.reconnectAttempts = 0
57
- this.emit('connected', null)
58
- resolve()
59
- }
60
-
61
- this.eventSource.onerror = (error) => {
62
- clearTimeout(connectionTimeout)
63
- if (!this.closed) {
64
- this.handleError(error, operationId, fromSequence)
78
+ handleTypedEvent(eventType, event) {
79
+ try {
80
+ const data = JSON.parse(event.data);
81
+ this.lastEventId = event.lastEventId;
82
+ this.emit(eventType, data);
83
+ // Check for completion events
84
+ if (eventType === EventType.OPERATION_COMPLETED ||
85
+ eventType === EventType.OPERATION_ERROR ||
86
+ eventType === EventType.OPERATION_CANCELLED) {
87
+ this.close();
88
+ }
89
+ }
90
+ catch (error) {
91
+ this.emit('parse_error', { error, rawData: event.data });
65
92
  }
66
- }
67
-
68
- this.eventSource.onmessage = (event) => {
69
- this.handleMessage(event)
70
- }
71
-
72
- // Set up specific event listeners
73
- Object.values(EventType).forEach((eventType) => {
74
- this.eventSource!.addEventListener(eventType, (event) => {
75
- this.handleTypedEvent(eventType, event)
76
- })
77
- })
78
- })
79
- }
80
-
81
- private handleMessage(event) {
82
- try {
83
- const data = JSON.parse(event.data)
84
- const sseEvent = {
85
- event.type || 'message',
86
- data,
87
- id.lastEventId,
88
- timestamp Date(),
89
- }
90
-
91
- this.lastEventId = event.lastEventId
92
- this.emit('event', sseEvent)
93
- } catch (error) {
94
- this.emit('parse_error', { error, rawData.data })
95
93
  }
96
- }
97
-
98
- private handleTypedEvent(eventType, event) {
99
- try {
100
- const data = JSON.parse(event.data)
101
- this.lastEventId = event.lastEventId
102
- this.emit(eventType, data)
103
-
104
- // Check for completion events
105
- if (
106
- eventType === EventType.OPERATION_COMPLETED ||
107
- eventType === EventType.OPERATION_ERROR ||
108
- eventType === EventType.OPERATION_CANCELLED
109
- ) {
110
- this.close()
111
- }
112
- } catch (error) {
113
- this.emit('parse_error', { error, rawData.data })
94
+ async handleError(error, operationId, fromSequence) {
95
+ if (this.closed)
96
+ return;
97
+ if (this.reconnectAttempts < this.config.maxRetries) {
98
+ this.reconnectAttempts++;
99
+ const delay = this.config.retryDelay * Math.pow(2, this.reconnectAttempts - 1);
100
+ this.emit('reconnecting', {
101
+ attempt: this.reconnectAttempts,
102
+ delay,
103
+ lastEventId: this.lastEventId,
104
+ });
105
+ setTimeout(() => {
106
+ const resumeFrom = this.lastEventId ? parseInt(this.lastEventId) + 1 : fromSequence;
107
+ this.connect(operationId, resumeFrom).catch(() => {
108
+ // Error handled in connect
109
+ });
110
+ }, delay);
111
+ }
112
+ else {
113
+ this.emit('max_retries_exceeded', error);
114
+ this.close();
115
+ }
114
116
  }
115
- }
116
-
117
- private async handleError(error, operationId, fromSequence) {
118
- if (this.closed) return
119
-
120
- if (this.reconnectAttempts {
121
- const resumeFrom = this.lastEventId ? parseInt(this.lastEventId) + 1
122
- this.connect(operationId, resumeFrom).catch(() => {
123
- // Error handled in connect
124
- })
125
- }, delay)
126
- } else {
127
- this.emit('max_retries_exceeded', error)
128
- this.close()
117
+ on(event, listener) {
118
+ if (!this.listeners.has(event)) {
119
+ this.listeners.set(event, new Set());
120
+ }
121
+ this.listeners.get(event).add(listener);
129
122
  }
130
- }
131
-
132
- on(event, listener) {
133
- if (!this.listeners.has(event)) {
134
- this.listeners.set(event, new Set())
123
+ off(event, listener) {
124
+ const listeners = this.listeners.get(event);
125
+ if (listeners) {
126
+ listeners.delete(listener);
127
+ }
135
128
  }
136
- this.listeners.get(event)!.add(listener)
137
- }
138
-
139
- off(event, listener) {
140
- const listeners = this.listeners.get(event)
141
- if (listeners) {
142
- listeners.delete(listener)
129
+ emit(event, data) {
130
+ const listeners = this.listeners.get(event);
131
+ if (listeners) {
132
+ listeners.forEach((listener) => listener(data));
133
+ }
143
134
  }
144
- }
145
-
146
- private emit(event, data) {
147
- const listeners = this.listeners.get(event)
148
- if (listeners) {
149
- listeners.forEach((listener) => listener(data))
135
+ close() {
136
+ this.closed = true;
137
+ if (this.eventSource) {
138
+ this.eventSource.close();
139
+ this.eventSource = undefined;
140
+ }
141
+ this.emit('closed', null);
142
+ this.listeners.clear();
150
143
  }
151
- }
152
-
153
- close() {
154
- this.closed = true
155
- if (this.eventSource) {
156
- this.eventSource.close()
157
- this.eventSource = undefined
144
+ isConnected() {
145
+ return this.eventSource !== undefined && this.eventSource.readyState === EventSource.OPEN;
158
146
  }
159
- this.emit('closed', null)
160
- this.listeners.clear()
161
- }
162
-
163
- isConnected() {
164
- return this.eventSource !== undefined && this.eventSource.readyState === EventSource.OPEN
165
- }
166
147
  }
148
+ exports.SSEClient = SSEClient;
@@ -1,66 +1,74 @@
1
- 'use client'
2
-
3
- /**
4
- * Configuration for SDK extensions
5
- * Provides centralized configuration for CORS, credentials, and other settings
6
- */
7
-
8
-
9
-
1
+ 'use client';
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.setSDKExtensionsConfig = setSDKExtensionsConfig;
5
+ exports.getSDKExtensionsConfig = getSDKExtensionsConfig;
6
+ exports.resetSDKExtensionsConfig = resetSDKExtensionsConfig;
7
+ exports.getEnvironmentConfig = getEnvironmentConfig;
10
8
  // Default configuration
11
9
  const defaultConfig = {
12
- baseUrl.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
13
- credentials,
14
- timeout,
15
- maxRetries,
16
- retryDelay,
17
- }
18
-
10
+ baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
11
+ credentials: 'include',
12
+ timeout: 30000,
13
+ maxRetries: 3,
14
+ retryDelay: 1000,
15
+ };
19
16
  // Global configuration singleton
20
- let globalConfig = { ...defaultConfig }
21
-
17
+ let globalConfig = { ...defaultConfig };
22
18
  /**
23
19
  * Set global configuration for SDK extensions
24
20
  * @param config Partial configuration to merge with defaults
25
21
  */
26
- export function setSDKExtensionsConfig(config) {
27
- globalConfig = {
28
- ...globalConfig,
29
- ...config,
30
- }
22
+ function setSDKExtensionsConfig(config) {
23
+ globalConfig = {
24
+ ...globalConfig,
25
+ ...config,
26
+ };
31
27
  }
32
-
33
28
  /**
34
29
  * Get current SDK extensions configuration
35
30
  * @returns Current configuration
36
31
  */
37
- export function getSDKExtensionsConfig() {
38
- return { ...globalConfig }
32
+ function getSDKExtensionsConfig() {
33
+ return { ...globalConfig };
39
34
  }
40
-
41
35
  /**
42
36
  * Reset configuration to defaults
43
37
  */
44
- export function resetSDKExtensionsConfig() {
45
- globalConfig = { ...defaultConfig }
38
+ function resetSDKExtensionsConfig() {
39
+ globalConfig = { ...defaultConfig };
46
40
  }
47
-
48
41
  /**
49
42
  * Get configuration for a specific environment
50
43
  * @param env Environment name (production, staging, development)
51
44
  * @returns Environment-specific configuration
52
45
  */
53
- export function getEnvironmentConfig(
54
- env | 'staging' | 'development' = 'development'
55
- ) {
56
- const baseConfigs> = {
57
- production,
58
- staging,
59
- development,
60
- }
61
-
62
- return {
63
- ...defaultConfig,
64
- ...baseConfigs[env],
65
- }
46
+ function getEnvironmentConfig(env = 'development') {
47
+ const baseConfigs = {
48
+ production: {
49
+ baseUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.robosystems.ai',
50
+ credentials: 'include',
51
+ timeout: 60000,
52
+ maxRetries: 5,
53
+ retryDelay: 2000,
54
+ },
55
+ staging: {
56
+ baseUrl: process.env.NEXT_PUBLIC_API_URL || 'https://staging-api.robosystems.ai',
57
+ credentials: 'include',
58
+ timeout: 45000,
59
+ maxRetries: 3,
60
+ retryDelay: 1500,
61
+ },
62
+ development: {
63
+ baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
64
+ credentials: 'include',
65
+ timeout: 30000,
66
+ maxRetries: 3,
67
+ retryDelay: 1000,
68
+ },
69
+ };
70
+ return {
71
+ ...defaultConfig,
72
+ ...baseConfigs[env],
73
+ };
66
74
  }