@eka-care/medassist-core 1.0.70 → 1.0.71
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/dist/index.d.mts +1442 -0
- package/dist/index.mjs +2 -0
- package/dist/messages/types.d.ts +1 -0
- package/package.json +1 -1
- package/dist/Synapse.d.ts.map +0 -1
- package/dist/connection/ConnectionFactory.d.ts.map +0 -1
- package/dist/connection/SSE.d.ts.map +0 -1
- package/dist/connection/Websocket.d.ts.map +0 -1
- package/dist/constants/index.d.ts.map +0 -1
- package/dist/constants/types.d.ts.map +0 -1
- package/dist/conversation.d.ts.map +0 -1
- package/dist/esm/Synapse.js +0 -612
- package/dist/esm/connection/ConnectionFactory.js +0 -27
- package/dist/esm/connection/SSE.js +0 -212
- package/dist/esm/connection/Websocket.js +0 -178
- package/dist/esm/constants/index.js +0 -25
- package/dist/esm/constants/types.js +0 -1
- package/dist/esm/conversation.js +0 -7
- package/dist/esm/events/Events.js +0 -41
- package/dist/esm/events/Incoming.js +0 -1
- package/dist/esm/events/Outgoing.js +0 -1
- package/dist/esm/events/index.js +0 -2
- package/dist/esm/events/types.js +0 -5
- package/dist/esm/index.js +0 -34
- package/dist/esm/internal/Api/BaseResource.js +0 -50
- package/dist/esm/internal/Api/HttpClient.js +0 -131
- package/dist/esm/internal/Api/types.js +0 -1
- package/dist/esm/internal/Error/Error.js +0 -229
- package/dist/esm/internal/Error/types.js +0 -9
- package/dist/esm/internal/connection/BaseConnection.js +0 -134
- package/dist/esm/internal/connection/types.js +0 -17
- package/dist/esm/internal/events/EventEmitter.js +0 -26
- package/dist/esm/internal/store/index.js +0 -5
- package/dist/esm/media/audio/Audio.copy.js +0 -363
- package/dist/esm/media/audio/Audio.js +0 -310
- package/dist/esm/media/audio/types.js +0 -13
- package/dist/esm/media/file/File.js +0 -159
- package/dist/esm/messages/MessageManager.js +0 -476
- package/dist/esm/messages/types.js +0 -35
- package/dist/esm/resources/config/Config.js +0 -11
- package/dist/esm/resources/feedback/Feedback.js +0 -9
- package/dist/esm/resources/feedback/types.js +0 -7
- package/dist/esm/resources/index.js +0 -152
- package/dist/esm/resources/session/Session.js +0 -44
- package/dist/esm/resources/session/types.js +0 -5
- package/dist/esm/resources/toolCall/ToolCall.js +0 -12
- package/dist/esm/resources/toolCall/types.js +0 -34
- package/dist/esm/resources/types.js +0 -4
- package/dist/esm/resources/voice/VoiceResource.js +0 -14
- package/dist/esm/resources/voice/types.js +0 -1
- package/dist/esm/types/index.js +0 -8
- package/dist/esm/utils/Error.js +0 -110
- package/dist/esm/voice/VoiceAgent.js +0 -305
- package/dist/esm/voice/VoiceAudioAnalyser.js +0 -32
- package/dist/esm/voice/index.js +0 -1
- package/dist/esm/voice/types.js +0 -15
- package/dist/events/Events.d.ts.map +0 -1
- package/dist/events/Incoming.d.ts.map +0 -1
- package/dist/events/Outgoing.d.ts.map +0 -1
- package/dist/events/index.d.ts.map +0 -1
- package/dist/events/types.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/internal/Api/BaseResource.d.ts.map +0 -1
- package/dist/internal/Api/HttpClient.d.ts.map +0 -1
- package/dist/internal/Api/types.d.ts.map +0 -1
- package/dist/internal/Error/Error.d.ts.map +0 -1
- package/dist/internal/Error/types.d.ts.map +0 -1
- package/dist/internal/connection/BaseConnection.d.ts.map +0 -1
- package/dist/internal/connection/types.d.ts.map +0 -1
- package/dist/internal/events/EventEmitter.d.ts.map +0 -1
- package/dist/internal/store/index.d.ts.map +0 -1
- package/dist/media/audio/Audio.copy.d.ts.map +0 -1
- package/dist/media/audio/Audio.d.ts.map +0 -1
- package/dist/media/audio/types.d.ts.map +0 -1
- package/dist/media/file/File.d.ts.map +0 -1
- package/dist/messages/MessageManager.d.ts.map +0 -1
- package/dist/messages/types.d.ts.map +0 -1
- package/dist/resources/config/Config.d.ts.map +0 -1
- package/dist/resources/feedback/Feedback.d.ts.map +0 -1
- package/dist/resources/feedback/types.d.ts.map +0 -1
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/resources/session/Session.d.ts.map +0 -1
- package/dist/resources/session/types.d.ts.map +0 -1
- package/dist/resources/toolCall/ToolCall.d.ts.map +0 -1
- package/dist/resources/toolCall/types.d.ts.map +0 -1
- package/dist/resources/types.d.ts.map +0 -1
- package/dist/resources/voice/VoiceResource.d.ts.map +0 -1
- package/dist/resources/voice/types.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/Error.d.ts.map +0 -1
- package/dist/voice/VoiceAgent.d.ts.map +0 -1
- package/dist/voice/VoiceAudioAnalyser.d.ts.map +0 -1
- package/dist/voice/index.d.ts.map +0 -1
- package/dist/voice/types.d.ts.map +0 -1
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { APIError, APIConnectionTimeoutError, } from "../Error/Error";
|
|
2
|
-
export class HttpClient {
|
|
3
|
-
baseUrl;
|
|
4
|
-
headers;
|
|
5
|
-
timeout;
|
|
6
|
-
maxRetries;
|
|
7
|
-
constructor(config) {
|
|
8
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, ""); // Remove trailing slash
|
|
9
|
-
this.timeout = config.timeout || 30000;
|
|
10
|
-
this.maxRetries = config.maxRetries || 3;
|
|
11
|
-
this.headers = {
|
|
12
|
-
"Content-Type": "application/json",
|
|
13
|
-
...config.headers, // Include custom headers
|
|
14
|
-
};
|
|
15
|
-
if (config.authorization) {
|
|
16
|
-
this.headers["Authorization"] = config.authorization;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
async request(method, path, options) {
|
|
20
|
-
const maxRetries = options?.retries ?? this.maxRetries;
|
|
21
|
-
let lastError;
|
|
22
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
23
|
-
try {
|
|
24
|
-
const url = this.buildUrl(path, options?.params);
|
|
25
|
-
const response = await fetch(url, {
|
|
26
|
-
method,
|
|
27
|
-
headers: {
|
|
28
|
-
...this.headers,
|
|
29
|
-
...options?.headers,
|
|
30
|
-
},
|
|
31
|
-
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
32
|
-
signal: AbortSignal.timeout(this.timeout),
|
|
33
|
-
});
|
|
34
|
-
if (!response.ok) {
|
|
35
|
-
await this.handleError(response);
|
|
36
|
-
}
|
|
37
|
-
return response.json();
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
lastError = error;
|
|
41
|
-
// Don't retry on the last attempt
|
|
42
|
-
if (attempt === maxRetries) {
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
// Only retry on network errors and timeouts
|
|
46
|
-
const shouldRetry = (error instanceof TypeError && error.message === "Failed to fetch") ||
|
|
47
|
-
(error instanceof DOMException && error.name === "AbortError") ||
|
|
48
|
-
error instanceof SyntaxError;
|
|
49
|
-
if (!shouldRetry) {
|
|
50
|
-
// Don't retry for API errors (4xx, 5xx), parsing errors, etc.
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
// Exponential backoff: wait 2^attempt * 100ms
|
|
54
|
-
const delay = Math.pow(2, attempt) * 100;
|
|
55
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// If we get here, all retries failed
|
|
59
|
-
if (!lastError) {
|
|
60
|
-
throw new APIError("Unknown error occurred", 500, {
|
|
61
|
-
type: "UNKNOWN_ERROR",
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
if (lastError instanceof TypeError &&
|
|
65
|
-
lastError.message === "Failed to fetch") {
|
|
66
|
-
// Network error - no internet, DNS failure, etc.
|
|
67
|
-
throw new APIError("Network error: Unable to connect to the server. Please check your internet connection.", 0, { type: "NETWORK_ERROR", originalError: lastError.message });
|
|
68
|
-
}
|
|
69
|
-
if (lastError instanceof DOMException && lastError.name === "AbortError") {
|
|
70
|
-
// Timeout error
|
|
71
|
-
throw new APIConnectionTimeoutError({
|
|
72
|
-
message: `Request timed out after ${this.timeout}ms`,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
if (lastError instanceof SyntaxError) {
|
|
76
|
-
// JSON parsing error
|
|
77
|
-
throw new APIError("Invalid response format from server", 502, {
|
|
78
|
-
type: "PARSE_ERROR",
|
|
79
|
-
originalError: lastError.message,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
// If it's already an APIError, re-throw it
|
|
83
|
-
if (lastError instanceof APIError) {
|
|
84
|
-
throw lastError;
|
|
85
|
-
}
|
|
86
|
-
// Any other unexpected error
|
|
87
|
-
throw new APIError(`Request failed: ${lastError.message || "Unknown error"}`, 500, { type: "UNKNOWN_ERROR", originalError: lastError });
|
|
88
|
-
}
|
|
89
|
-
async get(path, params, options) {
|
|
90
|
-
return this.request("GET", path, { params, ...options });
|
|
91
|
-
}
|
|
92
|
-
async post(path, body, options) {
|
|
93
|
-
return this.request("POST", path, { body, ...options });
|
|
94
|
-
}
|
|
95
|
-
async put(path, body, options) {
|
|
96
|
-
return this.request("PUT", path, { body, ...options });
|
|
97
|
-
}
|
|
98
|
-
async delete(path, options) {
|
|
99
|
-
return this.request("DELETE", path, { ...options });
|
|
100
|
-
}
|
|
101
|
-
async patch(path, body, options) {
|
|
102
|
-
return this.request("PATCH", path, { body, ...options });
|
|
103
|
-
}
|
|
104
|
-
buildUrl(path, params) {
|
|
105
|
-
let url = `${this.baseUrl}${path}`;
|
|
106
|
-
if (params) {
|
|
107
|
-
const queryString = new URLSearchParams(params).toString();
|
|
108
|
-
url += `?${queryString}`;
|
|
109
|
-
}
|
|
110
|
-
return url;
|
|
111
|
-
}
|
|
112
|
-
async handleError(response) {
|
|
113
|
-
let errorMessage;
|
|
114
|
-
let errorData;
|
|
115
|
-
try {
|
|
116
|
-
errorData = await response.json();
|
|
117
|
-
const body = errorData;
|
|
118
|
-
const nestedError = body?.error;
|
|
119
|
-
errorMessage =
|
|
120
|
-
body?.message ||
|
|
121
|
-
body?.msg ||
|
|
122
|
-
nestedError?.msg ||
|
|
123
|
-
nestedError?.message ||
|
|
124
|
-
response.statusText;
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
errorMessage = response.statusText;
|
|
128
|
-
}
|
|
129
|
-
throw APIError.generate(response.status, errorData, errorMessage, response.headers);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
export const SynapseErrorCode = {
|
|
2
|
-
API: "API_ERROR",
|
|
3
|
-
CONNECTION: "CONNECTION_ERROR",
|
|
4
|
-
RECORDING: "RECORDING_ERROR",
|
|
5
|
-
FILE: "FILE_ERROR",
|
|
6
|
-
SESSION: "SESSION_ERROR",
|
|
7
|
-
MESSAGE: "MESSAGE_ERROR",
|
|
8
|
-
STORE: "STORE_ERROR",
|
|
9
|
-
CONFIGURATION: "CONFIGURATION_ERROR",
|
|
10
|
-
VALIDATION: "VALIDATION_ERROR",
|
|
11
|
-
AUTH: "AUTH_ERROR",
|
|
12
|
-
UNKNOWN: "UNKNOWN_ERROR",
|
|
13
|
-
};
|
|
14
|
-
export class SynapseError extends Error {
|
|
15
|
-
code;
|
|
16
|
-
timestamp;
|
|
17
|
-
cause;
|
|
18
|
-
context;
|
|
19
|
-
hint;
|
|
20
|
-
displayMessage;
|
|
21
|
-
constructor(message, code = SynapseErrorCode.UNKNOWN, options = {}) {
|
|
22
|
-
super(message);
|
|
23
|
-
this.name = "SynapseError";
|
|
24
|
-
this.code = code;
|
|
25
|
-
this.timestamp = new Date();
|
|
26
|
-
this.cause = options.cause;
|
|
27
|
-
this.context = options.context;
|
|
28
|
-
this.hint = options.hint;
|
|
29
|
-
this.displayMessage = options.displayMessage || options?.hint || message;
|
|
30
|
-
if (Error.captureStackTrace) {
|
|
31
|
-
Error.captureStackTrace(this, this.constructor);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export class APIError extends SynapseError {
|
|
36
|
-
/** HTTP status code */
|
|
37
|
-
status;
|
|
38
|
-
/** JSON body of the error response or custom error object */
|
|
39
|
-
error;
|
|
40
|
-
/** HTTP response headers */
|
|
41
|
-
headers;
|
|
42
|
-
constructor(message, status, error, headers) {
|
|
43
|
-
const errorMessage = APIError.makeMessage(status, error, message);
|
|
44
|
-
super(errorMessage, SynapseErrorCode.API, {
|
|
45
|
-
cause: error,
|
|
46
|
-
context: {
|
|
47
|
-
status,
|
|
48
|
-
hasBody: Boolean(error),
|
|
49
|
-
},
|
|
50
|
-
hint: status && status >= 500
|
|
51
|
-
? "Retry the request or contact support if the issue persists."
|
|
52
|
-
: undefined,
|
|
53
|
-
displayMessage: message || "Something went wrong", //give user friednly message,
|
|
54
|
-
});
|
|
55
|
-
this.name = "APIError";
|
|
56
|
-
this.status = status;
|
|
57
|
-
this.error = error;
|
|
58
|
-
this.headers = headers;
|
|
59
|
-
}
|
|
60
|
-
static makeMessage(status, error, message) {
|
|
61
|
-
const msg = error instanceof Error ? error.message : message;
|
|
62
|
-
if (status && msg) {
|
|
63
|
-
return `HTTP ${status}: ${msg}`;
|
|
64
|
-
}
|
|
65
|
-
if (status) {
|
|
66
|
-
return `${status} status code (no body)`;
|
|
67
|
-
}
|
|
68
|
-
if (msg) {
|
|
69
|
-
return msg;
|
|
70
|
-
}
|
|
71
|
-
return "(no status code or body)";
|
|
72
|
-
}
|
|
73
|
-
static generate(status, errorResponse, message, headers) {
|
|
74
|
-
if (!status) {
|
|
75
|
-
return new APIUserAbortError({ message });
|
|
76
|
-
}
|
|
77
|
-
const extractedError = errorResponse?.["error"];
|
|
78
|
-
const error = extractedError &&
|
|
79
|
-
typeof extractedError === "object" &&
|
|
80
|
-
!Array.isArray(extractedError)
|
|
81
|
-
? extractedError
|
|
82
|
-
: undefined;
|
|
83
|
-
switch (status) {
|
|
84
|
-
case 400:
|
|
85
|
-
return new BadRequestError(message || "Bad Request", status, error, headers);
|
|
86
|
-
case 401:
|
|
87
|
-
return new UnauthorizedError(message || "Unauthorized", status, error, headers);
|
|
88
|
-
case 403:
|
|
89
|
-
return new PermissionDeniedError(message || "Permission Denied", status, error, headers);
|
|
90
|
-
case 404:
|
|
91
|
-
return new NotFoundError(message || "Not Found", status, error, headers);
|
|
92
|
-
case 405:
|
|
93
|
-
return new MethodNotAllowedError(message || "Method Not Allowed", status, error, headers);
|
|
94
|
-
case 429:
|
|
95
|
-
return new RateLimitError(message || "Rate Limit Exceeded", status, error, headers);
|
|
96
|
-
case 500:
|
|
97
|
-
return new InternalServerError(message || "Internal Server Error", status, error, headers);
|
|
98
|
-
default:
|
|
99
|
-
return new APIError(message || "API Error", status, error, headers);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
export class APIUserAbortError extends APIError {
|
|
104
|
-
constructor({ message } = {}) {
|
|
105
|
-
super(message || "Request was aborted.", undefined, undefined, undefined);
|
|
106
|
-
this.name = "APIUserAbortError";
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
export class APIConnectionTimeoutError extends APIError {
|
|
110
|
-
constructor({ message } = {}) {
|
|
111
|
-
super(message || "Request timed out.", undefined, undefined, undefined);
|
|
112
|
-
this.name = "APIConnectionTimeoutError";
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
export class BadRequestError extends APIError {
|
|
116
|
-
constructor(message, status, error, headers) {
|
|
117
|
-
super(message, status, error, headers);
|
|
118
|
-
this.name = "BadRequestError";
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
export class UnauthorizedError extends APIError {
|
|
122
|
-
constructor(message, status, error, headers) {
|
|
123
|
-
super(message, status, error, headers);
|
|
124
|
-
this.name = "UnauthorizedError";
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
export class PermissionDeniedError extends APIError {
|
|
128
|
-
constructor(message, status, error, headers) {
|
|
129
|
-
super(message, status, error, headers);
|
|
130
|
-
this.name = "PermissionDeniedError";
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
export class NotFoundError extends APIError {
|
|
134
|
-
constructor(message, status, error, headers) {
|
|
135
|
-
super(message, status, error, headers);
|
|
136
|
-
this.name = "NotFoundError";
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
export class MethodNotAllowedError extends APIError {
|
|
140
|
-
constructor(message, status, error, headers) {
|
|
141
|
-
super(message, status, error, headers);
|
|
142
|
-
this.name = "MethodNotAllowedError";
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
export class RateLimitError extends APIError {
|
|
146
|
-
constructor(message, status, error, headers) {
|
|
147
|
-
super(message, status, error, headers);
|
|
148
|
-
this.name = "RateLimitError";
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
export class InternalServerError extends APIError {
|
|
152
|
-
constructor(message, status, error, headers) {
|
|
153
|
-
super(message, status, error, headers);
|
|
154
|
-
this.name = "InternalServerError";
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
export class ConnectionError extends SynapseError {
|
|
158
|
-
constructor(message, options = {}) {
|
|
159
|
-
super(message, SynapseErrorCode.CONNECTION, options);
|
|
160
|
-
this.name = "ConnectionError";
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
export class RecordingError extends SynapseError {
|
|
164
|
-
constructor(message, options = {}) {
|
|
165
|
-
super(message, SynapseErrorCode.RECORDING, options);
|
|
166
|
-
this.name = "RecordingError";
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
export class AuthenticationError extends SynapseError {
|
|
170
|
-
constructor(message, options = {}) {
|
|
171
|
-
super(message, SynapseErrorCode.AUTH, options);
|
|
172
|
-
this.name = "AuthenticationError";
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
export class FileError extends SynapseError {
|
|
176
|
-
constructor(message, options = {}) {
|
|
177
|
-
super(message, SynapseErrorCode.FILE, options);
|
|
178
|
-
this.name = "FileError";
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
export class SessionError extends SynapseError {
|
|
182
|
-
constructor(message, options = {}) {
|
|
183
|
-
super(message, SynapseErrorCode.SESSION, options);
|
|
184
|
-
this.name = "SessionError";
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
export class MessageError extends SynapseError {
|
|
188
|
-
constructor(message, options = {}) {
|
|
189
|
-
super(message, SynapseErrorCode.MESSAGE, options);
|
|
190
|
-
this.name = "MessageError";
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
export class StoreError extends SynapseError {
|
|
194
|
-
constructor(message, options = {}) {
|
|
195
|
-
super(message, SynapseErrorCode.STORE, options);
|
|
196
|
-
this.name = "StoreError";
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
export class ConfigurationError extends SynapseError {
|
|
200
|
-
constructor(message, options = {}) {
|
|
201
|
-
super(message, SynapseErrorCode.CONFIGURATION, options);
|
|
202
|
-
this.name = "ConfigurationError";
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
export class ValidationError extends SynapseError {
|
|
206
|
-
constructor(message, options = {}) {
|
|
207
|
-
super(message, SynapseErrorCode.VALIDATION, options);
|
|
208
|
-
this.name = "ValidationError";
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
export function normalizeError(error, ctor, fallbackMessage, options = {}) {
|
|
212
|
-
if (error instanceof ctor) {
|
|
213
|
-
return error;
|
|
214
|
-
}
|
|
215
|
-
const baseOptions = {
|
|
216
|
-
...options,
|
|
217
|
-
context: {
|
|
218
|
-
...(error instanceof SynapseError ? error.context : undefined),
|
|
219
|
-
...options.context,
|
|
220
|
-
},
|
|
221
|
-
hint: options.hint ?? (error instanceof SynapseError ? error.hint : undefined),
|
|
222
|
-
cause: options.cause ?? error,
|
|
223
|
-
};
|
|
224
|
-
if (error instanceof SynapseError) {
|
|
225
|
-
return new ctor(error.message, baseOptions);
|
|
226
|
-
}
|
|
227
|
-
const message = error instanceof Error && error.message ? error.message : fallbackMessage;
|
|
228
|
-
return new ctor(message, baseOptions);
|
|
229
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Abstract base class for all connection types
|
|
3
|
-
*/
|
|
4
|
-
import { EventEmitter } from "../events/EventEmitter";
|
|
5
|
-
import { ConnectionStatus, } from "./types";
|
|
6
|
-
export class BaseConnection {
|
|
7
|
-
/**
|
|
8
|
-
* Current connection status
|
|
9
|
-
*/
|
|
10
|
-
status = ConnectionStatus.CONNECTING;
|
|
11
|
-
/**
|
|
12
|
-
* Queue to store messages received before callback is registered
|
|
13
|
-
*/
|
|
14
|
-
queue = [];
|
|
15
|
-
/**
|
|
16
|
-
* Event emitter to handle events
|
|
17
|
-
*/
|
|
18
|
-
eventEmitter = new EventEmitter();
|
|
19
|
-
/**
|
|
20
|
-
* Disconnection details (null if still connected)
|
|
21
|
-
*/
|
|
22
|
-
disconnectionDetails = null;
|
|
23
|
-
onErrorCallback = null;
|
|
24
|
-
onDisconnectCallback = null;
|
|
25
|
-
onMessageCallback = null;
|
|
26
|
-
onOpenCallback = null;
|
|
27
|
-
onStatusChangeCallback = null;
|
|
28
|
-
/**
|
|
29
|
-
* Get current connection status
|
|
30
|
-
*/
|
|
31
|
-
getStatus() {
|
|
32
|
-
return this.status;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Register callback for connection open events
|
|
36
|
-
*/
|
|
37
|
-
onOpen(callback) {
|
|
38
|
-
this.onOpenCallback = callback;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Register callback for incoming messages
|
|
42
|
-
*/
|
|
43
|
-
onMessage(callback) {
|
|
44
|
-
this.onMessageCallback = callback;
|
|
45
|
-
if (this.queue.length > 0) {
|
|
46
|
-
const pendingMessages = [...this.queue];
|
|
47
|
-
this.queue.length = 0;
|
|
48
|
-
queueMicrotask(() => {
|
|
49
|
-
pendingMessages.forEach((message) => {
|
|
50
|
-
this.onMessageCallback?.(message);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Register callback for disconnection events
|
|
57
|
-
*/
|
|
58
|
-
onDisconnect(callback) {
|
|
59
|
-
this.onDisconnectCallback = callback;
|
|
60
|
-
const details = this.disconnectionDetails;
|
|
61
|
-
if (details) {
|
|
62
|
-
queueMicrotask(() => {
|
|
63
|
-
this.onDisconnectCallback?.(details);
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Register callback for error events
|
|
69
|
-
*/
|
|
70
|
-
onError(callback) {
|
|
71
|
-
this.onErrorCallback = callback;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Register a listener for a specific event
|
|
75
|
-
*/
|
|
76
|
-
on(event, listener) {
|
|
77
|
-
this.eventEmitter.on(event, listener);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Remove a listener for a specific event
|
|
81
|
-
*/
|
|
82
|
-
off(event, listener) {
|
|
83
|
-
this.eventEmitter.off(event, listener);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Emit an event
|
|
87
|
-
*/
|
|
88
|
-
emit(event, ...args) {
|
|
89
|
-
this.eventEmitter.emit(event, ...args);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Register callback for status changes
|
|
93
|
-
*/
|
|
94
|
-
onStatusChange(callback) {
|
|
95
|
-
this.onStatusChangeCallback = callback;
|
|
96
|
-
// Immediately invoke with current status
|
|
97
|
-
queueMicrotask(() => {
|
|
98
|
-
callback(this.status);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Protected method to handle disconnection
|
|
103
|
-
* Ensures disconnect callback is only invoked once
|
|
104
|
-
*/
|
|
105
|
-
disconnect(details) {
|
|
106
|
-
if (!this.disconnectionDetails) {
|
|
107
|
-
this.disconnectionDetails = details;
|
|
108
|
-
this.updateStatus(ConnectionStatus.NOT_CONNECTED);
|
|
109
|
-
this.onDisconnectCallback?.(details);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Protected method to handle incoming messages
|
|
114
|
-
* Queues messages if no callback is registered yet
|
|
115
|
-
* message type can be extended to include more types of messages
|
|
116
|
-
*/
|
|
117
|
-
handleMessage(message) {
|
|
118
|
-
if (this.onMessageCallback) {
|
|
119
|
-
this.onMessageCallback(message);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
this.queue.push(message);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Protected method to update connection status
|
|
127
|
-
*/
|
|
128
|
-
updateStatus(status) {
|
|
129
|
-
if (this.status !== status) {
|
|
130
|
-
this.status = status;
|
|
131
|
-
this.onStatusChangeCallback?.(status);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Connection types and interfaces for the Synapse SDK
|
|
3
|
-
*/
|
|
4
|
-
export const ConnectionStatus = {
|
|
5
|
-
CONNECTING: "connecting",
|
|
6
|
-
CONNECTED: "connected",
|
|
7
|
-
NOT_CONNECTED: "not_connected",
|
|
8
|
-
};
|
|
9
|
-
export const DisconnectionReason = {
|
|
10
|
-
CLIENT_CLOSED: "client_closed",
|
|
11
|
-
SERVER_CLOSED: "server_closed",
|
|
12
|
-
CONNECTION_ERROR: "connection_error",
|
|
13
|
-
AUTHENTICATION_ERROR: "authentication_error",
|
|
14
|
-
MAX_RECONNECT_ATTEMPTS: "max_reconnect_attempts",
|
|
15
|
-
TIMEOUT: "timeout",
|
|
16
|
-
NETWORK_ERROR: "network_error",
|
|
17
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export class EventEmitter {
|
|
2
|
-
eventListeners = new Map();
|
|
3
|
-
on(event, listener) {
|
|
4
|
-
const listeners = this.eventListeners.get(event) || new Set();
|
|
5
|
-
listeners.add(listener);
|
|
6
|
-
this.eventListeners.set(event, listeners);
|
|
7
|
-
}
|
|
8
|
-
off(event, listener) {
|
|
9
|
-
const listeners = this.eventListeners.get(event);
|
|
10
|
-
if (listeners) {
|
|
11
|
-
listeners.delete(listener);
|
|
12
|
-
if (listeners.size === 0) {
|
|
13
|
-
this.eventListeners.delete(event);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
emit(event, ...args) {
|
|
18
|
-
const listeners = this.eventListeners.get(event);
|
|
19
|
-
if (listeners) {
|
|
20
|
-
listeners.forEach((listener) => listener(...args));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
removeAllListeners() {
|
|
24
|
-
this.eventListeners.clear();
|
|
25
|
-
}
|
|
26
|
-
}
|