@mcp-fe/mcp-worker 0.0.9 → 0.0.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.
- package/index.js +277 -153
- package/mcp-service-worker.js +28046 -0
- package/mcp-shared-worker.js +28065 -0
- package/package.json +1 -1
- package/src/index.d.ts.map +1 -0
- package/src/lib/database.d.ts.map +1 -0
- package/{lib → src/lib}/mcp-controller.d.ts +6 -0
- package/src/lib/mcp-controller.d.ts.map +1 -0
- package/{lib → src/lib}/mcp-server.d.ts +4 -0
- package/src/lib/mcp-server.d.ts.map +1 -0
- package/src/lib/websocket-transport.d.ts.map +1 -0
- package/src/lib/worker-client.d.ts.map +1 -0
- package/{lib/service-worker.d.ts → src/mcp-service-worker.d.ts} +1 -1
- package/src/mcp-service-worker.d.ts.map +1 -0
- package/{lib/shared-worker.d.ts → src/mcp-shared-worker.d.ts} +1 -1
- package/src/mcp-shared-worker.d.ts.map +1 -0
- package/index.d.ts.map +0 -1
- package/lib/database.d.ts.map +0 -1
- package/lib/mcp-controller.d.ts.map +0 -1
- package/lib/mcp-server.d.ts.map +0 -1
- package/lib/service-worker.d.ts.map +0 -1
- package/lib/shared-worker.d.ts.map +0 -1
- package/lib/websocket-transport.d.ts.map +0 -1
- package/lib/worker-client.d.ts.map +0 -1
- /package/{index.d.ts → src/index.d.ts} +0 -0
- /package/{lib → src/lib}/database.d.ts +0 -0
- /package/{lib → src/lib}/websocket-transport.d.ts +0 -0
- /package/{lib → src/lib}/worker-client.d.ts +0 -0
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// libs/mcp-worker/src/lib/worker-client.ts
|
|
2
|
+
var WorkerClient = class {
|
|
2
3
|
serviceWorkerRegistration = null;
|
|
3
4
|
sharedWorker = null;
|
|
4
5
|
sharedWorkerPort = null;
|
|
@@ -10,246 +11,369 @@ class W {
|
|
|
10
11
|
// Mutex/promise to prevent concurrent init runs
|
|
11
12
|
initPromise = null;
|
|
12
13
|
// Initialize and choose worker implementation (prefer SharedWorker)
|
|
13
|
-
async init(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
async init(registration) {
|
|
15
|
+
if (this.initPromise) {
|
|
16
|
+
return this.initPromise.then(async () => {
|
|
17
|
+
if (registration && this.workerType !== "service") {
|
|
18
|
+
await this.init(registration);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
this.initPromise = (async () => {
|
|
17
23
|
try {
|
|
18
|
-
if (
|
|
19
|
-
this.serviceWorkerRegistration =
|
|
24
|
+
if (registration) {
|
|
25
|
+
this.serviceWorkerRegistration = registration;
|
|
26
|
+
this.workerType = "service";
|
|
27
|
+
console.log("[WorkerClient] Using ServiceWorker (explicit registration)");
|
|
28
|
+
if (this.pendingAuthToken) {
|
|
29
|
+
this.sendAuthTokenToServiceWorker(this.pendingAuthToken);
|
|
30
|
+
this.pendingAuthToken = null;
|
|
31
|
+
}
|
|
20
32
|
return;
|
|
21
33
|
}
|
|
22
|
-
if (typeof SharedWorker
|
|
34
|
+
if (typeof SharedWorker !== "undefined") {
|
|
23
35
|
try {
|
|
24
|
-
|
|
36
|
+
this.sharedWorker = new SharedWorker("/mcp-shared-worker.js", { type: "module" });
|
|
37
|
+
this.sharedWorkerPort = this.sharedWorker.port;
|
|
38
|
+
this.sharedWorkerPort.start();
|
|
39
|
+
if (this.pendingAuthToken && this.sharedWorkerPort) {
|
|
25
40
|
try {
|
|
26
41
|
this.sharedWorkerPort.postMessage({ type: "SET_AUTH_TOKEN", token: this.pendingAuthToken });
|
|
27
|
-
} catch (
|
|
28
|
-
console.warn("[WorkerClient] Immediate postMessage to SharedWorker failed (will retry after init):",
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.warn("[WorkerClient] Immediate postMessage to SharedWorker failed (will retry after init):", err);
|
|
29
44
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
}
|
|
46
|
+
this.sharedWorker.onerror = (event) => {
|
|
47
|
+
console.error("[WorkerClient] SharedWorker error:", event.message || event.error || event);
|
|
48
|
+
if (this.workerType !== "shared") {
|
|
49
|
+
this.initServiceWorkerFallback().catch((err) => {
|
|
50
|
+
console.error("[WorkerClient] Failed to initialize ServiceWorker fallback:", err);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
await new Promise((resolve, reject) => {
|
|
55
|
+
let resolved = false;
|
|
56
|
+
const timeout = setTimeout(() => {
|
|
57
|
+
if (!resolved) {
|
|
58
|
+
const p2 = this.sharedWorkerPort;
|
|
59
|
+
if (p2)
|
|
60
|
+
p2.onmessage = null;
|
|
61
|
+
reject(new Error("SharedWorker initialization timeout"));
|
|
40
62
|
}
|
|
41
|
-
}, 2e3)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
63
|
+
}, 2e3);
|
|
64
|
+
const p = this.sharedWorkerPort;
|
|
65
|
+
if (!p) {
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
return reject(new Error("SharedWorker port not available"));
|
|
68
|
+
}
|
|
69
|
+
p.onmessage = (ev) => {
|
|
45
70
|
try {
|
|
46
|
-
const
|
|
47
|
-
|
|
71
|
+
const data = ev.data;
|
|
72
|
+
if (data && data.type === "CONNECTION_STATUS") {
|
|
73
|
+
clearTimeout(timeout);
|
|
74
|
+
resolved = true;
|
|
75
|
+
this.workerType = "shared";
|
|
76
|
+
p.onmessage = null;
|
|
77
|
+
resolve();
|
|
78
|
+
}
|
|
48
79
|
} catch {
|
|
49
80
|
}
|
|
50
81
|
};
|
|
51
82
|
});
|
|
52
|
-
const
|
|
53
|
-
if (this.pendingAuthToken &&
|
|
83
|
+
const portAfterInit = this.sharedWorkerPort;
|
|
84
|
+
if (this.pendingAuthToken && portAfterInit) {
|
|
54
85
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
86
|
+
portAfterInit.postMessage({ type: "SET_AUTH_TOKEN", token: this.pendingAuthToken });
|
|
87
|
+
this.pendingAuthToken = null;
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.error("[WorkerClient] Failed to send pending auth token to SharedWorker:", e);
|
|
58
90
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
}
|
|
92
|
+
if (portAfterInit) {
|
|
93
|
+
portAfterInit.onmessage = (ev) => {
|
|
94
|
+
try {
|
|
95
|
+
const data = ev.data;
|
|
96
|
+
if (data && data.type === "CONNECTION_STATUS") {
|
|
97
|
+
const connected = !!data.connected;
|
|
98
|
+
this.connectionStatusCallbacks.forEach((cb) => {
|
|
99
|
+
try {
|
|
100
|
+
cb(connected);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
70
106
|
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
console.log("[WorkerClient] Using SharedWorker");
|
|
74
110
|
return;
|
|
75
|
-
} catch (
|
|
76
|
-
console.warn("[WorkerClient] SharedWorker not available, falling back to ServiceWorker:",
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.warn("[WorkerClient] SharedWorker not available, falling back to ServiceWorker:", error);
|
|
77
113
|
}
|
|
78
|
-
|
|
114
|
+
}
|
|
115
|
+
console.log("this should not be called");
|
|
116
|
+
await this.initServiceWorkerFallback();
|
|
117
|
+
if (this.pendingAuthToken && this.workerType === "service") {
|
|
118
|
+
this.sendAuthTokenToServiceWorker(this.pendingAuthToken);
|
|
119
|
+
this.pendingAuthToken = null;
|
|
120
|
+
}
|
|
79
121
|
} finally {
|
|
80
122
|
this.initPromise = null;
|
|
81
123
|
}
|
|
82
|
-
})()
|
|
124
|
+
})();
|
|
125
|
+
return this.initPromise;
|
|
83
126
|
}
|
|
84
127
|
async initServiceWorkerFallback() {
|
|
85
|
-
|
|
128
|
+
console.log("initServiceWorkerFallback called");
|
|
129
|
+
if ("serviceWorker" in navigator) {
|
|
86
130
|
try {
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
this.serviceWorkerRegistration =
|
|
131
|
+
const existingRegistration = await navigator.serviceWorker.getRegistration();
|
|
132
|
+
if (existingRegistration) {
|
|
133
|
+
this.serviceWorkerRegistration = existingRegistration;
|
|
134
|
+
this.workerType = "service";
|
|
135
|
+
console.log("[WorkerClient] Using existing ServiceWorker registration");
|
|
90
136
|
return;
|
|
91
137
|
}
|
|
92
|
-
const
|
|
93
|
-
this.serviceWorkerRegistration =
|
|
138
|
+
const reg = await navigator.serviceWorker.register("/mcp-service-worker.js");
|
|
139
|
+
this.serviceWorkerRegistration = reg;
|
|
140
|
+
this.workerType = "service";
|
|
141
|
+
console.log("[WorkerClient] Using ServiceWorker (fallback)");
|
|
142
|
+
if (this.serviceWorkerMessageHandler) {
|
|
143
|
+
navigator.serviceWorker.removeEventListener("message", this.serviceWorkerMessageHandler);
|
|
144
|
+
this.serviceWorkerMessageHandler = null;
|
|
145
|
+
}
|
|
146
|
+
this.serviceWorkerMessageHandler = (ev) => {
|
|
94
147
|
try {
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
const
|
|
98
|
-
this.connectionStatusCallbacks.forEach((
|
|
148
|
+
const data = ev.data;
|
|
149
|
+
if (data && data.type === "CONNECTION_STATUS") {
|
|
150
|
+
const connected = !!data.connected;
|
|
151
|
+
this.connectionStatusCallbacks.forEach((cb) => {
|
|
99
152
|
try {
|
|
100
|
-
|
|
101
|
-
} catch {
|
|
153
|
+
cb(connected);
|
|
154
|
+
} catch (e) {
|
|
102
155
|
}
|
|
103
156
|
});
|
|
104
157
|
}
|
|
105
158
|
} catch {
|
|
106
159
|
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
160
|
+
};
|
|
161
|
+
navigator.serviceWorker.addEventListener("message", this.serviceWorkerMessageHandler);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error("[WorkerClient] Failed to register ServiceWorker:", error);
|
|
164
|
+
throw error;
|
|
110
165
|
}
|
|
111
|
-
else
|
|
166
|
+
} else {
|
|
112
167
|
throw new Error("Neither SharedWorker nor ServiceWorker is supported");
|
|
168
|
+
}
|
|
113
169
|
}
|
|
114
170
|
// Low-level request that expects a reply via MessageChannel
|
|
115
|
-
async request(
|
|
116
|
-
if (this.workerType === "shared" && this.sharedWorkerPort)
|
|
117
|
-
return new Promise((
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
171
|
+
async request(type, payload, timeoutMs = 5e3) {
|
|
172
|
+
if (this.workerType === "shared" && this.sharedWorkerPort) {
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
const mc = new MessageChannel();
|
|
175
|
+
const timer = setTimeout(() => {
|
|
176
|
+
mc.port1.onmessage = null;
|
|
177
|
+
reject(new Error("Request timeout"));
|
|
178
|
+
}, timeoutMs);
|
|
179
|
+
mc.port1.onmessage = (ev) => {
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
if (ev.data && ev.data.success) {
|
|
182
|
+
resolve(ev.data);
|
|
183
|
+
} else if (ev.data && ev.data.success === false) {
|
|
184
|
+
reject(new Error(ev.data.error || "Worker error"));
|
|
185
|
+
} else {
|
|
186
|
+
resolve(ev.data);
|
|
187
|
+
}
|
|
123
188
|
};
|
|
124
189
|
try {
|
|
125
|
-
const
|
|
126
|
-
if (!
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
190
|
+
const port = this.sharedWorkerPort;
|
|
191
|
+
if (!port) {
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
return reject(new Error("SharedWorker port not available"));
|
|
194
|
+
}
|
|
195
|
+
port.postMessage({ type, ...payload || {} }, [mc.port2]);
|
|
196
|
+
} catch (e) {
|
|
197
|
+
clearTimeout(timer);
|
|
198
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
131
199
|
}
|
|
132
200
|
});
|
|
201
|
+
}
|
|
133
202
|
if (this.workerType === "service" && this.serviceWorkerRegistration) {
|
|
134
|
-
const
|
|
135
|
-
if (!
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
203
|
+
const reg = this.serviceWorkerRegistration;
|
|
204
|
+
if (!reg)
|
|
205
|
+
throw new Error("Service worker registration missing");
|
|
206
|
+
if (!reg.active) {
|
|
207
|
+
await navigator.serviceWorker.ready;
|
|
208
|
+
if (!reg.active) {
|
|
209
|
+
throw new Error("Service worker not active");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
const mc = new MessageChannel();
|
|
214
|
+
const timer = setTimeout(() => {
|
|
215
|
+
mc.port1.onmessage = null;
|
|
216
|
+
reject(new Error("Request timeout"));
|
|
217
|
+
}, timeoutMs);
|
|
218
|
+
mc.port1.onmessage = (ev) => {
|
|
219
|
+
clearTimeout(timer);
|
|
220
|
+
if (ev.data && ev.data.success) {
|
|
221
|
+
resolve(ev.data);
|
|
222
|
+
} else if (ev.data && ev.data.success === false) {
|
|
223
|
+
reject(new Error(ev.data.error || "Worker error"));
|
|
224
|
+
} else {
|
|
225
|
+
resolve(ev.data);
|
|
226
|
+
}
|
|
144
227
|
};
|
|
145
228
|
try {
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
229
|
+
const active = reg.active;
|
|
230
|
+
if (!active) {
|
|
231
|
+
clearTimeout(timer);
|
|
232
|
+
return reject(new Error("Service worker active instance not available"));
|
|
233
|
+
}
|
|
234
|
+
active.postMessage({ type, ...payload || {} }, [mc.port2]);
|
|
235
|
+
} catch (e) {
|
|
236
|
+
clearTimeout(timer);
|
|
237
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
152
238
|
}
|
|
153
239
|
});
|
|
154
240
|
}
|
|
155
241
|
throw new Error("No worker registered");
|
|
156
242
|
}
|
|
157
243
|
// Fire-and-forget postMessage (no response expected)
|
|
158
|
-
async post(
|
|
244
|
+
async post(type, payload) {
|
|
159
245
|
if (this.workerType === "shared" && this.sharedWorkerPort) {
|
|
160
246
|
try {
|
|
161
|
-
this.sharedWorkerPort.postMessage({ type
|
|
162
|
-
} catch (
|
|
163
|
-
console.error("[WorkerClient] Failed to post to SharedWorker:",
|
|
247
|
+
this.sharedWorkerPort.postMessage({ type, ...payload || {} });
|
|
248
|
+
} catch (e) {
|
|
249
|
+
console.error("[WorkerClient] Failed to post to SharedWorker:", e);
|
|
164
250
|
}
|
|
165
251
|
return;
|
|
166
252
|
}
|
|
167
253
|
if (this.workerType === "service" && this.serviceWorkerRegistration?.active) {
|
|
168
254
|
try {
|
|
169
|
-
this.serviceWorkerRegistration.active.postMessage({ type
|
|
170
|
-
} catch (
|
|
171
|
-
console.error("[WorkerClient] Failed to post to ServiceWorker (active):",
|
|
255
|
+
this.serviceWorkerRegistration.active.postMessage({ type, ...payload || {} });
|
|
256
|
+
} catch (e) {
|
|
257
|
+
console.error("[WorkerClient] Failed to post to ServiceWorker (active):", e);
|
|
172
258
|
}
|
|
173
259
|
return;
|
|
174
260
|
}
|
|
175
261
|
if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
|
|
176
262
|
try {
|
|
177
|
-
navigator.serviceWorker.controller.postMessage({ type
|
|
178
|
-
} catch (
|
|
179
|
-
console.error("[WorkerClient] Failed to post to ServiceWorker.controller:",
|
|
263
|
+
navigator.serviceWorker.controller.postMessage({ type, ...payload || {} });
|
|
264
|
+
} catch (e) {
|
|
265
|
+
console.error("[WorkerClient] Failed to post to ServiceWorker.controller:", e);
|
|
180
266
|
}
|
|
181
267
|
return;
|
|
182
268
|
}
|
|
183
|
-
if (
|
|
184
|
-
const
|
|
185
|
-
typeof
|
|
269
|
+
if (type === "SET_AUTH_TOKEN" && payload) {
|
|
270
|
+
const token = payload["token"];
|
|
271
|
+
if (typeof token === "string")
|
|
272
|
+
this.pendingAuthToken = token;
|
|
186
273
|
}
|
|
187
274
|
}
|
|
188
|
-
sendAuthTokenToServiceWorker(
|
|
189
|
-
if (this.serviceWorkerRegistration?.active)
|
|
275
|
+
sendAuthTokenToServiceWorker(token) {
|
|
276
|
+
if (this.serviceWorkerRegistration?.active) {
|
|
190
277
|
try {
|
|
191
|
-
this.serviceWorkerRegistration.active.postMessage({ type: "SET_AUTH_TOKEN", token
|
|
192
|
-
} catch (
|
|
193
|
-
console.error("[WorkerClient] Failed to send auth token to ServiceWorker:",
|
|
278
|
+
this.serviceWorkerRegistration.active.postMessage({ type: "SET_AUTH_TOKEN", token });
|
|
279
|
+
} catch (e) {
|
|
280
|
+
console.error("[WorkerClient] Failed to send auth token to ServiceWorker:", e);
|
|
194
281
|
}
|
|
195
|
-
else if ("serviceWorker" in navigator && navigator.serviceWorker.controller)
|
|
282
|
+
} else if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
|
|
196
283
|
try {
|
|
197
|
-
navigator.serviceWorker.controller.postMessage({ type: "SET_AUTH_TOKEN", token
|
|
198
|
-
} catch (
|
|
199
|
-
console.error("[WorkerClient] Failed to send auth token to ServiceWorker.controller:",
|
|
284
|
+
navigator.serviceWorker.controller.postMessage({ type: "SET_AUTH_TOKEN", token });
|
|
285
|
+
} catch (e) {
|
|
286
|
+
console.error("[WorkerClient] Failed to send auth token to ServiceWorker.controller:", e);
|
|
200
287
|
}
|
|
201
|
-
else
|
|
202
|
-
this.pendingAuthToken =
|
|
288
|
+
} else {
|
|
289
|
+
this.pendingAuthToken = token;
|
|
290
|
+
}
|
|
203
291
|
}
|
|
204
292
|
// Subscription API for consumers to listen for connection status updates
|
|
205
|
-
onConnectionStatus(
|
|
206
|
-
this.connectionStatusCallbacks.add(
|
|
293
|
+
onConnectionStatus(cb) {
|
|
294
|
+
this.connectionStatusCallbacks.add(cb);
|
|
207
295
|
}
|
|
208
|
-
offConnectionStatus(
|
|
209
|
-
this.connectionStatusCallbacks.delete(
|
|
296
|
+
offConnectionStatus(cb) {
|
|
297
|
+
this.connectionStatusCallbacks.delete(cb);
|
|
210
298
|
}
|
|
211
299
|
async getConnectionStatus() {
|
|
212
300
|
try {
|
|
213
|
-
const
|
|
214
|
-
|
|
301
|
+
const res = await this.request("GET_CONNECTION_STATUS", void 0, 2e3);
|
|
302
|
+
if (res && typeof res === "object" && "connected" in res)
|
|
303
|
+
return !!res.connected;
|
|
304
|
+
return !!res.connected;
|
|
215
305
|
} catch {
|
|
216
|
-
return
|
|
306
|
+
return false;
|
|
217
307
|
}
|
|
218
308
|
}
|
|
219
|
-
setAuthToken(
|
|
220
|
-
|
|
309
|
+
setAuthToken(token) {
|
|
310
|
+
this.pendingAuthToken = token;
|
|
311
|
+
if (this.workerType === "shared" && this.sharedWorkerPort) {
|
|
221
312
|
try {
|
|
222
|
-
this.sharedWorkerPort.postMessage({ type: "SET_AUTH_TOKEN", token
|
|
223
|
-
|
|
224
|
-
|
|
313
|
+
this.sharedWorkerPort.postMessage({ type: "SET_AUTH_TOKEN", token });
|
|
314
|
+
this.pendingAuthToken = null;
|
|
315
|
+
} catch (e) {
|
|
316
|
+
console.error("[WorkerClient] Failed to set auth token on SharedWorker:", e);
|
|
225
317
|
}
|
|
226
|
-
else this.workerType === "service"
|
|
318
|
+
} else if (this.workerType === "service") {
|
|
319
|
+
this.sendAuthTokenToServiceWorker(token);
|
|
320
|
+
this.pendingAuthToken = null;
|
|
321
|
+
} else {
|
|
322
|
+
}
|
|
227
323
|
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// libs/mcp-worker/src/lib/database.ts
|
|
327
|
+
var DB_NAME = "user-activity-db";
|
|
328
|
+
var DB_VERSION = 1;
|
|
329
|
+
var STORE_NAME = "user-events";
|
|
330
|
+
async function initDB() {
|
|
331
|
+
return new Promise((resolve, reject) => {
|
|
332
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
333
|
+
request.onerror = () => reject(request.error);
|
|
334
|
+
request.onsuccess = () => resolve(request.result);
|
|
335
|
+
request.onupgradeneeded = (event) => {
|
|
336
|
+
const db = event.target.result;
|
|
337
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
338
|
+
const store = db.createObjectStore(STORE_NAME, { keyPath: "id" });
|
|
339
|
+
store.createIndex("timestamp", "timestamp", { unique: false });
|
|
340
|
+
store.createIndex("type", "type", { unique: false });
|
|
341
|
+
store.createIndex("path", "path", { unique: false });
|
|
238
342
|
}
|
|
239
343
|
};
|
|
240
344
|
});
|
|
241
345
|
}
|
|
242
|
-
async function
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
346
|
+
async function queryEvents(filters) {
|
|
347
|
+
const db = await initDB();
|
|
348
|
+
const transaction = db.transaction([STORE_NAME], "readonly");
|
|
349
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
350
|
+
const index = store.index("timestamp");
|
|
351
|
+
return new Promise((resolve, reject) => {
|
|
352
|
+
const request = index.getAll();
|
|
353
|
+
request.onsuccess = () => {
|
|
354
|
+
let events = request.result;
|
|
355
|
+
if (filters?.type) {
|
|
356
|
+
events = events.filter((e) => e.type === filters.type);
|
|
357
|
+
}
|
|
358
|
+
if (filters?.startTime) {
|
|
359
|
+
events = events.filter((e) => e.timestamp >= filters.startTime);
|
|
360
|
+
}
|
|
361
|
+
if (filters?.endTime) {
|
|
362
|
+
events = events.filter((e) => e.timestamp <= filters.endTime);
|
|
363
|
+
}
|
|
364
|
+
if (filters?.path) {
|
|
365
|
+
events = events.filter((e) => e.path?.includes(filters.path));
|
|
366
|
+
}
|
|
367
|
+
events.sort((a, b) => b.timestamp - a.timestamp);
|
|
368
|
+
if (filters?.limit) {
|
|
369
|
+
events = events.slice(0, filters.limit);
|
|
370
|
+
}
|
|
371
|
+
resolve(events);
|
|
372
|
+
};
|
|
373
|
+
request.onerror = () => reject(request.error);
|
|
250
374
|
});
|
|
251
375
|
}
|
|
252
376
|
export {
|
|
253
|
-
|
|
254
|
-
|
|
377
|
+
WorkerClient,
|
|
378
|
+
queryEvents
|
|
255
379
|
};
|