@utoo/web 1.2.0-rc.5 → 1.2.0-rc.7

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 (39) hide show
  1. package/README.md +52 -0
  2. package/esm/{8df7dc7828270e8a8ece.wasm → b0afc1b3f31b4fb74f6b.wasm} +0 -0
  3. package/esm/forkedProject.d.ts +2 -1
  4. package/esm/forkedProject.js +5 -0
  5. package/esm/internalProject.d.ts +3 -3
  6. package/esm/internalProject.js +36 -20
  7. package/esm/loaderWorker.js +1 -1
  8. package/esm/project.d.ts +2 -1
  9. package/esm/project.js +12 -3
  10. package/esm/sabcom.d.ts +17 -0
  11. package/esm/sabcom.js +93 -26
  12. package/esm/serviceWorker.js +1 -0
  13. package/esm/type.d.ts +38 -0
  14. package/esm/type.js +44 -0
  15. package/esm/utoo/index.d.ts +27 -24
  16. package/esm/utoo/index.js +104 -102
  17. package/esm/utoo/index_bg.wasm +0 -0
  18. package/esm/webpackLoaders/{worker/cjs.js → cjs.js} +71 -64
  19. package/esm/webpackLoaders/loaderWorkerPool.d.ts +2 -0
  20. package/esm/{loaderWorkerPool.js → webpackLoaders/loaderWorkerPool.js} +30 -18
  21. package/esm/webpackLoaders/polyfills/fsPolyfill.d.ts +78 -0
  22. package/esm/webpackLoaders/polyfills/fsPolyfill.js +279 -0
  23. package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.d.ts +26 -0
  24. package/esm/webpackLoaders/polyfills/fsPromisesPolyfill.js +112 -0
  25. package/esm/webpackLoaders/{worker/type.d.ts → type.d.ts} +1 -0
  26. package/esm/webpackLoaders/{worker/index.js → worker.js} +8 -3
  27. package/package.json +6 -6
  28. package/esm/loaderWorkerPool.d.ts +0 -3
  29. package/esm/webpackLoaders/worker/polyfills/fsPolyfill.d.ts +0 -244
  30. package/esm/webpackLoaders/worker/polyfills/fsPolyfill.js +0 -369
  31. package/esm/webpackLoaders/worker/polyfills/fsPromisesPolyfill.d.ts +0 -9
  32. package/esm/webpackLoaders/worker/polyfills/fsPromisesPolyfill.js +0 -9
  33. /package/esm/webpackLoaders/{worker/cjs.d.ts → cjs.d.ts} +0 -0
  34. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/nodePolyFills.d.ts +0 -0
  35. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/nodePolyFills.js +0 -0
  36. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/workerThreadsPolyfill.d.ts +0 -0
  37. /package/esm/webpackLoaders/{worker/polyfills → polyfills}/workerThreadsPolyfill.js +0 -0
  38. /package/esm/webpackLoaders/{worker/type.js → type.js} +0 -0
  39. /package/esm/webpackLoaders/{worker/index.d.ts → worker.d.ts} +0 -0
package/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # @utoo/web
2
+
3
+ > 🌖 Web-compatible version of the Utoo toolchain, powered by [Turbopack](https://turbo.build/pack) and WebAssembly.
4
+
5
+ `@utoo/web` brings the power of the Utoo bundler to the browser, leveraging WebAssembly to provide high-performance bundling in non-native environments. It enables a complete web development environment, including a virtual file system and dependency management, entirely within the browser.
6
+
7
+ ## ✨ Features
8
+
9
+ - 🌐 **Browser-based Bundling**: Run the Utoo bundler directly in the browser.
10
+ - ⚡ **WASM Powered**: High performance via WebAssembly bindings of the Turbopack-based core.
11
+ - 🛠️ **Web Worker Support**: Offloads heavy bundling tasks to background workers to keep the UI responsive.
12
+ - 🔌 **Webpack Compatibility**: Supports a subset of Webpack configurations in the browser.
13
+ - 📂 **Virtual File System**: Uses Origin Private File System (OPFS) for a Node.js-like file system experience.
14
+
15
+ ## 🧠 Core Concepts
16
+
17
+ 1. **Virtual File System**: The project lives in the browser's OPFS.
18
+ 2. **Project Main Worker**: Core logic runs in a dedicated worker to keep the UI responsive.
19
+ 3. **Thread Worker**: Heavy bundling tasks are offloaded to a worker powered by a ported `tokio` runtime.
20
+ 4. **Service Worker**: Acts as a local server to intercept requests and serve built files for preview.
21
+
22
+ ## 📦 Installation
23
+
24
+ ```bash
25
+ npm install @utoo/web
26
+ ```
27
+
28
+ ## 🛠️ Development
29
+
30
+ ### Prerequisites
31
+
32
+ - Rust toolchain (nightly)
33
+ - `wasm-bindgen-cli`
34
+ - `binaryen` (for `wasm-opt`)
35
+
36
+ ### Build
37
+
38
+ ```bash
39
+ # Install toolchain
40
+ npm run install-toolchain
41
+
42
+ # Build WASM and TypeScript
43
+ npm run build
44
+ ```
45
+
46
+ ## 📚 Documentation
47
+
48
+ For detailed API usage and examples, please refer to the [API Documentation](./API.md) ([中文版](./API_zh-CN.md)).
49
+
50
+ ## �📄 License
51
+
52
+ [MIT](./LICENSE)
@@ -1,4 +1,4 @@
1
- import { PackFile, ProjectEndpoint } from "./type";
1
+ import { PackFile, ProjectEndpoint, Stats } from "./type";
2
2
  export declare class ForkedProject implements ProjectEndpoint {
3
3
  private endpoint;
4
4
  constructor(port: MessagePort);
@@ -19,6 +19,7 @@ export declare class ForkedProject implements ProjectEndpoint {
19
19
  rmdir(path: string, options?: {
20
20
  recursive?: boolean;
21
21
  }): Promise<void>;
22
+ stat(path: string): Promise<Stats>;
22
23
  gzip(files: PackFile[]): Promise<Uint8Array>;
23
24
  sigMd5(content: Uint8Array): Promise<string>;
24
25
  }
@@ -1,4 +1,5 @@
1
1
  import * as comlink from "comlink";
2
+ import { Stats } from "./type";
2
3
  export class ForkedProject {
3
4
  constructor(port) {
4
5
  var _a;
@@ -31,6 +32,10 @@ export class ForkedProject {
31
32
  async rmdir(path, options) {
32
33
  return await this.endpoint.rmdir(path, options);
33
34
  }
35
+ async stat(path) {
36
+ const raw = (await this.endpoint.stat(path));
37
+ return new Stats(raw);
38
+ }
34
39
  async gzip(files) {
35
40
  return await this.endpoint.gzip(files);
36
41
  }
@@ -1,7 +1,6 @@
1
- import { PackFile, ProjectEndpoint, ProjectOptions } from "./type";
2
- import initWasm, { Project as ProjectInternal } from "./utoo";
1
+ import { PackFile, ProjectEndpoint, ProjectOptions, Stats } from "./type";
2
+ import initWasm from "./utoo";
3
3
  declare class InternalEndpoint implements ProjectEndpoint {
4
- projectInternal?: ProjectInternal;
5
4
  wasmInit?: ReturnType<typeof initWasm>;
6
5
  options?: Omit<ProjectOptions, "workerUrl" | "serviceWorker">;
7
6
  loaderWorkerPoolInitialized: boolean;
@@ -11,6 +10,7 @@ declare class InternalEndpoint implements ProjectEndpoint {
11
10
  readFile(path: string, encoding?: "utf8"): Promise<any>;
12
11
  writeFile(path: string, content: string | Uint8Array, _encoding?: "utf8"): Promise<void>;
13
12
  copyFile(src: string, dst: string): Promise<void>;
13
+ stat(path: string): Promise<Stats>;
14
14
  readdir(path: string, options?: {
15
15
  recursive?: boolean;
16
16
  }): Promise<any>;
@@ -1,5 +1,6 @@
1
- import { runLoaderWorkerPool } from "./loaderWorkerPool";
1
+ import * as comlink from "comlink";
2
2
  import initWasm, { init_log_filter, Project as ProjectInternal, } from "./utoo";
3
+ import { runLoaderWorkerPool } from "./webpackLoaders/loaderWorkerPool";
3
4
  class InternalEndpoint {
4
5
  constructor() {
5
6
  this.loaderWorkerPoolInitialized = false;
@@ -14,53 +15,67 @@ class InternalEndpoint {
14
15
  // Initialize log filter after wasm init
15
16
  const filter = logFilter || "pack_core=info,pack_api=info,utoo_wasm=info";
16
17
  init_log_filter(filter);
17
- this.projectInternal = new ProjectInternal(cwd, threadWorkerUrl);
18
+ const absoluteCwd = cwd.startsWith("/") ? cwd : "/" + cwd;
19
+ ProjectInternal.init(threadWorkerUrl || "");
20
+ ProjectInternal.setCwd(absoluteCwd);
18
21
  return;
19
22
  }
20
23
  async install(packageLock, maxConcurrentDownloads) {
21
24
  await this.wasmInit;
22
- await this.projectInternal.install(packageLock, maxConcurrentDownloads);
25
+ await ProjectInternal.install(packageLock, maxConcurrentDownloads);
23
26
  return;
24
27
  }
25
28
  async build() {
26
29
  var _a, _b;
27
30
  const binding = await this.wasmInit;
28
31
  if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.loaderWorkerUrl) && !this.loaderWorkerPoolInitialized) {
29
- runLoaderWorkerPool(binding, this.options.cwd, this.projectInternal, this.options.loaderWorkerUrl, (_b = this.options) === null || _b === void 0 ? void 0 : _b.loadersImportMap);
32
+ runLoaderWorkerPool(binding, this.options.cwd, this.options.loaderWorkerUrl, (_b = this.options) === null || _b === void 0 ? void 0 : _b.loadersImportMap);
30
33
  this.loaderWorkerPoolInitialized = true;
31
34
  }
32
- return await this.projectInternal.build();
35
+ return await ProjectInternal.build();
33
36
  }
34
37
  async readFile(path, encoding) {
35
38
  await this.wasmInit;
36
39
  let ret;
37
40
  if (encoding === "utf8") {
38
- ret = await this.projectInternal.readToString(path);
41
+ ret = await ProjectInternal.readToString(path);
39
42
  }
40
43
  else {
41
- ret = await this.projectInternal.read(path);
44
+ ret = await ProjectInternal.read(path);
45
+ return comlink.transfer(ret, [ret.buffer]);
42
46
  }
43
47
  return ret;
44
48
  }
45
49
  async writeFile(path, content, _encoding) {
46
50
  await this.wasmInit;
47
51
  if (typeof content === "string") {
48
- return await this.projectInternal.writeString(path, content);
52
+ return await ProjectInternal.writeString(path, content);
49
53
  }
50
54
  else {
51
- return await this.projectInternal.write(path, content);
55
+ return await ProjectInternal.write(path, content);
52
56
  }
53
57
  }
54
58
  async copyFile(src, dst) {
55
59
  await this.wasmInit;
56
- return await this.projectInternal.copyFile(src, dst);
60
+ return await ProjectInternal.copyFile(src, dst);
61
+ }
62
+ async stat(path) {
63
+ await this.wasmInit;
64
+ const metadata = await ProjectInternal.metadata(path);
65
+ const json = metadata.toJSON();
66
+ const raw = {
67
+ type: json.type,
68
+ size: Number(json.file_size),
69
+ };
70
+ // WARN: This is a hack, functions can not be structurally cloned
71
+ return raw;
57
72
  }
58
73
  async readdir(path, options) {
59
74
  await this.wasmInit;
60
75
  const dirEntries = (options === null || options === void 0 ? void 0 : options.recursive)
61
- ? await this.projectInternal.readDir(path)
76
+ ? await ProjectInternal.readDir(path)
62
77
  : // TODO: support recursive readDirAll
63
- await this.projectInternal.readDir(path);
78
+ await ProjectInternal.readDir(path);
64
79
  const rawDirents = dirEntries.map((e) => {
65
80
  const dir = e.toJSON();
66
81
  return {
@@ -74,20 +89,20 @@ class InternalEndpoint {
74
89
  async mkdir(path, options) {
75
90
  await this.wasmInit;
76
91
  if (options === null || options === void 0 ? void 0 : options.recursive) {
77
- return await this.projectInternal.createDirAll(path);
92
+ return await ProjectInternal.createDirAll(path);
78
93
  }
79
94
  else {
80
- return await this.projectInternal.createDir(path);
95
+ return await ProjectInternal.createDir(path);
81
96
  }
82
97
  }
83
98
  async rm(path, options) {
84
99
  await this.wasmInit;
85
- let metadata = (await this.projectInternal.metadata(path)).toJSON();
100
+ let metadata = (await ProjectInternal.metadata(path)).toJSON();
86
101
  switch (metadata.type) {
87
102
  case "file":
88
- return await this.projectInternal.removeFile(path);
103
+ return await ProjectInternal.removeFile(path);
89
104
  case "directory":
90
- return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
105
+ return await ProjectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
91
106
  default:
92
107
  // nothing to remove now
93
108
  break;
@@ -95,15 +110,16 @@ class InternalEndpoint {
95
110
  }
96
111
  async rmdir(path, options) {
97
112
  await this.wasmInit;
98
- return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
113
+ return await ProjectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
99
114
  }
100
115
  async gzip(files) {
101
116
  await this.wasmInit;
102
- return await this.projectInternal.gzip(files);
117
+ const ret = await ProjectInternal.gzip(files);
118
+ return comlink.transfer(ret, [ret.buffer]);
103
119
  }
104
120
  async sigMd5(content) {
105
121
  await this.wasmInit;
106
- return await this.projectInternal.sigMd5(content);
122
+ return await ProjectInternal.sigMd5(content);
107
123
  }
108
124
  }
109
125
  const internalEndpoint = new InternalEndpoint();