@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,371 @@
1
+ import fs from "fs";
2
+ import http from "http";
3
+ import https from "https";
4
+ import { isIPv6 } from "net";
5
+ import path from "path";
6
+ import send from "send";
7
+ import url from "url";
8
+ import { compatOptionsFromWebpack, readWebpackConfig, } from "../config/webpackCompat";
9
+ import { createHotReloader } from "../core/hmr";
10
+ import { blockStdout, getPackPath } from "../utils/common";
11
+ import { findRootDir } from "../utils/find-root";
12
+ import { createSelfSignedCertificate } from "../utils/mkcert";
13
+ import { printServerInfo } from "../utils/print-server-info";
14
+ import { xcodeProfilingReady } from "../utils/xcodeProfile";
15
+ export function serve(options, projectPath, rootPath, serverOptions) {
16
+ let bundleOptions;
17
+ if (options.webpackMode) {
18
+ let webpackConfig = options;
19
+ if (!webpackConfig.entry) {
20
+ const loadedConfig = readWebpackConfig(projectPath, rootPath);
21
+ webpackConfig = { ...webpackConfig, ...loadedConfig };
22
+ }
23
+ bundleOptions = compatOptionsFromWebpack(webpackConfig);
24
+ }
25
+ else {
26
+ bundleOptions = options;
27
+ }
28
+ if (!rootPath) {
29
+ // help user to find the rootDir automatically
30
+ rootPath = findRootDir(projectPath || process.cwd());
31
+ }
32
+ return serveInternal(bundleOptions, projectPath, rootPath, serverOptions);
33
+ }
34
+ async function serveInternal(options, projectPath, rootPath, serverOptions) {
35
+ blockStdout();
36
+ if (process.env.XCODE_PROFILE) {
37
+ await xcodeProfilingReady();
38
+ }
39
+ await startServer({
40
+ hostname: (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.hostname) || "localhost",
41
+ port: (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.port) || 3000,
42
+ https: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.https,
43
+ logServerInfo: serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.logServerInfo,
44
+ selfSignedCertificate: (serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.https)
45
+ ? await createSelfSignedCertificate((serverOptions === null || serverOptions === void 0 ? void 0 : serverOptions.hostname) || "localhost")
46
+ : undefined,
47
+ }, {
48
+ ...options,
49
+ config: {
50
+ ...options.config,
51
+ devServer: { hot: true },
52
+ },
53
+ packPath: getPackPath(),
54
+ }, projectPath || process.cwd(), rootPath);
55
+ }
56
+ export async function startServer(serverOptions, bundleOptions, projectPath, rootPath) {
57
+ let { port, hostname, selfSignedCertificate } = serverOptions;
58
+ process.title = "utoopack-dev-server";
59
+ let handlersReady = () => { };
60
+ let handlersError = () => { };
61
+ let handlersPromise = new Promise((resolve, reject) => {
62
+ handlersReady = resolve;
63
+ handlersError = reject;
64
+ });
65
+ let requestHandler = async (req, res) => {
66
+ if (handlersPromise) {
67
+ await handlersPromise;
68
+ return requestHandler(req, res);
69
+ }
70
+ throw new Error("Invariant request handler was not setup");
71
+ };
72
+ let upgradeHandler = async (req, socket, head) => {
73
+ if (handlersPromise) {
74
+ await handlersPromise;
75
+ return upgradeHandler(req, socket, head);
76
+ }
77
+ throw new Error("Invariant upgrade handler was not setup");
78
+ };
79
+ async function requestListener(req, res) {
80
+ try {
81
+ if (handlersPromise) {
82
+ await handlersPromise;
83
+ handlersPromise = undefined;
84
+ }
85
+ await requestHandler(req, res);
86
+ }
87
+ catch (err) {
88
+ res.statusCode = 500;
89
+ res.end("Internal Server Error");
90
+ console.error(`Failed to handle request for ${req.url}`);
91
+ console.error(err);
92
+ }
93
+ }
94
+ const server = selfSignedCertificate
95
+ ? https.createServer({
96
+ key: fs.readFileSync(selfSignedCertificate.key),
97
+ cert: fs.readFileSync(selfSignedCertificate.cert),
98
+ }, requestListener)
99
+ : http.createServer(requestListener);
100
+ server.on("upgrade", async (req, socket, head) => {
101
+ try {
102
+ await upgradeHandler(req, socket, head);
103
+ }
104
+ catch (err) {
105
+ socket.destroy();
106
+ console.error(`Failed to handle request for ${req.url}`);
107
+ console.error(err);
108
+ }
109
+ });
110
+ let portRetryCount = 0;
111
+ const originalPort = port;
112
+ server.on("error", (err) => {
113
+ if (port && err.code === "EADDRINUSE" && portRetryCount < 10) {
114
+ port += 1;
115
+ portRetryCount += 1;
116
+ server.listen(port, hostname);
117
+ }
118
+ else {
119
+ console.error(`Failed to start server`);
120
+ console.error(err);
121
+ process.exit(1);
122
+ }
123
+ });
124
+ await new Promise((resolve) => {
125
+ server.on("listening", async () => {
126
+ const addr = server.address();
127
+ const actualHostname = formatHostname(typeof addr === "object"
128
+ ? (addr === null || addr === void 0 ? void 0 : addr.address) || hostname || "localhost"
129
+ : addr);
130
+ const formattedHostname = !hostname || actualHostname === "0.0.0.0"
131
+ ? "localhost"
132
+ : actualHostname === "[::]"
133
+ ? "[::1]"
134
+ : formatHostname(hostname);
135
+ port = typeof addr === "object" ? (addr === null || addr === void 0 ? void 0 : addr.port) || port : port;
136
+ if (portRetryCount) {
137
+ console.warn(`Port ${originalPort} is in use, using available port ${port} instead.`);
138
+ }
139
+ if (serverOptions.logServerInfo !== false) {
140
+ printServerInfo(serverOptions.https ? "https" : "http", formattedHostname, port);
141
+ }
142
+ try {
143
+ let cleanupStarted = false;
144
+ let closeUpgraded = null;
145
+ const cleanup = () => {
146
+ if (cleanupStarted) {
147
+ return;
148
+ }
149
+ cleanupStarted = true;
150
+ (async () => {
151
+ console.debug("start-server process cleanup");
152
+ await new Promise((res) => {
153
+ server.close((err) => {
154
+ if (err)
155
+ console.error(err);
156
+ res();
157
+ });
158
+ server.closeAllConnections();
159
+ closeUpgraded === null || closeUpgraded === void 0 ? void 0 : closeUpgraded();
160
+ });
161
+ console.debug("start-server process cleanup finished");
162
+ process.exit(0);
163
+ })();
164
+ };
165
+ const exception = (err) => {
166
+ console.error(err);
167
+ };
168
+ process.on("SIGINT", cleanup);
169
+ process.on("SIGTERM", cleanup);
170
+ process.on("rejectionHandled", () => { });
171
+ process.on("uncaughtException", exception);
172
+ process.on("unhandledRejection", exception);
173
+ const initResult = await initialize(bundleOptions, projectPath, rootPath);
174
+ requestHandler = initResult.requestHandler;
175
+ upgradeHandler = initResult.upgradeHandler;
176
+ closeUpgraded = initResult.closeUpgraded;
177
+ handlersReady();
178
+ }
179
+ catch (err) {
180
+ handlersError();
181
+ console.error(err);
182
+ process.exit(1);
183
+ }
184
+ resolve();
185
+ });
186
+ server.listen(port, hostname);
187
+ });
188
+ }
189
+ export async function initialize(bundleOptions, projectPath, rootPath) {
190
+ process.env.NODE_ENV = "development";
191
+ const hotReloader = await createHotReloader(bundleOptions, projectPath, rootPath);
192
+ await hotReloader.start();
193
+ const requestHandlerImpl = async (req, res) => {
194
+ req.on("error", console.error);
195
+ res.on("error", console.error);
196
+ const handleRequest = async () => {
197
+ var _a;
198
+ if (!(req.method === "GET" || req.method === "HEAD")) {
199
+ res.setHeader("Allow", ["GET", "HEAD"]);
200
+ res.statusCode = 405;
201
+ res.end();
202
+ }
203
+ const distRoot = path.resolve(projectPath, ((_a = bundleOptions.config.output) === null || _a === void 0 ? void 0 : _a.path) || "./dist");
204
+ try {
205
+ const reqUrl = req.url || "";
206
+ const path = url.parse(reqUrl).pathname || "";
207
+ return await serveStatic(req, res, path, { root: distRoot });
208
+ }
209
+ catch (err) {
210
+ res.setHeader("Cache-Control", "private, no-cache, no-store, max-age=0, must-revalidate");
211
+ res.statusCode = 404;
212
+ res.end();
213
+ }
214
+ };
215
+ try {
216
+ await handleRequest();
217
+ }
218
+ catch (err) {
219
+ res.statusCode = 500;
220
+ res.end("Internal Server Error");
221
+ }
222
+ };
223
+ let requestHandler = requestHandlerImpl;
224
+ const logError = async (type, err) => {
225
+ if (type === "unhandledRejection") {
226
+ console.error("unhandledRejection: ", err);
227
+ }
228
+ else if (type === "uncaughtException") {
229
+ console.error("uncaughtException: ", err);
230
+ }
231
+ };
232
+ process.on("uncaughtException", logError.bind(null, "uncaughtException"));
233
+ process.on("unhandledRejection", logError.bind(null, "unhandledRejection"));
234
+ const upgradeHandler = async (req, socket, head) => {
235
+ var _a;
236
+ try {
237
+ const isHMRRequest = (_a = req.url) === null || _a === void 0 ? void 0 : _a.includes("turbopack-hmr");
238
+ if (isHMRRequest) {
239
+ hotReloader.onHMR(req, socket, head);
240
+ }
241
+ else {
242
+ socket.end();
243
+ }
244
+ }
245
+ catch (err) {
246
+ console.error("Error handling upgrade request", err);
247
+ socket.end();
248
+ }
249
+ };
250
+ return {
251
+ requestHandler,
252
+ upgradeHandler,
253
+ closeUpgraded() {
254
+ hotReloader.close();
255
+ },
256
+ };
257
+ }
258
+ export async function pipeToNodeResponse(readable, res, waitUntilForEnd) {
259
+ try {
260
+ const { errored, destroyed } = res;
261
+ if (errored || destroyed)
262
+ return;
263
+ const controller = createAbortController(res);
264
+ const writer = createWriterFromResponse(res, waitUntilForEnd);
265
+ await readable.pipeTo(writer, { signal: controller.signal });
266
+ }
267
+ catch (err) {
268
+ if (isAbortError(err))
269
+ return;
270
+ throw new Error("failed to pipe response", { cause: err });
271
+ }
272
+ }
273
+ export function createAbortController(response) {
274
+ const controller = new AbortController();
275
+ response.once("close", () => {
276
+ if (response.writableFinished)
277
+ return;
278
+ controller.abort(new ResponseAborted());
279
+ });
280
+ return controller;
281
+ }
282
+ export function isAbortError(e) {
283
+ return (e === null || e === void 0 ? void 0 : e.name) === "AbortError" || (e === null || e === void 0 ? void 0 : e.name) === ResponseAbortedName;
284
+ }
285
+ export const ResponseAbortedName = "ResponseAborted";
286
+ export class ResponseAborted extends Error {
287
+ constructor() {
288
+ super(...arguments);
289
+ this.name = ResponseAbortedName;
290
+ }
291
+ }
292
+ function createWriterFromResponse(res, waitUntilForEnd) {
293
+ let started = false;
294
+ let drained = new DetachedPromise();
295
+ function onDrain() {
296
+ drained.resolve();
297
+ }
298
+ res.on("drain", onDrain);
299
+ res.once("close", () => {
300
+ res.off("drain", onDrain);
301
+ drained.resolve();
302
+ });
303
+ const finished = new DetachedPromise();
304
+ res.once("finish", () => {
305
+ finished.resolve();
306
+ });
307
+ return new WritableStream({
308
+ write: async (chunk) => {
309
+ if (!started) {
310
+ started = true;
311
+ res.flushHeaders();
312
+ }
313
+ try {
314
+ const ok = res.write(chunk);
315
+ if ("flush" in res && typeof res.flush === "function") {
316
+ res.flush();
317
+ }
318
+ if (!ok) {
319
+ await drained.promise;
320
+ drained = new DetachedPromise();
321
+ }
322
+ }
323
+ catch (err) {
324
+ res.end();
325
+ throw new Error("failed to write chunk to response", { cause: err });
326
+ }
327
+ },
328
+ abort: (err) => {
329
+ if (res.writableFinished)
330
+ return;
331
+ res.destroy(err);
332
+ },
333
+ close: async () => {
334
+ if (waitUntilForEnd) {
335
+ await waitUntilForEnd;
336
+ }
337
+ if (res.writableFinished)
338
+ return;
339
+ res.end();
340
+ return finished.promise;
341
+ },
342
+ });
343
+ }
344
+ export class DetachedPromise {
345
+ constructor() {
346
+ let resolve;
347
+ let reject;
348
+ this.promise = new Promise((res, rej) => {
349
+ resolve = res;
350
+ reject = rej;
351
+ });
352
+ this.resolve = resolve;
353
+ this.reject = reject;
354
+ }
355
+ }
356
+ export function serveStatic(req, res, path, opts) {
357
+ return new Promise((resolve, reject) => {
358
+ send(req, path, opts)
359
+ .on("directory", () => {
360
+ const err = new Error("No directory access");
361
+ err.code = "ENOENT";
362
+ reject(err);
363
+ })
364
+ .on("error", reject)
365
+ .pipe(res)
366
+ .on("finish", resolve);
367
+ });
368
+ }
369
+ export function formatHostname(hostname) {
370
+ return isIPv6(hostname) ? `[${hostname}]` : hostname;
371
+ }
@@ -0,0 +1 @@
1
+ export declare function readWebpackConfig(projectPath?: string, rootPath?: string): any;
@@ -0,0 +1,8 @@
1
+ import path from "path";
2
+ export function readWebpackConfig(projectPath, rootPath) {
3
+ const projectPathOutOfRoot = projectPath === undefined
4
+ ? process.cwd()
5
+ : path.join(rootPath !== null && rootPath !== void 0 ? rootPath : "", projectPath);
6
+ const configPath = path.join(projectPathOutOfRoot, "webpack.config.js");
7
+ return require(configPath);
8
+ }
@@ -0,0 +1 @@
1
+ export * from "@utoo/pack-shared";
@@ -0,0 +1 @@
1
+ export * from "@utoo/pack-shared";
@@ -0,0 +1,2 @@
1
+ export { compatOptionsFromWebpack, type WebpackConfig, } from "@utoo/pack-shared";
2
+ export { readWebpackConfig } from "./readWebpackConfig";
@@ -0,0 +1,2 @@
1
+ export { compatOptionsFromWebpack, } from "@utoo/pack-shared";
2
+ export { readWebpackConfig } from "./readWebpackConfig";
@@ -0,0 +1,80 @@
1
+ import { IncomingMessage } from "http";
2
+ import { Duplex } from "stream";
3
+ import type webpack from "webpack";
4
+ import { BundleOptions, Project, Update as TurbopackUpdate } from "./types";
5
+ export declare const enum HMR_ACTIONS_SENT_TO_BROWSER {
6
+ RELOAD = "reload",
7
+ CLIENT_CHANGES = "clientChanges",
8
+ SERVER_ONLY_CHANGES = "serverOnlyChanges",
9
+ SYNC = "sync",
10
+ BUILT = "built",
11
+ BUILDING = "building",
12
+ TURBOPACK_MESSAGE = "turbopack-message",
13
+ TURBOPACK_CONNECTED = "turbopack-connected"
14
+ }
15
+ export interface TurbopackMessageAction {
16
+ action: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE;
17
+ data: TurbopackUpdate | TurbopackUpdate[];
18
+ }
19
+ export interface TurbopackConnectedAction {
20
+ action: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED;
21
+ data: {
22
+ sessionId: number;
23
+ };
24
+ }
25
+ interface BuildingAction {
26
+ action: HMR_ACTIONS_SENT_TO_BROWSER.BUILDING;
27
+ }
28
+ export interface CompilationError {
29
+ moduleName?: string;
30
+ message: string;
31
+ details?: string;
32
+ moduleTrace?: Array<{
33
+ moduleName?: string;
34
+ }>;
35
+ stack?: string;
36
+ }
37
+ export interface SyncAction {
38
+ action: HMR_ACTIONS_SENT_TO_BROWSER.SYNC;
39
+ hash: string;
40
+ errors: ReadonlyArray<CompilationError>;
41
+ warnings: ReadonlyArray<CompilationError>;
42
+ updatedModules?: ReadonlyArray<string>;
43
+ }
44
+ export interface BuiltAction {
45
+ action: HMR_ACTIONS_SENT_TO_BROWSER.BUILT;
46
+ hash: string;
47
+ errors: ReadonlyArray<CompilationError>;
48
+ warnings: ReadonlyArray<CompilationError>;
49
+ updatedModules?: ReadonlyArray<string>;
50
+ }
51
+ export interface ReloadAction {
52
+ action: HMR_ACTIONS_SENT_TO_BROWSER.RELOAD;
53
+ data: string;
54
+ }
55
+ export type HMR_ACTION_TYPES = TurbopackMessageAction | TurbopackConnectedAction | BuildingAction | SyncAction | BuiltAction | ReloadAction;
56
+ export interface HotReloaderInterface {
57
+ turbopackProject?: Project;
58
+ serverStats: webpack.Stats | null;
59
+ setHmrServerError(error: Error | null): void;
60
+ clearHmrServerError(): void;
61
+ start(): Promise<void>;
62
+ send(action: HMR_ACTION_TYPES): void;
63
+ onHMR(req: IncomingMessage, socket: Duplex, head: Buffer, onUpgrade?: (client: {
64
+ send(data: string): void;
65
+ }) => void): void;
66
+ buildFallbackError(): Promise<void>;
67
+ close(): void;
68
+ }
69
+ export type ChangeSubscriptions = Map<string, Promise<AsyncIterableIterator<TurbopackResult>>>;
70
+ export type ReadyIds = Set<string>;
71
+ export type StartBuilding = (id: string, forceRebuild: boolean) => () => void;
72
+ export type ClientState = {
73
+ hmrPayloads: Map<string, HMR_ACTION_TYPES>;
74
+ turbopackUpdates: TurbopackUpdate[];
75
+ subscriptions: Map<string, AsyncIterator<any>>;
76
+ };
77
+ export type SendHmr = (id: string, payload: HMR_ACTION_TYPES) => void;
78
+ export declare const FAST_REFRESH_RUNTIME_RELOAD = "Fast Refresh had to perform a full reload due to a runtime error.";
79
+ export declare function createHotReloader(bundleOptions: BundleOptions, projectPath?: string, rootPath?: string): Promise<HotReloaderInterface>;
80
+ export {};