@utoo/web 0.0.1 → 1.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 (38) hide show
  1. package/esm/forkedProject.d.ts +24 -0
  2. package/esm/forkedProject.js +40 -0
  3. package/esm/index.d.ts +1 -17
  4. package/esm/index.js +1 -104
  5. package/esm/installServiceWorker.d.ts +1 -0
  6. package/esm/installServiceWorker.js +36 -0
  7. package/esm/internalProject.d.ts +29 -0
  8. package/esm/internalProject.js +184 -0
  9. package/esm/message.d.ts +1 -0
  10. package/esm/message.js +1 -0
  11. package/esm/project.d.ts +31 -0
  12. package/esm/project.js +120 -0
  13. package/esm/serviceWorker.d.ts +1 -0
  14. package/esm/serviceWorker.js +62 -0
  15. package/esm/threadWorker.d.ts +1 -0
  16. package/esm/threadWorker.js +4 -0
  17. package/esm/type.d.ts +53 -8
  18. package/esm/type.js +12 -1
  19. package/esm/utoo/index.d.ts +156 -20
  20. package/esm/utoo/index.js +1079 -242
  21. package/esm/utoo/index_bg.wasm +0 -0
  22. package/esm/webpackLoaders/loaders/lessLoader/index.d.ts +3 -0
  23. package/esm/webpackLoaders/loaders/lessLoader/index.js +103 -0
  24. package/esm/webpackLoaders/loaders/lessLoader/options.json +67 -0
  25. package/esm/webpackLoaders/loaders/lessLoader/utils.d.ts +14 -0
  26. package/esm/webpackLoaders/loaders/lessLoader/utils.js +217 -0
  27. package/esm/webpackLoaders/worker/cjs.d.ts +2 -0
  28. package/esm/webpackLoaders/worker/cjs.js +77 -0
  29. package/esm/webpackLoaders/worker/index.d.ts +2 -0
  30. package/esm/webpackLoaders/worker/index.js +31 -0
  31. package/esm/webpackLoaders/worker/nodePolyFills.d.ts +14 -0
  32. package/esm/webpackLoaders/worker/nodePolyFills.js +24 -0
  33. package/esm/webpackLoaders/worker/type.d.ts +11 -0
  34. package/esm/webpackLoaders/worker/type.js +1 -0
  35. package/esm/webpackLoaders/workerContent.d.ts +2 -0
  36. package/esm/webpackLoaders/workerContent.js +1 -0
  37. package/esm/worker.js +2 -33
  38. package/package.json +29 -8
@@ -0,0 +1,24 @@
1
+ import { PackFile, ProjectEndpoint } from "./type";
2
+ export declare class ForkedProject implements ProjectEndpoint {
3
+ private endpoint;
4
+ constructor(port: MessagePort);
5
+ install(packageLock: string, maxConcurrentDownloads?: number): Promise<void>;
6
+ build(): Promise<import("./type").BuildOutput>;
7
+ readFile(path: string, encoding?: "utf8"): Promise<any>;
8
+ writeFile(path: string, content: string | Uint8Array, encoding?: "utf8"): Promise<void>;
9
+ copyFile(src: string, dst: string): Promise<void>;
10
+ readdir(path: string, options?: {
11
+ recursive?: boolean;
12
+ }): Promise<import("./type").Dirent[]>;
13
+ mkdir(path: string, options?: {
14
+ recursive?: boolean;
15
+ }): Promise<void>;
16
+ rm(path: string, options?: {
17
+ recursive?: boolean;
18
+ }): Promise<void>;
19
+ rmdir(path: string, options?: {
20
+ recursive?: boolean;
21
+ }): Promise<void>;
22
+ gzip(files: PackFile[]): Promise<Uint8Array>;
23
+ sigMd5(content: Uint8Array): Promise<string>;
24
+ }
@@ -0,0 +1,40 @@
1
+ import * as comlink from "comlink";
2
+ export class ForkedProject {
3
+ constructor(port) {
4
+ var _a;
5
+ (_a = this.endpoint) !== null && _a !== void 0 ? _a : (this.endpoint = comlink.wrap(port));
6
+ }
7
+ async install(packageLock, maxConcurrentDownloads) {
8
+ return await this.endpoint.install(packageLock, maxConcurrentDownloads);
9
+ }
10
+ async build() {
11
+ return await this.endpoint.build();
12
+ }
13
+ async readFile(path, encoding) {
14
+ return (await this.endpoint.readFile(path, encoding));
15
+ }
16
+ async writeFile(path, content, encoding) {
17
+ return await this.endpoint.writeFile(path, content, encoding);
18
+ }
19
+ async copyFile(src, dst) {
20
+ return await this.endpoint.copyFile(src, dst);
21
+ }
22
+ async readdir(path, options) {
23
+ return await this.endpoint.readdir(path, options);
24
+ }
25
+ async mkdir(path, options) {
26
+ return await this.endpoint.mkdir(path, options);
27
+ }
28
+ async rm(path, options) {
29
+ return await this.endpoint.rm(path, options);
30
+ }
31
+ async rmdir(path, options) {
32
+ return await this.endpoint.rmdir(path, options);
33
+ }
34
+ async gzip(files) {
35
+ return await this.endpoint.gzip(files);
36
+ }
37
+ async sigMd5(content) {
38
+ return await this.endpoint.sigMd5(content);
39
+ }
40
+ }
package/esm/index.d.ts CHANGED
@@ -1,18 +1,2 @@
1
- import { ProjectEndpoint } from "./type";
2
- import type { DirEntry } from "./utoo";
3
- export declare class Project implements ProjectEndpoint {
4
- #private;
5
- private cwd;
6
- private remote;
7
- constructor(cwd: string);
8
- install(packageLock: string): Promise<void>;
9
- build(): Promise<void>;
10
- readFile(path: string): Promise<string>;
11
- writeFile(path: string, content: string): Promise<void>;
12
- copyFile(src: string, dst: string): Promise<void>;
13
- readDir(path: string): Promise<DirEntry[]>;
14
- createDir(path: string): Promise<void>;
15
- createDirAll(path: string): Promise<void>;
16
- static fork(port1: MessagePort, port2: MessagePort): ProjectEndpoint;
17
- }
1
+ export { Project } from "./project";
18
2
  export * from "./type";
package/esm/index.js CHANGED
@@ -1,105 +1,2 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
- if (kind === "m") throw new TypeError("Private method is not writable");
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
- };
12
- var _Project_tunnel;
13
- import * as comlink from "comlink";
14
- import { Fork, HandShake } from "./message";
15
- let ProjectWorker;
16
- const ConnectedPorts = new Set();
17
- export class Project {
18
- constructor(cwd) {
19
- var _a, _b;
20
- _Project_tunnel.set(this, void 0);
21
- this.cwd = cwd;
22
- const { port1, port2 } = new MessageChannel();
23
- (_a = this.remote) !== null && _a !== void 0 ? _a : (this.remote = comlink.wrap(port1));
24
- if (!ProjectWorker) {
25
- ProjectWorker = new Worker(new URL("./worker", import.meta.url));
26
- self.addEventListener("message", (e) => {
27
- const port = e.ports[0];
28
- if (e.data === Fork && !ConnectedPorts.has(port)) {
29
- ProjectWorker.postMessage(HandShake, [port]);
30
- }
31
- });
32
- }
33
- ProjectWorker.postMessage(HandShake, [port2]);
34
- __classPrivateFieldSet(this, _Project_tunnel, (_b = __classPrivateFieldGet(this, _Project_tunnel, "f")) !== null && _b !== void 0 ? _b : this.remote.mount(this.cwd), "f");
35
- }
36
- async install(packageLock) {
37
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
38
- return await this.remote.install(packageLock);
39
- }
40
- async build() {
41
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
42
- return await this.remote.build();
43
- }
44
- async readFile(path) {
45
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
46
- return await this.remote.readFile(path);
47
- }
48
- async writeFile(path, content) {
49
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
50
- return await this.remote.writeFile(path, content);
51
- }
52
- async copyFile(src, dst) {
53
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
54
- return await this.remote.copyFile(src, dst);
55
- }
56
- async readDir(path) {
57
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
58
- return await this.remote.readDir(path);
59
- }
60
- async createDir(path) {
61
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
62
- return await this.remote.createDir(path);
63
- }
64
- async createDirAll(path) {
65
- await __classPrivateFieldGet(this, _Project_tunnel, "f");
66
- return await this.remote.createDirAll(path);
67
- }
68
- // This should be called from different worker
69
- static fork(port1, port2) {
70
- self.postMessage(Fork, [port2]);
71
- return new ForkedProject(port1);
72
- }
73
- }
74
- _Project_tunnel = new WeakMap();
75
- class ForkedProject {
76
- constructor(port) {
77
- var _a;
78
- (_a = this.endpoint) !== null && _a !== void 0 ? _a : (this.endpoint = comlink.wrap(port));
79
- }
80
- async install(packageLock) {
81
- return await this.endpoint.install(packageLock);
82
- }
83
- async build() {
84
- return await this.endpoint.build();
85
- }
86
- async readFile(path) {
87
- return await this.endpoint.readFile(path);
88
- }
89
- async writeFile(path, content) {
90
- return await this.endpoint.writeFile(path, content);
91
- }
92
- async copyFile(src, dst) {
93
- return await this.endpoint.copyFile(src, dst);
94
- }
95
- async readDir(path) {
96
- return await this.endpoint.readDir(path);
97
- }
98
- async createDir(path) {
99
- return await this.endpoint.createDir(path);
100
- }
101
- async createDirAll(path) {
102
- return await this.endpoint.createDirAll(path);
103
- }
104
- }
1
+ export { Project } from "./project";
105
2
  export * from "./type";
@@ -0,0 +1 @@
1
+ export declare function installServiceWorker(url: string, scope: string): Promise<void>;
@@ -0,0 +1,36 @@
1
+ import { ServiceWorkerHandShake } from "./message";
2
+ export async function installServiceWorker(url, scope) {
3
+ const registration = await navigator.serviceWorker.register(url, {
4
+ scope: "/",
5
+ });
6
+ return new Promise((resolve) => {
7
+ function sendMessage(sw) {
8
+ sw.postMessage({
9
+ [ServiceWorkerHandShake]: true,
10
+ scope,
11
+ });
12
+ resolve();
13
+ }
14
+ function listenForActivation(sw) {
15
+ sw.addEventListener("statechange", () => {
16
+ if (sw.state === "activated") {
17
+ sendMessage(sw);
18
+ }
19
+ });
20
+ }
21
+ function checkSWState(registration) {
22
+ if (registration.active) {
23
+ sendMessage(registration.active);
24
+ }
25
+ else if (registration.installing) {
26
+ listenForActivation(registration.installing);
27
+ }
28
+ registration.addEventListener("updatefound", () => {
29
+ if (registration.installing) {
30
+ listenForActivation(registration.installing);
31
+ }
32
+ });
33
+ }
34
+ checkSWState(registration);
35
+ });
36
+ }
@@ -0,0 +1,29 @@
1
+ import { PackFile, ProjectEndpoint, ProjectOptions } from "./type";
2
+ import initWasm, { Project as ProjectInternal } from "./utoo";
3
+ declare class InternalEndpoint implements ProjectEndpoint {
4
+ projectInternal?: ProjectInternal;
5
+ wasmInit?: ReturnType<typeof initWasm>;
6
+ options?: Omit<ProjectOptions, "workerUrl" | "serviceWorker">;
7
+ mount(opt: Omit<ProjectOptions, "workerUrl" | "serviceWorker">): Promise<void>;
8
+ install(packageLock: string, maxConcurrentDownloads?: number): Promise<void>;
9
+ build(): Promise<any>;
10
+ readFile(path: string, encoding?: "utf8"): Promise<any>;
11
+ writeFile(path: string, content: string | Uint8Array, _encoding?: "utf8"): Promise<void>;
12
+ copyFile(src: string, dst: string): Promise<void>;
13
+ readdir(path: string, options?: {
14
+ recursive?: boolean;
15
+ }): Promise<any>;
16
+ mkdir(path: string, options?: {
17
+ recursive?: boolean;
18
+ }): Promise<void>;
19
+ rm(path: string, options?: {
20
+ recursive?: boolean;
21
+ }): Promise<void>;
22
+ rmdir(path: string, options?: {
23
+ recursive?: boolean;
24
+ }): Promise<void>;
25
+ gzip(files: PackFile[]): Promise<Uint8Array<ArrayBufferLike>>;
26
+ sigMd5(content: Uint8Array): Promise<string>;
27
+ }
28
+ declare const internalEndpoint: InternalEndpoint;
29
+ export { internalEndpoint };
@@ -0,0 +1,184 @@
1
+ import initWasm, { init_log_filter, Project as ProjectInternal, recvPoolRequest, recvWorkerTermination, } from "./utoo";
2
+ // @ts-ignore
3
+ import webpackLoadersCode from "./webpackLoaders/workerContent";
4
+ let nextWorkerId = 0;
5
+ const loaderWorkers = {};
6
+ async function getTurbopackLoaderAssets() {
7
+ const turbopackLoaderAssets = {};
8
+ const dirEntries = await internalEndpoint.projectInternal.readDir(".turbopack");
9
+ await Promise.all(dirEntries.map(async (entry) => {
10
+ // only collect .js files
11
+ if (entry.type === "file" && entry.name.endsWith(".js")) {
12
+ turbopackLoaderAssets[`./${entry.name}`] =
13
+ await internalEndpoint.projectInternal.readToString(`.turbopack/${entry.name}`);
14
+ }
15
+ }));
16
+ return turbopackLoaderAssets;
17
+ }
18
+ const createOrScalePool = async (binding, loadersImportMap) => {
19
+ while (true) {
20
+ try {
21
+ let poolOptions = await recvPoolRequest();
22
+ const { filename: entrypoint, maxConcurrency } = poolOptions;
23
+ const workers = loaderWorkers[entrypoint] || (loaderWorkers[entrypoint] = []);
24
+ if (workers.length < maxConcurrency) {
25
+ for (let i = workers.length; i < maxConcurrency; i++) {
26
+ nextWorkerId += 1;
27
+ const turbopackLoaderAssets = await getTurbopackLoaderAssets();
28
+ const blob = new Blob([webpackLoadersCode], {
29
+ type: "text/javascript",
30
+ });
31
+ const workerUrl = URL.createObjectURL(blob);
32
+ const worker = new Worker(workerUrl);
33
+ worker.postMessage([
34
+ // @ts-ignore
35
+ initWasm.__wbindgen_wasm_module,
36
+ binding.memory,
37
+ {
38
+ workerData: {
39
+ poolId: entrypoint,
40
+ workerId: nextWorkerId,
41
+ },
42
+ loaderAssets: {
43
+ importMaps: { ...turbopackLoaderAssets, ...loadersImportMap },
44
+ entrypoint: entrypoint.replace(".turbopack/", ""),
45
+ },
46
+ },
47
+ ]);
48
+ // @ts-ignore
49
+ worker.workerId = nextWorkerId;
50
+ // @ts-ignore
51
+ workers.push(worker);
52
+ }
53
+ }
54
+ else if (workers.length > maxConcurrency) {
55
+ const workersToStop = workers.splice(0, workers.length - maxConcurrency);
56
+ workersToStop.forEach((worker) => worker.terminate());
57
+ }
58
+ }
59
+ catch (_e) {
60
+ // rust channel closed. do nothing
61
+ return;
62
+ }
63
+ }
64
+ };
65
+ const waitingForWorkerTermination = async () => {
66
+ while (true) {
67
+ try {
68
+ const { filename, workerId } = await recvWorkerTermination();
69
+ const workers = loaderWorkers[filename];
70
+ const workerIdx = workers.findIndex((worker) => worker.workerId === workerId);
71
+ if (workerIdx > -1) {
72
+ const worker = workers.splice(workerIdx, 1);
73
+ worker[0].terminate();
74
+ }
75
+ }
76
+ catch (_e) {
77
+ // rust channel closed. do nothing
78
+ return;
79
+ }
80
+ }
81
+ };
82
+ class InternalEndpoint {
83
+ // This should be called only once
84
+ async mount(opt) {
85
+ var _a;
86
+ this.options = opt;
87
+ const { cwd, wasmUrl, threadWorkerUrl, logFilter } = opt;
88
+ (_a = this.wasmInit) !== null && _a !== void 0 ? _a : (this.wasmInit = initWasm(wasmUrl));
89
+ await this.wasmInit;
90
+ // Initialize log filter after wasm init
91
+ const filter = logFilter || "pack_core=info,pack_api=info,utoo_wasm=info";
92
+ init_log_filter(filter);
93
+ this.projectInternal = new ProjectInternal(cwd, threadWorkerUrl);
94
+ return;
95
+ }
96
+ async install(packageLock, maxConcurrentDownloads) {
97
+ await this.wasmInit;
98
+ await this.projectInternal.install(packageLock, maxConcurrentDownloads);
99
+ return;
100
+ }
101
+ async build() {
102
+ var _a;
103
+ const binding = await this.wasmInit;
104
+ createOrScalePool(binding, (_a = this.options) === null || _a === void 0 ? void 0 : _a.loadersImportMap);
105
+ waitingForWorkerTermination();
106
+ return await this.projectInternal.build();
107
+ }
108
+ async readFile(path, encoding) {
109
+ await this.wasmInit;
110
+ let ret;
111
+ if (encoding === "utf8") {
112
+ ret = await this.projectInternal.readToString(path);
113
+ }
114
+ else {
115
+ ret = await this.projectInternal.read(path);
116
+ }
117
+ return ret;
118
+ }
119
+ async writeFile(path, content, _encoding) {
120
+ await this.wasmInit;
121
+ if (typeof content === "string") {
122
+ return await this.projectInternal.writeString(path, content);
123
+ }
124
+ else {
125
+ return await this.projectInternal.write(path, content);
126
+ }
127
+ }
128
+ async copyFile(src, dst) {
129
+ await this.wasmInit;
130
+ return await this.projectInternal.copyFile(src, dst);
131
+ }
132
+ async readdir(path, options) {
133
+ await this.wasmInit;
134
+ const dirEntries = (options === null || options === void 0 ? void 0 : options.recursive)
135
+ ? await this.projectInternal.readDir(path)
136
+ : // TODO: support recursive readDirAll
137
+ await this.projectInternal.readDir(path);
138
+ const rawDirents = dirEntries.map((e) => {
139
+ const dir = e.toJSON();
140
+ return {
141
+ name: dir.name,
142
+ type: dir.type,
143
+ };
144
+ });
145
+ // WARN: This is a hack, functions can not be structurally cloned
146
+ return rawDirents;
147
+ }
148
+ async mkdir(path, options) {
149
+ await this.wasmInit;
150
+ if (options === null || options === void 0 ? void 0 : options.recursive) {
151
+ return await this.projectInternal.createDirAll(path);
152
+ }
153
+ else {
154
+ return await this.projectInternal.createDir(path);
155
+ }
156
+ }
157
+ async rm(path, options) {
158
+ await this.wasmInit;
159
+ let metadata = (await this.projectInternal.metadata(path)).toJSON();
160
+ switch (metadata.type) {
161
+ case "file":
162
+ return await this.projectInternal.removeFile(path);
163
+ case "directory":
164
+ return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
165
+ default:
166
+ // nothing to remove now
167
+ break;
168
+ }
169
+ }
170
+ async rmdir(path, options) {
171
+ await this.wasmInit;
172
+ return await this.projectInternal.removeDir(path, !!(options === null || options === void 0 ? void 0 : options.recursive));
173
+ }
174
+ async gzip(files) {
175
+ await this.wasmInit;
176
+ return await this.projectInternal.gzip(files);
177
+ }
178
+ async sigMd5(content) {
179
+ await this.wasmInit;
180
+ return await this.projectInternal.sigMd5(content);
181
+ }
182
+ }
183
+ const internalEndpoint = new InternalEndpoint();
184
+ export { internalEndpoint };
package/esm/message.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export declare const HandShake = "__handshake__";
2
+ export declare const ServiceWorkerHandShake = "__service_worker_handshake__";
2
3
  export declare const Fork = "__fork__";
package/esm/message.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export const HandShake = "__handshake__";
2
+ export const ServiceWorkerHandShake = "__service_worker_handshake__";
2
3
  export const Fork = "__fork__";
@@ -0,0 +1,31 @@
1
+ import { BuildOutput, Dirent, PackFile, ProjectEndpoint, ProjectOptions, ServiceWorkerOptions } from "./type";
2
+ export declare class Project implements ProjectEndpoint {
3
+ #private;
4
+ readonly cwd: string;
5
+ readonly serviceWorkerOptions?: ServiceWorkerOptions;
6
+ private remote;
7
+ constructor(options: ProjectOptions);
8
+ private connectWorker;
9
+ installServiceWorker(): Promise<void>;
10
+ mount(): Promise<void>;
11
+ install(packageLock: string, maxConcurrentDownloads?: number): Promise<void>;
12
+ build(): Promise<BuildOutput>;
13
+ readFile(path: string, encoding?: "utf8"): Promise<any>;
14
+ writeFile(path: string, content: string | Uint8Array, encoding?: "utf8"): Promise<void>;
15
+ copyFile(src: string, dst: string): Promise<void>;
16
+ readdir(path: string, options?: {
17
+ recursive?: boolean;
18
+ }): Promise<Dirent[]>;
19
+ mkdir(path: string, options?: {
20
+ recursive?: boolean;
21
+ }): Promise<void>;
22
+ rm(path: string, options?: {
23
+ recursive?: boolean;
24
+ }): Promise<void>;
25
+ rmdir(path: string, options?: {
26
+ recursive?: boolean;
27
+ }): Promise<void>;
28
+ gzip(files: PackFile[]): Promise<Uint8Array>;
29
+ sigMd5(content: Uint8Array): Promise<string>;
30
+ static fork(channel: MessageChannel, eventSource?: Client | DedicatedWorkerGlobalScope): ProjectEndpoint;
31
+ }
package/esm/project.js ADDED
@@ -0,0 +1,120 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var _Project_mount;
13
+ import { handleIssues } from "@utoo/pack-shared";
14
+ import * as comlink from "comlink";
15
+ import { ForkedProject } from "./forkedProject";
16
+ import { installServiceWorker } from "./installServiceWorker";
17
+ import { Fork, HandShake } from "./message";
18
+ import { Dirent, } from "./type";
19
+ let ProjectWorker;
20
+ const ConnectedPorts = new Set();
21
+ export class Project {
22
+ constructor(options) {
23
+ var _a, _b;
24
+ _Project_mount.set(this, void 0);
25
+ const { cwd, workerUrl, wasmUrl, threadWorkerUrl, serviceWorker, logFilter, loadersImportMap, } = options;
26
+ this.cwd = cwd;
27
+ this.serviceWorkerOptions = serviceWorker;
28
+ const { port1, port2 } = new MessageChannel();
29
+ (_a = this.remote) !== null && _a !== void 0 ? _a : (this.remote = comlink.wrap(port1));
30
+ if (!ProjectWorker) {
31
+ ProjectWorker = new Worker(workerUrl);
32
+ window.addEventListener("message", (e) => {
33
+ this.connectWorker(e);
34
+ });
35
+ if (this.serviceWorkerOptions) {
36
+ navigator.serviceWorker.addEventListener("message", (e) => {
37
+ this.connectWorker(e);
38
+ });
39
+ }
40
+ }
41
+ ProjectWorker.postMessage(HandShake, [port2]);
42
+ __classPrivateFieldSet(this, _Project_mount, (_b = __classPrivateFieldGet(this, _Project_mount, "f")) !== null && _b !== void 0 ? _b : this.remote.mount({
43
+ cwd,
44
+ wasmUrl,
45
+ threadWorkerUrl,
46
+ loadersImportMap,
47
+ logFilter,
48
+ }), "f");
49
+ }
50
+ connectWorker(e) {
51
+ const port = e.ports[0];
52
+ if (e.data === Fork && !ConnectedPorts.has(port)) {
53
+ ProjectWorker.postMessage(HandShake, [port]);
54
+ }
55
+ }
56
+ async installServiceWorker() {
57
+ if (this.serviceWorkerOptions) {
58
+ const { url, scope } = this.serviceWorkerOptions;
59
+ // Should add "Service-Worker-Allowed": "/" in page root response headers,
60
+ return await installServiceWorker(url, scope);
61
+ }
62
+ }
63
+ async mount() {
64
+ return await __classPrivateFieldGet(this, _Project_mount, "f");
65
+ }
66
+ async install(packageLock, maxConcurrentDownloads) {
67
+ await __classPrivateFieldGet(this, _Project_mount, "f");
68
+ return await this.remote.install(packageLock, maxConcurrentDownloads);
69
+ }
70
+ async build() {
71
+ await __classPrivateFieldGet(this, _Project_mount, "f");
72
+ const res = await this.remote.build();
73
+ handleIssues(res.issues, false, false);
74
+ return res;
75
+ }
76
+ async readFile(path, encoding) {
77
+ await __classPrivateFieldGet(this, _Project_mount, "f");
78
+ return (await this.remote.readFile(path, encoding));
79
+ }
80
+ async writeFile(path, content, encoding) {
81
+ await __classPrivateFieldGet(this, _Project_mount, "f");
82
+ return await this.remote.writeFile(path, content, encoding);
83
+ }
84
+ async copyFile(src, dst) {
85
+ await __classPrivateFieldGet(this, _Project_mount, "f");
86
+ return await this.remote.copyFile(src, dst);
87
+ }
88
+ async readdir(path, options) {
89
+ await __classPrivateFieldGet(this, _Project_mount, "f");
90
+ const dirEntry = (await this.remote.readdir(path, options));
91
+ return dirEntry.map((e) => new Dirent(e));
92
+ }
93
+ async mkdir(path, options) {
94
+ await __classPrivateFieldGet(this, _Project_mount, "f");
95
+ return await this.remote.mkdir(path, options);
96
+ }
97
+ async rm(path, options) {
98
+ await __classPrivateFieldGet(this, _Project_mount, "f");
99
+ return await this.remote.rm(path, options);
100
+ }
101
+ async rmdir(path, options) {
102
+ await __classPrivateFieldGet(this, _Project_mount, "f");
103
+ return await this.remote.rmdir(path, options);
104
+ }
105
+ async gzip(files) {
106
+ await __classPrivateFieldGet(this, _Project_mount, "f");
107
+ return await this.remote.gzip(files);
108
+ }
109
+ async sigMd5(content) {
110
+ await __classPrivateFieldGet(this, _Project_mount, "f");
111
+ return await this.remote.sigMd5(content);
112
+ }
113
+ static fork(channel, eventSource) {
114
+ (eventSource || self).postMessage(Fork, {
115
+ transfer: [channel.port2],
116
+ });
117
+ return new ForkedProject(channel.port1);
118
+ }
119
+ }
120
+ _Project_mount = new WeakMap();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import { Project } from ".";
2
+ import { ServiceWorkerHandShake } from "./message";
3
+ let _resolve;
4
+ let _promise = new Promise((resolve) => {
5
+ _resolve = resolve;
6
+ });
7
+ let _projectEndpoint;
8
+ let _serviceWorkerScope;
9
+ self.addEventListener("install", (event) => {
10
+ event.waitUntil(self.skipWaiting());
11
+ });
12
+ self.addEventListener("activate", (event) => {
13
+ event.waitUntil(self.clients.claim());
14
+ });
15
+ self.addEventListener("message", (event) => {
16
+ if (event.data && event.data[ServiceWorkerHandShake] === true) {
17
+ _serviceWorkerScope = event.data.scope;
18
+ _projectEndpoint = Project.fork(new MessageChannel(), event.source);
19
+ _resolve();
20
+ }
21
+ });
22
+ self.addEventListener("fetch", async (event) => {
23
+ await _promise;
24
+ const { url, referrer } = event.request;
25
+ if (new URL(url).pathname.startsWith(_serviceWorkerScope) ||
26
+ (referrer && new URL(referrer).pathname.startsWith(_serviceWorkerScope))) {
27
+ const projectPath = "." + new URL(url).pathname.replace(_serviceWorkerScope, "");
28
+ event.respondWith(readFileFromProject(projectPath));
29
+ }
30
+ else {
31
+ return;
32
+ }
33
+ });
34
+ async function readFileFromProject(projectPath) {
35
+ try {
36
+ const content = await _projectEndpoint.readFile(projectPath);
37
+ let mimeType = "application/octet-stream";
38
+ if (projectPath.endsWith(".js")) {
39
+ mimeType = "application/javascript";
40
+ }
41
+ else if (projectPath.endsWith(".css")) {
42
+ mimeType = "text/css";
43
+ }
44
+ else if (projectPath.endsWith(".html")) {
45
+ mimeType = "text/html";
46
+ }
47
+ else if (projectPath.endsWith(".json")) {
48
+ mimeType = "application/json";
49
+ }
50
+ return new Response(content, {
51
+ headers: {
52
+ "Content-Type": mimeType,
53
+ ...(mimeType === "text/html"
54
+ ? { "Cross-Origin-Embedder-Policy": "require-corp" }
55
+ : {}),
56
+ },
57
+ });
58
+ }
59
+ catch (e) {
60
+ return new Response("Not Found", { status: 404 });
61
+ }
62
+ }
@@ -0,0 +1 @@
1
+ export {};