@utoo/web 1.2.0-rc.1 → 1.2.0-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +55 -0
  2. package/esm/{aa0ad15d2a587c43406f.wasm → 7a09b7ab69b3abceced7.wasm} +0 -0
  3. package/esm/index.d.ts +3 -2
  4. package/esm/index.js +3 -2
  5. package/esm/loaderWorker.js +1 -1
  6. package/esm/loaderWorker.js.LICENSE.txt +0 -21
  7. package/esm/{forkedProject.d.ts → project/ForkedProject.d.ts} +5 -3
  8. package/esm/{forkedProject.js → project/ForkedProject.js} +8 -0
  9. package/esm/{internalProject.d.ts → project/InternalProject.d.ts} +5 -4
  10. package/esm/project/InternalProject.js +134 -0
  11. package/esm/{project.d.ts → project/Project.d.ts} +3 -1
  12. package/esm/{project.js → project/Project.js} +19 -6
  13. package/esm/serviceWorker.js +4 -3
  14. package/esm/{type.d.ts → types.d.ts} +43 -0
  15. package/esm/types.js +56 -0
  16. package/esm/utils/sabcom.d.ts +61 -0
  17. package/esm/utils/sabcom.js +203 -0
  18. package/esm/utoo/index.d.ts +73 -38
  19. package/esm/utoo/index.js +167 -143
  20. package/esm/utoo/index_bg.wasm +0 -0
  21. package/esm/webpackLoaders/{worker/cjs.js → cjs.js} +65 -41
  22. package/esm/webpackLoaders/loaderWorkerPool.d.ts +2 -0
  23. package/esm/webpackLoaders/loaderWorkerPool.js +90 -0
  24. package/esm/webpackLoaders/polyfills/fsPolyfill.d.ts +78 -0
  25. package/esm/webpackLoaders/{worker/polyfills → polyfills}/fsPolyfill.js +154 -191
  26. package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.d.ts +26 -0
  27. package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.js +112 -0
  28. package/esm/webpackLoaders/{worker/polyfills → polyfills}/nodePolyFills.d.ts +0 -2
  29. package/esm/webpackLoaders/{worker/polyfills → polyfills}/nodePolyFills.js +4 -3
  30. package/esm/webpackLoaders/{worker/type.d.ts → types.d.ts} +1 -0
  31. package/esm/webpackLoaders/{worker/index.js → worker.js} +8 -3
  32. package/esm/worker.js +2 -2
  33. package/package.json +14 -13
  34. package/esm/internalProject.js +0 -110
  35. package/esm/loaderWorkerPool.d.ts +0 -3
  36. package/esm/loaderWorkerPool.js +0 -125
  37. package/esm/sabcom.d.ts +0 -31
  38. package/esm/sabcom.js +0 -71
  39. package/esm/type.js +0 -12
  40. package/esm/webpackLoaders/loaders/less-loader/index.d.ts +0 -3
  41. package/esm/webpackLoaders/loaders/less-loader/index.js +0 -103
  42. package/esm/webpackLoaders/loaders/less-loader/options.json +0 -67
  43. package/esm/webpackLoaders/loaders/less-loader/utils.d.ts +0 -14
  44. package/esm/webpackLoaders/loaders/less-loader/utils.js +0 -217
  45. package/esm/webpackLoaders/worker/polyfills/fastGlobPolyfill.d.ts +0 -2
  46. package/esm/webpackLoaders/worker/polyfills/fastGlobPolyfill.js +0 -48
  47. package/esm/webpackLoaders/worker/polyfills/fsPolyfill.d.ts +0 -124
  48. package/esm/webpackLoaders/worker/polyfills/fsPromisesPolyfill.d.ts +0 -9
  49. package/esm/webpackLoaders/worker/polyfills/fsPromisesPolyfill.js +0 -9
  50. /package/esm/{installServiceWorker.d.ts → utils/installServiceWorker.d.ts} +0 -0
  51. /package/esm/{installServiceWorker.js → utils/installServiceWorker.js} +0 -0
  52. /package/esm/{message.d.ts → utils/message.d.ts} +0 -0
  53. /package/esm/{message.js → utils/message.js} +0 -0
  54. /package/esm/webpackLoaders/{worker/cjs.d.ts → cjs.d.ts} +0 -0
  55. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/workerThreadsPolyfill.d.ts +0 -0
  56. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/workerThreadsPolyfill.js +0 -0
  57. /package/esm/webpackLoaders/{worker/type.js → types.js} +0 -0
  58. /package/esm/webpackLoaders/{worker/index.d.ts → worker.d.ts} +0 -0
@@ -0,0 +1,203 @@
1
+ export const SAB_STATE_IDLE = 0;
2
+ export const SAB_STATE_REQUEST = 1;
3
+ export const SAB_STATE_RESPONSE = 2;
4
+ export const SAB_STATE_ERROR = 3;
5
+ export const SAB_OP_READ_FILE = 1;
6
+ export const SAB_OP_READ_DIR = 2;
7
+ export const SAB_OP_WRITE_FILE = 3;
8
+ export const SAB_OP_MKDIR = 4;
9
+ export const SAB_OP_RM = 5;
10
+ export const SAB_OP_RMDIR = 6;
11
+ export const SAB_OP_COPY_FILE = 7;
12
+ export const SAB_OP_STAT = 8;
13
+ export const STAT_TYPE_FILE = 0;
14
+ export const STAT_TYPE_DIR = 1;
15
+ export const SAB_INDEX_STATE = 0;
16
+ export const SAB_INDEX_OP = 1;
17
+ export const SAB_INDEX_DATA_LEN = 2;
18
+ export const SAB_DATA_OFFSET = 12;
19
+ // Stat struct layout (starts at byte 12)
20
+ // type: Uint8 (1 byte) -> offset 0
21
+ // padding: 7 bytes
22
+ // size: BigUint64 (8 bytes) -> offset 8
23
+ // atimeMs: Float64 (8 bytes) -> offset 16
24
+ // mtimeMs: Float64 (8 bytes) -> offset 24
25
+ // ctimeMs: Float64 (8 bytes) -> offset 32
26
+ // birthtimeMs: Float64 (8 bytes) -> offset 40
27
+ const STAT_OFFSET_TYPE = 0;
28
+ const STAT_OFFSET_SIZE = 8;
29
+ const STAT_OFFSET_ATIME = 16;
30
+ const STAT_OFFSET_MTIME = 24;
31
+ const STAT_OFFSET_CTIME = 32;
32
+ const STAT_OFFSET_BIRTHTIME = 40;
33
+ // Layout:
34
+ // 0: State (Int32)
35
+ // 1: Op (Int32)
36
+ // 2: Data Length (Int32)
37
+ // 12...: Data (Uint8) - Start at byte 12 (3 * 4 bytes)
38
+ export class SabComHost {
39
+ constructor(sab) {
40
+ this.sab = sab;
41
+ this.int32 = new Int32Array(sab);
42
+ this.uint8 = new Uint8Array(sab);
43
+ this.dataView = new DataView(sab);
44
+ }
45
+ readRequest() {
46
+ const op = this.int32[SAB_INDEX_OP];
47
+ const len = this.int32[SAB_INDEX_DATA_LEN];
48
+ const data = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
49
+ return { op, data };
50
+ }
51
+ writeResponse(data) {
52
+ if (typeof data === "string") {
53
+ data = new TextEncoder().encode(data);
54
+ }
55
+ // TODO: Check size overflow
56
+ this.int32[SAB_INDEX_DATA_LEN] = data.length;
57
+ this.uint8.set(data, SAB_DATA_OFFSET);
58
+ Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_RESPONSE);
59
+ Atomics.notify(this.int32, SAB_INDEX_STATE);
60
+ }
61
+ writeError(message) {
62
+ const data = new TextEncoder().encode(message);
63
+ this.int32[SAB_INDEX_DATA_LEN] = data.length;
64
+ this.uint8.set(data, SAB_DATA_OFFSET);
65
+ Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_ERROR);
66
+ Atomics.notify(this.int32, SAB_INDEX_STATE);
67
+ }
68
+ writeStat(type, size, atimeMs, mtimeMs, ctimeMs, birthtimeMs) {
69
+ const base = SAB_DATA_OFFSET;
70
+ this.dataView.setUint8(base + STAT_OFFSET_TYPE, type);
71
+ this.dataView.setBigUint64(base + STAT_OFFSET_SIZE, size, true);
72
+ this.dataView.setFloat64(base + STAT_OFFSET_ATIME, atimeMs, true);
73
+ this.dataView.setFloat64(base + STAT_OFFSET_MTIME, mtimeMs, true);
74
+ this.dataView.setFloat64(base + STAT_OFFSET_CTIME, ctimeMs, true);
75
+ this.dataView.setFloat64(base + STAT_OFFSET_BIRTHTIME, birthtimeMs, true);
76
+ Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_RESPONSE);
77
+ Atomics.notify(this.int32, SAB_INDEX_STATE);
78
+ }
79
+ }
80
+ export class SabComClient {
81
+ constructor(sab, notifyHost) {
82
+ this.sab = sab;
83
+ this.notifyHost = notifyHost;
84
+ this.int32 = new Int32Array(sab);
85
+ this.uint8 = new Uint8Array(sab);
86
+ this.dataView = new DataView(sab);
87
+ }
88
+ call(op, data) {
89
+ const encoded = new TextEncoder().encode(data);
90
+ this.int32[SAB_INDEX_OP] = op;
91
+ this.int32[SAB_INDEX_DATA_LEN] = encoded.length;
92
+ this.uint8.set(encoded, SAB_DATA_OFFSET);
93
+ Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
94
+ this.notifyHost();
95
+ Atomics.wait(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
96
+ const state = Atomics.load(this.int32, SAB_INDEX_STATE);
97
+ if (state === SAB_STATE_ERROR) {
98
+ const len = this.int32[SAB_INDEX_DATA_LEN];
99
+ const msg = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
100
+ throw new Error(msg);
101
+ }
102
+ const len = this.int32[SAB_INDEX_DATA_LEN];
103
+ return this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len);
104
+ }
105
+ callStat(path) {
106
+ const encoded = new TextEncoder().encode(path);
107
+ this.int32[SAB_INDEX_OP] = SAB_OP_STAT;
108
+ this.int32[SAB_INDEX_DATA_LEN] = encoded.length;
109
+ this.uint8.set(encoded, SAB_DATA_OFFSET);
110
+ Atomics.store(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
111
+ this.notifyHost();
112
+ Atomics.wait(this.int32, SAB_INDEX_STATE, SAB_STATE_REQUEST);
113
+ const state = Atomics.load(this.int32, SAB_INDEX_STATE);
114
+ if (state === SAB_STATE_ERROR) {
115
+ const len = this.int32[SAB_INDEX_DATA_LEN];
116
+ const msg = new TextDecoder().decode(this.uint8.slice(SAB_DATA_OFFSET, SAB_DATA_OFFSET + len));
117
+ throw new Error(msg);
118
+ }
119
+ const base = SAB_DATA_OFFSET;
120
+ return {
121
+ type: this.dataView.getUint8(base + STAT_OFFSET_TYPE),
122
+ size: this.dataView.getBigUint64(base + STAT_OFFSET_SIZE, true),
123
+ atimeMs: this.dataView.getFloat64(base + STAT_OFFSET_ATIME, true),
124
+ mtimeMs: this.dataView.getFloat64(base + STAT_OFFSET_MTIME, true),
125
+ ctimeMs: this.dataView.getFloat64(base + STAT_OFFSET_CTIME, true),
126
+ birthtimeMs: this.dataView.getFloat64(base + STAT_OFFSET_BIRTHTIME, true),
127
+ };
128
+ }
129
+ }
130
+ export const handleSabRequest = async (sabHost, fs) => {
131
+ const { op, data: path } = sabHost.readRequest();
132
+ try {
133
+ if (op === SAB_OP_READ_FILE) {
134
+ const bytes = await fs.read(path);
135
+ sabHost.writeResponse(bytes);
136
+ }
137
+ else if (op === SAB_OP_READ_DIR) {
138
+ const entries = await fs.readDir(path);
139
+ sabHost.writeResponse(JSON.stringify(entries.map((e) => e.toJSON())));
140
+ }
141
+ else if (op === SAB_OP_WRITE_FILE) {
142
+ const { path: filePath, data: fileContent } = JSON.parse(path);
143
+ // TODO: handle binary content (base64?)
144
+ await fs.writeString(filePath, fileContent);
145
+ sabHost.writeResponse("ok");
146
+ }
147
+ else if (op === SAB_OP_MKDIR) {
148
+ const { path: dirPath, recursive } = JSON.parse(path);
149
+ if (recursive) {
150
+ await fs.createDirAll(dirPath);
151
+ }
152
+ else {
153
+ await fs.createDir(dirPath);
154
+ }
155
+ sabHost.writeResponse("ok");
156
+ }
157
+ else if (op === SAB_OP_RM) {
158
+ const { path: rmPath, recursive } = JSON.parse(path);
159
+ // Mimic internalProject.rm logic
160
+ const metadata = await fs.metadata(rmPath);
161
+ const json = metadata.toJSON
162
+ ? metadata.toJSON()
163
+ : metadata;
164
+ const type = json.type;
165
+ if (type === "file") {
166
+ await fs.removeFile(rmPath);
167
+ }
168
+ else if (type === "directory") {
169
+ await fs.removeDir(rmPath, !!recursive);
170
+ }
171
+ sabHost.writeResponse("ok");
172
+ }
173
+ else if (op === SAB_OP_RMDIR) {
174
+ const { path: rmPath, recursive } = JSON.parse(path);
175
+ await fs.removeDir(rmPath, !!recursive);
176
+ sabHost.writeResponse("ok");
177
+ }
178
+ else if (op === SAB_OP_COPY_FILE) {
179
+ const { src, dst } = JSON.parse(path);
180
+ await fs.copyFile(src, dst);
181
+ sabHost.writeResponse("ok");
182
+ }
183
+ else if (op === SAB_OP_STAT) {
184
+ const metadata = await fs.metadata(path);
185
+ const json = metadata.toJSON
186
+ ? metadata.toJSON()
187
+ : metadata;
188
+ const type = json.type === "directory" ? STAT_TYPE_DIR : STAT_TYPE_FILE;
189
+ const size = BigInt(json.file_size || 0);
190
+ const atimeMs = Number(json.atimeMs || 0);
191
+ const mtimeMs = Number(json.mtimeMs || 0);
192
+ const ctimeMs = Number(json.ctimeMs || 0);
193
+ const birthtimeMs = Number(json.birthtimeMs || 0);
194
+ sabHost.writeStat(type, size, atimeMs, mtimeMs, ctimeMs, birthtimeMs);
195
+ }
196
+ else {
197
+ sabHost.writeError("Unknown op");
198
+ }
199
+ }
200
+ catch (e) {
201
+ sabHost.writeError(e.message);
202
+ }
203
+ };
@@ -1,27 +1,27 @@
1
- /**
2
- * @param {any} message
3
- * @returns {Promise<void>}
4
- */
5
- export function sendTaskMessage(message: any): Promise<void>;
6
1
  /**
7
2
  * @param {number} worker_id
8
3
  * @returns {Promise<WasmTaskMessage>}
9
4
  */
10
5
  export function recvTaskMessageInWorker(worker_id: number): Promise<WasmTaskMessage>;
11
- export function init_pack(): void;
12
6
  /**
13
- * @param {string} filter
7
+ * @param {any} message
8
+ * @returns {Promise<void>}
14
9
  */
15
- export function init_log_filter(filter: string): void;
10
+ export function sendTaskMessage(message: any): Promise<void>;
11
+ export function init_pack(): void;
16
12
  /**
17
- * @param {number} worker_id
13
+ * @param {string} filter
18
14
  */
19
- export function workerCreated(worker_id: number): void;
15
+ export function initLogFilter(filter: string): void;
20
16
  /**
21
17
  * @param {Function} creator
22
18
  * @param {Function} terminator
23
19
  */
24
20
  export function registerWorkerScheduler(creator: Function, terminator: Function): void;
21
+ /**
22
+ * @param {number} worker_id
23
+ */
24
+ export function workerCreated(worker_id: number): void;
25
25
  /**
26
26
  * Entry point for web workers
27
27
  * @param {number} ptr
@@ -62,107 +62,142 @@ export class DirEntry {
62
62
  }
63
63
  export class Metadata {
64
64
  static __wrap(ptr: any): any;
65
- toJSON(): {};
65
+ toJSON(): {
66
+ type: DirEntryType;
67
+ file_size: bigint;
68
+ };
66
69
  toString(): string;
67
70
  __destroy_into_raw(): number | undefined;
68
71
  __wbg_ptr: number | undefined;
69
72
  free(): void;
70
- }
71
- export class Project {
72
73
  /**
73
- * @param {string} cwd
74
- * @param {string} thread_url
74
+ * @param {DirEntryType} arg0
75
75
  */
76
- constructor(cwd: string, thread_url: string);
77
- __destroy_into_raw(): number;
78
- __wbg_ptr: number;
79
- free(): void;
76
+ set type(arg0: DirEntryType);
77
+ /**
78
+ * @returns {DirEntryType}
79
+ */
80
+ get type(): DirEntryType;
81
+ /**
82
+ * @param {bigint} arg0
83
+ */
84
+ set file_size(arg0: bigint);
85
+ /**
86
+ * @returns {bigint}
87
+ */
88
+ get file_size(): bigint;
89
+ }
90
+ export class Project {
80
91
  /**
81
92
  * @param {string} path
82
93
  * @returns {Promise<void>}
83
94
  */
84
- createDir(path: string): Promise<void>;
95
+ static createDir(path: string): Promise<void>;
85
96
  /**
86
97
  * @param {string} path
87
98
  * @param {boolean} recursive
88
99
  * @returns {Promise<void>}
89
100
  */
90
- removeDir(path: string, recursive: boolean): Promise<void>;
101
+ static removeDir(path: string, recursive: boolean): Promise<void>;
91
102
  /**
92
103
  * @param {string} path
93
104
  * @returns {Promise<void>}
94
105
  */
95
- removeFile(path: string): Promise<void>;
106
+ static removeFile(path: string): Promise<void>;
96
107
  /**
97
108
  * @param {string} path
98
109
  * @param {string} content
99
110
  * @returns {Promise<void>}
100
111
  */
101
- writeString(path: string, content: string): Promise<void>;
112
+ static writeString(path: string, content: string): Promise<void>;
102
113
  /**
103
114
  * @param {string} path
104
115
  * @returns {Promise<void>}
105
116
  */
106
- createDirAll(path: string): Promise<void>;
117
+ static createDirAll(path: string): Promise<void>;
107
118
  /**
108
119
  * @param {string} path
109
120
  * @returns {Promise<string>}
110
121
  */
111
- readToString(path: string): Promise<string>;
122
+ static readToString(path: string): Promise<string>;
112
123
  /**
113
124
  * @returns {string}
114
125
  */
115
- get cwd(): string;
126
+ static get cwd(): string;
127
+ /**
128
+ * Generate package-lock.json by resolving dependencies.
129
+ *
130
+ * # Arguments
131
+ * * `registry` - Optional registry URL. If None, uses npmmirror.
132
+ * - "https://registry.npmmirror.com" - supports semver queries (faster)
133
+ * - "https://registry.npmjs.org" - official npm registry (slower, fetches full manifest)
134
+ * * `concurrency` - Optional concurrency limit (defaults to 20)
135
+ * @param {string | null} [registry]
136
+ * @param {number | null} [concurrency]
137
+ * @returns {Promise<string>}
138
+ */
139
+ static deps(registry?: string | null, concurrency?: number | null): Promise<string>;
116
140
  /**
117
141
  * Create a tar.gz archive and return bytes (no file I/O)
118
142
  * This is useful for main thread execution without OPFS access
119
143
  * @param {any} files
120
- * @returns {Uint8Array}
144
+ * @returns {Promise<Uint8Array>}
121
145
  */
122
- gzip(files: any): Uint8Array;
146
+ static gzip(files: any): Promise<Uint8Array>;
147
+ /**
148
+ * @param {string} thread_url
149
+ */
150
+ static init(thread_url: string): void;
123
151
  /**
124
152
  * @param {string} path
125
153
  * @returns {Promise<Uint8Array>}
126
154
  */
127
- read(path: string): Promise<Uint8Array>;
155
+ static read(path: string): Promise<Uint8Array>;
128
156
  /**
129
157
  * @returns {Promise<any>}
130
158
  */
131
- build(): Promise<any>;
159
+ static build(): Promise<any>;
132
160
  /**
133
161
  * @param {string} path
134
162
  * @param {Uint8Array} content
135
163
  * @returns {Promise<void>}
136
164
  */
137
- write(path: string, content: Uint8Array): Promise<void>;
165
+ static write(path: string, content: Uint8Array): Promise<void>;
138
166
  /**
139
167
  * @param {string} package_lock
140
168
  * @param {number | null} [max_concurrent_downloads]
141
169
  * @returns {Promise<void>}
142
170
  */
143
- install(package_lock: string, max_concurrent_downloads?: number | null): Promise<void>;
171
+ static install(package_lock: string, max_concurrent_downloads?: number | null): Promise<void>;
144
172
  /**
145
- * Calculate MD5 hash of byte content
173
+ * @param {string} path
174
+ */
175
+ static setCwd(path: string): void;
176
+ /**
177
+ * Calculate MD5 hash of byte content (async for better thread scheduling)
146
178
  * @param {Uint8Array} content
147
- * @returns {string}
179
+ * @returns {Promise<string>}
148
180
  */
149
- sigMd5(content: Uint8Array): string;
181
+ static sigMd5(content: Uint8Array): Promise<string>;
150
182
  /**
151
183
  * @param {string} path
152
184
  * @returns {Promise<Metadata>}
153
185
  */
154
- metadata(path: string): Promise<Metadata>;
186
+ static metadata(path: string): Promise<Metadata>;
155
187
  /**
156
188
  * @param {string} path
157
189
  * @returns {Promise<DirEntry[]>}
158
190
  */
159
- readDir(path: string): Promise<DirEntry[]>;
191
+ static readDir(path: string): Promise<DirEntry[]>;
160
192
  /**
161
193
  * @param {string} src
162
194
  * @param {string} dst
163
195
  * @returns {Promise<void>}
164
196
  */
165
- copyFile(src: string, dst: string): Promise<void>;
197
+ static copyFile(src: string, dst: string): Promise<void>;
198
+ __destroy_into_raw(): number | undefined;
199
+ __wbg_ptr: number | undefined;
200
+ free(): void;
166
201
  }
167
202
  export class WasmTaskMessage {
168
203
  static __wrap(ptr: any): any;