@mcp-fe/mcp-worker 0.0.8 → 0.0.11
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/database.js +49 -0
- package/database.js.map +1 -0
- package/index.js +74 -95
- package/index.js.map +1 -0
- package/mcp-controller.js +10565 -0
- package/mcp-controller.js.map +1 -0
- package/{lib/service-worker.d.ts → mcp-service-worker.d.ts} +1 -1
- package/mcp-service-worker.d.ts.map +1 -0
- package/mcp-service-worker.js +46 -0
- package/mcp-service-worker.js.map +1 -0
- package/{lib/shared-worker.d.ts → mcp-shared-worker.d.ts} +1 -1
- package/mcp-shared-worker.d.ts.map +1 -0
- package/mcp-shared-worker.js +76 -0
- package/mcp-shared-worker.js.map +1 -0
- package/package.json +1 -1
- package/lib/service-worker.d.ts.map +0 -1
- package/lib/shared-worker.d.ts.map +0 -1
package/database.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const y = "user-activity-db";
|
|
2
|
+
const i = "user-events";
|
|
3
|
+
async function p() {
|
|
4
|
+
return new Promise((e, d) => {
|
|
5
|
+
const r = indexedDB.open(y, 1);
|
|
6
|
+
r.onerror = () => d(r.error), r.onsuccess = () => e(r.result), r.onupgradeneeded = (a) => {
|
|
7
|
+
const c = a.target.result;
|
|
8
|
+
if (!c.objectStoreNames.contains(i)) {
|
|
9
|
+
const o = c.createObjectStore(i, { keyPath: "id" });
|
|
10
|
+
o.createIndex("timestamp", "timestamp", { unique: !1 }), o.createIndex("type", "type", { unique: !1 }), o.createIndex("path", "path", { unique: !1 });
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function b(e) {
|
|
16
|
+
const a = (await p()).transaction([i], "readwrite").objectStore(i), c = {
|
|
17
|
+
...e,
|
|
18
|
+
id: `${e.timestamp}-${Math.random().toString(36).substr(2, 9)}`
|
|
19
|
+
};
|
|
20
|
+
await new Promise((m, n) => {
|
|
21
|
+
const t = a.add(c);
|
|
22
|
+
t.onsuccess = () => m(), t.onerror = () => n(t.error);
|
|
23
|
+
});
|
|
24
|
+
const o = a.count();
|
|
25
|
+
o.onsuccess = () => {
|
|
26
|
+
if (o.result > 1e3) {
|
|
27
|
+
const n = a.index("timestamp").getAll();
|
|
28
|
+
n.onsuccess = () => {
|
|
29
|
+
const t = n.result;
|
|
30
|
+
t.sort((u, l) => u.timestamp - l.timestamp), t.slice(0, t.length - 1e3).forEach((u) => a.delete(u.id));
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function h(e) {
|
|
36
|
+
const c = (await p()).transaction([i], "readonly").objectStore(i).index("timestamp");
|
|
37
|
+
return new Promise((o, m) => {
|
|
38
|
+
const n = c.getAll();
|
|
39
|
+
n.onsuccess = () => {
|
|
40
|
+
let t = n.result;
|
|
41
|
+
e?.type && (t = t.filter((s) => s.type === e.type)), e?.startTime && (t = t.filter((s) => s.timestamp >= e.startTime)), e?.endTime && (t = t.filter((s) => s.timestamp <= e.endTime)), e?.path && (t = t.filter((s) => s.path?.includes(e.path))), t.sort((s, u) => u.timestamp - s.timestamp), e?.limit && (t = t.slice(0, e.limit)), o(t);
|
|
42
|
+
}, n.onerror = () => m(n.error);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
h as q,
|
|
47
|
+
b as s
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=database.js.map
|
package/database.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sources":["../../../libs/mcp-worker/src/lib/database.ts"],"sourcesContent":["/**\n * IndexedDB operations for storing and querying user events\n */\n\nconst DB_NAME = 'user-activity-db'\nconst DB_VERSION = 1\nconst STORE_NAME = 'user-events'\n\nexport interface UserEvent {\n id: string\n type: 'navigation' | 'click' | 'input' | 'custom'\n timestamp: number\n path?: string\n from?: string\n to?: string\n element?: string\n elementId?: string\n elementClass?: string\n elementText?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface EventFilters {\n type?: string\n startTime?: number\n endTime?: number\n path?: string\n limit?: number\n}\n\n// Initialize IndexedDB\nexport async function initDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION)\n\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(request.result)\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' })\n store.createIndex('timestamp', 'timestamp', { unique: false })\n store.createIndex('type', 'type', { unique: false })\n store.createIndex('path', 'path', { unique: false })\n }\n }\n })\n}\n\n// Store event in IndexedDB\nexport async function storeEvent(event: Omit<UserEvent, 'id'>): Promise<void> {\n const db = await initDB()\n const transaction = db.transaction([STORE_NAME], 'readwrite')\n const store = transaction.objectStore(STORE_NAME)\n\n const eventWithId: UserEvent = {\n ...event,\n id: `${event.timestamp}-${Math.random().toString(36).substr(2, 9)}`,\n }\n\n await new Promise<void>((resolve, reject) => {\n const request = store.add(eventWithId)\n request.onsuccess = () => resolve()\n request.onerror = () => reject(request.error)\n })\n\n // Clean up old events (keep last 1000 events)\n const countRequest = store.count()\n countRequest.onsuccess = () => {\n if (countRequest.result > 1000) {\n const index = store.index('timestamp')\n const getAllRequest = index.getAll()\n getAllRequest.onsuccess = () => {\n const events = getAllRequest.result as UserEvent[]\n events.sort((a, b) => a.timestamp - b.timestamp)\n const toDelete = events.slice(0, events.length - 1000)\n toDelete.forEach((event) => store.delete(event.id))\n }\n }\n }\n}\n\n// Query events from IndexedDB\nexport async function queryEvents(filters?: EventFilters): Promise<UserEvent[]> {\n const db = await initDB()\n const transaction = db.transaction([STORE_NAME], 'readonly')\n const store = transaction.objectStore(STORE_NAME)\n const index = store.index('timestamp')\n\n return new Promise((resolve, reject) => {\n const request = index.getAll()\n request.onsuccess = () => {\n let events = request.result as UserEvent[]\n\n // Apply filters\n if (filters?.type) {\n events = events.filter((e) => e.type === filters.type)\n }\n if (filters?.startTime) {\n events = events.filter((e) => e.timestamp >= filters.startTime!)\n }\n if (filters?.endTime) {\n events = events.filter((e) => e.timestamp <= filters.endTime!)\n }\n if (filters?.path) {\n events = events.filter((e) => e.path?.includes(filters.path!))\n }\n\n // Sort by timestamp descending (newest first)\n events.sort((a, b) => b.timestamp - a.timestamp)\n\n // Apply limit\n if (filters?.limit) {\n events = events.slice(0, filters.limit)\n }\n\n resolve(events)\n }\n request.onerror = () => reject(request.error)\n })\n}\n"],"names":["DB_NAME","STORE_NAME","initDB","resolve","reject","request","event","db","store","storeEvent","eventWithId","countRequest","getAllRequest","events","a","b","queryEvents","filters","index","e"],"mappings":"AAIA,MAAMA,IAAU;AAEhB,MAAMC,IAAa;AAyBnB,eAAsBC,IAA+B;AACnD,SAAO,IAAI,QAAQ,CAACC,GAASC,MAAW;AACtC,UAAMC,IAAU,UAAU,KAAKL,GAAS,CAAU;AAElD,IAAAK,EAAQ,UAAU,MAAMD,EAAOC,EAAQ,KAAK,GAC5CA,EAAQ,YAAY,MAAMF,EAAQE,EAAQ,MAAM,GAEhDA,EAAQ,kBAAkB,CAACC,MAAU;AACnC,YAAMC,IAAMD,EAAM,OAA4B;AAC9C,UAAI,CAACC,EAAG,iBAAiB,SAASN,CAAU,GAAG;AAC7C,cAAMO,IAAQD,EAAG,kBAAkBN,GAAY,EAAE,SAAS,MAAM;AAChE,QAAAO,EAAM,YAAY,aAAa,aAAa,EAAE,QAAQ,IAAO,GAC7DA,EAAM,YAAY,QAAQ,QAAQ,EAAE,QAAQ,IAAO,GACnDA,EAAM,YAAY,QAAQ,QAAQ,EAAE,QAAQ,IAAO;AAAA,MACrD;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAGA,eAAsBC,EAAWH,GAA6C;AAG5E,QAAME,KAFK,MAAMN,EAAA,GACM,YAAY,CAACD,CAAU,GAAG,WAAW,EAClC,YAAYA,CAAU,GAE1CS,IAAyB;AAAA,IAC7B,GAAGJ;AAAA,IACH,IAAI,GAAGA,EAAM,SAAS,IAAI,KAAK,SAAS,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,EAAA;AAGnE,QAAM,IAAI,QAAc,CAACH,GAASC,MAAW;AAC3C,UAAMC,IAAUG,EAAM,IAAIE,CAAW;AACrC,IAAAL,EAAQ,YAAY,MAAMF,EAAA,GAC1BE,EAAQ,UAAU,MAAMD,EAAOC,EAAQ,KAAK;AAAA,EAC9C,CAAC;AAGD,QAAMM,IAAeH,EAAM,MAAA;AAC3B,EAAAG,EAAa,YAAY,MAAM;AAC7B,QAAIA,EAAa,SAAS,KAAM;AAE9B,YAAMC,IADQJ,EAAM,MAAM,WAAW,EACT,OAAA;AAC5B,MAAAI,EAAc,YAAY,MAAM;AAC9B,cAAMC,IAASD,EAAc;AAC7B,QAAAC,EAAO,KAAK,CAACC,GAAGC,MAAMD,EAAE,YAAYC,EAAE,SAAS,GAC9BF,EAAO,MAAM,GAAGA,EAAO,SAAS,GAAI,EAC5C,QAAQ,CAACP,MAAUE,EAAM,OAAOF,EAAM,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAsBU,EAAYC,GAA8C;AAI9E,QAAMC,KAHK,MAAMhB,EAAA,GACM,YAAY,CAACD,CAAU,GAAG,UAAU,EACjC,YAAYA,CAAU,EAC5B,MAAM,WAAW;AAErC,SAAO,IAAI,QAAQ,CAACE,GAASC,MAAW;AACtC,UAAMC,IAAUa,EAAM,OAAA;AACtB,IAAAb,EAAQ,YAAY,MAAM;AACxB,UAAIQ,IAASR,EAAQ;AAGrB,MAAIY,GAAS,SACXJ,IAASA,EAAO,OAAO,CAACM,MAAMA,EAAE,SAASF,EAAQ,IAAI,IAEnDA,GAAS,cACXJ,IAASA,EAAO,OAAO,CAACM,MAAMA,EAAE,aAAaF,EAAQ,SAAU,IAE7DA,GAAS,YACXJ,IAASA,EAAO,OAAO,CAACM,MAAMA,EAAE,aAAaF,EAAQ,OAAQ,IAE3DA,GAAS,SACXJ,IAASA,EAAO,OAAO,CAACM,MAAMA,EAAE,MAAM,SAASF,EAAQ,IAAK,CAAC,IAI/DJ,EAAO,KAAK,CAACC,GAAGC,MAAMA,EAAE,YAAYD,EAAE,SAAS,GAG3CG,GAAS,UACXJ,IAASA,EAAO,MAAM,GAAGI,EAAQ,KAAK,IAGxCd,EAAQU,CAAM;AAAA,IAChB,GACAR,EAAQ,UAAU,MAAMD,EAAOC,EAAQ,KAAK;AAAA,EAC9C,CAAC;AACH;"}
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { q as W } from "./database.js";
|
|
2
|
+
class l {
|
|
2
3
|
serviceWorkerRegistration = null;
|
|
3
4
|
sharedWorker = null;
|
|
4
5
|
sharedWorkerPort = null;
|
|
@@ -21,30 +22,30 @@ class W {
|
|
|
21
22
|
}
|
|
22
23
|
if (typeof SharedWorker < "u")
|
|
23
24
|
try {
|
|
24
|
-
if (this.sharedWorker = new SharedWorker("/shared-worker.js", { type: "module" }), this.sharedWorkerPort = this.sharedWorker.port, this.sharedWorkerPort.start(), this.pendingAuthToken && this.sharedWorkerPort)
|
|
25
|
+
if (this.sharedWorker = new SharedWorker("/mcp-shared-worker.js", { type: "module" }), this.sharedWorkerPort = this.sharedWorker.port, this.sharedWorkerPort.start(), this.pendingAuthToken && this.sharedWorkerPort)
|
|
25
26
|
try {
|
|
26
27
|
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):",
|
|
28
|
+
} catch (r) {
|
|
29
|
+
console.warn("[WorkerClient] Immediate postMessage to SharedWorker failed (will retry after init):", r);
|
|
29
30
|
}
|
|
30
|
-
this.sharedWorker.onerror = (
|
|
31
|
-
console.error("[WorkerClient] SharedWorker error:",
|
|
32
|
-
console.error("[WorkerClient] Failed to initialize ServiceWorker fallback:",
|
|
31
|
+
this.sharedWorker.onerror = (r) => {
|
|
32
|
+
console.error("[WorkerClient] SharedWorker error:", r.message || r.error || r), this.workerType !== "shared" && this.initServiceWorkerFallback().catch((i) => {
|
|
33
|
+
console.error("[WorkerClient] Failed to initialize ServiceWorker fallback:", i);
|
|
33
34
|
});
|
|
34
|
-
}, await new Promise((
|
|
35
|
-
let
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
38
|
-
const
|
|
39
|
-
|
|
35
|
+
}, await new Promise((r, i) => {
|
|
36
|
+
let a = !1;
|
|
37
|
+
const n = setTimeout(() => {
|
|
38
|
+
if (!a) {
|
|
39
|
+
const o = this.sharedWorkerPort;
|
|
40
|
+
o && (o.onmessage = null), i(new Error("SharedWorker initialization timeout"));
|
|
40
41
|
}
|
|
41
|
-
}, 2e3),
|
|
42
|
-
if (!
|
|
43
|
-
return clearTimeout(
|
|
44
|
-
|
|
42
|
+
}, 2e3), c = this.sharedWorkerPort;
|
|
43
|
+
if (!c)
|
|
44
|
+
return clearTimeout(n), i(new Error("SharedWorker port not available"));
|
|
45
|
+
c.onmessage = (o) => {
|
|
45
46
|
try {
|
|
46
|
-
const
|
|
47
|
-
|
|
47
|
+
const s = o.data;
|
|
48
|
+
s && s.type === "CONNECTION_STATUS" && (clearTimeout(n), a = !0, this.workerType = "shared", c.onmessage = null, r());
|
|
48
49
|
} catch {
|
|
49
50
|
}
|
|
50
51
|
};
|
|
@@ -53,17 +54,17 @@ class W {
|
|
|
53
54
|
if (this.pendingAuthToken && t)
|
|
54
55
|
try {
|
|
55
56
|
t.postMessage({ type: "SET_AUTH_TOKEN", token: this.pendingAuthToken }), this.pendingAuthToken = null;
|
|
56
|
-
} catch (
|
|
57
|
-
console.error("[WorkerClient] Failed to send pending auth token to SharedWorker:",
|
|
57
|
+
} catch (r) {
|
|
58
|
+
console.error("[WorkerClient] Failed to send pending auth token to SharedWorker:", r);
|
|
58
59
|
}
|
|
59
|
-
t && (t.onmessage = (
|
|
60
|
+
t && (t.onmessage = (r) => {
|
|
60
61
|
try {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
const
|
|
64
|
-
this.connectionStatusCallbacks.forEach((
|
|
62
|
+
const i = r.data;
|
|
63
|
+
if (i && i.type === "CONNECTION_STATUS") {
|
|
64
|
+
const a = !!i.connected;
|
|
65
|
+
this.connectionStatusCallbacks.forEach((n) => {
|
|
65
66
|
try {
|
|
66
|
-
|
|
67
|
+
n(a);
|
|
67
68
|
} catch {
|
|
68
69
|
}
|
|
69
70
|
});
|
|
@@ -89,15 +90,15 @@ class W {
|
|
|
89
90
|
this.serviceWorkerRegistration = e, this.workerType = "service", console.log("[WorkerClient] Using existing ServiceWorker registration");
|
|
90
91
|
return;
|
|
91
92
|
}
|
|
92
|
-
const t = await navigator.serviceWorker.register("/
|
|
93
|
-
this.serviceWorkerRegistration = t, this.workerType = "service", console.log("[WorkerClient] Using ServiceWorker (fallback)"), this.serviceWorkerMessageHandler && (navigator.serviceWorker.removeEventListener("message", this.serviceWorkerMessageHandler), this.serviceWorkerMessageHandler = null), this.serviceWorkerMessageHandler = (
|
|
93
|
+
const t = await navigator.serviceWorker.register("/mcp-service-worker.js");
|
|
94
|
+
this.serviceWorkerRegistration = t, this.workerType = "service", console.log("[WorkerClient] Using ServiceWorker (fallback)"), this.serviceWorkerMessageHandler && (navigator.serviceWorker.removeEventListener("message", this.serviceWorkerMessageHandler), this.serviceWorkerMessageHandler = null), this.serviceWorkerMessageHandler = (r) => {
|
|
94
95
|
try {
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
const
|
|
98
|
-
this.connectionStatusCallbacks.forEach((
|
|
96
|
+
const i = r.data;
|
|
97
|
+
if (i && i.type === "CONNECTION_STATUS") {
|
|
98
|
+
const a = !!i.connected;
|
|
99
|
+
this.connectionStatusCallbacks.forEach((n) => {
|
|
99
100
|
try {
|
|
100
|
-
|
|
101
|
+
n(a);
|
|
101
102
|
} catch {
|
|
102
103
|
}
|
|
103
104
|
});
|
|
@@ -112,43 +113,43 @@ class W {
|
|
|
112
113
|
throw new Error("Neither SharedWorker nor ServiceWorker is supported");
|
|
113
114
|
}
|
|
114
115
|
// Low-level request that expects a reply via MessageChannel
|
|
115
|
-
async request(e, t,
|
|
116
|
+
async request(e, t, r = 5e3) {
|
|
116
117
|
if (this.workerType === "shared" && this.sharedWorkerPort)
|
|
117
|
-
return new Promise((
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
clearTimeout(
|
|
118
|
+
return new Promise((i, a) => {
|
|
119
|
+
const n = new MessageChannel(), c = setTimeout(() => {
|
|
120
|
+
n.port1.onmessage = null, a(new Error("Request timeout"));
|
|
121
|
+
}, r);
|
|
122
|
+
n.port1.onmessage = (o) => {
|
|
123
|
+
clearTimeout(c), o.data && o.data.success ? i(o.data) : o.data && o.data.success === !1 ? a(new Error(o.data.error || "Worker error")) : i(o.data);
|
|
123
124
|
};
|
|
124
125
|
try {
|
|
125
|
-
const
|
|
126
|
-
if (!
|
|
127
|
-
return clearTimeout(
|
|
128
|
-
|
|
129
|
-
} catch (
|
|
130
|
-
clearTimeout(
|
|
126
|
+
const o = this.sharedWorkerPort;
|
|
127
|
+
if (!o)
|
|
128
|
+
return clearTimeout(c), a(new Error("SharedWorker port not available"));
|
|
129
|
+
o.postMessage({ type: e, ...t || {} }, [n.port2]);
|
|
130
|
+
} catch (o) {
|
|
131
|
+
clearTimeout(c), a(o instanceof Error ? o : new Error(String(o)));
|
|
131
132
|
}
|
|
132
133
|
});
|
|
133
134
|
if (this.workerType === "service" && this.serviceWorkerRegistration) {
|
|
134
|
-
const
|
|
135
|
-
if (!
|
|
136
|
-
if (!
|
|
135
|
+
const i = this.serviceWorkerRegistration;
|
|
136
|
+
if (!i) throw new Error("Service worker registration missing");
|
|
137
|
+
if (!i.active && (await navigator.serviceWorker.ready, !i.active))
|
|
137
138
|
throw new Error("Service worker not active");
|
|
138
|
-
return new Promise((
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
clearTimeout(
|
|
139
|
+
return new Promise((a, n) => {
|
|
140
|
+
const c = new MessageChannel(), o = setTimeout(() => {
|
|
141
|
+
c.port1.onmessage = null, n(new Error("Request timeout"));
|
|
142
|
+
}, r);
|
|
143
|
+
c.port1.onmessage = (s) => {
|
|
144
|
+
clearTimeout(o), s.data && s.data.success ? a(s.data) : s.data && s.data.success === !1 ? n(new Error(s.data.error || "Worker error")) : a(s.data);
|
|
144
145
|
};
|
|
145
146
|
try {
|
|
146
|
-
const
|
|
147
|
-
if (!
|
|
148
|
-
return clearTimeout(
|
|
149
|
-
|
|
150
|
-
} catch (
|
|
151
|
-
clearTimeout(
|
|
147
|
+
const s = i.active;
|
|
148
|
+
if (!s)
|
|
149
|
+
return clearTimeout(o), n(new Error("Service worker active instance not available"));
|
|
150
|
+
s.postMessage({ type: e, ...t || {} }, [c.port2]);
|
|
151
|
+
} catch (s) {
|
|
152
|
+
clearTimeout(o), n(s instanceof Error ? s : new Error(String(s)));
|
|
152
153
|
}
|
|
153
154
|
});
|
|
154
155
|
}
|
|
@@ -159,30 +160,30 @@ class W {
|
|
|
159
160
|
if (this.workerType === "shared" && this.sharedWorkerPort) {
|
|
160
161
|
try {
|
|
161
162
|
this.sharedWorkerPort.postMessage({ type: e, ...t || {} });
|
|
162
|
-
} catch (
|
|
163
|
-
console.error("[WorkerClient] Failed to post to SharedWorker:",
|
|
163
|
+
} catch (r) {
|
|
164
|
+
console.error("[WorkerClient] Failed to post to SharedWorker:", r);
|
|
164
165
|
}
|
|
165
166
|
return;
|
|
166
167
|
}
|
|
167
168
|
if (this.workerType === "service" && this.serviceWorkerRegistration?.active) {
|
|
168
169
|
try {
|
|
169
170
|
this.serviceWorkerRegistration.active.postMessage({ type: e, ...t || {} });
|
|
170
|
-
} catch (
|
|
171
|
-
console.error("[WorkerClient] Failed to post to ServiceWorker (active):",
|
|
171
|
+
} catch (r) {
|
|
172
|
+
console.error("[WorkerClient] Failed to post to ServiceWorker (active):", r);
|
|
172
173
|
}
|
|
173
174
|
return;
|
|
174
175
|
}
|
|
175
176
|
if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
|
|
176
177
|
try {
|
|
177
178
|
navigator.serviceWorker.controller.postMessage({ type: e, ...t || {} });
|
|
178
|
-
} catch (
|
|
179
|
-
console.error("[WorkerClient] Failed to post to ServiceWorker.controller:",
|
|
179
|
+
} catch (r) {
|
|
180
|
+
console.error("[WorkerClient] Failed to post to ServiceWorker.controller:", r);
|
|
180
181
|
}
|
|
181
182
|
return;
|
|
182
183
|
}
|
|
183
184
|
if (e === "SET_AUTH_TOKEN" && t) {
|
|
184
|
-
const
|
|
185
|
-
typeof
|
|
185
|
+
const r = t.token;
|
|
186
|
+
typeof r == "string" && (this.pendingAuthToken = r);
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
sendAuthTokenToServiceWorker(e) {
|
|
@@ -226,30 +227,8 @@ class W {
|
|
|
226
227
|
else this.workerType === "service" && (this.sendAuthTokenToServiceWorker(e), this.pendingAuthToken = null);
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
|
-
const d = "user-activity-db", u = 1, h = "user-events";
|
|
230
|
-
async function g() {
|
|
231
|
-
return new Promise((l, e) => {
|
|
232
|
-
const t = indexedDB.open(d, u);
|
|
233
|
-
t.onerror = () => e(t.error), t.onsuccess = () => l(t.result), t.onupgradeneeded = (o) => {
|
|
234
|
-
const s = o.target.result;
|
|
235
|
-
if (!s.objectStoreNames.contains(h)) {
|
|
236
|
-
const n = s.createObjectStore(h, { keyPath: "id" });
|
|
237
|
-
n.createIndex("timestamp", "timestamp", { unique: !1 }), n.createIndex("type", "type", { unique: !1 }), n.createIndex("path", "path", { unique: !1 });
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
async function T(l) {
|
|
243
|
-
const s = (await g()).transaction([h], "readonly").objectStore(h).index("timestamp");
|
|
244
|
-
return new Promise((n, c) => {
|
|
245
|
-
const a = s.getAll();
|
|
246
|
-
a.onsuccess = () => {
|
|
247
|
-
let r = a.result;
|
|
248
|
-
l?.type && (r = r.filter((i) => i.type === l.type)), l?.startTime && (r = r.filter((i) => i.timestamp >= l.startTime)), l?.endTime && (r = r.filter((i) => i.timestamp <= l.endTime)), l?.path && (r = r.filter((i) => i.path?.includes(l.path))), r.sort((i, k) => k.timestamp - i.timestamp), l?.limit && (r = r.slice(0, l.limit)), n(r);
|
|
249
|
-
}, a.onerror = () => c(a.error);
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
230
|
export {
|
|
253
|
-
|
|
254
|
-
|
|
231
|
+
l as WorkerClient,
|
|
232
|
+
W as queryEvents
|
|
255
233
|
};
|
|
234
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../libs/mcp-worker/src/lib/worker-client.ts"],"sourcesContent":["type WorkerType = 'shared' | 'service';\n\nexport class WorkerClient {\n private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;\n private sharedWorker: SharedWorker | null = null;\n private sharedWorkerPort: MessagePort | null = null;\n private workerType: WorkerType | null = null;\n private pendingAuthToken: string | null = null;\n // connection status subscribers\n private connectionStatusCallbacks: Set<(connected: boolean) => void> = new Set();\n private serviceWorkerMessageHandler: ((ev: MessageEvent) => void) | null = null;\n\n // Mutex/promise to prevent concurrent init runs\n private initPromise: Promise<void> | null = null;\n\n // Initialize and choose worker implementation (prefer SharedWorker)\n public async init(registration?: ServiceWorkerRegistration): Promise<void> {\n // If an init is already in progress, wait for it and optionally retry if caller provided a registration\n if (this.initPromise) {\n return this.initPromise.then(async () => {\n if (registration && this.workerType !== 'service') {\n // retry once with provided registration after current init finished\n await this.init(registration);\n }\n });\n }\n\n // Start initialization and store the promise as a mutex\n this.initPromise = (async () => {\n try {\n // If an explicit ServiceWorker registration is provided, use it\n if (registration) {\n this.serviceWorkerRegistration = registration;\n this.workerType = 'service';\n console.log('[WorkerClient] Using ServiceWorker (explicit registration)');\n // send pending token if exists\n if (this.pendingAuthToken) {\n this.sendAuthTokenToServiceWorker(this.pendingAuthToken);\n this.pendingAuthToken = null;\n }\n return;\n }\n\n // Try SharedWorker first\n if (typeof SharedWorker !== 'undefined') {\n try {\n this.sharedWorker = new SharedWorker('/mcp-shared-worker.js', { type: 'module' });\n this.sharedWorkerPort = this.sharedWorker.port;\n this.sharedWorkerPort.start();\n\n if (this.pendingAuthToken && this.sharedWorkerPort) {\n try {\n this.sharedWorkerPort.postMessage({ type: 'SET_AUTH_TOKEN', token: this.pendingAuthToken });\n } catch (err) {\n console.warn('[WorkerClient] Immediate postMessage to SharedWorker failed (will retry after init):', err);\n }\n }\n\n this.sharedWorker.onerror = (event: ErrorEvent) => {\n console.error('[WorkerClient] SharedWorker error:', event.message || event.error || event);\n if (this.workerType !== 'shared') {\n this.initServiceWorkerFallback().catch((err) => {\n console.error('[WorkerClient] Failed to initialize ServiceWorker fallback:', err);\n });\n }\n };\n\n await new Promise<void>((resolve, reject) => {\n let resolved = false;\n const timeout = setTimeout(() => {\n if (!resolved) {\n const p = this.sharedWorkerPort;\n if (p) p.onmessage = null;\n reject(new Error('SharedWorker initialization timeout'));\n }\n }, 2000);\n\n const p = this.sharedWorkerPort;\n if (!p) {\n clearTimeout(timeout);\n return reject(new Error('SharedWorker port not available'));\n }\n\n p.onmessage = (ev: MessageEvent) => {\n try {\n const data = ev.data;\n if (data && data.type === 'CONNECTION_STATUS') {\n clearTimeout(timeout);\n resolved = true;\n this.workerType = 'shared';\n p.onmessage = null;\n resolve();\n }\n } catch {\n // ignore parse/handler errors\n }\n };\n });\n\n const portAfterInit = this.sharedWorkerPort;\n if (this.pendingAuthToken && portAfterInit) {\n try {\n portAfterInit.postMessage({ type: 'SET_AUTH_TOKEN', token: this.pendingAuthToken });\n this.pendingAuthToken = null;\n } catch (e) {\n console.error('[WorkerClient] Failed to send pending auth token to SharedWorker:', e);\n }\n }\n\n if (portAfterInit) {\n portAfterInit.onmessage = (ev: MessageEvent) => {\n try {\n const data = ev.data;\n if (data && data.type === 'CONNECTION_STATUS') {\n const connected = !!data.connected;\n this.connectionStatusCallbacks.forEach((cb) => {\n try { cb(connected); } catch (e) { /* ignore callback errors */ }\n });\n }\n } catch {\n // ignore\n }\n };\n }\n\n console.log('[WorkerClient] Using SharedWorker');\n return;\n } catch (error) {\n console.warn('[WorkerClient] SharedWorker not available, falling back to ServiceWorker:', error);\n }\n }\n\n // If SharedWorker isn't supported or failed, use service worker\n console.log(\"this should not be called\");\n await this.initServiceWorkerFallback();\n\n // Send pending token if any\n if (this.pendingAuthToken && this.workerType === 'service') {\n this.sendAuthTokenToServiceWorker(this.pendingAuthToken);\n this.pendingAuthToken = null;\n }\n } finally {\n // Clear the mutex so future init calls can proceed\n this.initPromise = null;\n }\n })();\n\n return this.initPromise;\n }\n\n private async initServiceWorkerFallback(): Promise<void> {\n console.log(\"initServiceWorkerFallback called\");\n if ('serviceWorker' in navigator) {\n try {\n const existingRegistration = await navigator.serviceWorker.getRegistration();\n if (existingRegistration) {\n this.serviceWorkerRegistration = existingRegistration;\n this.workerType = 'service';\n console.log('[WorkerClient] Using existing ServiceWorker registration');\n return;\n }\n\n const reg = await navigator.serviceWorker.register('/mcp-service-worker.js');\n this.serviceWorkerRegistration = reg;\n this.workerType = 'service';\n console.log('[WorkerClient] Using ServiceWorker (fallback)');\n if (this.serviceWorkerMessageHandler) {\n navigator.serviceWorker.removeEventListener('message', this.serviceWorkerMessageHandler);\n this.serviceWorkerMessageHandler = null;\n }\n this.serviceWorkerMessageHandler = (ev: MessageEvent) => {\n try {\n const data = ev.data;\n if (data && data.type === 'CONNECTION_STATUS') {\n const connected = !!data.connected;\n this.connectionStatusCallbacks.forEach((cb) => {\n try { cb(connected); } catch (e) { /* ignore callback errors */ }\n });\n }\n } catch {\n // ignore\n }\n };\n navigator.serviceWorker.addEventListener('message', this.serviceWorkerMessageHandler);\n } catch (error) {\n console.error('[WorkerClient] Failed to register ServiceWorker:', error);\n throw error;\n }\n } else {\n throw new Error('Neither SharedWorker nor ServiceWorker is supported');\n }\n }\n\n // Low-level request that expects a reply via MessageChannel\n public async request<T = any>(type: string, payload?: Record<string, unknown>, timeoutMs = 5000): Promise<T> {\n // If using shared worker\n if (this.workerType === 'shared' && this.sharedWorkerPort) {\n return new Promise<T>((resolve, reject) => {\n const mc = new MessageChannel();\n const timer = setTimeout(() => {\n mc.port1.onmessage = null;\n reject(new Error('Request timeout'));\n }, timeoutMs);\n\n mc.port1.onmessage = (ev: MessageEvent) => {\n clearTimeout(timer);\n if (ev.data && ev.data.success) {\n resolve(ev.data as T);\n } else if (ev.data && ev.data.success === false) {\n reject(new Error(ev.data.error || 'Worker error'));\n } else {\n resolve(ev.data as T);\n }\n };\n\n try {\n const port = this.sharedWorkerPort;\n if (!port) {\n clearTimeout(timer);\n return reject(new Error('SharedWorker port not available'));\n }\n port.postMessage({ type, ...(payload || {}) }, [mc.port2]);\n } catch (e) {\n clearTimeout(timer);\n reject(e instanceof Error ? e : new Error(String(e)));\n }\n });\n }\n\n // If using service worker\n if (this.workerType === 'service' && this.serviceWorkerRegistration) {\n // Ensure service worker active\n const reg = this.serviceWorkerRegistration;\n if (!reg) throw new Error('Service worker registration missing');\n if (!reg.active) {\n await navigator.serviceWorker.ready;\n if (!reg.active) {\n throw new Error('Service worker not active');\n }\n }\n\n return new Promise<T>((resolve, reject) => {\n const mc = new MessageChannel();\n const timer = setTimeout(() => {\n mc.port1.onmessage = null;\n reject(new Error('Request timeout'));\n }, timeoutMs);\n\n mc.port1.onmessage = (ev: MessageEvent) => {\n clearTimeout(timer);\n if (ev.data && ev.data.success) {\n resolve(ev.data as T);\n } else if (ev.data && ev.data.success === false) {\n reject(new Error(ev.data.error || 'Worker error'));\n } else {\n resolve(ev.data as T);\n }\n };\n\n try {\n const active = reg.active;\n if (!active) {\n clearTimeout(timer);\n return reject(new Error('Service worker active instance not available'));\n }\n active.postMessage({ type, ...(payload || {}) }, [mc.port2]);\n } catch (e) {\n clearTimeout(timer);\n reject(e instanceof Error ? e : new Error(String(e)));\n }\n });\n }\n\n // No worker available\n throw new Error('No worker registered');\n }\n\n // Fire-and-forget postMessage (no response expected)\n public async post(type: string, payload?: Record<string, unknown>): Promise<void> {\n if (this.workerType === 'shared' && this.sharedWorkerPort) {\n try {\n this.sharedWorkerPort.postMessage({ type, ...(payload || {}) });\n } catch (e) {\n console.error('[WorkerClient] Failed to post to SharedWorker:', e);\n }\n return;\n }\n\n if (this.workerType === 'service' && this.serviceWorkerRegistration?.active) {\n try {\n this.serviceWorkerRegistration.active.postMessage({ type, ...(payload || {}) });\n } catch (e) {\n console.error('[WorkerClient] Failed to post to ServiceWorker (active):', e);\n }\n return;\n }\n\n if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {\n try {\n navigator.serviceWorker.controller.postMessage({ type, ...(payload || {}) });\n } catch (e) {\n console.error('[WorkerClient] Failed to post to ServiceWorker.controller:', e);\n }\n return;\n }\n\n // If no worker yet, queue token if SET_AUTH_TOKEN\n if (type === 'SET_AUTH_TOKEN' && payload) {\n const token = (payload as any)['token'];\n if (typeof token === 'string') this.pendingAuthToken = token;\n }\n }\n\n private sendAuthTokenToServiceWorker(token: string): void {\n if (this.serviceWorkerRegistration?.active) {\n try {\n this.serviceWorkerRegistration.active.postMessage({ type: 'SET_AUTH_TOKEN', token });\n } catch (e) {\n console.error('[WorkerClient] Failed to send auth token to ServiceWorker:', e);\n }\n } else if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {\n try {\n navigator.serviceWorker.controller.postMessage({ type: 'SET_AUTH_TOKEN', token });\n } catch (e) {\n console.error('[WorkerClient] Failed to send auth token to ServiceWorker.controller:', e);\n }\n } else {\n // keep as pending\n this.pendingAuthToken = token;\n }\n }\n\n // Subscription API for consumers to listen for connection status updates\n public onConnectionStatus(cb: (connected: boolean) => void): void {\n this.connectionStatusCallbacks.add(cb);\n }\n\n public offConnectionStatus(cb: (connected: boolean) => void): void {\n this.connectionStatusCallbacks.delete(cb);\n }\n\n public async getConnectionStatus(): Promise<boolean> {\n try {\n const res = await this.request('GET_CONNECTION_STATUS', undefined, 2000);\n if (res && typeof res === 'object' && 'connected' in (res as any)) return !!(res as any).connected;\n return !!(res as any).connected;\n } catch {\n return false;\n }\n }\n\n public setAuthToken(token: string): void {\n this.pendingAuthToken = token;\n // Try to send immediately if possible\n if (this.workerType === 'shared' && this.sharedWorkerPort) {\n try {\n this.sharedWorkerPort.postMessage({ type: 'SET_AUTH_TOKEN', token });\n this.pendingAuthToken = null;\n } catch (e) {\n console.error('[WorkerClient] Failed to set auth token on SharedWorker:', e);\n }\n } else if (this.workerType === 'service') {\n this.sendAuthTokenToServiceWorker(token);\n this.pendingAuthToken = null;\n } else {\n // queued and will be sent when init finishes\n }\n }\n}\n"],"names":["WorkerClient","registration","err","event","resolve","reject","resolved","timeout","p","ev","data","portAfterInit","e","connected","cb","error","existingRegistration","reg","type","payload","timeoutMs","mc","timer","port","active","token","res"],"mappings":"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"}
|