@mochabug/adapt-core 1.0.0-rc21
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 +76 -0
- package/dist/esm/index.js +164 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/pubsub-client.js +559 -0
- package/dist/esm/pubsub-client.js.map +1 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/pubsub-client.d.ts +59 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @mochabug/adapt-core
|
|
2
|
+
|
|
3
|
+
Low-level client for Adapt. REST API + WebSocket subscriptions.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @mochabug/adapt-core
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Start a session
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { startSession, stopSession } from '@mochabug/adapt-core';
|
|
13
|
+
|
|
14
|
+
const { token } = await startSession({ id: 'auto-123' }, authToken);
|
|
15
|
+
|
|
16
|
+
// later
|
|
17
|
+
await stopSession('auto-123', token);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Inherit existing session
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { inheritSession } from '@mochabug/adapt-core';
|
|
24
|
+
|
|
25
|
+
const { token } = await inheritSession('auto-123', inheritToken);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Real-time updates
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { PubsubClient } from '@mochabug/adapt-core';
|
|
32
|
+
|
|
33
|
+
const pubsub = new PubsubClient();
|
|
34
|
+
|
|
35
|
+
await pubsub.subscribe({
|
|
36
|
+
id: 'auto-123',
|
|
37
|
+
sessionToken: token,
|
|
38
|
+
onUrl: (url) => console.log('url:', url),
|
|
39
|
+
onSession: (session) => console.log('status:', session.status),
|
|
40
|
+
onOutput: (output) => console.log('output:', output)
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await pubsub.unsubscribe();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Other API calls
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { getSession, readOutput, readUrls } from '@mochabug/adapt-core';
|
|
50
|
+
|
|
51
|
+
const session = await getSession('auto-123', token);
|
|
52
|
+
const output = await readOutput('auto-123', token, { pageSize: 100 });
|
|
53
|
+
const urls = await readUrls('auto-123', token);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Error handling
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { RestClientError } from '@mochabug/adapt-core';
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await startSession({ id: 'auto-123' });
|
|
63
|
+
} catch (e) {
|
|
64
|
+
if (e instanceof RestClientError) {
|
|
65
|
+
console.error(e.status, e.statusText);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Retry behavior
|
|
71
|
+
|
|
72
|
+
All REST calls retry automatically on 429, 502, 503, 504. Max 5 attempts, exponential backoff.
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
ISC © mochabug AB
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Re-export from the new PubsubClient module
|
|
2
|
+
export * from "./pubsub-client.js";
|
|
3
|
+
// Default configuration
|
|
4
|
+
const defaultConfig = {
|
|
5
|
+
baseUrl: "https://adapt-dev.mochabugapis.com/v1/automations",
|
|
6
|
+
wsBaseUrl: "wss://adapt-dev.mochabugapis.com/v1/automations",
|
|
7
|
+
};
|
|
8
|
+
// Global configuration
|
|
9
|
+
let globalConfig = { ...defaultConfig };
|
|
10
|
+
// Configure the Adapt client
|
|
11
|
+
export function configure(config) {
|
|
12
|
+
globalConfig = { ...globalConfig, ...config };
|
|
13
|
+
}
|
|
14
|
+
// Get current configuration
|
|
15
|
+
export function getConfig() {
|
|
16
|
+
return { ...globalConfig };
|
|
17
|
+
}
|
|
18
|
+
// Reset to default configuration
|
|
19
|
+
export function resetConfig() {
|
|
20
|
+
globalConfig = { ...defaultConfig };
|
|
21
|
+
}
|
|
22
|
+
// Retry configuration
|
|
23
|
+
const RETRY_CONFIG = {
|
|
24
|
+
maxAttempts: 5,
|
|
25
|
+
initialDelay: 50, // 50ms
|
|
26
|
+
maxDelay: 5000, // 5 seconds
|
|
27
|
+
retryableStatusCodes: [429, 502, 503, 504], // Too Many Requests, Bad Gateway, Service Unavailable, Gateway Timeout
|
|
28
|
+
};
|
|
29
|
+
// Sleep helper
|
|
30
|
+
function sleep(ms) {
|
|
31
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
32
|
+
}
|
|
33
|
+
// Retry wrapper with exponential backoff
|
|
34
|
+
async function fetchWithRetry(url, options) {
|
|
35
|
+
let lastError;
|
|
36
|
+
for (let attempt = 1; attempt <= RETRY_CONFIG.maxAttempts; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(url, options);
|
|
39
|
+
if (response.ok) {
|
|
40
|
+
return response;
|
|
41
|
+
}
|
|
42
|
+
if (RETRY_CONFIG.retryableStatusCodes.includes(response.status)) {
|
|
43
|
+
lastError = new RestClientError(response);
|
|
44
|
+
if (attempt < RETRY_CONFIG.maxAttempts) {
|
|
45
|
+
const delay = Math.min(RETRY_CONFIG.initialDelay * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelay);
|
|
46
|
+
console.warn(`Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt}/${RETRY_CONFIG.maxAttempts})`);
|
|
47
|
+
await sleep(delay);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw new RestClientError(response);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof RestClientError) {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
if (attempt < RETRY_CONFIG.maxAttempts) {
|
|
58
|
+
const delay = Math.min(RETRY_CONFIG.initialDelay * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelay);
|
|
59
|
+
console.warn(`Network error, retrying in ${delay}ms (attempt ${attempt}/${RETRY_CONFIG.maxAttempts})`, error);
|
|
60
|
+
await sleep(delay);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw lastError || new Error("All retry attempts failed");
|
|
67
|
+
}
|
|
68
|
+
// REST API functions
|
|
69
|
+
export async function startSession(req, token) {
|
|
70
|
+
const headers = new Headers({
|
|
71
|
+
"Content-Type": "application/json",
|
|
72
|
+
"Response-Type": "application/json",
|
|
73
|
+
});
|
|
74
|
+
if (token) {
|
|
75
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
76
|
+
}
|
|
77
|
+
const response = await fetchWithRetry(`${globalConfig.baseUrl}/${req.id}/session/start`, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
body: JSON.stringify(req),
|
|
80
|
+
headers,
|
|
81
|
+
});
|
|
82
|
+
return await response.json();
|
|
83
|
+
}
|
|
84
|
+
export async function inheritSession(id, sessionToken) {
|
|
85
|
+
const response = await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session/inherit`, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
body: JSON.stringify({ id }),
|
|
88
|
+
headers: {
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
"Response-Type": "application/json",
|
|
91
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
return await response.json();
|
|
95
|
+
}
|
|
96
|
+
export async function getSession(id, sessionToken) {
|
|
97
|
+
const response = await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session`, {
|
|
98
|
+
method: "GET",
|
|
99
|
+
headers: {
|
|
100
|
+
"Response-Type": "application/json",
|
|
101
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
return await response.json();
|
|
105
|
+
}
|
|
106
|
+
export async function readOutput(id, sessionToken, options) {
|
|
107
|
+
const params = new URLSearchParams();
|
|
108
|
+
if (options?.pageSize !== undefined) {
|
|
109
|
+
params.set("page_size", options.pageSize.toString());
|
|
110
|
+
}
|
|
111
|
+
if (options?.vertex) {
|
|
112
|
+
params.set("vertex", options.vertex);
|
|
113
|
+
}
|
|
114
|
+
if (options?.newerThan) {
|
|
115
|
+
params.set("newer_than", options.newerThan);
|
|
116
|
+
}
|
|
117
|
+
const queryString = params.toString();
|
|
118
|
+
const url = `${globalConfig.baseUrl}/${id}/session/output${queryString ? `?${queryString}` : ""}`;
|
|
119
|
+
const response = await fetchWithRetry(url, {
|
|
120
|
+
method: "GET",
|
|
121
|
+
headers: {
|
|
122
|
+
"Response-Type": "application/json",
|
|
123
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
return await response.json();
|
|
127
|
+
}
|
|
128
|
+
export async function readUrls(id, sessionToken, options) {
|
|
129
|
+
const params = new URLSearchParams();
|
|
130
|
+
if (options?.pageSize !== undefined) {
|
|
131
|
+
params.set("page_size", options.pageSize.toString());
|
|
132
|
+
}
|
|
133
|
+
if (options?.newerThan) {
|
|
134
|
+
params.set("newer_than", options.newerThan);
|
|
135
|
+
}
|
|
136
|
+
const queryString = params.toString();
|
|
137
|
+
const url = `${globalConfig.baseUrl}/${id}/session/urls${queryString ? `?${queryString}` : ""}`;
|
|
138
|
+
const response = await fetchWithRetry(url, {
|
|
139
|
+
method: "GET",
|
|
140
|
+
headers: {
|
|
141
|
+
"Response-Type": "application/json",
|
|
142
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
return await response.json();
|
|
146
|
+
}
|
|
147
|
+
export async function stopSession(id, sessionToken) {
|
|
148
|
+
await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session`, {
|
|
149
|
+
method: "DELETE",
|
|
150
|
+
headers: {
|
|
151
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
export class RestClientError extends Error {
|
|
156
|
+
constructor(response) {
|
|
157
|
+
super(`HTTP Error: ${response.status} ${response.statusText}`);
|
|
158
|
+
this.name = "RestClientError";
|
|
159
|
+
this.status = response.status;
|
|
160
|
+
this.statusText = response.statusText;
|
|
161
|
+
this.response = response;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { fromBinary, toJson } from "@bufbuild/protobuf";
|
|
2
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
3
|
+
import WebSocket from "isomorphic-ws";
|
|
4
|
+
import { parse as parseUuid } from "uuid";
|
|
5
|
+
import { SessionSchema, Status, UrlSchema, WebsocketMessageSchema, } from "@mochabug/genproto/mochabugapis/adapt/automations/v1/automations_pb.js";
|
|
6
|
+
import { getConfig } from "./index.js";
|
|
7
|
+
// Connection states
|
|
8
|
+
export var ConnectionState;
|
|
9
|
+
(function (ConnectionState) {
|
|
10
|
+
ConnectionState["DISCONNECTED"] = "disconnected";
|
|
11
|
+
ConnectionState["CONNECTING"] = "connecting";
|
|
12
|
+
ConnectionState["CONNECTED"] = "connected";
|
|
13
|
+
ConnectionState["CLOSING"] = "closing";
|
|
14
|
+
})(ConnectionState || (ConnectionState = {}));
|
|
15
|
+
// WebSocket close codes (following RFC 6455)
|
|
16
|
+
var CloseCode;
|
|
17
|
+
(function (CloseCode) {
|
|
18
|
+
CloseCode[CloseCode["NORMAL"] = 1000] = "NORMAL";
|
|
19
|
+
CloseCode[CloseCode["GOING_AWAY"] = 1001] = "GOING_AWAY";
|
|
20
|
+
CloseCode[CloseCode["PROTOCOL_ERROR"] = 1002] = "PROTOCOL_ERROR";
|
|
21
|
+
CloseCode[CloseCode["UNSUPPORTED_DATA"] = 1003] = "UNSUPPORTED_DATA";
|
|
22
|
+
CloseCode[CloseCode["ABNORMAL"] = 1006] = "ABNORMAL";
|
|
23
|
+
CloseCode[CloseCode["POLICY_VIOLATION"] = 1008] = "POLICY_VIOLATION";
|
|
24
|
+
CloseCode[CloseCode["SERVER_RESTART"] = 1012] = "SERVER_RESTART";
|
|
25
|
+
CloseCode[CloseCode["TRY_AGAIN_LATER"] = 1013] = "TRY_AGAIN_LATER";
|
|
26
|
+
CloseCode[CloseCode["BAD_GATEWAY"] = 1014] = "BAD_GATEWAY";
|
|
27
|
+
CloseCode[CloseCode["TLS_HANDSHAKE"] = 1015] = "TLS_HANDSHAKE";
|
|
28
|
+
})(CloseCode || (CloseCode = {}));
|
|
29
|
+
// Logger class for consistent logging
|
|
30
|
+
class Logger {
|
|
31
|
+
constructor(debug) {
|
|
32
|
+
this.debug = debug;
|
|
33
|
+
}
|
|
34
|
+
log(level, message, data) {
|
|
35
|
+
if (!this.debug && level === "debug")
|
|
36
|
+
return;
|
|
37
|
+
const timestamp = new Date().toISOString();
|
|
38
|
+
const prefix = `[PubSub ${timestamp}]`;
|
|
39
|
+
const fullMessage = `${prefix} ${message}`;
|
|
40
|
+
if (data !== undefined) {
|
|
41
|
+
console[level](fullMessage, data);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console[level](fullMessage);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ACK tracker to prevent duplicate message processing
|
|
49
|
+
class AckTracker {
|
|
50
|
+
constructor(logger) {
|
|
51
|
+
this.logger = logger;
|
|
52
|
+
this.ackedMessages = new Map();
|
|
53
|
+
this.MESSAGE_TTL = 60000; // 60 seconds
|
|
54
|
+
this.cleanupTimer = null;
|
|
55
|
+
}
|
|
56
|
+
start() {
|
|
57
|
+
// Cleanup old messages every 30 seconds
|
|
58
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), 30000);
|
|
59
|
+
}
|
|
60
|
+
stop() {
|
|
61
|
+
if (this.cleanupTimer) {
|
|
62
|
+
clearInterval(this.cleanupTimer);
|
|
63
|
+
this.cleanupTimer = null;
|
|
64
|
+
}
|
|
65
|
+
this.ackedMessages.clear();
|
|
66
|
+
}
|
|
67
|
+
isProcessed(messageId) {
|
|
68
|
+
return this.ackedMessages.has(messageId);
|
|
69
|
+
}
|
|
70
|
+
markProcessed(messageId) {
|
|
71
|
+
this.ackedMessages.set(messageId, Date.now());
|
|
72
|
+
}
|
|
73
|
+
cleanup() {
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
const deadline = now - this.MESSAGE_TTL;
|
|
76
|
+
let removed = 0;
|
|
77
|
+
for (const [messageId, timestamp] of this.ackedMessages.entries()) {
|
|
78
|
+
if (timestamp < deadline) {
|
|
79
|
+
this.ackedMessages.delete(messageId);
|
|
80
|
+
removed++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (removed > 0) {
|
|
84
|
+
this.logger.log("debug", `Cleaned up ${removed} old ACKed messages`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Reconnection manager with exponential backoff
|
|
89
|
+
class ReconnectionManager {
|
|
90
|
+
constructor(logger) {
|
|
91
|
+
this.logger = logger;
|
|
92
|
+
this.attempts = 0;
|
|
93
|
+
this.timer = null;
|
|
94
|
+
this.FAST_INITIAL_DELAY = 50; // 50ms for first 10 attempts
|
|
95
|
+
this.FAST_ATTEMPTS_THRESHOLD = 10; // First 10 attempts are fast
|
|
96
|
+
this.SLOW_INITIAL_DELAY = 1000; // 1 second after fast attempts
|
|
97
|
+
this.MAX_DELAY = 30000; // 30 seconds
|
|
98
|
+
this.MAX_ATTEMPTS = -1; // -1 = infinite
|
|
99
|
+
}
|
|
100
|
+
reset() {
|
|
101
|
+
this.attempts = 0;
|
|
102
|
+
this.cancel();
|
|
103
|
+
}
|
|
104
|
+
cancel() {
|
|
105
|
+
if (this.timer) {
|
|
106
|
+
clearTimeout(this.timer);
|
|
107
|
+
this.timer = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
scheduleReconnect(callback, immediate = false) {
|
|
111
|
+
if (this.MAX_ATTEMPTS !== -1 && this.attempts >= this.MAX_ATTEMPTS) {
|
|
112
|
+
this.logger.log("error", "Max reconnection attempts reached");
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
this.attempts++;
|
|
116
|
+
// Calculate delay with fast exponential backoff for first 10 attempts
|
|
117
|
+
let delay;
|
|
118
|
+
if (immediate) {
|
|
119
|
+
// Immediate reconnection for server restart
|
|
120
|
+
delay = 0;
|
|
121
|
+
this.logger.log("info", "Scheduling immediate reconnect (server restart)");
|
|
122
|
+
}
|
|
123
|
+
else if (this.attempts <= this.FAST_ATTEMPTS_THRESHOLD) {
|
|
124
|
+
// Fast reconnection: 50 => 100 => 200 => 400 => 800 => 1600 => 3200 => 6400 => 12800 => 25600
|
|
125
|
+
delay = this.FAST_INITIAL_DELAY * Math.pow(2, this.attempts - 1);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// After fast attempts, use slower backoff starting from SLOW_INITIAL_DELAY
|
|
129
|
+
const slowAttempt = this.attempts - this.FAST_ATTEMPTS_THRESHOLD;
|
|
130
|
+
delay = this.SLOW_INITIAL_DELAY * Math.pow(2, slowAttempt - 1);
|
|
131
|
+
}
|
|
132
|
+
// Cap at MAX_DELAY (except for immediate reconnects)
|
|
133
|
+
if (!immediate) {
|
|
134
|
+
delay = Math.min(delay, this.MAX_DELAY);
|
|
135
|
+
}
|
|
136
|
+
if (!immediate) {
|
|
137
|
+
this.logger.log("info", `Scheduling reconnect attempt ${this.attempts} in ${delay}ms`);
|
|
138
|
+
}
|
|
139
|
+
this.timer = setTimeout(() => {
|
|
140
|
+
this.timer = null;
|
|
141
|
+
callback();
|
|
142
|
+
}, delay);
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// WebSocket connection manager
|
|
147
|
+
class WebSocketManager {
|
|
148
|
+
constructor(logger) {
|
|
149
|
+
this.logger = logger;
|
|
150
|
+
this.ws = null;
|
|
151
|
+
this.closePromise = null;
|
|
152
|
+
this.closeResolve = null;
|
|
153
|
+
}
|
|
154
|
+
connect(url, onOpen, onMessage, onClose, onError) {
|
|
155
|
+
if (this.ws) {
|
|
156
|
+
throw new Error("WebSocket already exists");
|
|
157
|
+
}
|
|
158
|
+
this.logger.log("info", `Connecting to: ${url}`);
|
|
159
|
+
// Create a promise that resolves when the WebSocket closes
|
|
160
|
+
this.closePromise = new Promise((resolve) => {
|
|
161
|
+
this.closeResolve = resolve;
|
|
162
|
+
});
|
|
163
|
+
this.ws = new WebSocket(url);
|
|
164
|
+
this.ws.binaryType = "arraybuffer";
|
|
165
|
+
this.ws.onopen = () => {
|
|
166
|
+
this.logger.log("info", "✓ WebSocket connected");
|
|
167
|
+
onOpen();
|
|
168
|
+
};
|
|
169
|
+
this.ws.onmessage = (event) => {
|
|
170
|
+
if (event.data instanceof ArrayBuffer) {
|
|
171
|
+
onMessage(event.data);
|
|
172
|
+
}
|
|
173
|
+
else if (event.data instanceof Blob) {
|
|
174
|
+
// Handle Blob data (some browsers may return Blob instead of ArrayBuffer)
|
|
175
|
+
event.data
|
|
176
|
+
.arrayBuffer()
|
|
177
|
+
.then(onMessage)
|
|
178
|
+
.catch((error) => {
|
|
179
|
+
this.logger.log("error", "Failed to convert Blob to ArrayBuffer:", error);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
this.logger.log("warn", "Received non-binary message, ignoring");
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
this.ws.onerror = (error) => {
|
|
187
|
+
this.logger.log("error", "WebSocket error:", error);
|
|
188
|
+
onError(error);
|
|
189
|
+
};
|
|
190
|
+
this.ws.onclose = (event) => {
|
|
191
|
+
this.logger.log("info", `WebSocket closed: ${event.code} - ${event.reason}`);
|
|
192
|
+
onClose(event.code, event.reason);
|
|
193
|
+
this.ws = null;
|
|
194
|
+
// Resolve the close promise
|
|
195
|
+
this.closeResolve();
|
|
196
|
+
this.closeResolve = null;
|
|
197
|
+
this.closePromise = null;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
sendAck(messageId) {
|
|
201
|
+
if (!this.isConnected()) {
|
|
202
|
+
this.logger.log("warn", `Cannot send ACK (not connected): ${messageId}`);
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
// Parse UUID string to bytes (16 bytes)
|
|
207
|
+
const uuid = new Uint8Array(parseUuid(messageId));
|
|
208
|
+
this.ws.send(uuid);
|
|
209
|
+
this.logger.log("debug", `Sent ACK: ${messageId}`);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
this.logger.log("error", `Failed to send ACK for ${messageId}:`, error);
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async close(code = CloseCode.NORMAL, reason = "Client disconnecting") {
|
|
218
|
+
if (!this.ws) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (this.ws.readyState === WebSocket.OPEN ||
|
|
222
|
+
this.ws.readyState === WebSocket.CONNECTING) {
|
|
223
|
+
this.ws.close(code, reason);
|
|
224
|
+
}
|
|
225
|
+
await this.closePromise;
|
|
226
|
+
}
|
|
227
|
+
isConnected() {
|
|
228
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Message processor for handling incoming WebSocket messages
|
|
232
|
+
class MessageProcessor {
|
|
233
|
+
constructor(logger, handlers) {
|
|
234
|
+
this.logger = logger;
|
|
235
|
+
this.handlers = handlers;
|
|
236
|
+
this.sessionEnded = false;
|
|
237
|
+
}
|
|
238
|
+
process(data) {
|
|
239
|
+
try {
|
|
240
|
+
const message = fromBinary(WebsocketMessageSchema, new Uint8Array(data));
|
|
241
|
+
this.logger.log("debug", `Processing message: ${message.id}`);
|
|
242
|
+
// Process based on message type
|
|
243
|
+
switch (message.message.case) {
|
|
244
|
+
case "output":
|
|
245
|
+
this.processOutput(message.message.value);
|
|
246
|
+
break;
|
|
247
|
+
case "session":
|
|
248
|
+
this.processSession(message.message.value);
|
|
249
|
+
break;
|
|
250
|
+
case "url":
|
|
251
|
+
this.processUrl(message.message.value);
|
|
252
|
+
break;
|
|
253
|
+
default:
|
|
254
|
+
this.logger.log("warn", `Unknown message type: ${message.message.case}`);
|
|
255
|
+
}
|
|
256
|
+
return { messageId: message.id, sessionEnded: this.sessionEnded };
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
this.logger.log("error", "Failed to process message:", error);
|
|
260
|
+
return { messageId: null, sessionEnded: this.sessionEnded };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
hasSessionEnded() {
|
|
264
|
+
return this.sessionEnded;
|
|
265
|
+
}
|
|
266
|
+
processOutput(output) {
|
|
267
|
+
if (!this.handlers.onOutput)
|
|
268
|
+
return;
|
|
269
|
+
try {
|
|
270
|
+
const result = {
|
|
271
|
+
vertex: output.vertex,
|
|
272
|
+
fork: output.fork,
|
|
273
|
+
data: output.data,
|
|
274
|
+
};
|
|
275
|
+
if (output.created) {
|
|
276
|
+
result.created = timestampDate(output.created);
|
|
277
|
+
}
|
|
278
|
+
this.handlers.onOutput(result);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
this.logger.log("error", "Error in output handler:", error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
processSession(session) {
|
|
285
|
+
// Check for terminal status
|
|
286
|
+
switch (session.status) {
|
|
287
|
+
case Status.STOPPED:
|
|
288
|
+
case Status.COMPLETED:
|
|
289
|
+
case Status.ERRORED:
|
|
290
|
+
case Status.EXPIRED:
|
|
291
|
+
this.sessionEnded = true;
|
|
292
|
+
this.logger.log("info", `Session ended with status: ${Status[session.status]}`);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
if (!this.handlers.onSession)
|
|
296
|
+
return;
|
|
297
|
+
try {
|
|
298
|
+
this.handlers.onSession(toJson(SessionSchema, session));
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
this.logger.log("error", "Error in session handler:", error);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
processUrl(url) {
|
|
305
|
+
if (!this.handlers.onUrl)
|
|
306
|
+
return;
|
|
307
|
+
try {
|
|
308
|
+
this.handlers.onUrl(toJson(UrlSchema, url));
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
this.logger.log("error", "Error in URL handler:", error);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// Main PubsubClient class
|
|
316
|
+
export class PubsubClient {
|
|
317
|
+
constructor(debug = false) {
|
|
318
|
+
this.state = ConnectionState.DISCONNECTED;
|
|
319
|
+
this.sessionInfo = null;
|
|
320
|
+
this.messageProcessor = null;
|
|
321
|
+
this.shouldReconnect = true;
|
|
322
|
+
this.sessionComplete = false;
|
|
323
|
+
this.logger = new Logger(debug);
|
|
324
|
+
this.ackTracker = new AckTracker(this.logger);
|
|
325
|
+
this.reconnectManager = new ReconnectionManager(this.logger);
|
|
326
|
+
this.wsManager = new WebSocketManager(this.logger);
|
|
327
|
+
}
|
|
328
|
+
async subscribe(opts) {
|
|
329
|
+
this.logger.log("debug", "Subscribe called", {
|
|
330
|
+
automation: opts.id,
|
|
331
|
+
hasToken: !!opts.sessionToken,
|
|
332
|
+
});
|
|
333
|
+
// Validate input
|
|
334
|
+
if (!opts.sessionToken || !opts.id) {
|
|
335
|
+
throw new Error("Session token and automation are required");
|
|
336
|
+
}
|
|
337
|
+
// Check if already connected to same session
|
|
338
|
+
if (this.isSameSession(opts)) {
|
|
339
|
+
this.logger.log("debug", "Already connected to same session, updating handlers");
|
|
340
|
+
this.updateHandlers(opts);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// Check state
|
|
344
|
+
if (this.state === ConnectionState.CONNECTING) {
|
|
345
|
+
throw new Error("Already connecting, please wait");
|
|
346
|
+
}
|
|
347
|
+
// Disconnect if connected to different session
|
|
348
|
+
if (this.state === ConnectionState.CONNECTED) {
|
|
349
|
+
await this.unsubscribe();
|
|
350
|
+
}
|
|
351
|
+
// Store configuration
|
|
352
|
+
this.sessionInfo = {
|
|
353
|
+
token: opts.sessionToken,
|
|
354
|
+
id: opts.id,
|
|
355
|
+
};
|
|
356
|
+
// Create message processor with handlers
|
|
357
|
+
const handlers = {};
|
|
358
|
+
if (opts.onOutput)
|
|
359
|
+
handlers.onOutput = opts.onOutput;
|
|
360
|
+
if (opts.onSession)
|
|
361
|
+
handlers.onSession = opts.onSession;
|
|
362
|
+
if (opts.onUrl)
|
|
363
|
+
handlers.onUrl = opts.onUrl;
|
|
364
|
+
this.messageProcessor = new MessageProcessor(this.logger, handlers);
|
|
365
|
+
// Reset state
|
|
366
|
+
this.shouldReconnect = true;
|
|
367
|
+
this.sessionComplete = false;
|
|
368
|
+
this.reconnectManager.reset();
|
|
369
|
+
// Start ACK tracker
|
|
370
|
+
this.ackTracker.start();
|
|
371
|
+
// Connect
|
|
372
|
+
await this.connect();
|
|
373
|
+
}
|
|
374
|
+
async unsubscribe() {
|
|
375
|
+
if (this.state === ConnectionState.DISCONNECTED ||
|
|
376
|
+
this.state === ConnectionState.CLOSING) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
this.logger.log("info", "Unsubscribing...");
|
|
380
|
+
// Update state
|
|
381
|
+
this.state = ConnectionState.CLOSING;
|
|
382
|
+
this.shouldReconnect = false;
|
|
383
|
+
// Cancel any pending reconnects
|
|
384
|
+
this.reconnectManager.cancel();
|
|
385
|
+
// Close WebSocket and wait for it to fully close
|
|
386
|
+
await this.wsManager.close();
|
|
387
|
+
// Stop ACK tracker
|
|
388
|
+
this.ackTracker.stop();
|
|
389
|
+
// Clear state
|
|
390
|
+
this.sessionInfo = null;
|
|
391
|
+
this.messageProcessor = null;
|
|
392
|
+
this.state = ConnectionState.DISCONNECTED;
|
|
393
|
+
this.logger.log("info", "Unsubscribed successfully");
|
|
394
|
+
}
|
|
395
|
+
isConnected() {
|
|
396
|
+
return this.state === ConnectionState.CONNECTED;
|
|
397
|
+
}
|
|
398
|
+
getConnectionState() {
|
|
399
|
+
return this.state;
|
|
400
|
+
}
|
|
401
|
+
getSessionInfo() {
|
|
402
|
+
if (!this.sessionInfo) {
|
|
403
|
+
throw new Error("No active session");
|
|
404
|
+
}
|
|
405
|
+
return this.sessionInfo;
|
|
406
|
+
}
|
|
407
|
+
async connect() {
|
|
408
|
+
if (!this.sessionInfo) {
|
|
409
|
+
throw new Error("No session configuration");
|
|
410
|
+
}
|
|
411
|
+
this.state = ConnectionState.CONNECTING;
|
|
412
|
+
const config = getConfig();
|
|
413
|
+
const wsUrl = `${config.wsBaseUrl}/${this.sessionInfo.id}/ws?token=${encodeURIComponent(this.sessionInfo.token)}`;
|
|
414
|
+
try {
|
|
415
|
+
this.wsManager.connect(wsUrl, () => this.handleOpen(), (data) => this.handleMessage(data), (code, reason) => this.handleClose(code, reason), (error) => this.handleError(error));
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
this.state = ConnectionState.DISCONNECTED;
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
handleOpen() {
|
|
423
|
+
this.state = ConnectionState.CONNECTED;
|
|
424
|
+
this.reconnectManager.reset();
|
|
425
|
+
}
|
|
426
|
+
handleMessage(data) {
|
|
427
|
+
if (!this.messageProcessor) {
|
|
428
|
+
this.logger.log("error", "No message processor configured");
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
// Process the message
|
|
432
|
+
const result = this.messageProcessor.process(data);
|
|
433
|
+
if (!result.messageId) {
|
|
434
|
+
return; // Failed to parse
|
|
435
|
+
}
|
|
436
|
+
// Update session complete flag if session ended
|
|
437
|
+
if (result.sessionEnded && !this.sessionComplete) {
|
|
438
|
+
this.logger.log("info", "Session has ended (detected from message)");
|
|
439
|
+
this.sessionComplete = true;
|
|
440
|
+
}
|
|
441
|
+
// Check for duplicate
|
|
442
|
+
if (this.ackTracker.isProcessed(result.messageId)) {
|
|
443
|
+
this.logger.log("debug", `Duplicate message: ${result.messageId}`);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
this.ackTracker.markProcessed(result.messageId);
|
|
447
|
+
}
|
|
448
|
+
// ACK the message (skip for session-ending messages as connection will close)
|
|
449
|
+
if (!result.sessionEnded) {
|
|
450
|
+
this.wsManager.sendAck(result.messageId);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
handleClose(code, reason) {
|
|
454
|
+
this.state = ConnectionState.DISCONNECTED;
|
|
455
|
+
// Analyze close code
|
|
456
|
+
const reconnectStrategy = this.analyzeCloseCode(code, reason);
|
|
457
|
+
// Schedule reconnect if appropriate
|
|
458
|
+
if (reconnectStrategy.shouldReconnect &&
|
|
459
|
+
this.shouldReconnect &&
|
|
460
|
+
!this.sessionComplete) {
|
|
461
|
+
this.scheduleReconnect(reconnectStrategy.immediate);
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
// Clean shutdown (fire and forget - cleanup is async but we don't need to wait)
|
|
465
|
+
this.cleanup().catch((error) => {
|
|
466
|
+
this.logger.log("error", "Error during cleanup:", error);
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
handleError(error) {
|
|
471
|
+
this.logger.log("error", "WebSocket error:", error);
|
|
472
|
+
}
|
|
473
|
+
analyzeCloseCode(code, reason) {
|
|
474
|
+
switch (code) {
|
|
475
|
+
case CloseCode.NORMAL:
|
|
476
|
+
// Normal closure - session complete or client requested
|
|
477
|
+
this.logger.log("info", "Normal closure");
|
|
478
|
+
this.sessionComplete = true;
|
|
479
|
+
return { shouldReconnect: false, immediate: false };
|
|
480
|
+
case CloseCode.GOING_AWAY:
|
|
481
|
+
// Server shutting down
|
|
482
|
+
this.logger.log("warn", "Server going away");
|
|
483
|
+
return { shouldReconnect: true, immediate: false };
|
|
484
|
+
case CloseCode.SERVER_RESTART:
|
|
485
|
+
// Server restart - reconnect immediately (no backoff)
|
|
486
|
+
this.logger.log("warn", "Server restarting - will reconnect immediately");
|
|
487
|
+
return { shouldReconnect: true, immediate: true };
|
|
488
|
+
case CloseCode.TRY_AGAIN_LATER:
|
|
489
|
+
// Service temporarily unavailable - reconnect with backoff
|
|
490
|
+
this.logger.log("warn", "Service temporarily unavailable, will retry");
|
|
491
|
+
return { shouldReconnect: true, immediate: false };
|
|
492
|
+
case CloseCode.PROTOCOL_ERROR:
|
|
493
|
+
case CloseCode.UNSUPPORTED_DATA:
|
|
494
|
+
case CloseCode.POLICY_VIOLATION:
|
|
495
|
+
// Critical errors - don't reconnect
|
|
496
|
+
this.logger.log("error", `Critical error (${code}): ${reason}`);
|
|
497
|
+
return { shouldReconnect: false, immediate: false };
|
|
498
|
+
case CloseCode.ABNORMAL:
|
|
499
|
+
// Connection lost - try to reconnect
|
|
500
|
+
this.logger.log("warn", "Connection lost (abnormal closure)");
|
|
501
|
+
return { shouldReconnect: true, immediate: false };
|
|
502
|
+
default:
|
|
503
|
+
// Unknown code - try to reconnect
|
|
504
|
+
this.logger.log("warn", `Unknown close code ${code}: ${reason}`);
|
|
505
|
+
return { shouldReconnect: true, immediate: false };
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
scheduleReconnect(immediate = false) {
|
|
509
|
+
const scheduled = this.reconnectManager.scheduleReconnect(() => {
|
|
510
|
+
// Double-check state to avoid race conditions
|
|
511
|
+
if (this.shouldReconnect &&
|
|
512
|
+
this.state === ConnectionState.DISCONNECTED &&
|
|
513
|
+
!this.sessionComplete) {
|
|
514
|
+
this.connect().catch((error) => {
|
|
515
|
+
this.logger.log("error", "Reconnection failed:", error);
|
|
516
|
+
// Try again with normal backoff (not immediate)
|
|
517
|
+
this.scheduleReconnect(false);
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}, immediate);
|
|
521
|
+
if (!scheduled) {
|
|
522
|
+
// Max attempts reached (fire and forget cleanup)
|
|
523
|
+
this.cleanup().catch((error) => {
|
|
524
|
+
this.logger.log("error", "Error during cleanup:", error);
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async cleanup() {
|
|
529
|
+
this.shouldReconnect = false;
|
|
530
|
+
this.reconnectManager.cancel();
|
|
531
|
+
this.ackTracker.stop();
|
|
532
|
+
await this.wsManager.close();
|
|
533
|
+
this.sessionInfo = null;
|
|
534
|
+
this.messageProcessor = null;
|
|
535
|
+
this.state = ConnectionState.DISCONNECTED;
|
|
536
|
+
}
|
|
537
|
+
isSameSession(opts) {
|
|
538
|
+
if (!this.sessionInfo || this.state !== ConnectionState.CONNECTED) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
return (this.sessionInfo.token === opts.sessionToken &&
|
|
542
|
+
this.sessionInfo.id === opts.id);
|
|
543
|
+
}
|
|
544
|
+
updateHandlers(opts) {
|
|
545
|
+
if (!this.messageProcessor) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
// Update handlers in message processor
|
|
549
|
+
const handlers = {};
|
|
550
|
+
if (opts.onOutput)
|
|
551
|
+
handlers.onOutput = opts.onOutput;
|
|
552
|
+
if (opts.onSession)
|
|
553
|
+
handlers.onSession = opts.onSession;
|
|
554
|
+
if (opts.onUrl)
|
|
555
|
+
handlers.onUrl = opts.onUrl;
|
|
556
|
+
this.messageProcessor = new MessageProcessor(this.logger, handlers);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
//# sourceMappingURL=pubsub-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pubsub-client.js","sourceRoot":"","sources":["../../src/pubsub-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { GetSessionResponseJson, InheritSessionResponseJson, ReadOutputResponseJson, ReadUrlsResponseJson, StartSessionRequestJson, StartSessionResponseJson } from "@mochabug/genproto/mochabugapis/adapt/automations/v1/automations_pb.js";
|
|
2
|
+
export * from "./pubsub-client.js";
|
|
3
|
+
export interface AdaptConfig {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
wsBaseUrl: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function configure(config: Partial<AdaptConfig>): void;
|
|
8
|
+
export declare function getConfig(): AdaptConfig;
|
|
9
|
+
export declare function resetConfig(): void;
|
|
10
|
+
export declare function startSession(req: StartSessionRequestJson, token?: string): Promise<StartSessionResponseJson>;
|
|
11
|
+
export declare function inheritSession(id: string, sessionToken: string): Promise<InheritSessionResponseJson>;
|
|
12
|
+
export declare function getSession(id: string, sessionToken: string): Promise<GetSessionResponseJson>;
|
|
13
|
+
export declare function readOutput(id: string, sessionToken: string, options?: {
|
|
14
|
+
pageSize?: number;
|
|
15
|
+
vertex?: string;
|
|
16
|
+
newerThan?: string;
|
|
17
|
+
}): Promise<ReadOutputResponseJson>;
|
|
18
|
+
export declare function readUrls(id: string, sessionToken: string, options?: {
|
|
19
|
+
pageSize?: number;
|
|
20
|
+
newerThan?: string;
|
|
21
|
+
}): Promise<ReadUrlsResponseJson>;
|
|
22
|
+
export declare function stopSession(id: string, sessionToken: string): Promise<void>;
|
|
23
|
+
export declare class RestClientError extends Error {
|
|
24
|
+
status: number;
|
|
25
|
+
statusText: string;
|
|
26
|
+
response: Response;
|
|
27
|
+
constructor(response: Response);
|
|
28
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Output as OutputMessage, Session, SessionJson, Session as SessionMessage, StatusJson, Url, UrlJson, Url as UrlMessage } from "@mochabug/genproto/mochabugapis/adapt/automations/v1/automations_pb.js";
|
|
2
|
+
import { Status } from "@mochabug/genproto/mochabugapis/adapt/automations/v1/automations_pb.js";
|
|
3
|
+
import type { SignalData } from "@mochabug/genproto/mochabugapis/adapt/graph/signal_data_pb.js";
|
|
4
|
+
export type { OutputMessage, Session, SessionJson, SessionMessage, SignalData, Status, StatusJson, Url, UrlJson, UrlMessage, };
|
|
5
|
+
export interface Output {
|
|
6
|
+
vertex: string;
|
|
7
|
+
fork: string;
|
|
8
|
+
data: {
|
|
9
|
+
[key: string]: SignalData;
|
|
10
|
+
};
|
|
11
|
+
created?: Date;
|
|
12
|
+
}
|
|
13
|
+
export interface MessageHandlers {
|
|
14
|
+
onOutput?: (output: Output) => void;
|
|
15
|
+
onSession?: (session: SessionJson) => void;
|
|
16
|
+
onUrl?: (url: UrlJson) => void;
|
|
17
|
+
}
|
|
18
|
+
export interface SubscriptionOptions extends MessageHandlers {
|
|
19
|
+
sessionToken: string;
|
|
20
|
+
id: string;
|
|
21
|
+
debug?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare enum ConnectionState {
|
|
24
|
+
DISCONNECTED = "disconnected",
|
|
25
|
+
CONNECTING = "connecting",
|
|
26
|
+
CONNECTED = "connected",
|
|
27
|
+
CLOSING = "closing"
|
|
28
|
+
}
|
|
29
|
+
export interface SessionInfo {
|
|
30
|
+
id: string;
|
|
31
|
+
token: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class PubsubClient {
|
|
34
|
+
private state;
|
|
35
|
+
private sessionInfo;
|
|
36
|
+
private readonly logger;
|
|
37
|
+
private readonly ackTracker;
|
|
38
|
+
private readonly reconnectManager;
|
|
39
|
+
private readonly wsManager;
|
|
40
|
+
private messageProcessor;
|
|
41
|
+
private shouldReconnect;
|
|
42
|
+
private sessionComplete;
|
|
43
|
+
constructor(debug?: boolean);
|
|
44
|
+
subscribe(opts: SubscriptionOptions): Promise<void>;
|
|
45
|
+
unsubscribe(): Promise<void>;
|
|
46
|
+
isConnected(): boolean;
|
|
47
|
+
getConnectionState(): ConnectionState;
|
|
48
|
+
getSessionInfo(): SessionInfo;
|
|
49
|
+
private connect;
|
|
50
|
+
private handleOpen;
|
|
51
|
+
private handleMessage;
|
|
52
|
+
private handleClose;
|
|
53
|
+
private handleError;
|
|
54
|
+
private analyzeCloseCode;
|
|
55
|
+
private scheduleReconnect;
|
|
56
|
+
private cleanup;
|
|
57
|
+
private isSameSession;
|
|
58
|
+
private updateHandlers;
|
|
59
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mochabug/adapt-core",
|
|
3
|
+
"version": "1.0.0-rc21",
|
|
4
|
+
"description": "Cross-platform core client library for Adapt automation platform",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types/index.d.ts",
|
|
11
|
+
"import": "./dist/esm/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build:esm": "tsc --project tsconfig.esm.json",
|
|
19
|
+
"build:types": "tsc --project tsconfig.types.json",
|
|
20
|
+
"build": "rm -rf dist && npm run build:esm && npm run build:types",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:ui": "vitest --ui"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"adapt",
|
|
26
|
+
"automations",
|
|
27
|
+
"mochabug"
|
|
28
|
+
],
|
|
29
|
+
"author": "mochabug AB",
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/ws": "^8.18.1",
|
|
33
|
+
"@vitest/ui": "^4.0.12",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"vitest": "^4.0.12",
|
|
36
|
+
"ws": "^8.18.3"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@bufbuild/protobuf": "^2.10.1",
|
|
40
|
+
"@types/uuid": "^11.0.0",
|
|
41
|
+
"isomorphic-ws": "^5.0.0",
|
|
42
|
+
"uuid": "^13.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|