@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.
Files changed (71) hide show
  1. package/.ctirc +11 -0
  2. package/.turbo/turbo-build.log +26 -0
  3. package/.turbo/turbo-test.log +103 -0
  4. package/README.md +91 -0
  5. package/demo/worker-demo.ts +73 -0
  6. package/dist/cache.d.ts +119 -0
  7. package/dist/cache.d.ts.map +1 -0
  8. package/dist/cache.js +106 -0
  9. package/dist/cache.js.map +1 -0
  10. package/dist/cache.test.d.ts +2 -0
  11. package/dist/cache.test.d.ts.map +1 -0
  12. package/dist/errors.d.ts +2 -0
  13. package/dist/errors.d.ts.map +1 -0
  14. package/dist/errors.js +15 -0
  15. package/dist/errors.js.map +1 -0
  16. package/dist/files.d.ts +4 -0
  17. package/dist/files.d.ts.map +1 -0
  18. package/dist/files.js +28 -0
  19. package/dist/files.js.map +1 -0
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +35 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/ls.d.ts +6 -0
  25. package/dist/ls.d.ts.map +1 -0
  26. package/dist/ls.js +12 -0
  27. package/dist/ls.js.map +1 -0
  28. package/dist/measure.d.ts +35 -0
  29. package/dist/measure.d.ts.map +1 -0
  30. package/dist/measure.js +60 -0
  31. package/dist/measure.js.map +1 -0
  32. package/dist/mutex.d.ts +6 -0
  33. package/dist/mutex.d.ts.map +1 -0
  34. package/dist/mutex.js +21 -0
  35. package/dist/mutex.js.map +1 -0
  36. package/dist/worker.d.ts +98 -0
  37. package/dist/worker.d.ts.map +1 -0
  38. package/dist/worker.js +226 -0
  39. package/dist/worker.js.map +1 -0
  40. package/dist/worker.test.d.ts +2 -0
  41. package/dist/worker.test.d.ts.map +1 -0
  42. package/dist/workerUtils.d.ts +3 -0
  43. package/dist/workerUtils.d.ts.map +1 -0
  44. package/dist/workerUtils.js +31 -0
  45. package/dist/workerUtils.js.map +1 -0
  46. package/dist/wrpc.d.ts +45 -0
  47. package/dist/wrpc.d.ts.map +1 -0
  48. package/dist/wrpc.fixture.d.ts +26 -0
  49. package/dist/wrpc.fixture.d.ts.map +1 -0
  50. package/dist/wrpc.js +241 -0
  51. package/dist/wrpc.js.map +1 -0
  52. package/dist/wrpc.test.d.ts +1 -0
  53. package/dist/wrpc.test.d.ts.map +1 -0
  54. package/package.json +46 -0
  55. package/src/cache.test.ts +121 -0
  56. package/src/cache.ts +245 -0
  57. package/src/errors.ts +17 -0
  58. package/src/files.ts +29 -0
  59. package/src/index.ts +9 -0
  60. package/src/ls.ts +15 -0
  61. package/src/measure.ts +109 -0
  62. package/src/mutex.ts +22 -0
  63. package/src/worker.test.ts +197 -0
  64. package/src/worker.ts +347 -0
  65. package/src/workerUtils.ts +32 -0
  66. package/src/wrpc.fixture.ts +106 -0
  67. package/src/wrpc.test.ts +225 -0
  68. package/src/wrpc.ts +377 -0
  69. package/tsconfig.json +10 -0
  70. package/turbo.json +10 -0
  71. package/vite.config.ts +2 -0
package/.ctirc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "addNewline": true,
3
+ "fileExcludePatterns": [
4
+ "*.stories.*",
5
+ "*.test.*",
6
+ "*.fixture.*"
7
+ ],
8
+ "verbose": false,
9
+ "withoutBackupFile": true,
10
+ "withoutComment": true
11
+ }
@@ -0,0 +1,26 @@
1
+ vite v7.0.6 building SSR bundle for production...
2
+ create succeeded: /home/runner/work/utils/utils/packages/core/src
3
+ transforming...
4
+ ✓ 10 modules transformed.
5
+ rendering chunks...
6
+
7
+ [vite:dts] Start generate declaration files...
8
+ src/workerUtils.ts:22:64 - error TS2322: Type 'null' is not assignable to type 'boolean'.
9
+
10
+ 22 return transferrable.some((t) => obj instanceof t) ? obj : null;
11
+    ~~~~
12
+
13
+ dist/errors.js 0.33 kB │ map: 0.90 kB
14
+ dist/mutex.js 0.40 kB │ map: 1.18 kB
15
+ dist/ls.js 0.44 kB │ map: 1.05 kB
16
+ dist/files.js 0.84 kB │ map: 1.89 kB
17
+ dist/index.js 0.92 kB │ map: 0.10 kB
18
+ dist/workerUtils.js 0.97 kB │ map: 1.82 kB
19
+ dist/measure.js 1.44 kB │ map: 4.08 kB
20
+ dist/cache.js 2.92 kB │ map: 10.21 kB
21
+ dist/worker.js 7.06 kB │ map: 16.69 kB
22
+ dist/wrpc.js 8.73 kB │ map: 20.98 kB
23
+ [vite:dts] Declaration files built in 1945ms.
24
+
25
+ ✓ built in 2.75s
26
+ Updated package.json with exports
@@ -0,0 +1,103 @@
1
+ create succeeded: /home/runner/work/utils/utils/packages/core/src
2
+
3
+  RUN  v3.2.4 /home/runner/work/utils/utils/packages/core
4
+ Coverage enabled with v8
5
+
6
+ stderr | src/wrpc.test.ts
7
+ Using 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
+ stdout | src/cache.test.ts > TransformerMap > key transform
10
+ CLEAR cache test
11
+
12
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
13
+ DATA 1
14
+
15
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
16
+ DATA 2
17
+
18
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
19
+ DATA 3
20
+
21
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
22
+ DATA { value: 1, done: false }
23
+
24
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
25
+ DATA { value: 2, done: false }
26
+
27
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
28
+ DATA { value: 3, done: false }
29
+
30
+ ✓ src/cache.test.ts (4 tests) 13ms
31
+ stdout | src/wrpc.test.ts > WRPC > for await ... of return yield
32
+ DATA { value: undefined, done: true }
33
+
34
+ ✓ src/worker.test.ts (8 tests) 13ms
35
+ stdout | src/wrpc.test.ts > WRPC > for await ... of separate return & yield
36
+ DATA { progress: 0 }
37
+
38
+ stdout | src/wrpc.test.ts > WRPC > for await ... of separate return & yield
39
+ DATA { progress: 0.5 }
40
+
41
+ stdout | src/wrpc.test.ts > WRPC > for await ... of separate return & yield
42
+ DATA { progress: 1, aborted: false }
43
+
44
+ stdout | src/wrpc.test.ts > WRPC > do ... while
45
+ DATA { value: { progress: 0 }, done: false }
46
+
47
+ stdout | src/wrpc.test.ts > WRPC > do ... while
48
+ DATA { value: { progress: 0.5 }, done: false }
49
+
50
+ stdout | src/wrpc.test.ts > WRPC > do ... while
51
+ DATA { value: { progress: 1, aborted: false }, done: false }
52
+
53
+ stdout | src/wrpc.test.ts > WRPC > do ... while
54
+ DATA { value: 'foo', done: true }
55
+
56
+ stdout | src/wrpc.test.ts > WRPC > break
57
+ DATA { progress: 0 }
58
+
59
+ stdout | src/wrpc.test.ts > WRPC > abort
60
+ DATA { progress: 0 }
61
+
62
+ ✓ src/wrpc.test.ts (13 tests | 1 skipped) 719ms
63
+ ✓ WRPC > stop  503ms
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
+  Test Files  3 passed (3)
78
+  Tests  24 passed | 1 skipped (25)
79
+  Start at  01:30:13
80
+  Duration  1.33s (transform 220ms, setup 0ms, collect 329ms, tests 746ms, environment 1ms, prepare 444ms)
81
+
82
+  % Coverage report from v8
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
+ });
@@ -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":";AAIO,MAAM,iBAAiB,CAAC,MAAW,SACtC,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,IAAI,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,KAAK,GAAG,MAAM,KAAK,GAAG,CAAC;AAErG,MAAM,QAAQ,CAAC,MAAW,SAAuB,SAAS;AAEjE,MAAM,SAAS,OAAO,QAAQ;AACvB,MAAM,MAAqB,OAAO,GAAG;AAErC,SAAS,cAAyB,eAA+C,UAAU,OAAO;AACrG,MAAI,iBAAsB;AAE1B,QAAM,aAAa,UAAU,iBAAiB;AAE9C,SAAO,SAAS,QAAQ,YAA8B;AAGlD,QAAI,mBAAmB,UAAU,WAAW,gBAAgB,UAAU,GAAG;AAErE,aAAO;AAAA,IACX;AAIA,UAAM,MAAM,cAAc,YAAY,mBAAmB,SAAS,SAAY,cAAc,KAAK;AAEjG,qBAAiB;AAEjB,WAAO;AAAA,EACX;AACJ;AAmBO,SAAS,KACZ,IACA;AAAA,EACI,MAAM,IAAI,MAAW;AAAA,EACrB;AAAA,EACA;AACJ,IAII,IAQN;AACE,QAAM,MAAM,IAAI,YAAA;AAGhB,QAAM,QAAQ,IAAI,cAA2B;AACzC,QAAI,CAAC,WAAW,QAAQ;AACpB,UAAI,QAAQ,CAAC,OAAO,kBAAkB;AAClC,kBAAU,OAAO,GAAG,aAAa;AAAA,MACrC,CAAC;AACD,UAAI,MAAA;AACJ;AAAA,IACJ;AAEA,UAAM,aAAa,IAAI,GAAI,SAAiB;AAE5C,QAAI,QAAQ,CAAC,OAAO,kBAAkB;AAClC,UAAI,CAAC,cAAc,MAAM,CAAC,IAAI,MAAM,WAAW,CAAC,MAAM,OAAO,OAAO,WAAW,CAAC,CAAC,EAAG;AACpF,gBAAU,OAAO,GAAG,aAAa;AACjC,UAAI,OAAO,aAAa;AAAA,IAC5B,CAAC;AAAA,EACL;AAEA,QAAM,OAAO,MAAM,IAAI;AAEvB,iBAAe,YAAY,MAAW;AAClC,UAAM,IAAI,IAAI,GAAG,IAAI;AAErB,UAAM,MAAM,IAAI,IAAI,CAAC;AACrB,UAAM,MAAM,IAAI,IAAI,CAAC;AAErB,QAAI,OAAO,CAAC,aAAa,KAAqB,GAAG,CAAC,GAAG;AACjD,aAAO,EAAE,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,KAAA;AAAA,IACrC;AAEA,UAAM,QAAQ,MAAM,GAAG,GAAG,IAAI;AAE9B,QAAI,IAAI,GAAG,KAAK;AAEhB,WAAO,EAAE,KAAK,OAAO,MAAA;AAAA,EACzB;AAEA,WAAS,QAAQ;AACjB,WAAS,OAAO;AAIhB,SAAO;AACX;AAuEO,MAAe,uBAAuC,IAAc;AAAA,EACvE,YAA+B,MAAc;AAEzC,UAAA;AAF2B,SAAA,OAAA;AAAA,EAG/B;AAAA,EAEU,MAAM,KAAU,UAAgB,UAAmC;AACzE,WAAO;AAAA,EACX;AAAA,EAEU,KAAK,UAAe,KAA6B;AACvD,WAAO;AAAA,EACX;AAAA,EAEA,OAAO,KAAmB;AACtB,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,MAAM,OAAO,QAAQ;AAC3B,QAAI,IAAK,MAAK,QAAQ,KAAK,GAAG;AAC9B,UAAM,OAAO,GAAG;AAChB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,QAAQ,OAAY,KAAgB;AAAA,EAAC;AAAA,EAE/C,QAAc;AACV,YAAQ,IAAI,eAAe,KAAK,IAAI;AACpC,SAAK,QAAQ,KAAK,OAAO;AACzB,UAAM,MAAA;AAAA,EACV;AAAA,EAEA,IAAI,KAAU,OAAkB;AAC5B,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC/C;AAAA,EAEA,MAAM,KAAK,KAAU,UAA8B;AAC/C,UAAM,WAAW,KAAK,IAAI,GAAG;AAE7B,QAAI,CAAC,CAAC,aAAa,CAAC,YAAY,aAAa,WAAW;AAEpD,aAAO,KAAK,OAAO,UAAU,GAAG;AAAA,IACpC;AAEA,QAAI,KAAK,IAAI,GAAG,EAAG,MAAK,OAAO,GAAG;AAElC,UAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,UAAU,QAAQ;AAEtD,UAAM,IAAI,KAAK,KAAK;AAIpB,WAAO;AAAA,EACX;AACJ;"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../src/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function catchErrors<T, E extends Error = Error>(promise: Promise<T>, errors?: E[]): Promise<any[] | (T | undefined)[]>;
2
+ //# sourceMappingURL=errors.d.ts.map
@@ -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;"}
@@ -0,0 +1,4 @@
1
+ export declare const downloadFile: (file: File) => Promise<void>;
2
+ export declare const createFile: (text: any, filename?: string, type?: string) => Promise<File>;
3
+ export declare const openFile: () => Promise<string>;
4
+ //# sourceMappingURL=files.d.ts.map
@@ -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;"}
@@ -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