@kbve/droid 0.0.2 → 0.0.4
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 +17 -7
- package/comlink.js +253 -0
- package/package.json +8 -4
- package/src/index.ts +18 -0
- package/src/lib/droid.ts +5 -3
- package/src/lib/mod/mod-manager.ts +3 -2
- package/src/lib/workers/main.ts +256 -81
- package/workers/main.js +1091 -0
- package/assets/canvas-worker-DbsoY2Xv.js +0 -5
- package/assets/db-worker-CjXS52DQ.js +0 -14
- package/assets/ws-worker-FssAQgaD.js +0 -5
- package/droid.cjs.js +0 -1
- package/droid.es.js +0 -14
- package/index-DSyyyiLP.js +0 -3034
- package/main-BYzQVPCs.js +0 -1455
package/README.md
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: droid
|
|
3
|
-
description:
|
|
4
|
-
---
|
|
5
1
|
# Droid
|
|
6
2
|
|
|
7
|
-
<
|
|
8
|
-
src="https://kbve.com/assets/images/brand/letter_logo.svg">
|
|
3
|
+
<a href="https://kbve.com" style="float: right;"><img width="150" height="50" title="KBVE logo" src="https://kbve.com/assets/images/brand/letter_logo.svg" /></a>
|
|
9
4
|
|
|
10
5
|
Droid is a lightweight manager for service workers, shared workers, and web workers in modern JavaScript and TypeScript applications.
|
|
11
6
|
It simplifies the setup, communication, and lifecycle management of workers, making it easier to offload heavy computations, enable background tasks, and improve the responsiveness of your web apps.
|
|
@@ -13,6 +8,9 @@ With Droid, you can quickly integrate multi-threaded capabilities into your proj
|
|
|
13
8
|
|
|
14
9
|
Droid provides a unified API to register, manage, and communicate with different types of web workers. Whether you are using service workers for offline support, shared workers for cross-tab communication, or web workers for parallel processing, Droid abstracts away the boilerplate and browser inconsistencies. It is designed to be framework-agnostic, making it suitable for use in vanilla JavaScript projects as well as with popular frameworks like React, Vue, or Angular. The library aims to help developers harness the power of multi-threading in the browser with simple, consistent patterns and robust error handling.
|
|
15
10
|
|
|
11
|
+
<a href="https://kbve.com/application/javascript/#droid" style="float: right;"><img width="250" height="250" title="Droid WebP Logo" src="https://kbve.com/assets/images/brand/npm/droid.webp" /></a>
|
|
12
|
+
|
|
13
|
+
|
|
16
14
|
### Dependencies
|
|
17
15
|
|
|
18
16
|
Droid requires a few runtime dependencies to provide its full feature set:
|
|
@@ -28,6 +26,18 @@ These dependencies are automatically installed when you add Droid to your projec
|
|
|
28
26
|
- Optional: TypeScript for type safety and better development experience
|
|
29
27
|
- Optional: Framework-specific packages if integrating with React, Vue, Angular, etc.
|
|
30
28
|
|
|
29
|
+
### Support
|
|
30
|
+
|
|
31
|
+
For questions, help, or to connect with the community, support can be reached via our [Discord server](https://kbve.com/discord/). Click the badge below to join and get assistance from the KBVE team and other users.
|
|
32
|
+
|
|
33
|
+
[](https://kbve.com/discord/)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Examples
|
|
37
|
+
|
|
38
|
+
[Discord.SH](https://discord.sh/)
|
|
39
|
+
|
|
40
|
+
|
|
31
41
|
### Chores
|
|
32
42
|
|
|
33
|
-
Preparing to release next batch.
|
|
43
|
+
Preparing to release next batch, trying to resolving the CDN issue, which might still be broken.
|
package/comlink.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2019 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
const M = Symbol("Comlink.proxy"), z = Symbol("Comlink.endpoint"), N = Symbol("Comlink.releaseProxy"), x = Symbol("Comlink.finalizer"), h = Symbol("Comlink.thrown"), S = (e) => typeof e == "object" && e !== null || typeof e == "function", H = {
|
|
7
|
+
canHandle: (e) => S(e) && e[M],
|
|
8
|
+
serialize(e) {
|
|
9
|
+
const { port1: t, port2: r } = new MessageChannel();
|
|
10
|
+
return R(e, t), [r, [r]];
|
|
11
|
+
},
|
|
12
|
+
deserialize(e) {
|
|
13
|
+
return e.start(), I(e);
|
|
14
|
+
}
|
|
15
|
+
}, L = {
|
|
16
|
+
canHandle: (e) => S(e) && h in e,
|
|
17
|
+
serialize({ value: e }) {
|
|
18
|
+
let t;
|
|
19
|
+
return e instanceof Error ? t = {
|
|
20
|
+
isError: !0,
|
|
21
|
+
value: {
|
|
22
|
+
message: e.message,
|
|
23
|
+
name: e.name,
|
|
24
|
+
stack: e.stack
|
|
25
|
+
}
|
|
26
|
+
} : t = { isError: !1, value: e }, [t, []];
|
|
27
|
+
},
|
|
28
|
+
deserialize(e) {
|
|
29
|
+
throw e.isError ? Object.assign(new Error(e.value.message), e.value) : e.value;
|
|
30
|
+
}
|
|
31
|
+
}, A = /* @__PURE__ */ new Map([
|
|
32
|
+
["proxy", H],
|
|
33
|
+
["throw", L]
|
|
34
|
+
]);
|
|
35
|
+
function V(e, t) {
|
|
36
|
+
for (const r of e)
|
|
37
|
+
if (t === r || r === "*" || r instanceof RegExp && r.test(t))
|
|
38
|
+
return !0;
|
|
39
|
+
return !1;
|
|
40
|
+
}
|
|
41
|
+
function R(e, t = globalThis, r = ["*"]) {
|
|
42
|
+
t.addEventListener("message", function g(n) {
|
|
43
|
+
if (!n || !n.data)
|
|
44
|
+
return;
|
|
45
|
+
if (!V(r, n.origin)) {
|
|
46
|
+
console.warn(`Invalid origin '${n.origin}' for comlink proxy`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const { id: a, type: f, path: c } = Object.assign({ path: [] }, n.data), l = (n.data.argumentList || []).map(y);
|
|
50
|
+
let s;
|
|
51
|
+
try {
|
|
52
|
+
const o = c.slice(0, -1).reduce((i, d) => i[d], e), u = c.reduce((i, d) => i[d], e);
|
|
53
|
+
switch (f) {
|
|
54
|
+
case "GET":
|
|
55
|
+
s = u;
|
|
56
|
+
break;
|
|
57
|
+
case "SET":
|
|
58
|
+
o[c.slice(-1)[0]] = y(n.data.value), s = !0;
|
|
59
|
+
break;
|
|
60
|
+
case "APPLY":
|
|
61
|
+
s = u.apply(o, l);
|
|
62
|
+
break;
|
|
63
|
+
case "CONSTRUCT":
|
|
64
|
+
{
|
|
65
|
+
const i = new u(...l);
|
|
66
|
+
s = U(i);
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case "ENDPOINT":
|
|
70
|
+
{
|
|
71
|
+
const { port1: i, port2: d } = new MessageChannel();
|
|
72
|
+
R(e, d), s = F(i, [i]);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
case "RELEASE":
|
|
76
|
+
s = void 0;
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
} catch (o) {
|
|
82
|
+
s = { value: o, [h]: 0 };
|
|
83
|
+
}
|
|
84
|
+
Promise.resolve(s).catch((o) => ({ value: o, [h]: 0 })).then((o) => {
|
|
85
|
+
const [u, i] = p(o);
|
|
86
|
+
t.postMessage(Object.assign(Object.assign({}, u), { id: a }), i), f === "RELEASE" && (t.removeEventListener("message", g), T(t), x in e && typeof e[x] == "function" && e[x]());
|
|
87
|
+
}).catch((o) => {
|
|
88
|
+
const [u, i] = p({
|
|
89
|
+
value: new TypeError("Unserializable return value"),
|
|
90
|
+
[h]: 0
|
|
91
|
+
});
|
|
92
|
+
t.postMessage(Object.assign(Object.assign({}, u), { id: a }), i);
|
|
93
|
+
});
|
|
94
|
+
}), t.start && t.start();
|
|
95
|
+
}
|
|
96
|
+
function _(e) {
|
|
97
|
+
return e.constructor.name === "MessagePort";
|
|
98
|
+
}
|
|
99
|
+
function T(e) {
|
|
100
|
+
_(e) && e.close();
|
|
101
|
+
}
|
|
102
|
+
function I(e, t) {
|
|
103
|
+
const r = /* @__PURE__ */ new Map();
|
|
104
|
+
return e.addEventListener("message", function(n) {
|
|
105
|
+
const { data: a } = n;
|
|
106
|
+
if (!a || !a.id)
|
|
107
|
+
return;
|
|
108
|
+
const f = r.get(a.id);
|
|
109
|
+
if (f)
|
|
110
|
+
try {
|
|
111
|
+
f(a);
|
|
112
|
+
} finally {
|
|
113
|
+
r.delete(a.id);
|
|
114
|
+
}
|
|
115
|
+
}), P(e, r, [], t);
|
|
116
|
+
}
|
|
117
|
+
function w(e) {
|
|
118
|
+
if (e)
|
|
119
|
+
throw new Error("Proxy has been released and is not useable");
|
|
120
|
+
}
|
|
121
|
+
function C(e) {
|
|
122
|
+
return m(e, /* @__PURE__ */ new Map(), {
|
|
123
|
+
type: "RELEASE"
|
|
124
|
+
}).then(() => {
|
|
125
|
+
T(e);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const E = /* @__PURE__ */ new WeakMap(), b = "FinalizationRegistry" in globalThis && new FinalizationRegistry((e) => {
|
|
129
|
+
const t = (E.get(e) || 0) - 1;
|
|
130
|
+
E.set(e, t), t === 0 && C(e);
|
|
131
|
+
});
|
|
132
|
+
function W(e, t) {
|
|
133
|
+
const r = (E.get(t) || 0) + 1;
|
|
134
|
+
E.set(t, r), b && b.register(e, t, e);
|
|
135
|
+
}
|
|
136
|
+
function j(e) {
|
|
137
|
+
b && b.unregister(e);
|
|
138
|
+
}
|
|
139
|
+
function P(e, t, r = [], g = function() {
|
|
140
|
+
}) {
|
|
141
|
+
let n = !1;
|
|
142
|
+
const a = new Proxy(g, {
|
|
143
|
+
get(f, c) {
|
|
144
|
+
if (w(n), c === N)
|
|
145
|
+
return () => {
|
|
146
|
+
j(a), C(e), t.clear(), n = !0;
|
|
147
|
+
};
|
|
148
|
+
if (c === "then") {
|
|
149
|
+
if (r.length === 0)
|
|
150
|
+
return { then: () => a };
|
|
151
|
+
const l = m(e, t, {
|
|
152
|
+
type: "GET",
|
|
153
|
+
path: r.map((s) => s.toString())
|
|
154
|
+
}).then(y);
|
|
155
|
+
return l.then.bind(l);
|
|
156
|
+
}
|
|
157
|
+
return P(e, t, [...r, c]);
|
|
158
|
+
},
|
|
159
|
+
set(f, c, l) {
|
|
160
|
+
w(n);
|
|
161
|
+
const [s, o] = p(l);
|
|
162
|
+
return m(e, t, {
|
|
163
|
+
type: "SET",
|
|
164
|
+
path: [...r, c].map((u) => u.toString()),
|
|
165
|
+
value: s
|
|
166
|
+
}, o).then(y);
|
|
167
|
+
},
|
|
168
|
+
apply(f, c, l) {
|
|
169
|
+
w(n);
|
|
170
|
+
const s = r[r.length - 1];
|
|
171
|
+
if (s === z)
|
|
172
|
+
return m(e, t, {
|
|
173
|
+
type: "ENDPOINT"
|
|
174
|
+
}).then(y);
|
|
175
|
+
if (s === "bind")
|
|
176
|
+
return P(e, t, r.slice(0, -1));
|
|
177
|
+
const [o, u] = k(l);
|
|
178
|
+
return m(e, t, {
|
|
179
|
+
type: "APPLY",
|
|
180
|
+
path: r.map((i) => i.toString()),
|
|
181
|
+
argumentList: o
|
|
182
|
+
}, u).then(y);
|
|
183
|
+
},
|
|
184
|
+
construct(f, c) {
|
|
185
|
+
w(n);
|
|
186
|
+
const [l, s] = k(c);
|
|
187
|
+
return m(e, t, {
|
|
188
|
+
type: "CONSTRUCT",
|
|
189
|
+
path: r.map((o) => o.toString()),
|
|
190
|
+
argumentList: l
|
|
191
|
+
}, s).then(y);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return W(a, e), a;
|
|
195
|
+
}
|
|
196
|
+
function D(e) {
|
|
197
|
+
return Array.prototype.concat.apply([], e);
|
|
198
|
+
}
|
|
199
|
+
function k(e) {
|
|
200
|
+
const t = e.map(p);
|
|
201
|
+
return [t.map((r) => r[0]), D(t.map((r) => r[1]))];
|
|
202
|
+
}
|
|
203
|
+
const O = /* @__PURE__ */ new WeakMap();
|
|
204
|
+
function F(e, t) {
|
|
205
|
+
return O.set(e, t), e;
|
|
206
|
+
}
|
|
207
|
+
function U(e) {
|
|
208
|
+
return Object.assign(e, { [M]: !0 });
|
|
209
|
+
}
|
|
210
|
+
function p(e) {
|
|
211
|
+
for (const [t, r] of A)
|
|
212
|
+
if (r.canHandle(e)) {
|
|
213
|
+
const [g, n] = r.serialize(e);
|
|
214
|
+
return [
|
|
215
|
+
{
|
|
216
|
+
type: "HANDLER",
|
|
217
|
+
name: t,
|
|
218
|
+
value: g
|
|
219
|
+
},
|
|
220
|
+
n
|
|
221
|
+
];
|
|
222
|
+
}
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
type: "RAW",
|
|
226
|
+
value: e
|
|
227
|
+
},
|
|
228
|
+
O.get(e) || []
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
function y(e) {
|
|
232
|
+
switch (e.type) {
|
|
233
|
+
case "HANDLER":
|
|
234
|
+
return A.get(e.name).deserialize(e.value);
|
|
235
|
+
case "RAW":
|
|
236
|
+
return e.value;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function m(e, t, r, g) {
|
|
240
|
+
return new Promise((n) => {
|
|
241
|
+
const a = G();
|
|
242
|
+
t.set(a, n), e.start && e.start(), e.postMessage(Object.assign({ id: a }, r), g);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
function G() {
|
|
246
|
+
return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
|
|
247
|
+
}
|
|
248
|
+
export {
|
|
249
|
+
R as e,
|
|
250
|
+
U as p,
|
|
251
|
+
F as t,
|
|
252
|
+
I as w
|
|
253
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kbve/droid",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A manager for web, shared and service workers, aimming to make it as modular and upgradable.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"workers",
|
|
@@ -27,11 +27,14 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
|
+
"workers/",
|
|
30
31
|
"assets/",
|
|
31
32
|
"src/",
|
|
33
|
+
"comlink*.js",
|
|
34
|
+
"reference-*.js",
|
|
32
35
|
"droid.*.js",
|
|
33
|
-
"main
|
|
34
|
-
"index
|
|
36
|
+
"main.js",
|
|
37
|
+
"index.*.js",
|
|
35
38
|
"index.d.ts",
|
|
36
39
|
"*.md",
|
|
37
40
|
"LICENSE",
|
|
@@ -42,7 +45,8 @@
|
|
|
42
45
|
"comlink": "^4.3.1",
|
|
43
46
|
"@nanostores/persistent": "^0.7.1",
|
|
44
47
|
"dexie": "^3.2.4",
|
|
45
|
-
"zod": "^3.22.4"
|
|
48
|
+
"zod": "^3.22.4",
|
|
49
|
+
"flatbuffers": "^25.2.10"
|
|
46
50
|
},
|
|
47
51
|
"publishConfig": {
|
|
48
52
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
export * from './lib/droid';
|
|
2
2
|
export * from './lib/types/bento';
|
|
3
3
|
export * from './lib/mod/mod-urls';
|
|
4
|
+
|
|
5
|
+
export const workerURLs = {
|
|
6
|
+
canvasWorker: new URL(
|
|
7
|
+
'./lib/workers/canvas-worker.js',
|
|
8
|
+
import.meta.url,
|
|
9
|
+
),
|
|
10
|
+
dbWorker: new URL('./lib/workers/db-worker.js', import.meta.url),
|
|
11
|
+
wsWorker: new URL('./lib/workers/ws-worker.js', import.meta.url),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const workerStrings = {
|
|
15
|
+
canvasWorker: new URL(
|
|
16
|
+
'./lib/workers/canvas-worker.js',
|
|
17
|
+
import.meta.url,
|
|
18
|
+
).toString(),
|
|
19
|
+
dbWorker: new URL('./lib/workers/db-worker.js', import.meta.url).toString(),
|
|
20
|
+
wsWorker: new URL('./lib/workers/ws-worker.js', import.meta.url).toString(),
|
|
21
|
+
};
|
package/src/lib/droid.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export async function droid(opts?: {
|
|
2
|
-
|
|
3
|
-
await main
|
|
1
|
+
export async function droid(opts?: { workerURLs?: Record<string, string> }): Promise<{ initialized: boolean }> {
|
|
2
|
+
console.log('[DROID]: droid<T>');
|
|
3
|
+
const { main } = await import('./workers/main.js');
|
|
4
|
+
await main({ workerURLs: opts?.workerURLs });
|
|
5
|
+
console.log('[DROID]: droid<T> => await WorkerURLs');
|
|
4
6
|
return { initialized: true };
|
|
5
7
|
}
|
|
@@ -5,13 +5,14 @@ import type { KBVEGlobal } from '../../types';
|
|
|
5
5
|
|
|
6
6
|
let _modManager: ModManager | null = null;
|
|
7
7
|
|
|
8
|
-
export async function getModManager(): Promise<ModManager> {
|
|
8
|
+
export async function getModManager(modWorkerResolver?: (url: string) => string): Promise<ModManager> {
|
|
9
9
|
if (_modManager) return _modManager;
|
|
10
10
|
|
|
11
11
|
const registry: Record<string, ModHandle> = {};
|
|
12
12
|
|
|
13
13
|
async function load(url: string): Promise<ModHandle> {
|
|
14
|
-
const
|
|
14
|
+
const resolvedURL = modWorkerResolver?.(url) ?? url;
|
|
15
|
+
const worker = new Worker(resolvedURL, { type: 'module' });
|
|
15
16
|
const instance = wrap<BaseModAPI>(worker);
|
|
16
17
|
|
|
17
18
|
const meta: ModMeta = await instance.getMeta?.() ?? {
|