@kirill.konshin/core 0.0.1
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/.ctirc +11 -0
- package/.turbo/turbo-build.log +26 -0
- package/.turbo/turbo-test.log +103 -0
- package/README.md +91 -0
- package/demo/worker-demo.ts +73 -0
- package/dist/cache.d.ts +119 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +106 -0
- package/dist/cache.js.map +1 -0
- package/dist/cache.test.d.ts +2 -0
- package/dist/cache.test.d.ts.map +1 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +4 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +28 -0
- package/dist/files.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/ls.d.ts +6 -0
- package/dist/ls.d.ts.map +1 -0
- package/dist/ls.js +12 -0
- package/dist/ls.js.map +1 -0
- package/dist/measure.d.ts +35 -0
- package/dist/measure.d.ts.map +1 -0
- package/dist/measure.js +60 -0
- package/dist/measure.js.map +1 -0
- package/dist/mutex.d.ts +6 -0
- package/dist/mutex.d.ts.map +1 -0
- package/dist/mutex.js +21 -0
- package/dist/mutex.js.map +1 -0
- package/dist/worker.d.ts +98 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +226 -0
- package/dist/worker.js.map +1 -0
- package/dist/worker.test.d.ts +2 -0
- package/dist/worker.test.d.ts.map +1 -0
- package/dist/workerUtils.d.ts +3 -0
- package/dist/workerUtils.d.ts.map +1 -0
- package/dist/workerUtils.js +31 -0
- package/dist/workerUtils.js.map +1 -0
- package/dist/wrpc.d.ts +45 -0
- package/dist/wrpc.d.ts.map +1 -0
- package/dist/wrpc.fixture.d.ts +26 -0
- package/dist/wrpc.fixture.d.ts.map +1 -0
- package/dist/wrpc.js +241 -0
- package/dist/wrpc.js.map +1 -0
- package/dist/wrpc.test.d.ts +1 -0
- package/dist/wrpc.test.d.ts.map +1 -0
- package/package.json +46 -0
- package/src/cache.test.ts +121 -0
- package/src/cache.ts +245 -0
- package/src/errors.ts +17 -0
- package/src/files.ts +29 -0
- package/src/index.ts +9 -0
- package/src/ls.ts +15 -0
- package/src/measure.ts +109 -0
- package/src/mutex.ts +22 -0
- package/src/worker.test.ts +197 -0
- package/src/worker.ts +347 -0
- package/src/workerUtils.ts +32 -0
- package/src/wrpc.fixture.ts +106 -0
- package/src/wrpc.test.ts +225 -0
- package/src/wrpc.ts +377 -0
- package/tsconfig.json +10 -0
- package/turbo.json +10 -0
- package/vite.config.ts +2 -0
package/.ctirc
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[36mvite v7.0.6 [32mbuilding SSR bundle for production...[36m[39m
|
|
2
|
+
create succeeded: /home/runner/work/utils/utils/packages/core/src
|
|
3
|
+
transforming...
|
|
4
|
+
[32m✓[39m 10 modules transformed.
|
|
5
|
+
rendering chunks...
|
|
6
|
+
|
|
7
|
+
[vite:dts] Start generate declaration files...
|
|
8
|
+
[96msrc/workerUtils.ts[0m:[93m22[0m:[93m64[0m - [91merror[0m[90m TS2322: [0mType 'null' is not assignable to type 'boolean'.
|
|
9
|
+
|
|
10
|
+
[7m22[0m return transferrable.some((t) => obj instanceof t) ? obj : null;
|
|
11
|
+
[7m [0m [91m ~~~~[0m
|
|
12
|
+
|
|
13
|
+
[2mdist/[22m[36merrors.js [39m[1m[2m0.33 kB[22m[1m[22m[2m │ map: 0.90 kB[22m
|
|
14
|
+
[2mdist/[22m[36mmutex.js [39m[1m[2m0.40 kB[22m[1m[22m[2m │ map: 1.18 kB[22m
|
|
15
|
+
[2mdist/[22m[36mls.js [39m[1m[2m0.44 kB[22m[1m[22m[2m │ map: 1.05 kB[22m
|
|
16
|
+
[2mdist/[22m[36mfiles.js [39m[1m[2m0.84 kB[22m[1m[22m[2m │ map: 1.89 kB[22m
|
|
17
|
+
[2mdist/[22m[36mindex.js [39m[1m[2m0.92 kB[22m[1m[22m[2m │ map: 0.10 kB[22m
|
|
18
|
+
[2mdist/[22m[36mworkerUtils.js [39m[1m[2m0.97 kB[22m[1m[22m[2m │ map: 1.82 kB[22m
|
|
19
|
+
[2mdist/[22m[36mmeasure.js [39m[1m[2m1.44 kB[22m[1m[22m[2m │ map: 4.08 kB[22m
|
|
20
|
+
[2mdist/[22m[36mcache.js [39m[1m[2m2.92 kB[22m[1m[22m[2m │ map: 10.21 kB[22m
|
|
21
|
+
[2mdist/[22m[36mworker.js [39m[1m[2m7.06 kB[22m[1m[22m[2m │ map: 16.69 kB[22m
|
|
22
|
+
[2mdist/[22m[36mwrpc.js [39m[1m[2m8.73 kB[22m[1m[22m[2m │ map: 20.98 kB[22m
|
|
23
|
+
[vite:dts] Declaration files built in 1945ms.
|
|
24
|
+
|
|
25
|
+
[32m✓ built in 2.75s[39m
|
|
26
|
+
Updated package.json with exports
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
create succeeded: /home/runner/work/utils/utils/packages/core/src
|
|
2
|
+
|
|
3
|
+
[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90m/home/runner/work/utils/utils/packages/core[39m
|
|
4
|
+
[2mCoverage enabled with [22m[33mv8[39m
|
|
5
|
+
|
|
6
|
+
[90mstderr[2m | src/wrpc.test.ts
|
|
7
|
+
[22m[39mUsing an object as a third argument is deprecated. Vitest 4 will throw an error if the third argument is not a timeout number. Please use the second argument for options. See more at https://vitest.dev/guide/migration
|
|
8
|
+
|
|
9
|
+
[90mstdout[2m | src/cache.test.ts[2m > [22m[2mTransformerMap[2m > [22m[2mkey transform
|
|
10
|
+
[22m[39mCLEAR cache test
|
|
11
|
+
|
|
12
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
13
|
+
[22m[39mDATA [33m1[39m
|
|
14
|
+
|
|
15
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
16
|
+
[22m[39mDATA [33m2[39m
|
|
17
|
+
|
|
18
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
19
|
+
[22m[39mDATA [33m3[39m
|
|
20
|
+
|
|
21
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
22
|
+
[22m[39mDATA { value: [33m1[39m, done: [33mfalse[39m }
|
|
23
|
+
|
|
24
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
25
|
+
[22m[39mDATA { value: [33m2[39m, done: [33mfalse[39m }
|
|
26
|
+
|
|
27
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
28
|
+
[22m[39mDATA { value: [33m3[39m, done: [33mfalse[39m }
|
|
29
|
+
|
|
30
|
+
[32m✓[39m src/cache.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 13[2mms[22m[39m
|
|
31
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of return yield
|
|
32
|
+
[22m[39mDATA { value: [90mundefined[39m, done: [33mtrue[39m }
|
|
33
|
+
|
|
34
|
+
[32m✓[39m src/worker.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 13[2mms[22m[39m
|
|
35
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of separate return & yield
|
|
36
|
+
[22m[39mDATA { progress: [33m0[39m }
|
|
37
|
+
|
|
38
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of separate return & yield
|
|
39
|
+
[22m[39mDATA { progress: [33m0.5[39m }
|
|
40
|
+
|
|
41
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mfor await ... of separate return & yield
|
|
42
|
+
[22m[39mDATA { progress: [33m1[39m, aborted: [33mfalse[39m }
|
|
43
|
+
|
|
44
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mdo ... while
|
|
45
|
+
[22m[39mDATA { value: { progress: [33m0[39m }, done: [33mfalse[39m }
|
|
46
|
+
|
|
47
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mdo ... while
|
|
48
|
+
[22m[39mDATA { value: { progress: [33m0.5[39m }, done: [33mfalse[39m }
|
|
49
|
+
|
|
50
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mdo ... while
|
|
51
|
+
[22m[39mDATA { value: { progress: [33m1[39m, aborted: [33mfalse[39m }, done: [33mfalse[39m }
|
|
52
|
+
|
|
53
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mdo ... while
|
|
54
|
+
[22m[39mDATA { value: [32m'foo'[39m, done: [33mtrue[39m }
|
|
55
|
+
|
|
56
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mbreak
|
|
57
|
+
[22m[39mDATA { progress: [33m0[39m }
|
|
58
|
+
|
|
59
|
+
[90mstdout[2m | src/wrpc.test.ts[2m > [22m[2mWRPC[2m > [22m[2mabort
|
|
60
|
+
[22m[39mDATA { progress: [33m0[39m }
|
|
61
|
+
|
|
62
|
+
[32m✓[39m src/wrpc.test.ts [2m([22m[2m13 tests[22m[2m | [22m[33m1 skipped[39m[2m)[22m[33m 719[2mms[22m[39m
|
|
63
|
+
[33m[2m✓[22m[39m WRPC[2m > [22mstop [33m 503[2mms[22m[39m
|
|
64
|
+
Failed to convert coverage for file:///home/runner/work/utils/utils/packages/core/src/wrpc.ts.
|
|
65
|
+
TypeError: Cannot read properties of undefined (reading 'endCol')
|
|
66
|
+
at range.sliceRange (file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:556:55)
|
|
67
|
+
at CovSource.offsetToOriginalRelative (file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:1987:20)
|
|
68
|
+
at V8ToIstanbul._maybeRemapStartColEndCol (file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2396:93)
|
|
69
|
+
at file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2305:61
|
|
70
|
+
at Array.forEach (<anonymous>)
|
|
71
|
+
at file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2303:21
|
|
72
|
+
at Array.forEach (<anonymous>)
|
|
73
|
+
at V8ToIstanbul.applyCoverage (file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2302:13)
|
|
74
|
+
at V8CoverageProvider.v8ToIstanbul (file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2732:14)
|
|
75
|
+
at async file:///home/runner/work/utils/utils/node_modules/@vitest/coverage-v8/dist/provider.js:2825:23
|
|
76
|
+
|
|
77
|
+
[2m Test Files [22m [1m[32m3 passed[39m[22m[90m (3)[39m
|
|
78
|
+
[2m Tests [22m [1m[32m24 passed[39m[22m[2m | [22m[33m1 skipped[39m[90m (25)[39m
|
|
79
|
+
[2m Start at [22m 01:30:13
|
|
80
|
+
[2m Duration [22m 1.33s[2m (transform 220ms, setup 0ms, collect 329ms, tests 746ms, environment 1ms, prepare 444ms)[22m
|
|
81
|
+
|
|
82
|
+
[34m % [39m[2mCoverage report from [22m[33mv8[39m
|
|
83
|
+
------------------|---------|----------|---------|---------|--------------------
|
|
84
|
+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
85
|
+
------------------|---------|----------|---------|---------|--------------------
|
|
86
|
+
All files | 73.18 | 88.88 | 77.77 | 73.18 |
|
|
87
|
+
demo | 0 | 0 | 0 | 0 |
|
|
88
|
+
worker-demo.ts | 0 | 0 | 0 | 0 | 1-73
|
|
89
|
+
src | 78.07 | 89.51 | 79.03 | 78.07 |
|
|
90
|
+
cache.ts | 81.25 | 89.65 | 56.25 | 81.25 | ...200-201,224-225
|
|
91
|
+
errors.ts | 0 | 100 | 100 | 0 | 2-17
|
|
92
|
+
files.ts | 0 | 0 | 0 | 0 | 1-29
|
|
93
|
+
index.ts | 0 | 0 | 0 | 0 | 1-9
|
|
94
|
+
ls.ts | 0 | 0 | 0 | 0 | 1-15
|
|
95
|
+
measure.ts | 0 | 0 | 0 | 0 | 1-109
|
|
96
|
+
mutex.ts | 0 | 100 | 100 | 0 | 3-22
|
|
97
|
+
worker.ts | 100 | 98.71 | 100 | 100 | 57
|
|
98
|
+
workerUtils.ts | 100 | 75 | 100 | 100 | 17,22,26,29
|
|
99
|
+
wrpc.fixture.ts | 81.81 | 78.57 | 75 | 81.81 | 70,73-76,95-99
|
|
100
|
+
wrpc.ts | 100 | 100 | 100 | 100 |
|
|
101
|
+
------------------|---------|----------|---------|---------|--------------------
|
|
102
|
+
Updated package.json with exports
|
|
103
|
+
Updated package.json with exports
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# WRPC
|
|
2
|
+
|
|
3
|
+
TODO
|
|
4
|
+
|
|
5
|
+
- [ ] Add to readme https://stackoverflow.com/questions/77727664/how-to-get-returned-value-from-async-generator-when-using-for-await
|
|
6
|
+
- [ ] Value passed to next are ignored https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator/next#sending_values_to_the_generator
|
|
7
|
+
|
|
8
|
+
```mermaid
|
|
9
|
+
sequenceDiagram
|
|
10
|
+
box Main
|
|
11
|
+
participant Code
|
|
12
|
+
participant Caller
|
|
13
|
+
end
|
|
14
|
+
box Worker
|
|
15
|
+
participant Worker
|
|
16
|
+
participant Resolver
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
%% autonumber
|
|
20
|
+
|
|
21
|
+
Code->>Caller: caller.generator(payload)
|
|
22
|
+
|
|
23
|
+
Caller-->>Code: iterator & promise
|
|
24
|
+
|
|
25
|
+
Code->>Code: Start main CONSUMER loop
|
|
26
|
+
|
|
27
|
+
Code->>Caller: iterator[Symbol]()
|
|
28
|
+
|
|
29
|
+
Caller->>Caller: Start replica GENERATOR loop
|
|
30
|
+
|
|
31
|
+
Code->>Caller: iterator.next()
|
|
32
|
+
|
|
33
|
+
Caller->>Worker: postMessage(payload)
|
|
34
|
+
|
|
35
|
+
Worker->>Resolver: resolver(payload)
|
|
36
|
+
|
|
37
|
+
Resolver-->>Worker: iterator
|
|
38
|
+
|
|
39
|
+
Worker->>Worker: Start replica CONSUMER loop
|
|
40
|
+
|
|
41
|
+
Worker->>Resolver: iterator[Symbol]()
|
|
42
|
+
|
|
43
|
+
Resolver->>Resolver: Start GENERATOR loop
|
|
44
|
+
|
|
45
|
+
rect rgb(232, 244, 248)
|
|
46
|
+
|
|
47
|
+
loop Synchronized iteration
|
|
48
|
+
Worker->>+Resolver: iterator.next(payload)
|
|
49
|
+
|
|
50
|
+
Resolver-->>-Worker: yield value
|
|
51
|
+
|
|
52
|
+
Worker-->>Caller: postMessage(value, done=false)
|
|
53
|
+
|
|
54
|
+
Note over Worker: Wait for ACK or ABORT
|
|
55
|
+
|
|
56
|
+
Caller-->>Code: yield value
|
|
57
|
+
|
|
58
|
+
Code->>Caller: iterator.next(nextPayload)
|
|
59
|
+
|
|
60
|
+
Caller->>Worker: postMessage(ack, nextPayload)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
break Break or AbortSignal (maybe)
|
|
66
|
+
Code-->>Code: Loop exits
|
|
67
|
+
Code->>Caller: signal.abort()
|
|
68
|
+
|
|
69
|
+
Caller-->>Caller: Loop exits
|
|
70
|
+
|
|
71
|
+
Caller->>Worker: postMessage(abort)
|
|
72
|
+
|
|
73
|
+
Worker-->>Worker: Loop exits via Break
|
|
74
|
+
|
|
75
|
+
Resolver-->>Resolver: Loop exits
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
opt Occurs on Error
|
|
79
|
+
Resolver-->>Worker: throw Error
|
|
80
|
+
|
|
81
|
+
Worker-->>Caller: postMessage(error, done=true)
|
|
82
|
+
|
|
83
|
+
Caller-->>Code: throw Error
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
Resolver-->>Worker: return value
|
|
87
|
+
|
|
88
|
+
Worker-->>Caller: postMessage(value, done=true)
|
|
89
|
+
|
|
90
|
+
Caller-->>Code: return value
|
|
91
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { RespondersBase, WorkerDialog } from '../src';
|
|
2
|
+
|
|
3
|
+
class Responders extends RespondersBase<Responders> {
|
|
4
|
+
encode = this.create(
|
|
5
|
+
'encode',
|
|
6
|
+
async (
|
|
7
|
+
{ file, abort = false }: { file: File; abort: boolean }, // should have all possible combinations for strong typing
|
|
8
|
+
encodeContext,
|
|
9
|
+
) => {
|
|
10
|
+
// send within same message
|
|
11
|
+
encodeContext.send({ progress: 0 }); // ✅ Valid
|
|
12
|
+
encodeContext.send({ junk: 'xxx' }); // ❌ Bad & should be red
|
|
13
|
+
|
|
14
|
+
// listen same message
|
|
15
|
+
encodeContext.listen(({ abort }) => {
|
|
16
|
+
if (abort) alert('Aborted'); // ✅ Valid
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// send same message as received
|
|
20
|
+
encodeContext.send({ junk: 'xxx' }); // ❌ Bad & should be red
|
|
21
|
+
encodeContext.send({ progress: 0.5 }); // ✅ Valid
|
|
22
|
+
|
|
23
|
+
// send or listen different message
|
|
24
|
+
encodeContext.withMessage('decode').listen(() => {}); // ✅ Valid
|
|
25
|
+
encodeContext.withMessage('decode').send({ file: null }); // ✅ Valid
|
|
26
|
+
encodeContext.withMessage('decode').send({ junk: 'xxx' }); // ❌ Bad & should be red
|
|
27
|
+
encodeContext.withMessage('junk'); // ❌ Bad & should be red
|
|
28
|
+
|
|
29
|
+
return { bitmap: await createImageBitmap(file), progress: 1.0 }; // should have all possible combinations for strong typing
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// another responder for demo purposes
|
|
34
|
+
decode = this.create('decode', async ({ bitmap }) => {
|
|
35
|
+
return { file: new File([], 'test') };
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const workerDialog = new WorkerDialog(self, new Responders(), 'Worker');
|
|
40
|
+
|
|
41
|
+
/////
|
|
42
|
+
|
|
43
|
+
// import type { workerDialog } from './worker';
|
|
44
|
+
|
|
45
|
+
const mainDialog = new WorkerDialog(self, {} as typeof workerDialog.responders, 'Main');
|
|
46
|
+
|
|
47
|
+
mainDialog
|
|
48
|
+
.withMessage('encode')
|
|
49
|
+
.fetch(
|
|
50
|
+
{
|
|
51
|
+
file: new File([], 'test'), // ✅ Valid
|
|
52
|
+
junk: 'xxx', // ❌ Bad & should be red
|
|
53
|
+
},
|
|
54
|
+
(encodeContext) => {
|
|
55
|
+
// Listen same message, partial data update
|
|
56
|
+
encodeContext.listen((data) => {
|
|
57
|
+
console.log(data.progress); // ✅ Valid
|
|
58
|
+
console.log(data.junk); // ❌ Bad & should be red
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Listen or send other message
|
|
62
|
+
encodeContext.withMessage('decode').listen((data, decodeContext) => {});
|
|
63
|
+
encodeContext.withMessage('decode').send({ bitmap: null }); // ✅ Valid
|
|
64
|
+
encodeContext.withMessage('decode').send({ junk: 'xxx' }); // ❌❌❌ Bad & should be red, broken
|
|
65
|
+
|
|
66
|
+
// Send abort
|
|
67
|
+
encodeContext.send({ abort: true }); // ✅ Valid
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
.then((result) => {
|
|
71
|
+
console.log(result.bitmap); // ✅ Valid
|
|
72
|
+
console.log(result.junk); // ❌ Bad & should be red
|
|
73
|
+
});
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
2
|
+
export declare const shallowCompare: (prev: any, next: any) => boolean;
|
|
3
|
+
export declare const equal: (prev: any, next: any) => boolean;
|
|
4
|
+
export declare const ANY: unique symbol;
|
|
5
|
+
export declare function createTracker<Dep = any>(whenDifferent: (next: Dep, prev?: Dep) => any, shallow?: boolean): (dependency: Dep) => Dep | false;
|
|
6
|
+
/**
|
|
7
|
+
* https://github.com/futpib/deep-weak-map
|
|
8
|
+
* https://github.com/fregante/many-keys-map
|
|
9
|
+
* https://github.com/fregante/many-keys-weakmap
|
|
10
|
+
* https://github.com/sindresorhus/memoize?tab=readme-ov-file#example-multiple-non-serializable-arguments
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const memoized = memo(
|
|
14
|
+
* (file, options, ...args) => { ... },
|
|
15
|
+
* {
|
|
16
|
+
* key: (file, options, ...args) => [file, JSON.stringify(options), ...args],
|
|
17
|
+
* invalidate: (bitmap) => !bitmap.width,
|
|
18
|
+
* dispose: (bitmap) => bitmap.close(),
|
|
19
|
+
* }
|
|
20
|
+
* );
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function memo<Key extends any[], Val, SerializedKey extends any[] = Key>(fn: (...args: Key) => MaybePromise<Val>, { key, invalidate, dispose, }?: {
|
|
24
|
+
key?: (...key: Key) => SerializedKey;
|
|
25
|
+
invalidate?: (prev: Val, ...key: SerializedKey) => boolean;
|
|
26
|
+
dispose?: (prev: Val, ...key: SerializedKey) => void;
|
|
27
|
+
}): {
|
|
28
|
+
(...args: Key): Promise<{
|
|
29
|
+
value?: Val;
|
|
30
|
+
hit: boolean;
|
|
31
|
+
}>;
|
|
32
|
+
clear: (...condition: Key | any[]) => void;
|
|
33
|
+
size: () => number;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Allows to memoize values by key and invalidate them based on the previous value.
|
|
37
|
+
*
|
|
38
|
+
* This makes possible to implement various one-off and subsequent transformations.
|
|
39
|
+
*
|
|
40
|
+
* 1. `write`: Transform value BEFORE writing to cache, called only once if cache IS NOT present or IS NOT valid
|
|
41
|
+
* 2. `read`: Transform value AFTER it's read from cache, always called if cache IS valid, keep in mind this transform is applied on top of BEFORE
|
|
42
|
+
*
|
|
43
|
+
* Both should return same type or null.
|
|
44
|
+
*
|
|
45
|
+
* If `newValue` is null, old is returned, and no cache is set.
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* class InputCache extends TypedCache<string, ImageBitmap> {
|
|
49
|
+
* dispose(bitmap: ImageBitmap, key: string) {
|
|
50
|
+
* bitmap.close();
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* const cache = new InputCache('input');
|
|
55
|
+
*
|
|
56
|
+
* // Cache provided OffscreenCanvas by name and create context once per canvas
|
|
57
|
+
*
|
|
58
|
+
* class CanvasCache extends TypedCache<string, OffscreenCanvas> {
|
|
59
|
+
* protected write(key: string, canvas: OffscreenCanvas): OffscreenCanvas {
|
|
60
|
+
* const canvas = newValue.getContext('2d');
|
|
61
|
+
* canvas.ctx = canvas;
|
|
62
|
+
* return canvas;
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
*
|
|
66
|
+
* // Transfer control to offscreen canvas and track removal of original
|
|
67
|
+
* // When called again, always return null, because canvas is handed to worker, and never returned to main
|
|
68
|
+
*
|
|
69
|
+
* class CanvasCache extends TypedCache<HTMLCanvasElement, OffscreenCanvas> {
|
|
70
|
+
*
|
|
71
|
+
* protected write(canvas: HTMLCanvasElement): OffscreenCanvas {
|
|
72
|
+
* canvas.addEventListener(
|
|
73
|
+
* 'remove',
|
|
74
|
+
* function listener() {
|
|
75
|
+
* console.log('Removing canvas from cache', key);
|
|
76
|
+
* this.delete(canvas);
|
|
77
|
+
* key.removeEventListener('remove', listener);
|
|
78
|
+
* },
|
|
79
|
+
* );
|
|
80
|
+
* return canvas.transferControlToOffscreen();
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* protected read() {
|
|
84
|
+
* return null;
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* // Create bitmap from file and check if was used, return null if used
|
|
89
|
+
* // Since bitmaps are also cached in worker, used bitmaps are not sent
|
|
90
|
+
*
|
|
91
|
+
* class BitmapCache extends TypedCache<File, ImageBitmap, File> {
|
|
92
|
+
* protected async write(file: File): Promise<ImageBitmap> {
|
|
93
|
+
* return await createImageBitmap(file);
|
|
94
|
+
* }
|
|
95
|
+
*
|
|
96
|
+
* protected read(bitmap: ImageBitmap): Promise<ImageBitmap> | ImageBitmap {
|
|
97
|
+
* if (!bitmap.width) return null;
|
|
98
|
+
* return bitmap;
|
|
99
|
+
* }
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare abstract class TransformerMap<Key, Val = Key> extends Map<Key, Val> {
|
|
105
|
+
protected readonly name: string;
|
|
106
|
+
constructor(name: string);
|
|
107
|
+
protected write(key: Key, newValue?: Val, oldValue?: Val): MaybePromise<Val>;
|
|
108
|
+
protected read(oldValue: Val, key: Key): MaybePromise<Val>;
|
|
109
|
+
delete(key: Key): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Do something with the value and key before removing it from cache
|
|
112
|
+
* For example, close a file or a bitmap
|
|
113
|
+
*/
|
|
114
|
+
protected dispose(value: Val, key: Key): void;
|
|
115
|
+
clear(): void;
|
|
116
|
+
set(key: Key, value: Val): this;
|
|
117
|
+
memo(key: Key, newValue?: Val): Promise<Val>;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7C,eAAO,MAAM,cAAc,GAAI,MAAM,GAAG,EAAE,MAAM,GAAG,KAAG,OACuD,CAAC;AAE9G,eAAO,MAAM,KAAK,GAAI,MAAM,GAAG,EAAE,MAAM,GAAG,KAAG,OAAwB,CAAC;AAGtE,eAAO,MAAM,GAAG,EAAE,OAAO,MAAoB,CAAC;AAE9C,wBAAgB,aAAa,CAAC,GAAG,GAAG,GAAG,EAAE,aAAa,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,GAAG,EAAE,OAAO,UAAQ,IAK3E,YAAY,GAAG,KAAG,GAAG,GAAG,KAAK,CAgBxD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAAC,GAAG,SAAS,GAAG,EAAE,EAAE,GAAG,EAAE,aAAa,SAAS,GAAG,EAAE,GAAG,GAAG,EAC1E,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,YAAY,CAAC,GAAG,CAAC,EACvC,EACI,GAAgD,EAChD,UAAU,EACV,OAAO,GACV,GAAE;IACC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,GAAG,KAAK,aAAa,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC;IAC3D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;CACnD,GACP;IACC,CAAC,GAAG,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;QACpB,KAAK,CAAC,EAAE,GAAG,CAAC;QACZ,GAAG,EAAE,OAAO,CAAC;KAChB,CAAC,CAAC;IACH,KAAK,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE,KAAK,IAAI,CAAC;IAC3C,IAAI,EAAE,MAAM,MAAM,CAAC;CACtB,CA+CA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,8BAAsB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAE,SAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;IAK3C,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;IAI5E,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;IAI1D,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAQzB;;;OAGG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;IAE7C,KAAK,IAAI,IAAI;IAMb,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAIzB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;CAkBrD"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import ManyKeysMap from "many-keys-map";
|
|
2
|
+
const shallowCompare = (prev, next) => Array.from(/* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(next)])).every((key) => prev[key] === next[key]);
|
|
3
|
+
const equal = (prev, next) => prev === next;
|
|
4
|
+
const UNUSED = Symbol("UNUSED");
|
|
5
|
+
const ANY = Symbol("*");
|
|
6
|
+
function createTracker(whenDifferent, shallow = false) {
|
|
7
|
+
let lastDependency = UNUSED;
|
|
8
|
+
const comparator = shallow ? shallowCompare : equal;
|
|
9
|
+
return function tracker(dependency) {
|
|
10
|
+
if (lastDependency !== UNUSED && comparator(lastDependency, dependency)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const res = whenDifferent(dependency, lastDependency === UNUSED ? void 0 : lastDependency) || true;
|
|
14
|
+
lastDependency = dependency;
|
|
15
|
+
return res;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function memo(fn, {
|
|
19
|
+
key = (...k) => k,
|
|
20
|
+
invalidate,
|
|
21
|
+
dispose
|
|
22
|
+
} = {}) {
|
|
23
|
+
const map = new ManyKeysMap();
|
|
24
|
+
const clear = (...condition) => {
|
|
25
|
+
if (!condition?.length) {
|
|
26
|
+
map.forEach((value, serializedKey) => {
|
|
27
|
+
dispose?.(value, ...serializedKey);
|
|
28
|
+
});
|
|
29
|
+
map.clear();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const keyToClear = key(...condition);
|
|
33
|
+
map.forEach((value, serializedKey) => {
|
|
34
|
+
if (!serializedKey.every((kk, i) => keyToClear[i] === ANY || kk === keyToClear[i])) return;
|
|
35
|
+
dispose?.(value, ...serializedKey);
|
|
36
|
+
map.delete(serializedKey);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
const size = () => map.size;
|
|
40
|
+
async function memoized(...args) {
|
|
41
|
+
const k = key(...args);
|
|
42
|
+
const has = map.has(k);
|
|
43
|
+
const old = map.get(k);
|
|
44
|
+
if (has && !invalidate?.(old, ...k)) {
|
|
45
|
+
return { value: map.get(k), hit: true };
|
|
46
|
+
}
|
|
47
|
+
const value = await fn(...args);
|
|
48
|
+
map.set(k, value);
|
|
49
|
+
return { hit: false, value };
|
|
50
|
+
}
|
|
51
|
+
memoized.clear = clear;
|
|
52
|
+
memoized.size = size;
|
|
53
|
+
return memoized;
|
|
54
|
+
}
|
|
55
|
+
class TransformerMap extends Map {
|
|
56
|
+
constructor(name) {
|
|
57
|
+
super();
|
|
58
|
+
this.name = name;
|
|
59
|
+
}
|
|
60
|
+
write(key, newValue, oldValue) {
|
|
61
|
+
return newValue;
|
|
62
|
+
}
|
|
63
|
+
read(oldValue, key) {
|
|
64
|
+
return oldValue;
|
|
65
|
+
}
|
|
66
|
+
delete(key) {
|
|
67
|
+
const val = this.get(key);
|
|
68
|
+
const has = typeof val !== "undefined";
|
|
69
|
+
if (has) this.dispose(val, key);
|
|
70
|
+
super.delete(key);
|
|
71
|
+
return has;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Do something with the value and key before removing it from cache
|
|
75
|
+
* For example, close a file or a bitmap
|
|
76
|
+
*/
|
|
77
|
+
dispose(value, key) {
|
|
78
|
+
}
|
|
79
|
+
clear() {
|
|
80
|
+
console.log("CLEAR cache", this.name);
|
|
81
|
+
this.forEach(this.dispose);
|
|
82
|
+
super.clear();
|
|
83
|
+
}
|
|
84
|
+
set(key, value) {
|
|
85
|
+
throw new Error("Use memo() method instead");
|
|
86
|
+
}
|
|
87
|
+
async memo(key, newValue) {
|
|
88
|
+
const oldValue = this.get(key);
|
|
89
|
+
if (!!oldValue && (!newValue || newValue === oldValue)) {
|
|
90
|
+
return this.read?.(oldValue, key);
|
|
91
|
+
}
|
|
92
|
+
if (this.has(key)) this.delete(key);
|
|
93
|
+
const value = await this.write(key, newValue, oldValue);
|
|
94
|
+
super.set(key, value);
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
ANY,
|
|
100
|
+
TransformerMap,
|
|
101
|
+
createTracker,
|
|
102
|
+
equal,
|
|
103
|
+
memo,
|
|
104
|
+
shallowCompare
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sources":["../src/cache.ts"],"sourcesContent":["import ManyKeysMap from 'many-keys-map';\n\nexport type MaybePromise<T> = T | Promise<T>;\n\nexport const shallowCompare = (prev: any, next: any): boolean =>\n Array.from(new Set([...Object.keys(prev), ...Object.keys(next)])).every((key) => prev[key] === next[key]);\n\nexport const equal = (prev: any, next: any): boolean => prev === next;\n\nconst UNUSED = Symbol('UNUSED');\nexport const ANY: unique symbol = Symbol('*');\n\nexport function createTracker<Dep = any>(whenDifferent: (next: Dep, prev?: Dep) => any, shallow = false) {\n let lastDependency: Dep = UNUSED as any;\n\n const comparator = shallow ? shallowCompare : equal;\n\n return function tracker(dependency: Dep): Dep | false {\n // console.log('Tracker', lastDependency, dependency);\n\n if (lastDependency !== UNUSED && comparator(lastDependency, dependency)) {\n // console.log('RETAINED cache', { lastDependency, dependency });\n return false;\n }\n\n // console.log('INVALIDATED cache', {lastDependency, dependency});\n\n const res = whenDifferent(dependency, lastDependency === UNUSED ? undefined : lastDependency) || true;\n\n lastDependency = dependency;\n\n return res;\n };\n}\n\n/**\n * https://github.com/futpib/deep-weak-map\n * https://github.com/fregante/many-keys-map\n * https://github.com/fregante/many-keys-weakmap\n * https://github.com/sindresorhus/memoize?tab=readme-ov-file#example-multiple-non-serializable-arguments\n *\n * ```ts\n * const memoized = memo(\n * (file, options, ...args) => { ... },\n * {\n * key: (file, options, ...args) => [file, JSON.stringify(options), ...args],\n * invalidate: (bitmap) => !bitmap.width,\n * dispose: (bitmap) => bitmap.close(),\n * }\n * );\n * ```\n */\nexport function memo<Key extends any[], Val, SerializedKey extends any[] = Key>(\n fn: (...args: Key) => MaybePromise<Val>,\n {\n key = (...k: Key) => k as never as SerializedKey,\n invalidate,\n dispose,\n }: {\n key?: (...key: Key) => SerializedKey;\n invalidate?: (prev: Val, ...key: SerializedKey) => boolean;\n dispose?: (prev: Val, ...key: SerializedKey) => void;\n } = {},\n): {\n (...args: Key): Promise<{\n value?: Val;\n hit: boolean;\n }>;\n clear: (...condition: Key | any[]) => void;\n size: () => number;\n} {\n const map = new ManyKeysMap<SerializedKey, Val>();\n\n //TODO Extend ManyKeysMap\n const clear = (...condition: Key | any[]) => {\n if (!condition?.length) {\n map.forEach((value, serializedKey) => {\n dispose?.(value, ...serializedKey);\n });\n map.clear();\n return;\n }\n\n const keyToClear = key(...(condition as any));\n\n map.forEach((value, serializedKey) => {\n if (!serializedKey.every((kk, i) => keyToClear[i] === ANY || kk === keyToClear[i])) return;\n dispose?.(value, ...serializedKey);\n map.delete(serializedKey);\n });\n };\n\n const size = () => map.size;\n\n async function memoized(...args: Key) {\n const k = key(...args);\n\n const has = map.has(k);\n const old = map.get(k);\n\n if (has && !invalidate?.(old as never as Val, ...k)) {\n return { value: map.get(k), hit: true };\n }\n\n const value = await fn(...args);\n\n map.set(k, value);\n\n return { hit: false, value };\n }\n\n memoized.clear = clear;\n memoized.size = size;\n\n //TODO return mimic-function(memorized, fn);\n\n return memoized;\n}\n\n/**\n * Allows to memoize values by key and invalidate them based on the previous value.\n *\n * This makes possible to implement various one-off and subsequent transformations.\n *\n * 1. `write`: Transform value BEFORE writing to cache, called only once if cache IS NOT present or IS NOT valid\n * 2. `read`: Transform value AFTER it's read from cache, always called if cache IS valid, keep in mind this transform is applied on top of BEFORE\n *\n * Both should return same type or null.\n *\n * If `newValue` is null, old is returned, and no cache is set.\n *\n * ```ts\n * class InputCache extends TypedCache<string, ImageBitmap> {\n * dispose(bitmap: ImageBitmap, key: string) {\n * bitmap.close();\n * }\n * }\n *\n * const cache = new InputCache('input');\n *\n * // Cache provided OffscreenCanvas by name and create context once per canvas\n *\n * class CanvasCache extends TypedCache<string, OffscreenCanvas> {\n * protected write(key: string, canvas: OffscreenCanvas): OffscreenCanvas {\n * const canvas = newValue.getContext('2d');\n * canvas.ctx = canvas;\n * return canvas;\n * }\n * }\n *\n * // Transfer control to offscreen canvas and track removal of original\n * // When called again, always return null, because canvas is handed to worker, and never returned to main\n *\n * class CanvasCache extends TypedCache<HTMLCanvasElement, OffscreenCanvas> {\n *\n * protected write(canvas: HTMLCanvasElement): OffscreenCanvas {\n * canvas.addEventListener(\n * 'remove',\n * function listener() {\n * console.log('Removing canvas from cache', key);\n * this.delete(canvas);\n * key.removeEventListener('remove', listener);\n * },\n * );\n * return canvas.transferControlToOffscreen();\n * }\n *\n * protected read() {\n * return null;\n * }\n * }\n *\n * // Create bitmap from file and check if was used, return null if used\n * // Since bitmaps are also cached in worker, used bitmaps are not sent\n *\n * class BitmapCache extends TypedCache<File, ImageBitmap, File> {\n * protected async write(file: File): Promise<ImageBitmap> {\n * return await createImageBitmap(file);\n * }\n *\n * protected read(bitmap: ImageBitmap): Promise<ImageBitmap> | ImageBitmap {\n * if (!bitmap.width) return null;\n * return bitmap;\n * }\n * }\n *\n * ```\n */\nexport abstract class TransformerMap<Key, Val = Key> extends Map<Key, Val> {\n constructor(protected readonly name: string) {\n // console.warn('CREATE cache', name);\n super();\n }\n\n protected write(key: Key, newValue?: Val, oldValue?: Val): MaybePromise<Val> {\n return newValue as Val;\n }\n\n protected read(oldValue: Val, key: Key): MaybePromise<Val> {\n return oldValue;\n }\n\n delete(key: Key): boolean {\n const val = this.get(key);\n const has = typeof val !== 'undefined';\n if (has) this.dispose(val, key);\n super.delete(key);\n return has;\n }\n\n /**\n * Do something with the value and key before removing it from cache\n * For example, close a file or a bitmap\n */\n protected dispose(value: Val, key: Key): void {}\n\n clear(): void {\n console.log('CLEAR cache', this.name);\n this.forEach(this.dispose);\n super.clear();\n }\n\n set(key: Key, value: Val): this {\n throw new Error('Use memo() method instead');\n }\n\n async memo(key: Key, newValue?: Val): Promise<Val> {\n const oldValue = this.get(key);\n\n if (!!oldValue && (!newValue || newValue === oldValue)) {\n // console.log('FROM cache', this.name, key, 'old value', oldValue);\n return this.read?.(oldValue, key);\n }\n\n if (this.has(key)) this.delete(key);\n\n const value = await this.write(key, newValue, oldValue);\n\n super.set(key, value);\n\n // console.log('INVALIDATED KEY cache', this.name, key, 'has', has, 'invalidate', invalidate, 'new value', value);\n\n return value;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../src/cache.test.ts"],"names":[],"mappings":""}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,EAClD,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,MAAM,CAAC,EAAE,CAAC,EAAE,GACb,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAYpC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function catchErrors(promise, errors) {
|
|
2
|
+
return promise.then((data) => [void 0, data]).catch((error) => {
|
|
3
|
+
if (!errors?.length) {
|
|
4
|
+
return [error];
|
|
5
|
+
}
|
|
6
|
+
if (errors.some((e) => e instanceof error)) {
|
|
7
|
+
return [error];
|
|
8
|
+
}
|
|
9
|
+
throw error;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
catchErrors
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sources":["../src/errors.ts"],"sourcesContent":["// @see https://www.youtube.com/watch?v=AdmGHwvgaVs\nexport function catchErrors<T, E extends Error = Error>(\n promise: Promise<T>,\n errors?: E[],\n): Promise<any[] | (T | undefined)[]> {\n return promise\n .then((data) => [undefined, data])\n .catch((error) => {\n if (!errors?.length) {\n return [error];\n }\n if (errors.some((e) => e instanceof error)) {\n return [error];\n }\n throw error;\n });\n}\n"],"names":[],"mappings":"AACO,SAAS,YACZ,SACA,QACkC;AAClC,SAAO,QACF,KAAK,CAAC,SAAS,CAAC,QAAW,IAAI,CAAC,EAChC,MAAM,CAAC,UAAU;AACd,QAAI,CAAC,QAAQ,QAAQ;AACjB,aAAO,CAAC,KAAK;AAAA,IACjB;AACA,QAAI,OAAO,KAAK,CAAC,MAAM,aAAa,KAAK,GAAG;AACxC,aAAO,CAAC,KAAK;AAAA,IACjB;AACA,UAAM;AAAA,EACV,CAAC;AACT;"}
|
package/dist/files.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAM3D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,MAAM,GAAG,EAAE,iBAAsB,EAAE,aAAyB,KAAG,OAAO,CAAC,IAAI,CAE3G,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,OAAO,CAAC,MAAM,CAgBpC,CAAC"}
|
package/dist/files.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const downloadFile = async (file) => {
|
|
2
|
+
const { saveAs } = require("file-saver");
|
|
3
|
+
return saveAs(file, file.name);
|
|
4
|
+
};
|
|
5
|
+
const createFile = async (text, filename = "file.json", type = "application/json") => {
|
|
6
|
+
return new File([new Blob([text], { type })], filename);
|
|
7
|
+
};
|
|
8
|
+
const openFile = () => new Promise((res, rej) => {
|
|
9
|
+
const input = document.createElement("input");
|
|
10
|
+
input.type = "file";
|
|
11
|
+
input.addEventListener("change", function readFile(e) {
|
|
12
|
+
input.removeEventListener("change", readFile);
|
|
13
|
+
const [file] = e.target.files;
|
|
14
|
+
if (!file) return;
|
|
15
|
+
const reader = new FileReader();
|
|
16
|
+
reader.onload = (e2) => res(e2.target?.result);
|
|
17
|
+
reader.onerror = rej;
|
|
18
|
+
reader.onabort = rej;
|
|
19
|
+
reader.readAsText(file);
|
|
20
|
+
});
|
|
21
|
+
input.click();
|
|
22
|
+
});
|
|
23
|
+
export {
|
|
24
|
+
createFile,
|
|
25
|
+
downloadFile,
|
|
26
|
+
openFile
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sources":["../src/files.ts"],"sourcesContent":["export const downloadFile = async (file: File): Promise<void> => {\n //FIXME https://github.com/eligrey/FileSaver.js/issues/471\n const { saveAs } = require('file-saver');\n\n //FIXME https://github.com/eligrey/FileSaver.js/issues/731\n return saveAs(file, file.name);\n};\n\nexport const createFile = async (text: any, filename = 'file.json', type = 'application/json'): Promise<File> => {\n return new File([new Blob([text], { type })], filename);\n};\n\nexport const openFile = (): Promise<string> =>\n new Promise((res, rej) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.addEventListener('change', function readFile(e) {\n input.removeEventListener('change', readFile);\n // @ts-expect-error file is always there\n const [file] = e.target.files;\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (e) => res(e.target?.result as string);\n reader.onerror = rej;\n reader.onabort = rej;\n reader.readAsText(file);\n });\n input.click();\n });\n"],"names":["e"],"mappings":"AAAO,MAAM,eAAe,OAAO,SAA8B;AAE7D,QAAM,EAAE,OAAA,IAAW,QAAQ,YAAY;AAGvC,SAAO,OAAO,MAAM,KAAK,IAAI;AACjC;AAEO,MAAM,aAAa,OAAO,MAAW,WAAW,aAAa,OAAO,uBAAsC;AAC7G,SAAO,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,KAAA,CAAM,CAAC,GAAG,QAAQ;AAC1D;AAEO,MAAM,WAAW,MACpB,IAAI,QAAQ,CAAC,KAAK,QAAQ;AACtB,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,OAAO;AACb,QAAM,iBAAiB,UAAU,SAAS,SAAS,GAAG;AAClD,UAAM,oBAAoB,UAAU,QAAQ;AAE5C,UAAM,CAAC,IAAI,IAAI,EAAE,OAAO;AACxB,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,IAAI,WAAA;AACnB,WAAO,SAAS,CAACA,OAAM,IAAIA,GAAE,QAAQ,MAAgB;AACrD,WAAO,UAAU;AACjB,WAAO,UAAU;AACjB,WAAO,WAAW,IAAI;AAAA,EAC1B,CAAC;AACD,QAAM,MAAA;AACV,CAAC;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './cache';
|
|
2
|
+
export * from './errors';
|
|
3
|
+
export * from './files';
|
|
4
|
+
export * from './ls';
|
|
5
|
+
export * from './measure';
|
|
6
|
+
export * from './mutex';
|
|
7
|
+
export * from './worker';
|
|
8
|
+
export * from './workerUtils';
|
|
9
|
+
export * from './wrpc';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|