@utoo/pack 1.1.3 → 1.1.4

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 (65) hide show
  1. package/cjs/commands/build.d.ts +3 -0
  2. package/cjs/commands/build.js +165 -0
  3. package/cjs/commands/dev.d.ts +44 -0
  4. package/cjs/commands/dev.js +387 -0
  5. package/cjs/config/readWebpackConfig.d.ts +1 -0
  6. package/cjs/config/readWebpackConfig.js +14 -0
  7. package/cjs/config/types.d.ts +1 -0
  8. package/cjs/config/types.js +17 -0
  9. package/cjs/config/webpackCompat.d.ts +2 -0
  10. package/cjs/config/webpackCompat.js +7 -0
  11. package/cjs/core/hmr.d.ts +80 -0
  12. package/cjs/core/hmr.js +341 -0
  13. package/cjs/core/loaderWorkerPool.d.ts +1 -0
  14. package/cjs/core/loaderWorkerPool.js +35 -0
  15. package/cjs/core/project.d.ts +43 -0
  16. package/cjs/core/project.js +291 -0
  17. package/cjs/core/types.d.ts +94 -0
  18. package/cjs/core/types.js +2 -0
  19. package/cjs/plugins/HtmlPlugin.d.ts +9 -0
  20. package/cjs/plugins/HtmlPlugin.js +116 -0
  21. package/cjs/utils/common.d.ts +3 -0
  22. package/cjs/utils/common.js +32 -0
  23. package/cjs/utils/find-root.d.ts +4 -0
  24. package/cjs/utils/find-root.js +75 -0
  25. package/cjs/utils/html-entry.d.ts +2 -0
  26. package/cjs/utils/html-entry.js +47 -0
  27. package/cjs/utils/mkcert.d.ts +7 -0
  28. package/cjs/utils/mkcert.js +183 -0
  29. package/cjs/utils/print-server-info.d.ts +1 -0
  30. package/cjs/utils/print-server-info.js +50 -0
  31. package/cjs/utils/xcodeProfile.d.ts +1 -0
  32. package/cjs/utils/xcodeProfile.js +16 -0
  33. package/esm/commands/build.d.ts +3 -0
  34. package/esm/commands/build.js +129 -0
  35. package/esm/commands/dev.d.ts +44 -0
  36. package/esm/commands/dev.js +371 -0
  37. package/esm/config/readWebpackConfig.d.ts +1 -0
  38. package/esm/config/readWebpackConfig.js +8 -0
  39. package/esm/config/types.d.ts +1 -0
  40. package/esm/config/types.js +1 -0
  41. package/esm/config/webpackCompat.d.ts +2 -0
  42. package/esm/config/webpackCompat.js +2 -0
  43. package/esm/core/hmr.d.ts +80 -0
  44. package/esm/core/hmr.js +334 -0
  45. package/esm/core/loaderWorkerPool.d.ts +1 -0
  46. package/esm/core/loaderWorkerPool.js +32 -0
  47. package/esm/core/project.d.ts +43 -0
  48. package/esm/core/project.js +253 -0
  49. package/esm/core/types.d.ts +94 -0
  50. package/esm/core/types.js +1 -0
  51. package/esm/plugins/HtmlPlugin.d.ts +9 -0
  52. package/esm/plugins/HtmlPlugin.js +109 -0
  53. package/esm/utils/common.d.ts +3 -0
  54. package/esm/utils/common.js +18 -0
  55. package/esm/utils/find-root.d.ts +4 -0
  56. package/esm/utils/find-root.js +66 -0
  57. package/esm/utils/html-entry.d.ts +2 -0
  58. package/esm/utils/html-entry.js +41 -0
  59. package/esm/utils/mkcert.d.ts +7 -0
  60. package/esm/utils/mkcert.js +176 -0
  61. package/esm/utils/print-server-info.d.ts +1 -0
  62. package/esm/utils/print-server-info.js +44 -0
  63. package/esm/utils/xcodeProfile.d.ts +1 -0
  64. package/esm/utils/xcodeProfile.js +13 -0
  65. package/package.json +12 -14
@@ -0,0 +1,334 @@
1
+ import fs from "fs";
2
+ import { nanoid } from "nanoid";
3
+ import { join } from "path";
4
+ import ws from "ws";
5
+ import { HtmlPlugin } from "../plugins/HtmlPlugin";
6
+ import { createDefineEnv, debounce, getPackPath, processIssues, } from "../utils/common";
7
+ import { processHtmlEntry } from "../utils/html-entry";
8
+ import { projectFactory } from "./project";
9
+ const wsServer = new ws.Server({ noServer: true });
10
+ const sessionId = Math.floor(Number.MAX_SAFE_INTEGER * Math.random());
11
+ export const FAST_REFRESH_RUNTIME_RELOAD = "Fast Refresh had to perform a full reload due to a runtime error.";
12
+ export async function createHotReloader(bundleOptions, projectPath, rootPath) {
13
+ var _a;
14
+ processHtmlEntry(bundleOptions.config, projectPath || process.cwd());
15
+ const createProject = projectFactory();
16
+ const project = await createProject({
17
+ processEnv: (_a = bundleOptions.processEnv) !== null && _a !== void 0 ? _a : {},
18
+ defineEnv: createDefineEnv({
19
+ config: bundleOptions.config,
20
+ dev: true,
21
+ optionDefineEnv: bundleOptions.defineEnv,
22
+ }),
23
+ watch: {
24
+ enable: true,
25
+ },
26
+ dev: true,
27
+ buildId: bundleOptions.buildId || nanoid(),
28
+ config: {
29
+ ...bundleOptions.config,
30
+ mode: "development",
31
+ stats: Boolean(process.env.ANALYZE) ||
32
+ bundleOptions.config.stats ||
33
+ bundleOptions.config.entry.some((e) => !!e.html),
34
+ optimization: {
35
+ ...bundleOptions.config.optimization,
36
+ minify: false,
37
+ moduleIds: "named",
38
+ },
39
+ },
40
+ projectPath: projectPath || process.cwd(),
41
+ rootPath: rootPath || projectPath || process.cwd(),
42
+ packPath: getPackPath(),
43
+ }, {
44
+ persistentCaching: true,
45
+ });
46
+ const entrypointsSubscription = project.entrypointsSubscribe();
47
+ let currentEntriesHandlingResolve;
48
+ let currentEntriesHandling = new Promise((resolve) => (currentEntriesHandlingResolve = resolve));
49
+ let hmrEventHappened = false;
50
+ let hmrHash = 0;
51
+ const clients = new Set();
52
+ const clientStates = new WeakMap();
53
+ function sendToClient(client, payload) {
54
+ client.send(JSON.stringify(payload));
55
+ }
56
+ function sendEnqueuedMessages() {
57
+ for (const client of clients) {
58
+ const state = clientStates.get(client);
59
+ if (!state) {
60
+ continue;
61
+ }
62
+ for (const payload of state.hmrPayloads.values()) {
63
+ sendToClient(client, payload);
64
+ }
65
+ state.hmrPayloads.clear();
66
+ if (state.turbopackUpdates.length > 0) {
67
+ sendToClient(client, {
68
+ action: "turbopack-message" /* HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE */,
69
+ data: state.turbopackUpdates,
70
+ });
71
+ state.turbopackUpdates.length = 0;
72
+ }
73
+ }
74
+ }
75
+ const sendEnqueuedMessagesDebounce = debounce(sendEnqueuedMessages, 2);
76
+ function sendTurbopackMessage(payload) {
77
+ var _a;
78
+ payload.diagnostics = [];
79
+ payload.issues = [];
80
+ for (const client of clients) {
81
+ (_a = clientStates.get(client)) === null || _a === void 0 ? void 0 : _a.turbopackUpdates.push(payload);
82
+ }
83
+ hmrEventHappened = true;
84
+ sendEnqueuedMessagesDebounce();
85
+ }
86
+ async function subscribeToHmrEvents(client, id) {
87
+ const state = clientStates.get(client);
88
+ if (!state || state.subscriptions.has(id)) {
89
+ return;
90
+ }
91
+ const subscription = project.hmrEvents(id);
92
+ state.subscriptions.set(id, subscription);
93
+ // The subscription will always emit once, which is the initial
94
+ // computation. This is not a change, so swallow it.
95
+ try {
96
+ await subscription.next();
97
+ for await (const data of subscription) {
98
+ processIssues(data, true, true);
99
+ if (data.type !== "issues") {
100
+ sendTurbopackMessage(data);
101
+ }
102
+ }
103
+ }
104
+ catch (e) {
105
+ // The client might be using an HMR session from a previous server, tell them
106
+ // to fully reload the page to resolve the issue. We can't use
107
+ // `hotReloader.send` since that would force every connected client to
108
+ // reload, only this client is out of date.
109
+ const reloadAction = {
110
+ action: "reload" /* HMR_ACTIONS_SENT_TO_BROWSER.RELOAD */,
111
+ data: `error in HMR event subscription for ${id}: ${e}`,
112
+ };
113
+ sendToClient(client, reloadAction);
114
+ client.close();
115
+ return;
116
+ }
117
+ }
118
+ function unsubscribeFromHmrEvents(client, id) {
119
+ const state = clientStates.get(client);
120
+ if (!state) {
121
+ return;
122
+ }
123
+ const subscription = state.subscriptions.get(id);
124
+ subscription === null || subscription === void 0 ? void 0 : subscription.return();
125
+ }
126
+ async function handleEntrypointsSubscription() {
127
+ var _a, _b;
128
+ for await (const entrypoints of entrypointsSubscription) {
129
+ if (!currentEntriesHandlingResolve) {
130
+ currentEntriesHandling = new Promise(
131
+ // eslint-disable-next-line no-loop-func
132
+ (resolve) => (currentEntriesHandlingResolve = resolve));
133
+ }
134
+ const assets = { js: [], css: [] };
135
+ await Promise.all(entrypoints.apps.map((l) => l.writeToDisk().then((res) => {
136
+ processIssues(res, true, true);
137
+ res.clientPaths.forEach((p) => {
138
+ if (p.endsWith(".js"))
139
+ assets.js.push(p);
140
+ if (p.endsWith(".css"))
141
+ assets.css.push(p);
142
+ });
143
+ })));
144
+ const htmlConfigs = [
145
+ ...(Array.isArray(bundleOptions.config.html)
146
+ ? bundleOptions.config.html
147
+ : bundleOptions.config.html
148
+ ? [bundleOptions.config.html]
149
+ : []),
150
+ ...bundleOptions.config.entry
151
+ .filter((e) => !!e.html)
152
+ .map((e) => e.html),
153
+ ];
154
+ if (htmlConfigs.length > 0) {
155
+ const outputDir = ((_a = bundleOptions.config.output) === null || _a === void 0 ? void 0 : _a.path) || join(process.cwd(), "dist");
156
+ const publicPath = (_b = bundleOptions.config.output) === null || _b === void 0 ? void 0 : _b.publicPath;
157
+ if (assets.js.length === 0 && assets.css.length === 0) {
158
+ const statsPath = join(outputDir, "stats.json");
159
+ if (fs.existsSync(statsPath)) {
160
+ try {
161
+ const stats = JSON.parse(fs.readFileSync(statsPath, "utf-8"));
162
+ if (stats.assets) {
163
+ stats.assets.forEach((asset) => {
164
+ if (asset.name.endsWith(".js"))
165
+ assets.js.push(asset.name);
166
+ if (asset.name.endsWith(".css"))
167
+ assets.css.push(asset.name);
168
+ });
169
+ }
170
+ }
171
+ catch (e) {
172
+ console.warn("Failed to read stats.json for assets discovery", e);
173
+ }
174
+ }
175
+ }
176
+ for (const config of htmlConfigs) {
177
+ const plugin = new HtmlPlugin(config);
178
+ await plugin.generate(outputDir, assets, publicPath);
179
+ }
180
+ }
181
+ currentEntriesHandlingResolve();
182
+ currentEntriesHandlingResolve = undefined;
183
+ }
184
+ }
185
+ const hotReloader = {
186
+ turbopackProject: project,
187
+ serverStats: null,
188
+ onHMR(req, socket, head, onUpgrade) {
189
+ wsServer.handleUpgrade(req, socket, head, (client) => {
190
+ onUpgrade === null || onUpgrade === void 0 ? void 0 : onUpgrade(client);
191
+ const subscriptions = new Map();
192
+ clients.add(client);
193
+ clientStates.set(client, {
194
+ hmrPayloads: new Map(),
195
+ turbopackUpdates: [],
196
+ subscriptions,
197
+ });
198
+ client.on("close", () => {
199
+ var _a;
200
+ // Remove active subscriptions
201
+ for (const subscription of subscriptions.values()) {
202
+ (_a = subscription.return) === null || _a === void 0 ? void 0 : _a.call(subscription);
203
+ }
204
+ clientStates.delete(client);
205
+ clients.delete(client);
206
+ });
207
+ client.addEventListener("message", ({ data }) => {
208
+ const parsedData = JSON.parse(typeof data !== "string" ? data.toString() : data);
209
+ // messages
210
+ switch (parsedData.event) {
211
+ case "client-error": // { errorCount, clientId }
212
+ case "client-warning": // { warningCount, clientId }
213
+ case "client-success": // { clientId }
214
+ case "client-full-reload": // { stackTrace, hadRuntimeError }
215
+ const { hadRuntimeError, dependencyChain } = parsedData;
216
+ if (hadRuntimeError) {
217
+ console.warn(FAST_REFRESH_RUNTIME_RELOAD);
218
+ }
219
+ if (Array.isArray(dependencyChain) &&
220
+ typeof dependencyChain[0] === "string") {
221
+ const cleanedModulePath = dependencyChain[0]
222
+ .replace(/^\[project\]/, ".")
223
+ .replace(/ \[.*\] \(.*\)$/, "");
224
+ console.warn(`Fast Refresh had to perform a full reload when ${cleanedModulePath} changed.`);
225
+ }
226
+ break;
227
+ default:
228
+ // Might be a Turbopack message...
229
+ if (!parsedData.type) {
230
+ throw new Error(`unrecognized HMR message "${data}"`);
231
+ }
232
+ }
233
+ // Turbopack messages
234
+ switch (parsedData.type) {
235
+ case "turbopack-subscribe":
236
+ subscribeToHmrEvents(client, parsedData.path);
237
+ break;
238
+ case "turbopack-unsubscribe":
239
+ unsubscribeFromHmrEvents(client, parsedData.path);
240
+ break;
241
+ default:
242
+ if (!parsedData.event) {
243
+ throw new Error(`unrecognized Turbopack HMR message "${data}"`);
244
+ }
245
+ }
246
+ });
247
+ const turbopackConnected = {
248
+ action: "turbopack-connected" /* HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED */,
249
+ data: { sessionId },
250
+ };
251
+ sendToClient(client, turbopackConnected);
252
+ const errors = [];
253
+ (async function () {
254
+ const sync = {
255
+ action: "sync" /* HMR_ACTIONS_SENT_TO_BROWSER.SYNC */,
256
+ errors,
257
+ warnings: [],
258
+ hash: "",
259
+ };
260
+ sendToClient(client, sync);
261
+ })();
262
+ });
263
+ },
264
+ send(action) {
265
+ const payload = JSON.stringify(action);
266
+ for (const client of clients) {
267
+ client.send(payload);
268
+ }
269
+ },
270
+ setHmrServerError(_error) {
271
+ // Not implemented yet.
272
+ },
273
+ clearHmrServerError() {
274
+ // Not implemented yet.
275
+ },
276
+ async start() { },
277
+ async buildFallbackError() {
278
+ // Not implemented yet.
279
+ },
280
+ close() {
281
+ for (const wsClient of clients) {
282
+ // it's okay to not cleanly close these websocket connections, this is dev
283
+ wsClient.terminate();
284
+ }
285
+ clients.clear();
286
+ },
287
+ };
288
+ handleEntrypointsSubscription().catch((err) => {
289
+ console.error(err);
290
+ process.exit(1);
291
+ });
292
+ // Write empty manifests
293
+ await currentEntriesHandling;
294
+ async function handleProjectUpdates() {
295
+ for await (const updateMessage of project.updateInfoSubscribe(30)) {
296
+ switch (updateMessage.updateType) {
297
+ case "start": {
298
+ hotReloader.send({ action: "building" /* HMR_ACTIONS_SENT_TO_BROWSER.BUILDING */ });
299
+ break;
300
+ }
301
+ case "end": {
302
+ sendEnqueuedMessages();
303
+ const errors = new Map();
304
+ for (const client of clients) {
305
+ const state = clientStates.get(client);
306
+ if (!state) {
307
+ continue;
308
+ }
309
+ const clientErrors = new Map(errors);
310
+ sendToClient(client, {
311
+ action: "built" /* HMR_ACTIONS_SENT_TO_BROWSER.BUILT */,
312
+ hash: String(++hmrHash),
313
+ errors: [...clientErrors.values()],
314
+ warnings: [],
315
+ });
316
+ }
317
+ if (hmrEventHappened) {
318
+ const time = updateMessage.value.duration;
319
+ const timeMessage = time > 2000 ? `${Math.round(time / 100) / 10}s` : `${time}ms`;
320
+ console.log(`Compiled in ${timeMessage}`);
321
+ hmrEventHappened = false;
322
+ }
323
+ break;
324
+ }
325
+ default:
326
+ }
327
+ }
328
+ }
329
+ handleProjectUpdates().catch((err) => {
330
+ console.error(err);
331
+ process.exit(1);
332
+ });
333
+ return hotReloader;
334
+ }
@@ -0,0 +1 @@
1
+ export declare function runLoaderWorkerPool(binding: typeof import("../binding"), bindingPath: string): Promise<void>;
@@ -0,0 +1,32 @@
1
+ import { Worker } from "worker_threads";
2
+ const loaderWorkers = {};
3
+ function getPoolId(cwd, filename) {
4
+ return `${cwd}:${filename}`;
5
+ }
6
+ let workerSchedulerRegistered = false;
7
+ export async function runLoaderWorkerPool(binding, bindingPath) {
8
+ if (workerSchedulerRegistered) {
9
+ return;
10
+ }
11
+ binding.registerWorkerScheduler((creation) => {
12
+ const { options: { filename, cwd }, } = creation;
13
+ let poolId = getPoolId(cwd, filename);
14
+ const worker = new Worker(filename, {
15
+ workerData: {
16
+ bindingPath,
17
+ cwd,
18
+ },
19
+ });
20
+ worker.unref();
21
+ const workers = loaderWorkers[poolId] || (loaderWorkers[poolId] = new Map());
22
+ workers.set(worker.threadId, worker);
23
+ }, (termination) => {
24
+ var _a;
25
+ const { options: { filename, cwd }, workerId, } = termination;
26
+ let poolId = getPoolId(cwd, filename);
27
+ const workers = loaderWorkers[poolId];
28
+ (_a = workers.get(workerId)) === null || _a === void 0 ? void 0 : _a.terminate();
29
+ workers.delete(workerId);
30
+ });
31
+ workerSchedulerRegistered = true;
32
+ }
@@ -0,0 +1,43 @@
1
+ import type { HmrIdentifiers, NapiUpdateMessage, NapiWrittenEndpoint, StackFrame } from "../binding";
2
+ import * as binding from "../binding";
3
+ import { ProjectOptions, RawEntrypoints, Update } from "./types";
4
+ export declare class TurbopackInternalError extends Error {
5
+ name: string;
6
+ constructor(cause: Error);
7
+ }
8
+ export declare function projectFactory(): (options: Required<ProjectOptions>, turboEngineOptions: binding.NapiTurboEngineOptions) => Promise<{
9
+ readonly _nativeProject: {
10
+ __napiType: "Project";
11
+ };
12
+ update(options: Partial<ProjectOptions>): Promise<void>;
13
+ writeAllEntrypointsToDisk(): Promise<TurbopackResult<RawEntrypoints>>;
14
+ entrypointsSubscribe(): AsyncGenerator<{
15
+ apps: {
16
+ readonly _nativeEndpoint: {
17
+ __napiType: "Endpoint";
18
+ };
19
+ writeToDisk(): Promise<TurbopackResult<NapiWrittenEndpoint>>;
20
+ clientChanged(): Promise<AsyncIterableIterator<TurbopackResult<{}>>>;
21
+ serverChanged(includeIssues: boolean): Promise<AsyncIterableIterator<TurbopackResult<{}>>>;
22
+ }[];
23
+ libraries: {
24
+ readonly _nativeEndpoint: {
25
+ __napiType: "Endpoint";
26
+ };
27
+ writeToDisk(): Promise<TurbopackResult<NapiWrittenEndpoint>>;
28
+ clientChanged(): Promise<AsyncIterableIterator<TurbopackResult<{}>>>;
29
+ serverChanged(includeIssues: boolean): Promise<AsyncIterableIterator<TurbopackResult<{}>>>;
30
+ }[];
31
+ issues: binding.NapiIssue[];
32
+ diagnostics: binding.NapiDiagnostic[];
33
+ }, void, unknown>;
34
+ hmrEvents(identifier: string): AsyncIterableIterator<TurbopackResult<Update>>;
35
+ hmrIdentifiersSubscribe(): AsyncIterableIterator<TurbopackResult<HmrIdentifiers>>;
36
+ traceSource(stackFrame: StackFrame, currentDirectoryFileUrl: string): Promise<StackFrame | null>;
37
+ getSourceForAsset(filePath: string): Promise<string | null>;
38
+ getSourceMap(filePath: string): Promise<string | null>;
39
+ getSourceMapSync(filePath: string): string | null;
40
+ updateInfoSubscribe(aggregationMs: number): AsyncIterableIterator<TurbopackResult<NapiUpdateMessage>>;
41
+ shutdown(): Promise<void>;
42
+ onExit(): Promise<void>;
43
+ }>;
@@ -0,0 +1,253 @@
1
+ import { isDeepStrictEqual } from "util";
2
+ import * as binding from "../binding";
3
+ import { rustifyEnv } from "../utils/common";
4
+ import { runLoaderWorkerPool } from "./loaderWorkerPool";
5
+ export class TurbopackInternalError extends Error {
6
+ constructor(cause) {
7
+ super(cause.message);
8
+ this.name = "TurbopackInternalError";
9
+ this.stack = cause.stack;
10
+ }
11
+ }
12
+ async function withErrorCause(fn) {
13
+ try {
14
+ return await fn();
15
+ }
16
+ catch (nativeError) {
17
+ throw new TurbopackInternalError(nativeError);
18
+ }
19
+ }
20
+ function ensureLoadersHaveSerializableOptions(turbopackRules) {
21
+ for (const [glob, rule] of Object.entries(turbopackRules)) {
22
+ if (Array.isArray(rule)) {
23
+ checkLoaderItems(rule, glob);
24
+ }
25
+ else {
26
+ checkConfigItem(rule, glob);
27
+ }
28
+ }
29
+ function checkConfigItem(rule, glob) {
30
+ if (!rule)
31
+ return;
32
+ if ("loaders" in rule) {
33
+ checkLoaderItems(rule.loaders, glob);
34
+ }
35
+ else {
36
+ for (const key in rule) {
37
+ const inner = rule[key];
38
+ if (typeof inner === "object" && inner) {
39
+ checkConfigItem(inner, glob);
40
+ }
41
+ }
42
+ }
43
+ }
44
+ function checkLoaderItems(loaderItems, glob) {
45
+ for (const loaderItem of loaderItems) {
46
+ if (typeof loaderItem !== "string" &&
47
+ !isDeepStrictEqual(loaderItem, JSON.parse(JSON.stringify(loaderItem)))) {
48
+ throw new Error(`loader ${loaderItem.loader} for match "${glob}" does not have serializable options. Ensure that options passed are plain JavaScript objects and values.`);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ async function serializeConfig(config) {
54
+ var _a;
55
+ const configSerializable = { ...config };
56
+ if (configSerializable.entry) {
57
+ configSerializable.entry = configSerializable.entry.map((entry) => {
58
+ const { html, ...rest } = entry;
59
+ return rest;
60
+ });
61
+ }
62
+ if ((_a = configSerializable.module) === null || _a === void 0 ? void 0 : _a.rules) {
63
+ ensureLoadersHaveSerializableOptions(configSerializable.module.rules);
64
+ }
65
+ if (configSerializable.optimization) {
66
+ configSerializable.optimization = { ...configSerializable.optimization };
67
+ const { modularizeImports } = configSerializable.optimization;
68
+ if (modularizeImports) {
69
+ configSerializable.optimization.modularizeImports = Object.fromEntries(Object.entries(modularizeImports).map(([mod, config]) => [
70
+ mod,
71
+ {
72
+ ...config,
73
+ transform: typeof config.transform === "string"
74
+ ? config.transform
75
+ : Object.entries(config.transform).map(([key, value]) => [
76
+ key,
77
+ value,
78
+ ]),
79
+ },
80
+ ]));
81
+ }
82
+ }
83
+ return JSON.stringify(configSerializable, null, 2);
84
+ }
85
+ async function rustifyPartialProjectOptions(options) {
86
+ return {
87
+ ...options,
88
+ config: options.config && (await serializeConfig(options.config)),
89
+ processEnv: options.processEnv && rustifyEnv(options.processEnv),
90
+ };
91
+ }
92
+ async function rustifyProjectOptions(options) {
93
+ var _a;
94
+ return {
95
+ ...options,
96
+ config: await serializeConfig(options.config),
97
+ processEnv: rustifyEnv((_a = options.processEnv) !== null && _a !== void 0 ? _a : {}),
98
+ };
99
+ }
100
+ export function projectFactory() {
101
+ const cancel = new (class Cancel extends Error {
102
+ })();
103
+ function subscribe(useBuffer, nativeFunction) {
104
+ // A buffer of produced items. This will only contain values if the
105
+ // consumer is slower than the producer.
106
+ let buffer = [];
107
+ // A deferred value waiting for the next produced item. This will only
108
+ // exist if the consumer is faster than the producer.
109
+ let waiting;
110
+ let canceled = false;
111
+ // The native function will call this every time it emits a new result. We
112
+ // either need to notify a waiting consumer, or buffer the new result until
113
+ // the consumer catches up.
114
+ function emitResult(err, value) {
115
+ if (waiting) {
116
+ let { resolve, reject } = waiting;
117
+ waiting = undefined;
118
+ if (err)
119
+ reject(err);
120
+ else
121
+ resolve(value);
122
+ }
123
+ else {
124
+ const item = { err, value };
125
+ if (useBuffer)
126
+ buffer.push(item);
127
+ else
128
+ buffer[0] = item;
129
+ }
130
+ }
131
+ async function* createIterator() {
132
+ const task = await withErrorCause(() => nativeFunction(emitResult));
133
+ try {
134
+ while (!canceled) {
135
+ if (buffer.length > 0) {
136
+ const item = buffer.shift();
137
+ if (item.err)
138
+ throw item.err;
139
+ yield item.value;
140
+ }
141
+ else {
142
+ // eslint-disable-next-line no-loop-func
143
+ yield new Promise((resolve, reject) => {
144
+ waiting = { resolve, reject };
145
+ });
146
+ }
147
+ }
148
+ }
149
+ catch (e) {
150
+ if (e === cancel)
151
+ return;
152
+ if (e instanceof Error) {
153
+ throw new TurbopackInternalError(e);
154
+ }
155
+ throw e;
156
+ }
157
+ finally {
158
+ if (task) {
159
+ binding.rootTaskDispose(task);
160
+ }
161
+ }
162
+ }
163
+ const iterator = createIterator();
164
+ iterator.return = async () => {
165
+ canceled = true;
166
+ if (waiting)
167
+ waiting.reject(cancel);
168
+ return { value: undefined, done: true };
169
+ };
170
+ return iterator;
171
+ }
172
+ class ProjectImpl {
173
+ constructor(nativeProject) {
174
+ this._nativeProject = nativeProject;
175
+ if (typeof binding.registerWorkerScheduler === "function") {
176
+ runLoaderWorkerPool(binding, require.resolve("@utoo/pack/cjs/binding.js"));
177
+ }
178
+ }
179
+ async update(options) {
180
+ await withErrorCause(async () => binding.projectUpdate(this._nativeProject, await rustifyPartialProjectOptions(options)));
181
+ }
182
+ async writeAllEntrypointsToDisk() {
183
+ return await withErrorCause(async () => {
184
+ const napiEndpoints = (await binding.projectWriteAllEntrypointsToDisk(this._nativeProject));
185
+ return napiEntrypointsToRawEntrypoints(napiEndpoints);
186
+ });
187
+ }
188
+ entrypointsSubscribe() {
189
+ const subscription = subscribe(false, async (callback) => binding.projectEntrypointsSubscribe(this._nativeProject, callback));
190
+ return (async function* () {
191
+ for await (const entrypoints of subscription) {
192
+ yield napiEntrypointsToRawEntrypoints(entrypoints);
193
+ }
194
+ })();
195
+ }
196
+ hmrEvents(identifier) {
197
+ return subscribe(true, async (callback) => binding.projectHmrEvents(this._nativeProject, identifier, callback));
198
+ }
199
+ hmrIdentifiersSubscribe() {
200
+ return subscribe(false, async (callback) => binding.projectHmrIdentifiersSubscribe(this._nativeProject, callback));
201
+ }
202
+ traceSource(stackFrame, currentDirectoryFileUrl) {
203
+ return binding.projectTraceSource(this._nativeProject, stackFrame, currentDirectoryFileUrl);
204
+ }
205
+ getSourceForAsset(filePath) {
206
+ return binding.projectGetSourceForAsset(this._nativeProject, filePath);
207
+ }
208
+ getSourceMap(filePath) {
209
+ return binding.projectGetSourceMap(this._nativeProject, filePath);
210
+ }
211
+ getSourceMapSync(filePath) {
212
+ return binding.projectGetSourceMapSync(this._nativeProject, filePath);
213
+ }
214
+ updateInfoSubscribe(aggregationMs) {
215
+ return subscribe(true, async (callback) => binding.projectUpdateInfoSubscribe(this._nativeProject, aggregationMs, callback));
216
+ }
217
+ shutdown() {
218
+ return binding.projectShutdown(this._nativeProject);
219
+ }
220
+ onExit() {
221
+ return binding.projectOnExit(this._nativeProject);
222
+ }
223
+ }
224
+ class EndpointImpl {
225
+ constructor(nativeEndpoint) {
226
+ this._nativeEndpoint = nativeEndpoint;
227
+ }
228
+ async writeToDisk() {
229
+ return await withErrorCause(() => binding.endpointWriteToDisk(this._nativeEndpoint));
230
+ }
231
+ async clientChanged() {
232
+ const clientSubscription = subscribe(false, async (callback) => binding.endpointClientChangedSubscribe(await this._nativeEndpoint, callback));
233
+ await clientSubscription.next();
234
+ return clientSubscription;
235
+ }
236
+ async serverChanged(includeIssues) {
237
+ const serverSubscription = subscribe(false, async (callback) => binding.endpointServerChangedSubscribe(await this._nativeEndpoint, includeIssues, callback));
238
+ await serverSubscription.next();
239
+ return serverSubscription;
240
+ }
241
+ }
242
+ function napiEntrypointsToRawEntrypoints(entrypoints) {
243
+ return {
244
+ apps: (entrypoints.apps || []).map((e) => new EndpointImpl(e)),
245
+ libraries: (entrypoints.libraries || []).map((e) => new EndpointImpl(e)),
246
+ issues: entrypoints.issues,
247
+ diagnostics: entrypoints.diagnostics,
248
+ };
249
+ }
250
+ return async function createProject(options, turboEngineOptions) {
251
+ return new ProjectImpl(await binding.projectNew(await rustifyProjectOptions(options), turboEngineOptions || {}));
252
+ };
253
+ }