@lvce-editor/cache-worker 0.0.2
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 +48 -0
- package/cacheWorkerMain.js +809 -0
- package/index.js +1 -0
- package/package.json +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Cache Worker
|
|
2
|
+
|
|
3
|
+
Browser storage APIs for LVCE workers. `@lvce-editor/cache-worker` provides Cache Storage, IndexedDB, and Origin Private File System (OPFS) operations through a worker RPC command map.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Arguments | Result |
|
|
8
|
+
| ------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `Cache.getCacheStorageItem` | `(request, cacheName = 'lvce-cache')` | Structured-cloneable `{ body: ArrayBuffer, headers: [string, string][], status, statusText }` or `null` when missing |
|
|
10
|
+
| `Cache.setCacheStorageItem` | `(request, value, cacheName = 'lvce-cache')` | `undefined`; stores a body accepted by the browser `Response` constructor |
|
|
11
|
+
| `Cache.removeCacheStorageItem` | `(request, cacheName = 'lvce-cache')` | `boolean` indicating whether an item was removed |
|
|
12
|
+
| `IndexedDb.addIndexedDbFileHandle` | `(key, handle, databaseName = 'lvce-cache-worker')` | `undefined` after the write transaction commits |
|
|
13
|
+
| `IndexedDb.getIndexedDbFileHandle` | `(key, databaseName = 'lvce-cache-worker')` | Stored handle or `null` when missing through worker RPC |
|
|
14
|
+
| `IndexedDb.removeIndexedDbFileHandle` | `(key, databaseName = 'lvce-cache-worker')` | `undefined` after the delete transaction commits; deleting a missing key is a no-op |
|
|
15
|
+
| `Opfs.readFile` | `(name)` | UTF-8 text; rejects when the file does not exist |
|
|
16
|
+
| `Opfs.writeFile` | `(name, content)` | `undefined` after the writable is closed |
|
|
17
|
+
| `Opfs.removeFile` | `(name)` | `undefined`; rejects when the file does not exist |
|
|
18
|
+
|
|
19
|
+
Missing browser APIs reject with an error that names the unavailable capability. Browser storage quota, security, invalid key, structured-clone, and transaction errors are propagated to the caller. File handles must be structured-cloneable by the browser and writable in the current origin. OPFS filenames are single path components; directory traversal is not supported.
|
|
20
|
+
|
|
21
|
+
Resolve the worker entry URL with `getCacheWorkerUrl` and connect it using `@lvce-editor/rpc`'s `ModuleWorkerRpcParent`:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import { ModuleWorkerRpcParent } from '@lvce-editor/rpc'
|
|
25
|
+
import { getCacheWorkerUrl } from '@lvce-editor/cache-worker'
|
|
26
|
+
|
|
27
|
+
const rpc = await ModuleWorkerRpcParent.create({
|
|
28
|
+
commandMap: {},
|
|
29
|
+
url: getCacheWorkerUrl().href,
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The worker registers the commands in `src/parts/CommandMap/CommandMap.js`. `Response` values are converted to structured-cloneable data before crossing RPC; callers can create a new `Response` from the returned body and metadata.
|
|
34
|
+
|
|
35
|
+
## Development
|
|
36
|
+
|
|
37
|
+
This repository uses npm workspaces and a root `package-lock.json`.
|
|
38
|
+
|
|
39
|
+
The cross-browser suite checks Cache Storage and OPFS through worker RPC in Chromium and Firefox. IndexedDB file-handle restoration is covered in Firefox; Chromium checks general structured-clone persistence.
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npm ci
|
|
43
|
+
npm test
|
|
44
|
+
npm run build
|
|
45
|
+
npm run e2e
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The browser suite runs against Chromium and Firefox. Install both with `npx playwright install --with-deps chromium firefox`.
|
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// node_modules/@lvce-editor/ipc/dist/index.js
|
|
8
|
+
var isMessagePort = (value) => {
|
|
9
|
+
return value && value instanceof MessagePort;
|
|
10
|
+
};
|
|
11
|
+
var isMessagePortMain = (value) => {
|
|
12
|
+
return value && value.constructor && value.constructor.name === "MessagePortMain";
|
|
13
|
+
};
|
|
14
|
+
var isOffscreenCanvas = (value) => {
|
|
15
|
+
return typeof OffscreenCanvas !== "undefined" && value instanceof OffscreenCanvas;
|
|
16
|
+
};
|
|
17
|
+
var isInstanceOf = (value, constructorName) => {
|
|
18
|
+
return value?.constructor?.name === constructorName;
|
|
19
|
+
};
|
|
20
|
+
var isSocket = (value) => {
|
|
21
|
+
return isInstanceOf(value, "Socket");
|
|
22
|
+
};
|
|
23
|
+
var transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
|
|
24
|
+
var isTransferrable = (value) => {
|
|
25
|
+
for (const fn of transferrables) {
|
|
26
|
+
if (fn(value)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
};
|
|
32
|
+
var walkValue = (value, transferrables2, isTransferrable2) => {
|
|
33
|
+
if (!value) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (isTransferrable2(value)) {
|
|
37
|
+
transferrables2.push(value);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(value)) {
|
|
41
|
+
for (const item of value) {
|
|
42
|
+
walkValue(item, transferrables2, isTransferrable2);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === "object") {
|
|
47
|
+
for (const property of Object.values(value)) {
|
|
48
|
+
walkValue(property, transferrables2, isTransferrable2);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var getTransferrables = (value) => {
|
|
53
|
+
const transferrables2 = [];
|
|
54
|
+
walkValue(value, transferrables2, isTransferrable);
|
|
55
|
+
return transferrables2;
|
|
56
|
+
};
|
|
57
|
+
var attachEvents = (that) => {
|
|
58
|
+
const handleMessage2 = (...args) => {
|
|
59
|
+
const data = that.getData(...args);
|
|
60
|
+
that.dispatchEvent(new MessageEvent("message", {
|
|
61
|
+
data
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
that.onMessage(handleMessage2);
|
|
65
|
+
const handleClose = (event) => {
|
|
66
|
+
that.dispatchEvent(new Event("close"));
|
|
67
|
+
};
|
|
68
|
+
that.onClose(handleClose);
|
|
69
|
+
};
|
|
70
|
+
var Ipc = class extends EventTarget {
|
|
71
|
+
constructor(rawIpc) {
|
|
72
|
+
super();
|
|
73
|
+
this._rawIpc = rawIpc;
|
|
74
|
+
attachEvents(this);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var readyMessage = "ready";
|
|
78
|
+
var getData$2 = (event) => {
|
|
79
|
+
return event.data;
|
|
80
|
+
};
|
|
81
|
+
var listen$7 = () => {
|
|
82
|
+
if (typeof WorkerGlobalScope === "undefined") {
|
|
83
|
+
throw new TypeError("module is not in web worker scope");
|
|
84
|
+
}
|
|
85
|
+
return globalThis;
|
|
86
|
+
};
|
|
87
|
+
var signal$8 = (global) => {
|
|
88
|
+
global.postMessage(readyMessage);
|
|
89
|
+
};
|
|
90
|
+
var IpcChildWithModuleWorker = class extends Ipc {
|
|
91
|
+
getData(event) {
|
|
92
|
+
return getData$2(event);
|
|
93
|
+
}
|
|
94
|
+
send(message) {
|
|
95
|
+
this._rawIpc.postMessage(message);
|
|
96
|
+
}
|
|
97
|
+
sendAndTransfer(message) {
|
|
98
|
+
const transfer = getTransferrables(message);
|
|
99
|
+
this._rawIpc.postMessage(message, transfer);
|
|
100
|
+
}
|
|
101
|
+
dispose() {
|
|
102
|
+
}
|
|
103
|
+
onClose(callback) {
|
|
104
|
+
}
|
|
105
|
+
onMessage(callback) {
|
|
106
|
+
this._rawIpc.addEventListener("message", callback);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var wrap$f = (global) => {
|
|
110
|
+
return new IpcChildWithModuleWorker(global);
|
|
111
|
+
};
|
|
112
|
+
var IpcChildWithModuleWorker$1 = {
|
|
113
|
+
__proto__: null,
|
|
114
|
+
listen: listen$7,
|
|
115
|
+
signal: signal$8,
|
|
116
|
+
wrap: wrap$f
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// node_modules/@lvce-editor/command/dist/index.js
|
|
120
|
+
var CommandNotFoundError = class extends Error {
|
|
121
|
+
constructor(command) {
|
|
122
|
+
super(`Command not found ${command}`);
|
|
123
|
+
this.name = "CommandNotFoundError";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var commands = /* @__PURE__ */ Object.create(null);
|
|
127
|
+
var register = (commandMap2) => {
|
|
128
|
+
Object.assign(commands, commandMap2);
|
|
129
|
+
};
|
|
130
|
+
var getCommand = (key) => {
|
|
131
|
+
return commands[key];
|
|
132
|
+
};
|
|
133
|
+
var execute = (command, ...args) => {
|
|
134
|
+
const fn = getCommand(command);
|
|
135
|
+
if (!fn) {
|
|
136
|
+
throw new CommandNotFoundError(command);
|
|
137
|
+
}
|
|
138
|
+
return fn(...args);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// node_modules/@lvce-editor/json-rpc/dist/index.js
|
|
142
|
+
var Two = "2.0";
|
|
143
|
+
var callbacks = /* @__PURE__ */ Object.create(null);
|
|
144
|
+
var get = (id2) => {
|
|
145
|
+
return callbacks[id2];
|
|
146
|
+
};
|
|
147
|
+
var remove = (id2) => {
|
|
148
|
+
delete callbacks[id2];
|
|
149
|
+
};
|
|
150
|
+
var JsonRpcError = class extends Error {
|
|
151
|
+
constructor(message) {
|
|
152
|
+
super(message);
|
|
153
|
+
this.name = "JsonRpcError";
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
var NewLine = "\n";
|
|
157
|
+
var DomException = "DOMException";
|
|
158
|
+
var ReferenceError$1 = "ReferenceError";
|
|
159
|
+
var SyntaxError$1 = "SyntaxError";
|
|
160
|
+
var TypeError$1 = "TypeError";
|
|
161
|
+
var getErrorConstructor = (message, type) => {
|
|
162
|
+
if (type) {
|
|
163
|
+
switch (type) {
|
|
164
|
+
case DomException:
|
|
165
|
+
return DOMException;
|
|
166
|
+
case ReferenceError$1:
|
|
167
|
+
return ReferenceError;
|
|
168
|
+
case SyntaxError$1:
|
|
169
|
+
return SyntaxError;
|
|
170
|
+
case TypeError$1:
|
|
171
|
+
return TypeError;
|
|
172
|
+
default:
|
|
173
|
+
return Error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (message.startsWith("TypeError: ")) {
|
|
177
|
+
return TypeError;
|
|
178
|
+
}
|
|
179
|
+
if (message.startsWith("SyntaxError: ")) {
|
|
180
|
+
return SyntaxError;
|
|
181
|
+
}
|
|
182
|
+
if (message.startsWith("ReferenceError: ")) {
|
|
183
|
+
return ReferenceError;
|
|
184
|
+
}
|
|
185
|
+
return Error;
|
|
186
|
+
};
|
|
187
|
+
var constructError = (message, type, name) => {
|
|
188
|
+
const ErrorConstructor = getErrorConstructor(message, type);
|
|
189
|
+
if (ErrorConstructor === DOMException && name) {
|
|
190
|
+
return new ErrorConstructor(message, name);
|
|
191
|
+
}
|
|
192
|
+
if (ErrorConstructor === Error) {
|
|
193
|
+
const error = new Error(message);
|
|
194
|
+
if (name && name !== "VError") {
|
|
195
|
+
Object.defineProperty(error, "name", {
|
|
196
|
+
configurable: true,
|
|
197
|
+
value: name
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return error;
|
|
201
|
+
}
|
|
202
|
+
return new ErrorConstructor(message);
|
|
203
|
+
};
|
|
204
|
+
var joinLines = (lines) => {
|
|
205
|
+
return lines.join(NewLine);
|
|
206
|
+
};
|
|
207
|
+
var splitLines = (lines) => {
|
|
208
|
+
return lines.split(NewLine);
|
|
209
|
+
};
|
|
210
|
+
var getCurrentStack = () => {
|
|
211
|
+
const stackLinesToSkip = 3;
|
|
212
|
+
const currentStack = joinLines(splitLines(new Error().stack || "").slice(stackLinesToSkip));
|
|
213
|
+
return currentStack;
|
|
214
|
+
};
|
|
215
|
+
var getNewLineIndex = (string2, startIndex) => {
|
|
216
|
+
{
|
|
217
|
+
return string2.indexOf(NewLine);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var getParentStack = (error) => {
|
|
221
|
+
let parentStack = error.stack || error.data || error.message || "";
|
|
222
|
+
if (parentStack.startsWith(" at")) {
|
|
223
|
+
parentStack = error.message + NewLine + parentStack;
|
|
224
|
+
}
|
|
225
|
+
return parentStack;
|
|
226
|
+
};
|
|
227
|
+
var MethodNotFound = -32601;
|
|
228
|
+
var Custom = -32001;
|
|
229
|
+
var setStack = (error, stack) => {
|
|
230
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, "stack");
|
|
231
|
+
if (descriptor) {
|
|
232
|
+
if (!descriptor.configurable && !descriptor.writable) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (!descriptor.configurable && descriptor.writable) {
|
|
236
|
+
error.stack = stack;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
Object.defineProperty(error, "stack", {
|
|
241
|
+
configurable: true,
|
|
242
|
+
value: stack,
|
|
243
|
+
writable: true
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
var restoreExistingError = (error, currentStack) => {
|
|
247
|
+
if (typeof error.stack === "string") {
|
|
248
|
+
setStack(error, `${error.stack}${NewLine}${currentStack}`);
|
|
249
|
+
}
|
|
250
|
+
return error;
|
|
251
|
+
};
|
|
252
|
+
var restoreMethodNotFoundError = (error, currentStack) => {
|
|
253
|
+
const restoredError = new JsonRpcError(error.message);
|
|
254
|
+
Object.assign(restoredError, {
|
|
255
|
+
code: error.code
|
|
256
|
+
});
|
|
257
|
+
const parentStack = getParentStack(error);
|
|
258
|
+
setStack(restoredError, `${parentStack}${NewLine}${currentStack}`);
|
|
259
|
+
return restoredError;
|
|
260
|
+
};
|
|
261
|
+
var restoreStackFromData = (restoredError, error, currentStack) => {
|
|
262
|
+
if (error.data.stack && error.data.type && error.message) {
|
|
263
|
+
setStack(restoredError, `${error.data.type}: ${error.message}${NewLine}${error.data.stack}${NewLine}${currentStack}`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (error.data.stack) {
|
|
267
|
+
setStack(restoredError, error.data.stack);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
var applyDataProperties = (restoredError, error) => {
|
|
271
|
+
restoreStackFromData(restoredError, error, getCurrentStack());
|
|
272
|
+
if (error.data.codeFrame) {
|
|
273
|
+
restoredError.codeFrame = error.data.codeFrame;
|
|
274
|
+
}
|
|
275
|
+
if (typeof error.data.code === "string" || typeof error.data.code === "number") {
|
|
276
|
+
Object.defineProperty(restoredError, "code", {
|
|
277
|
+
configurable: true,
|
|
278
|
+
value: error.data.code,
|
|
279
|
+
writable: true
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
if (error.data.type) {
|
|
283
|
+
restoredError.name = error.data.type;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var applyDirectProperties = (restoredError, error) => {
|
|
287
|
+
if (error.stack) {
|
|
288
|
+
const lowerStack = restoredError.stack || "";
|
|
289
|
+
const indexNewLine = getNewLineIndex(lowerStack);
|
|
290
|
+
const parentStack = getParentStack(error);
|
|
291
|
+
setStack(restoredError, `${parentStack}${lowerStack.slice(indexNewLine)}`);
|
|
292
|
+
}
|
|
293
|
+
if (error.codeFrame) {
|
|
294
|
+
restoredError.codeFrame = error.codeFrame;
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
var restoreMessageError = (error, _currentStack) => {
|
|
298
|
+
const restoredError = constructError(error.message, error.type || error.data?.type, error.name);
|
|
299
|
+
if (typeof error.code === "string" || typeof error.code === "number") {
|
|
300
|
+
Object.defineProperty(restoredError, "code", {
|
|
301
|
+
configurable: true,
|
|
302
|
+
value: error.code,
|
|
303
|
+
writable: true
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
if (error.data) {
|
|
307
|
+
applyDataProperties(restoredError, error);
|
|
308
|
+
} else {
|
|
309
|
+
applyDirectProperties(restoredError, error);
|
|
310
|
+
}
|
|
311
|
+
return restoredError;
|
|
312
|
+
};
|
|
313
|
+
var getFallbackMessage = (error) => {
|
|
314
|
+
if (error && typeof error.message === "string" && error.message) {
|
|
315
|
+
return error.message;
|
|
316
|
+
}
|
|
317
|
+
if (error && error.data) {
|
|
318
|
+
return getFallbackMessage(error.data);
|
|
319
|
+
}
|
|
320
|
+
const stringified = String(error);
|
|
321
|
+
if (stringified !== "[object Object]") {
|
|
322
|
+
return stringified;
|
|
323
|
+
}
|
|
324
|
+
try {
|
|
325
|
+
return JSON.stringify(error);
|
|
326
|
+
} catch {
|
|
327
|
+
return stringified;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
var restoreJsonRpcError = (error) => {
|
|
331
|
+
const currentStack = getCurrentStack();
|
|
332
|
+
if (error && error instanceof Error) {
|
|
333
|
+
return restoreExistingError(error, currentStack);
|
|
334
|
+
}
|
|
335
|
+
if (error && error.code && error.code === MethodNotFound) {
|
|
336
|
+
return restoreMethodNotFoundError(error, currentStack);
|
|
337
|
+
}
|
|
338
|
+
if (error && error.error) {
|
|
339
|
+
return restoreJsonRpcError(error.error);
|
|
340
|
+
}
|
|
341
|
+
if (error && error.message) {
|
|
342
|
+
return restoreMessageError(error);
|
|
343
|
+
}
|
|
344
|
+
return new Error(`JsonRpc Error: ${getFallbackMessage(error)}`);
|
|
345
|
+
};
|
|
346
|
+
var unwrapJsonRpcResult = (responseMessage) => {
|
|
347
|
+
if ("error" in responseMessage) {
|
|
348
|
+
const restoredError = restoreJsonRpcError(responseMessage.error);
|
|
349
|
+
throw restoredError;
|
|
350
|
+
}
|
|
351
|
+
if ("result" in responseMessage) {
|
|
352
|
+
return responseMessage.result;
|
|
353
|
+
}
|
|
354
|
+
throw new JsonRpcError("unexpected response message");
|
|
355
|
+
};
|
|
356
|
+
var warn = (...args) => {
|
|
357
|
+
console.warn(...args);
|
|
358
|
+
};
|
|
359
|
+
var resolve = (id2, response) => {
|
|
360
|
+
const fn = get(id2);
|
|
361
|
+
if (!fn) {
|
|
362
|
+
console.log(response);
|
|
363
|
+
warn(`callback ${id2} may already be disposed`);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
fn(response);
|
|
367
|
+
remove(id2);
|
|
368
|
+
};
|
|
369
|
+
var E_COMMAND_NOT_FOUND = "E_COMMAND_NOT_FOUND";
|
|
370
|
+
var getErrorType = (prettyError) => {
|
|
371
|
+
if (prettyError && prettyError.type) {
|
|
372
|
+
return prettyError.type;
|
|
373
|
+
}
|
|
374
|
+
if (prettyError && prettyError.constructor && prettyError.constructor.name) {
|
|
375
|
+
return prettyError.constructor.name;
|
|
376
|
+
}
|
|
377
|
+
return void 0;
|
|
378
|
+
};
|
|
379
|
+
var isAlreadyStack = (line) => {
|
|
380
|
+
return line.trim().startsWith("at ");
|
|
381
|
+
};
|
|
382
|
+
var getStack = (prettyError) => {
|
|
383
|
+
const stackString = prettyError.stack || "";
|
|
384
|
+
const newLineIndex = stackString.indexOf("\n");
|
|
385
|
+
if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
|
|
386
|
+
return stackString.slice(newLineIndex + 1);
|
|
387
|
+
}
|
|
388
|
+
return stackString;
|
|
389
|
+
};
|
|
390
|
+
var getErrorProperty = (error, prettyError) => {
|
|
391
|
+
if (error && error.code === E_COMMAND_NOT_FOUND) {
|
|
392
|
+
return {
|
|
393
|
+
code: MethodNotFound,
|
|
394
|
+
data: error.stack,
|
|
395
|
+
message: error.message
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
code: Custom,
|
|
400
|
+
data: {
|
|
401
|
+
code: prettyError.code ?? error?.code,
|
|
402
|
+
codeFrame: prettyError.codeFrame,
|
|
403
|
+
name: prettyError.name ?? error?.name,
|
|
404
|
+
stack: getStack(prettyError),
|
|
405
|
+
type: getErrorType(prettyError)
|
|
406
|
+
},
|
|
407
|
+
message: prettyError.message
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
var create$1 = (id2, error) => {
|
|
411
|
+
return {
|
|
412
|
+
error,
|
|
413
|
+
id: id2,
|
|
414
|
+
jsonrpc: Two
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
var getErrorResponse = (id2, error, preparePrettyError2, logError2) => {
|
|
418
|
+
const prettyError = preparePrettyError2(error);
|
|
419
|
+
logError2(error, prettyError);
|
|
420
|
+
const errorProperty = getErrorProperty(error, prettyError);
|
|
421
|
+
return create$1(id2, errorProperty);
|
|
422
|
+
};
|
|
423
|
+
var create = (message, result) => {
|
|
424
|
+
return {
|
|
425
|
+
id: message.id,
|
|
426
|
+
jsonrpc: Two,
|
|
427
|
+
result: result ?? null
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
var getSuccessResponse = (message, result) => {
|
|
431
|
+
const resultProperty = result ?? null;
|
|
432
|
+
return create(message, resultProperty);
|
|
433
|
+
};
|
|
434
|
+
var getErrorResponseSimple = (id2, error) => {
|
|
435
|
+
return {
|
|
436
|
+
error: {
|
|
437
|
+
code: Custom,
|
|
438
|
+
data: error instanceof Error ? {
|
|
439
|
+
...error,
|
|
440
|
+
code: "code" in error ? error.code : void 0,
|
|
441
|
+
stack: error.stack,
|
|
442
|
+
type: error.name
|
|
443
|
+
} : error,
|
|
444
|
+
// @ts-ignore
|
|
445
|
+
message: error.message
|
|
446
|
+
},
|
|
447
|
+
id: id2,
|
|
448
|
+
jsonrpc: Two
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
var getResponse = async (message, ipc, execute2, preparePrettyError2, logError2, requiresSocket2) => {
|
|
452
|
+
try {
|
|
453
|
+
const result = requiresSocket2(message.method) ? await execute2(message.method, ipc, ...message.params) : await execute2(message.method, ...message.params);
|
|
454
|
+
return getSuccessResponse(message, result);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
if (ipc.canUseSimpleErrorResponse) {
|
|
457
|
+
return getErrorResponseSimple(message.id, error);
|
|
458
|
+
}
|
|
459
|
+
return getErrorResponse(message.id, error, preparePrettyError2, logError2);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
var defaultPreparePrettyError = (error) => {
|
|
463
|
+
return error;
|
|
464
|
+
};
|
|
465
|
+
var defaultLogError = () => {
|
|
466
|
+
};
|
|
467
|
+
var defaultRequiresSocket = () => {
|
|
468
|
+
return false;
|
|
469
|
+
};
|
|
470
|
+
var defaultResolve = resolve;
|
|
471
|
+
var normalizeParams = (args) => {
|
|
472
|
+
if (args.length === 1) {
|
|
473
|
+
const options = args[0];
|
|
474
|
+
return {
|
|
475
|
+
execute: options.execute,
|
|
476
|
+
ipc: options.ipc,
|
|
477
|
+
logError: options.logError || defaultLogError,
|
|
478
|
+
message: options.message,
|
|
479
|
+
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
|
|
480
|
+
requiresSocket: options.requiresSocket || defaultRequiresSocket,
|
|
481
|
+
resolve: options.resolve || defaultResolve
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
return {
|
|
485
|
+
execute: args[2],
|
|
486
|
+
ipc: args[0],
|
|
487
|
+
logError: args[5],
|
|
488
|
+
message: args[1],
|
|
489
|
+
preparePrettyError: args[4],
|
|
490
|
+
requiresSocket: args[6],
|
|
491
|
+
resolve: args[3]
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
var handleJsonRpcMessage = async (...args) => {
|
|
495
|
+
const options = normalizeParams(args);
|
|
496
|
+
const {
|
|
497
|
+
execute: execute2,
|
|
498
|
+
ipc,
|
|
499
|
+
logError: logError2,
|
|
500
|
+
message,
|
|
501
|
+
preparePrettyError: preparePrettyError2,
|
|
502
|
+
requiresSocket: requiresSocket2,
|
|
503
|
+
resolve: resolve2
|
|
504
|
+
} = options;
|
|
505
|
+
if ("id" in message) {
|
|
506
|
+
if ("method" in message) {
|
|
507
|
+
const response = await getResponse(message, ipc, execute2, preparePrettyError2, logError2, requiresSocket2);
|
|
508
|
+
try {
|
|
509
|
+
ipc.send(response);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
const errorResponse = getErrorResponse(message.id, error, preparePrettyError2, logError2);
|
|
512
|
+
ipc.send(errorResponse);
|
|
513
|
+
}
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
resolve2(message.id, message);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if ("method" in message) {
|
|
520
|
+
await getResponse(message, ipc, execute2, preparePrettyError2, logError2, requiresSocket2);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
throw new JsonRpcError("unexpected message");
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// node_modules/@lvce-editor/rpc/dist/parts/JsonRpcVersion/JsonRpcVersion.js
|
|
527
|
+
var Two2 = "2.0";
|
|
528
|
+
|
|
529
|
+
// node_modules/@lvce-editor/rpc/dist/parts/JsonRpcEvent/JsonRpcEvent.js
|
|
530
|
+
var create2 = (method, params) => {
|
|
531
|
+
return {
|
|
532
|
+
jsonrpc: Two2,
|
|
533
|
+
method,
|
|
534
|
+
params
|
|
535
|
+
};
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// node_modules/@lvce-editor/rpc/dist/parts/JsonRpcRequest/JsonRpcRequest.js
|
|
539
|
+
var create3 = (id2, method, params) => {
|
|
540
|
+
const message = {
|
|
541
|
+
id: id2,
|
|
542
|
+
jsonrpc: Two2,
|
|
543
|
+
method,
|
|
544
|
+
params
|
|
545
|
+
};
|
|
546
|
+
return message;
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
// node_modules/@lvce-editor/rpc/dist/parts/Id/Id.js
|
|
550
|
+
var id = 0;
|
|
551
|
+
var create4 = () => {
|
|
552
|
+
return ++id;
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
// node_modules/@lvce-editor/rpc/dist/parts/RegisterPromise/RegisterPromise.js
|
|
556
|
+
var registerPromise = (map) => {
|
|
557
|
+
const id2 = create4();
|
|
558
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
559
|
+
map[id2] = resolve2;
|
|
560
|
+
return { id: id2, promise };
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// node_modules/@lvce-editor/rpc/dist/parts/CreateRpc/CreateRpc.js
|
|
564
|
+
var invokeHelper = async (callbacks2, ipc, method, params, useSendAndTransfer) => {
|
|
565
|
+
const { id: id2, promise } = registerPromise(callbacks2);
|
|
566
|
+
const message = create3(id2, method, params);
|
|
567
|
+
if (useSendAndTransfer && ipc.sendAndTransfer) {
|
|
568
|
+
ipc.sendAndTransfer(message);
|
|
569
|
+
} else {
|
|
570
|
+
ipc.send(message);
|
|
571
|
+
}
|
|
572
|
+
const responseMessage = await promise;
|
|
573
|
+
return unwrapJsonRpcResult(responseMessage);
|
|
574
|
+
};
|
|
575
|
+
var createRpc = (ipc) => {
|
|
576
|
+
const callbacks2 = /* @__PURE__ */ Object.create(null);
|
|
577
|
+
ipc._resolve = (id2, response) => {
|
|
578
|
+
const fn = callbacks2[id2];
|
|
579
|
+
if (!fn) {
|
|
580
|
+
console.warn(`callback ${id2} may already be disposed`);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
fn(response);
|
|
584
|
+
delete callbacks2[id2];
|
|
585
|
+
};
|
|
586
|
+
const rpc = {
|
|
587
|
+
async dispose() {
|
|
588
|
+
await ipc?.dispose();
|
|
589
|
+
},
|
|
590
|
+
invoke(method, ...params) {
|
|
591
|
+
return invokeHelper(callbacks2, ipc, method, params, false);
|
|
592
|
+
},
|
|
593
|
+
invokeAndTransfer(method, ...params) {
|
|
594
|
+
return invokeHelper(callbacks2, ipc, method, params, true);
|
|
595
|
+
},
|
|
596
|
+
// @ts-ignore
|
|
597
|
+
ipc,
|
|
598
|
+
/**
|
|
599
|
+
* @deprecated
|
|
600
|
+
*/
|
|
601
|
+
send(method, ...params) {
|
|
602
|
+
const message = create2(method, params);
|
|
603
|
+
ipc.send(message);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
return rpc;
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// node_modules/@lvce-editor/rpc/dist/parts/HandleMessage/HandleMessage.js
|
|
610
|
+
var requiresSocket = () => {
|
|
611
|
+
return false;
|
|
612
|
+
};
|
|
613
|
+
var preparePrettyError = (error) => {
|
|
614
|
+
return error;
|
|
615
|
+
};
|
|
616
|
+
var logError = () => {
|
|
617
|
+
};
|
|
618
|
+
var handleMessage = (event) => {
|
|
619
|
+
if (event.data === "ready") {
|
|
620
|
+
return Promise.resolve();
|
|
621
|
+
}
|
|
622
|
+
const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
|
|
623
|
+
const actualExecute = event?.target?.execute || execute;
|
|
624
|
+
return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
// node_modules/@lvce-editor/rpc/dist/parts/HandleIpc/HandleIpc.js
|
|
628
|
+
var handleIpc = (ipc) => {
|
|
629
|
+
if ("addEventListener" in ipc) {
|
|
630
|
+
ipc.addEventListener("message", handleMessage);
|
|
631
|
+
} else if ("on" in ipc) {
|
|
632
|
+
ipc.on("message", handleMessage);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
// node_modules/@lvce-editor/rpc/dist/parts/IpcChildNode/IpcChildNode.js
|
|
637
|
+
var listen = async (module, options) => {
|
|
638
|
+
const rawIpc = await module.listen(options);
|
|
639
|
+
if (module.signal) {
|
|
640
|
+
module.signal(rawIpc);
|
|
641
|
+
}
|
|
642
|
+
const ipc = module.wrap(rawIpc);
|
|
643
|
+
return ipc;
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
// node_modules/@lvce-editor/rpc/dist/parts/WebWorkerRpcClient2/WebWorkerRpcClient2.js
|
|
647
|
+
var WebWorkerRpcClient2_exports = {};
|
|
648
|
+
__export(WebWorkerRpcClient2_exports, {
|
|
649
|
+
create: () => create5
|
|
650
|
+
});
|
|
651
|
+
var create5 = async ({ commandMap: commandMap2 }) => {
|
|
652
|
+
register(commandMap2);
|
|
653
|
+
const ipc = await listen(IpcChildWithModuleWorker$1);
|
|
654
|
+
handleIpc(ipc);
|
|
655
|
+
const rpc = createRpc(ipc);
|
|
656
|
+
return rpc;
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// packages/cache-worker/src/parts/Cache/Cache.js
|
|
660
|
+
var getCacheStorage = () => {
|
|
661
|
+
if (typeof caches === "undefined") {
|
|
662
|
+
throw new Error("Cache Storage is not available in this context");
|
|
663
|
+
}
|
|
664
|
+
return caches;
|
|
665
|
+
};
|
|
666
|
+
var getCacheStorageItem = async (request, cacheName = "lvce-cache") => {
|
|
667
|
+
const cache = await getCacheStorage().open(cacheName);
|
|
668
|
+
const response = await cache.match(request);
|
|
669
|
+
if (!response) {
|
|
670
|
+
return null;
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
body: await response.arrayBuffer(),
|
|
674
|
+
headers: [...response.headers.entries()],
|
|
675
|
+
status: response.status,
|
|
676
|
+
statusText: response.statusText
|
|
677
|
+
};
|
|
678
|
+
};
|
|
679
|
+
var setCacheStorageItem = async (request, value, cacheName = "lvce-cache") => {
|
|
680
|
+
const cache = await getCacheStorage().open(cacheName);
|
|
681
|
+
const response = new Response(value);
|
|
682
|
+
await cache.put(request, response);
|
|
683
|
+
};
|
|
684
|
+
var removeCacheStorageItem = async (request, cacheName = "lvce-cache") => {
|
|
685
|
+
const cache = await getCacheStorage().open(cacheName);
|
|
686
|
+
return cache.delete(request);
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
// packages/cache-worker/src/parts/IndexedDb/IndexedDb.js
|
|
690
|
+
var requestResult = (request) => new Promise((resolve2, reject) => {
|
|
691
|
+
request.onsuccess = () => resolve2(request.result);
|
|
692
|
+
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
|
|
693
|
+
});
|
|
694
|
+
var transactionDone = (transaction) => new Promise((resolve2, reject) => {
|
|
695
|
+
transaction.oncomplete = () => resolve2();
|
|
696
|
+
transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
|
|
697
|
+
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
|
|
698
|
+
});
|
|
699
|
+
var openDatabase = (name) => {
|
|
700
|
+
if (typeof indexedDB === "undefined") {
|
|
701
|
+
throw new Error("IndexedDB is not available in this context");
|
|
702
|
+
}
|
|
703
|
+
return new Promise((resolve2, reject) => {
|
|
704
|
+
const request = indexedDB.open(name, 1);
|
|
705
|
+
request.onupgradeneeded = () => {
|
|
706
|
+
if (!request.result.objectStoreNames.contains("file-handles")) {
|
|
707
|
+
request.result.createObjectStore("file-handles");
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
request.onsuccess = () => {
|
|
711
|
+
request.result.onversionchange = () => request.result.close();
|
|
712
|
+
resolve2(request.result);
|
|
713
|
+
};
|
|
714
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB database"));
|
|
715
|
+
request.onblocked = () => reject(new Error(`Opening IndexedDB database "${name}" was blocked`));
|
|
716
|
+
});
|
|
717
|
+
};
|
|
718
|
+
var addIndexedDbFileHandle = async (key, handle, databaseName = "lvce-cache-worker") => {
|
|
719
|
+
const database = await openDatabase(databaseName);
|
|
720
|
+
const transaction = database.transaction("file-handles", "readwrite");
|
|
721
|
+
const done = transactionDone(transaction);
|
|
722
|
+
const request = transaction.objectStore("file-handles").put(handle, key);
|
|
723
|
+
try {
|
|
724
|
+
await Promise.all([requestResult(request), done]);
|
|
725
|
+
} finally {
|
|
726
|
+
database.close();
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
var getIndexedDbFileHandle = async (key, databaseName = "lvce-cache-worker") => {
|
|
730
|
+
const database = await openDatabase(databaseName);
|
|
731
|
+
const transaction = database.transaction("file-handles", "readonly");
|
|
732
|
+
const done = transactionDone(transaction);
|
|
733
|
+
try {
|
|
734
|
+
const value = await requestResult(transaction.objectStore("file-handles").get(key));
|
|
735
|
+
await done;
|
|
736
|
+
return value;
|
|
737
|
+
} finally {
|
|
738
|
+
database.close();
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
var removeIndexedDbFileHandle = async (key, databaseName = "lvce-cache-worker") => {
|
|
742
|
+
const database = await openDatabase(databaseName);
|
|
743
|
+
const transaction = database.transaction("file-handles", "readwrite");
|
|
744
|
+
const done = transactionDone(transaction);
|
|
745
|
+
const request = transaction.objectStore("file-handles").delete(key);
|
|
746
|
+
try {
|
|
747
|
+
await Promise.all([requestResult(request), done]);
|
|
748
|
+
} finally {
|
|
749
|
+
database.close();
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
// packages/cache-worker/src/parts/Opfs/Opfs.js
|
|
754
|
+
var getRoot = async () => {
|
|
755
|
+
if (typeof navigator === "undefined" || typeof navigator.storage?.getDirectory !== "function") {
|
|
756
|
+
throw new Error("Origin Private File System is not available in this context");
|
|
757
|
+
}
|
|
758
|
+
return navigator.storage.getDirectory();
|
|
759
|
+
};
|
|
760
|
+
var validateName = (name) => {
|
|
761
|
+
if (typeof name !== "string" || name.length === 0 || name === "." || name === ".." || /[/\\]/.test(name)) {
|
|
762
|
+
throw new TypeError("OPFS filename must be a non-empty single path component");
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var readFile = async (name) => {
|
|
766
|
+
validateName(name);
|
|
767
|
+
const root = await getRoot();
|
|
768
|
+
const handle = await root.getFileHandle(name);
|
|
769
|
+
return (await handle.getFile()).text();
|
|
770
|
+
};
|
|
771
|
+
var writeFile = async (name, content) => {
|
|
772
|
+
validateName(name);
|
|
773
|
+
const root = await getRoot();
|
|
774
|
+
const handle = await root.getFileHandle(name, { create: true });
|
|
775
|
+
const writable = await handle.createWritable();
|
|
776
|
+
try {
|
|
777
|
+
await writable.write(content);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
await writable.abort();
|
|
780
|
+
throw error;
|
|
781
|
+
}
|
|
782
|
+
await writable.close();
|
|
783
|
+
};
|
|
784
|
+
var removeFile = async (name) => {
|
|
785
|
+
validateName(name);
|
|
786
|
+
const root = await getRoot();
|
|
787
|
+
await root.removeEntry(name);
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// packages/cache-worker/src/parts/CommandMap/CommandMap.js
|
|
791
|
+
var commandMap = {
|
|
792
|
+
"Cache.getCacheStorageItem": getCacheStorageItem,
|
|
793
|
+
"Cache.setCacheStorageItem": setCacheStorageItem,
|
|
794
|
+
"Cache.removeCacheStorageItem": removeCacheStorageItem,
|
|
795
|
+
"IndexedDb.addIndexedDbFileHandle": addIndexedDbFileHandle,
|
|
796
|
+
"IndexedDb.getIndexedDbFileHandle": getIndexedDbFileHandle,
|
|
797
|
+
"IndexedDb.removeIndexedDbFileHandle": removeIndexedDbFileHandle,
|
|
798
|
+
"Opfs.readFile": readFile,
|
|
799
|
+
"Opfs.writeFile": writeFile,
|
|
800
|
+
"Opfs.removeFile": removeFile
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// packages/cache-worker/src/parts/Listen/Listen.js
|
|
804
|
+
var listen2 = async () => {
|
|
805
|
+
await WebWorkerRpcClient2_exports.create({ commandMap });
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// packages/cache-worker/src/cacheWorkerMain.js
|
|
809
|
+
await listen2();
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const getCacheWorkerUrl = () => new URL('./cacheWorkerMain.js', import.meta.url)
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lvce-editor/cache-worker",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Worker APIs for Cache Storage, IndexedDB, and OPFS",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Lvce Editor",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/lvce-editor/cache-worker.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "index.js",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./index.js",
|
|
15
|
+
"./cacheWorkerMain.js": "./cacheWorkerMain.js"
|
|
16
|
+
}
|
|
17
|
+
}
|