@marko/run 0.5.12 → 0.5.14

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.
@@ -1,21 +1,382 @@
1
1
  // src/adapter/index.ts
2
- import path2 from "path";
2
+ import { start as explorerStart } from "@marko/run-explorer";
3
3
  import fs2 from "fs";
4
4
  import inspector from "inspector";
5
+ import path2 from "path";
5
6
  import { fileURLToPath } from "url";
6
7
 
7
- // src/adapter/dev-server.ts
8
- import path from "path";
9
- import {
10
- createServer,
11
- buildErrorMessage
12
- } from "vite";
8
+ // src/vite/utils/server.ts
9
+ import cp from "child_process";
10
+ import cluster from "cluster";
11
+ import { config, parse } from "dotenv";
12
+ import fs from "fs";
13
+ import net from "net";
14
+ async function parseEnv(envFile) {
15
+ if (fs.existsSync(envFile)) {
16
+ const content = await fs.promises.readFile(envFile, "utf8");
17
+ return parse(content);
18
+ }
19
+ }
20
+ function loadEnv(envFile) {
21
+ config({ path: envFile });
22
+ }
23
+ async function spawnServer(cmd, args = [], port = 0, env, cwd = process.cwd(), wait = 3e4, stdio = ["ignore", "inherit", "inherit"]) {
24
+ if (port <= 0) {
25
+ port = await getAvailablePort();
26
+ }
27
+ if (typeof env === "string") {
28
+ env = await parseEnv(env);
29
+ }
30
+ const proc = cp.spawn(cmd, args, {
31
+ cwd,
32
+ shell: true,
33
+ stdio,
34
+ windowsHide: true,
35
+ env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
36
+ });
37
+ const close = () => {
38
+ proc.unref();
39
+ proc.kill();
40
+ };
41
+ try {
42
+ await Promise.race([waitForError(proc, port), waitForServer(port, wait)]);
43
+ } catch (err) {
44
+ close();
45
+ throw err;
46
+ }
47
+ return {
48
+ port,
49
+ close
50
+ };
51
+ }
52
+ async function spawnServerWorker(module, args = [], port = 0, env, wait = true) {
53
+ if (port <= 0) {
54
+ port = await getAvailablePort();
55
+ }
56
+ if (typeof env === "string") {
57
+ env = await parseEnv(env);
58
+ }
59
+ const originalExec = cluster.settings.exec;
60
+ const originalArgs = cluster.settings.execArgv;
61
+ try {
62
+ cluster.settings.exec = module;
63
+ cluster.settings.execArgv = args;
64
+ const worker = cluster.fork({
65
+ ...env,
66
+ NODE_ENV: "development",
67
+ ...process.env,
68
+ PORT: `${port}`
69
+ });
70
+ if (wait) {
71
+ return new Promise((resolve) => {
72
+ function ready(message) {
73
+ if (message === "ready") {
74
+ worker.off("message", ready);
75
+ resolve(worker);
76
+ }
77
+ }
78
+ worker.on("message", ready);
79
+ });
80
+ }
81
+ return worker;
82
+ } finally {
83
+ cluster.settings.exec = originalExec;
84
+ cluster.settings.execArgv = originalArgs;
85
+ }
86
+ }
87
+ async function waitForError(proc, port) {
88
+ return new Promise((_, reject) => {
89
+ proc.once("error", reject);
90
+ proc.once("exit", (code) => {
91
+ reject(
92
+ new Error(
93
+ `Process exited with code ${code} while waiting for server to start on port "${port}".`
94
+ )
95
+ );
96
+ });
97
+ });
98
+ }
99
+ async function waitForServer(port, wait = 0) {
100
+ let remaining = wait > 0 ? wait : Infinity;
101
+ let connection;
102
+ while (!(connection = await getConnection(port))) {
103
+ if (remaining >= 100) {
104
+ remaining -= 100;
105
+ await sleep(100);
106
+ } else {
107
+ throw new Error(
108
+ `Timeout while wating for server to start on port "${port}".`
109
+ );
110
+ }
111
+ }
112
+ return connection;
113
+ }
114
+ async function waitForWorker(worker, port) {
115
+ return new Promise((resolve, reject) => {
116
+ function listening(address) {
117
+ if (address.port === port) {
118
+ worker.off("listening", listening);
119
+ resolve();
120
+ }
121
+ }
122
+ worker.on("listening", listening).once("error", reject).once("exit", (code) => {
123
+ reject(
124
+ new Error(
125
+ `Worker exited with code ${code} while waiting for dev server to start on port "${port}".`
126
+ )
127
+ );
128
+ });
129
+ });
130
+ }
131
+ async function getConnection(port) {
132
+ return new Promise((resolve) => {
133
+ const connection = net.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => {
134
+ connection.end();
135
+ resolve(null);
136
+ }).on("connect", () => {
137
+ resolve(connection);
138
+ });
139
+ });
140
+ }
141
+ async function isPortInUse(port) {
142
+ return Boolean(await getConnection(port));
143
+ }
144
+ async function getAvailablePort(port) {
145
+ if (port && !await isPortInUse(port)) {
146
+ return port;
147
+ }
148
+ return new Promise((resolve) => {
149
+ const server = net.createServer().listen(0, () => {
150
+ const { port: port2 } = server.address();
151
+ server.close(() => resolve(port2));
152
+ });
153
+ });
154
+ }
155
+ function sleep(ms) {
156
+ return new Promise((resolve) => setTimeout(resolve, ms));
157
+ }
158
+ function getInspectOptions(args) {
159
+ for (const arg of args) {
160
+ const match = arg.match(/^--inspect(-brk)?(?:=(?:(.+):)?(.+))?$/);
161
+ if (match) {
162
+ return {
163
+ host: match[2],
164
+ port: parseInt(match[3], 10) || void 0,
165
+ wait: !!match[1]
166
+ };
167
+ }
168
+ }
169
+ }
170
+
171
+ // src/adapter/dev-server.ts
172
+ import path from "path";
173
+ import {
174
+ buildErrorMessage,
175
+ createServer
176
+ } from "vite";
177
+
178
+ // src/adapter/logger.ts
179
+ import DraftLog from "draftlog";
180
+ import format from "human-format";
181
+ import inpspector from "inspector";
182
+ import kleur from "kleur";
183
+ if (!inpspector.url()) {
184
+ DraftLog.into(console);
185
+ DraftLog.defaults.canReWrite = false;
186
+ }
187
+ var HttpStatusColors = [
188
+ "",
189
+ // Unused
190
+ "green",
191
+ // 1xx
192
+ "green",
193
+ // 2xx
194
+ "cyan",
195
+ // 3xx
196
+ "yellow",
197
+ // 4xx
198
+ "red"
199
+ // 5xx
200
+ ];
201
+ var IdChars = [
202
+ "",
203
+ kleur.cyan("\xB9"),
204
+ kleur.magenta("\xB2"),
205
+ kleur.green("\xB3"),
206
+ kleur.red("\u2074"),
207
+ kleur.cyan("\u2075"),
208
+ kleur.magenta("\u2076"),
209
+ kleur.green("\u2077"),
210
+ kleur.red("\u2078"),
211
+ kleur.cyan("\u2079"),
212
+ kleur.red("\u207A")
213
+ ];
214
+ var ArrowSteps = [" ", " \u25C0", " \u25C0\u2501", "\u25C0\u2501\u2501", "\u2501\u2501 ", "\u2501 ", " "];
215
+ function logger_default(_options = {}) {
216
+ let inFlight = 0;
217
+ return function logger(req, res, next) {
218
+ const startTime = Date.now();
219
+ const handleFinish = () => done("finish");
220
+ const handleClose = () => done("close");
221
+ res.on("finish", handleFinish);
222
+ res.on("close", handleClose);
223
+ const bitMask = ~inFlight & inFlight + 1;
224
+ const index = Math.log2(bitMask);
225
+ const id = IdChars[index];
226
+ if (index < IdChars.length) {
227
+ inFlight |= bitMask;
228
+ }
229
+ const finalizeLog = logRequest(id, req);
230
+ let bodyLength = 0;
231
+ const _write = res.write;
232
+ const _end = res.end;
233
+ res.write = (...args) => {
234
+ if (args[0]) {
235
+ if (typeof args[1] !== "function") {
236
+ bodyLength += Buffer.byteLength(args[0], args[1]);
237
+ } else {
238
+ bodyLength += args[0].length;
239
+ }
240
+ }
241
+ return _write.apply(res, args);
242
+ };
243
+ res.end = (...args) => {
244
+ if (args[0] && typeof args[0] !== "function") {
245
+ if (typeof args[1] !== "function") {
246
+ bodyLength += Buffer.byteLength(args[0], args[1]);
247
+ } else {
248
+ bodyLength += args[0].length;
249
+ }
250
+ }
251
+ return _end.apply(res, args);
252
+ };
253
+ next == null ? void 0 : next();
254
+ function done(event) {
255
+ res.off("finish", handleFinish);
256
+ res.off("close", handleClose);
257
+ finalizeLog();
258
+ if (index < 10) {
259
+ inFlight ^= bitMask;
260
+ }
261
+ let contentLength = res.getHeader("content-length") || 0;
262
+ if (Array.isArray(contentLength)) {
263
+ contentLength = parseInt(contentLength[0], 10) || 0;
264
+ } else if (typeof contentLength === "string") {
265
+ contentLength = parseInt(contentLength, 10) || 0;
266
+ }
267
+ logResponse(
268
+ id,
269
+ req,
270
+ res,
271
+ startTime,
272
+ contentLength || bodyLength,
273
+ event === "finish"
274
+ );
275
+ }
276
+ };
277
+ }
278
+ var spinners;
279
+ function logRequest(id, req) {
280
+ const info = id + " " + kleur.bold(req.method) + " " + kleur.dim(req.url);
281
+ const final = kleur.dim(requestArrow(id)) + info;
282
+ if (console.draft) {
283
+ spinners ?? (spinners = createAnimationManager({ steps: ArrowSteps.length }));
284
+ const update = console.draft();
285
+ const stop = spinners.add((step) => {
286
+ update(kleur.cyan(requestArrow(id, step)) + info);
287
+ });
288
+ return () => {
289
+ stop();
290
+ update(final);
291
+ };
292
+ }
293
+ console.log(final);
294
+ return () => {
295
+ };
296
+ }
297
+ function logResponse(id, req, res, startTime, contentLength, success) {
298
+ const status = res.statusCode;
299
+ const color = HttpStatusColors[status / 100 | 0] || "red";
300
+ let length;
301
+ if (req.method === "HEAD" || [204, 205, 304].includes(status)) {
302
+ length = "";
303
+ } else if (!contentLength) {
304
+ length = kleur.dim("-");
305
+ } else {
306
+ length = formatMeasurement(bytes(contentLength));
307
+ }
308
+ let arrow = id ? "\u2501" : "\u2501\u2501";
309
+ if (success) {
310
+ arrow = kleur.dim(arrow + "\u25B6");
311
+ } else {
312
+ arrow = kleur.red(kleur.dim(arrow) + kleur.bold("x"));
313
+ }
314
+ console.log(
315
+ arrow + id + " " + kleur.bold(req.method) + " " + kleur.dim(req.url) + " " + kleur[color](status) + " " + formatMeasurement(time(startTime)) + " " + length
316
+ );
317
+ }
318
+ function requestArrow(id, step = 3) {
319
+ const arrow = ArrowSteps[step];
320
+ return id ? arrow.slice(0, -1) : arrow;
321
+ }
322
+ function time(start) {
323
+ const delta = Date.now() - start;
324
+ return delta < 5e3 ? [delta, "ms"] : [(delta / 1e3).toFixed(1), "s"];
325
+ }
326
+ function bytes(size) {
327
+ const { value, prefix } = format.raw(size, { maxDecimals: 2, unit: "b" });
328
+ return [value.toFixed(2), (prefix + "b").toLowerCase()];
329
+ }
330
+ function formatMeasurement([value, unit]) {
331
+ return kleur.dim(value + kleur.yellow(kleur.bold(unit)));
332
+ }
333
+ function createAnimationManager(options = {}) {
334
+ const { steps = 1e4, ms = 100 } = options;
335
+ const fns = /* @__PURE__ */ new Set();
336
+ let step = 0;
337
+ let isRunning = false;
338
+ let interval;
339
+ function start() {
340
+ step = 0;
341
+ isRunning = true;
342
+ interval = setInterval(() => {
343
+ if (isRunning) {
344
+ for (const fn of fns) {
345
+ fn(step);
346
+ }
347
+ step = (step + 1) % steps;
348
+ }
349
+ }, ms);
350
+ }
351
+ function stop() {
352
+ isRunning = false;
353
+ clearInterval(interval);
354
+ }
355
+ return {
356
+ add(fn) {
357
+ fns.add(fn);
358
+ if (!isRunning) {
359
+ start();
360
+ }
361
+ fn(step);
362
+ return () => {
363
+ fns.delete(fn);
364
+ if (!fns.size) {
365
+ stop();
366
+ }
367
+ };
368
+ }
369
+ };
370
+ }
371
+
372
+ // src/adapter/middleware.ts
373
+ import { Readable } from "node:stream";
13
374
 
14
375
  // src/adapter/polyfill.ts
15
- import * as webStream from "stream/web";
16
376
  import { webcrypto } from "crypto";
17
- import * as undici from "undici";
18
377
  import { ServerResponse } from "http";
378
+ import * as webStream from "stream/web";
379
+ import * as undici from "undici";
19
380
  globalThis.crypto ?? (globalThis.crypto = webcrypto);
20
381
  globalThis.fetch ?? (globalThis.fetch = undici.fetch);
21
382
  globalThis.Response ?? (globalThis.Response = undici.Response);
@@ -80,7 +441,6 @@ function getSetCookie_fallback(headers) {
80
441
  }
81
442
 
82
443
  // src/adapter/middleware.ts
83
- import { Readable } from "node:stream";
84
444
  function getForwardedHeader(req, name) {
85
445
  const value = req.headers["x-forwarded-" + name];
86
446
  if (value) {
@@ -191,277 +551,83 @@ function createMiddleware(fetch2, options) {
191
551
  } else {
192
552
  body = req;
193
553
  }
194
- break;
195
- }
196
- const request = new Request(url, {
197
- method: req.method,
198
- headers: req.headers,
199
- body,
200
- // @ts-expect-error: Node requires this for streams
201
- duplex: "half",
202
- signal
203
- });
204
- const platform = createPlatform({
205
- request: req,
206
- response: res
207
- });
208
- let response;
209
- try {
210
- response = await fetch2(request, platform);
211
- } catch (err) {
212
- normalizeError(err);
213
- if (next) {
214
- next(err);
215
- } else {
216
- console.error(err);
217
- }
218
- return;
219
- }
220
- if (!response) {
221
- if (next) {
222
- next();
223
- }
224
- return;
225
- }
226
- res.statusCode = response.status;
227
- copyResponseHeaders(res, response.headers);
228
- if (!response.body) {
229
- if (!response.headers.has("content-length")) {
230
- res.setHeader("content-length", "0");
231
- }
232
- res.end();
233
- return;
234
- } else if (res.destroyed) {
235
- controller.abort(new Error("Response stream destroyed"));
236
- return;
237
- }
238
- writeResponse(response.body.getReader(), res, controller);
239
- };
240
- }
241
- async function writeResponse(reader, res, controller) {
242
- try {
243
- while (!controller.signal.aborted) {
244
- const { done, value } = await reader.read();
245
- if (done) {
246
- res.end();
247
- return;
248
- }
249
- res.write(value);
250
- if (res.flush) {
251
- res.flush();
252
- }
253
- }
254
- } catch (err) {
255
- controller.abort(err);
256
- }
257
- }
258
- var bodyConsumedErrorStream = new ReadableStream({
259
- pull(controller) {
260
- controller.error(
261
- new Error(
262
- "The request body stream has been destroyed or consumed by something before Marko Run."
263
- )
264
- );
265
- }
266
- });
267
-
268
- // src/adapter/logger.ts
269
- import kleur from "kleur";
270
- import DraftLog from "draftlog";
271
- import format from "human-format";
272
- import inpspector from "inspector";
273
- if (!inpspector.url()) {
274
- DraftLog.into(console);
275
- DraftLog.defaults.canReWrite = false;
276
- }
277
- var HttpStatusColors = [
278
- "",
279
- // Unused
280
- "green",
281
- // 1xx
282
- "green",
283
- // 2xx
284
- "cyan",
285
- // 3xx
286
- "yellow",
287
- // 4xx
288
- "red"
289
- // 5xx
290
- ];
291
- var IdChars = [
292
- "",
293
- kleur.cyan("\xB9"),
294
- kleur.magenta("\xB2"),
295
- kleur.green("\xB3"),
296
- kleur.red("\u2074"),
297
- kleur.cyan("\u2075"),
298
- kleur.magenta("\u2076"),
299
- kleur.green("\u2077"),
300
- kleur.red("\u2078"),
301
- kleur.cyan("\u2079"),
302
- kleur.red("\u207A")
303
- ];
304
- var ArrowSteps = [" ", " \u25C0", " \u25C0\u2501", "\u25C0\u2501\u2501", "\u2501\u2501 ", "\u2501 ", " "];
305
- function logger_default(_options = {}) {
306
- let inFlight = 0;
307
- return function logger(req, res, next) {
308
- let startTime = Date.now();
309
- const handleFinish = () => done("finish");
310
- const handleClose = () => done("close");
311
- res.on("finish", handleFinish);
312
- res.on("close", handleClose);
313
- const bitMask = ~inFlight & inFlight + 1;
314
- const index = Math.log2(bitMask);
315
- const id = IdChars[index];
316
- if (index < IdChars.length) {
317
- inFlight |= bitMask;
318
- }
319
- const finalizeLog = logRequest(id, req);
320
- let bodyLength = 0;
321
- const _write = res.write;
322
- const _end = res.end;
323
- res.write = (...args) => {
324
- if (args[0]) {
325
- if (typeof args[1] !== "function") {
326
- bodyLength += Buffer.byteLength(args[0], args[1]);
327
- } else {
328
- bodyLength += args[0].length;
329
- }
330
- }
331
- return _write.apply(res, args);
332
- };
333
- res.end = (...args) => {
334
- if (args[0] && typeof args[0] !== "function") {
335
- if (typeof args[1] !== "function") {
336
- bodyLength += Buffer.byteLength(args[0], args[1]);
337
- } else {
338
- bodyLength += args[0].length;
339
- }
340
- }
341
- return _end.apply(res, args);
342
- };
343
- next == null ? void 0 : next();
344
- function done(event) {
345
- res.off("finish", handleFinish);
346
- res.off("close", handleClose);
347
- finalizeLog();
348
- if (index < 10) {
349
- inFlight ^= bitMask;
350
- }
351
- let contentLength = res.getHeader("content-length") || 0;
352
- if (Array.isArray(contentLength)) {
353
- contentLength = parseInt(contentLength[0], 10) || 0;
354
- } else if (typeof contentLength === "string") {
355
- contentLength = parseInt(contentLength, 10) || 0;
356
- }
357
- logResponse(
358
- id,
359
- req,
360
- res,
361
- startTime,
362
- contentLength || bodyLength,
363
- event === "finish"
364
- );
365
- }
366
- };
367
- }
368
- var spinners;
369
- function logRequest(id, req) {
370
- const info = id + " " + kleur.bold(req.method) + " " + kleur.dim(req.url);
371
- const final = kleur.dim(requestArrow(id)) + info;
372
- if (console.draft) {
373
- spinners ?? (spinners = createAnimationManager({ steps: ArrowSteps.length }));
374
- const update = console.draft();
375
- const stop = spinners.add((step) => {
376
- update(kleur.cyan(requestArrow(id, step)) + info);
377
- });
378
- return () => {
379
- stop();
380
- update(final);
381
- };
382
- }
383
- console.log(final);
384
- return () => {
385
- };
386
- }
387
- function logResponse(id, req, res, startTime, contentLength, success) {
388
- const status = res.statusCode;
389
- const color = HttpStatusColors[status / 100 | 0] || "red";
390
- let length;
391
- if (req.method === "HEAD" || [204, 205, 304].includes(status)) {
392
- length = "";
393
- } else if (!contentLength) {
394
- length = kleur.dim("-");
395
- } else {
396
- length = formatMeasurement(bytes(contentLength));
397
- }
398
- let arrow = id ? "\u2501" : "\u2501\u2501";
399
- if (success) {
400
- arrow = kleur.dim(arrow + "\u25B6");
401
- } else {
402
- arrow = kleur.red(kleur.dim(arrow) + kleur.bold("x"));
403
- }
404
- console.log(
405
- arrow + id + " " + kleur.bold(req.method) + " " + kleur.dim(req.url) + " " + kleur[color](status) + " " + formatMeasurement(time(startTime)) + " " + length
406
- );
407
- }
408
- function requestArrow(id, step = 3) {
409
- const arrow = ArrowSteps[step];
410
- return id ? arrow.slice(0, -1) : arrow;
411
- }
412
- function time(start) {
413
- const delta = Date.now() - start;
414
- return delta < 5e3 ? [delta, "ms"] : [(delta / 1e3).toFixed(1), "s"];
415
- }
416
- function bytes(size) {
417
- const { value, prefix } = format.raw(size, { maxDecimals: 2, unit: "b" });
418
- return [value.toFixed(2), (prefix + "b").toLowerCase()];
419
- }
420
- function formatMeasurement([value, unit]) {
421
- return kleur.dim(value + kleur.yellow(kleur.bold(unit)));
422
- }
423
- function createAnimationManager(options = {}) {
424
- const { steps = 1e4, ms = 100 } = options;
425
- const fns = /* @__PURE__ */ new Set();
426
- let step = 0;
427
- let isRunning = false;
428
- let interval;
429
- function start() {
430
- step = 0;
431
- isRunning = true;
432
- interval = setInterval(() => {
433
- if (isRunning) {
434
- for (const fn of fns) {
435
- fn(step);
436
- }
437
- step = (step + 1) % steps;
554
+ break;
555
+ }
556
+ const request = new Request(url, {
557
+ method: req.method,
558
+ headers: req.headers,
559
+ body,
560
+ // @ts-expect-error: Node requires this for streams
561
+ duplex: "half",
562
+ signal
563
+ });
564
+ const platform = createPlatform({
565
+ request: req,
566
+ response: res
567
+ });
568
+ let response;
569
+ try {
570
+ response = await fetch2(request, platform);
571
+ } catch (err) {
572
+ normalizeError(err);
573
+ if (next) {
574
+ next(err);
575
+ } else {
576
+ console.error(err);
438
577
  }
439
- }, ms);
440
- }
441
- function stop() {
442
- isRunning = false;
443
- clearInterval(interval);
444
- }
445
- return {
446
- add(fn) {
447
- fns.add(fn);
448
- if (!isRunning) {
449
- start();
578
+ return;
579
+ }
580
+ if (!response) {
581
+ if (next) {
582
+ next();
450
583
  }
451
- fn(step);
452
- return () => {
453
- fns.delete(fn);
454
- if (!fns.size) {
455
- stop();
456
- }
457
- };
584
+ return;
458
585
  }
586
+ res.statusCode = response.status;
587
+ copyResponseHeaders(res, response.headers);
588
+ if (!response.body) {
589
+ if (!response.headers.has("content-length")) {
590
+ res.setHeader("content-length", "0");
591
+ }
592
+ res.end();
593
+ return;
594
+ } else if (res.destroyed) {
595
+ controller.abort(new Error("Response stream destroyed"));
596
+ return;
597
+ }
598
+ writeResponse(response.body.getReader(), res, controller);
459
599
  };
460
600
  }
601
+ async function writeResponse(reader, res, controller) {
602
+ try {
603
+ while (!controller.signal.aborted) {
604
+ const { done, value } = await reader.read();
605
+ if (done) {
606
+ res.end();
607
+ return;
608
+ }
609
+ res.write(value);
610
+ if (res.flush) {
611
+ res.flush();
612
+ }
613
+ }
614
+ } catch (err) {
615
+ controller.abort(err);
616
+ }
617
+ }
618
+ var bodyConsumedErrorStream = new ReadableStream({
619
+ pull(controller) {
620
+ controller.error(
621
+ new Error(
622
+ "The request body stream has been destroyed or consumed by something before Marko Run."
623
+ )
624
+ );
625
+ }
626
+ });
461
627
 
462
628
  // src/adapter/utils.ts
463
- import supporsColor from "supports-color";
464
629
  import kleur2 from "kleur";
630
+ import supporsColor from "supports-color";
465
631
  function stripAnsi(string) {
466
632
  return string.replace(
467
633
  /([\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><])/g,
@@ -487,7 +653,7 @@ function logInfoBox(address, explorer) {
487
653
  const color = !!supporsColor.stdout;
488
654
  let message = kleur2.bold("Marko Run");
489
655
  if (true) {
490
- message += ` v${"0.5.12"}`;
656
+ message += ` v${"0.5.14"}`;
491
657
  }
492
658
  message += "\n\n";
493
659
  message += kleur2.dim("Server listening at");
@@ -534,7 +700,7 @@ function drawMarkoBox(message, options) {
534
700
  }
535
701
  line += textPadding;
536
702
  if (i >= textStartLine && i < textEndLine) {
537
- let index = i - textStartLine;
703
+ const index = i - textStartLine;
538
704
  line += textLines[index];
539
705
  line += " ".repeat(textWidth - textWidths[index]);
540
706
  } else {
@@ -569,13 +735,16 @@ B\u2572 \u2572 GG\u203E\u203E\u203E\u203E O\u2571 \u2571 P\u2571 \u2571
569
735
  O: "#ff9500",
570
736
  R: "#f3154d",
571
737
  P: "#ce176c"
572
- }).reduce((acc, [key, hex]) => {
573
- const r = parseInt(hex.slice(1, 3), 16);
574
- const g = parseInt(hex.slice(3, 5), 16);
575
- const b = parseInt(hex.slice(5, 7), 16);
576
- acc[key] = `\x1B[38;2;${r};${g};${b}m`;
577
- return acc;
578
- }, {});
738
+ }).reduce(
739
+ (acc, [key, hex]) => {
740
+ const r = parseInt(hex.slice(1, 3), 16);
741
+ const g = parseInt(hex.slice(3, 5), 16);
742
+ const b = parseInt(hex.slice(5, 7), 16);
743
+ acc[key] = `\x1B[38;2;${r};${g};${b}m`;
744
+ return acc;
745
+ },
746
+ {}
747
+ );
579
748
  const lines = [];
580
749
  const lineWidths = [];
581
750
  let line = "";
@@ -720,7 +889,11 @@ function getDevGlobal() {
720
889
  function createErrorMiddleware(devServer) {
721
890
  return function errorMiddleware(error, _req, res, _next) {
722
891
  if (!error.id) {
723
- devServer.config.logger.error(buildErrorMessage(error, [`\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`]));
892
+ devServer.config.logger.error(
893
+ buildErrorMessage(error, [
894
+ `\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`
895
+ ])
896
+ );
724
897
  }
725
898
  res.statusCode = 500;
726
899
  res.end(`
@@ -757,171 +930,7 @@ function createErrorMiddleware(devServer) {
757
930
  };
758
931
  }
759
932
 
760
- // src/vite/utils/server.ts
761
- import net from "net";
762
- import cp from "child_process";
763
- import { parse, config } from "dotenv";
764
- import fs from "fs";
765
- import cluster from "cluster";
766
- async function parseEnv(envFile) {
767
- if (fs.existsSync(envFile)) {
768
- const content = await fs.promises.readFile(envFile, "utf8");
769
- return parse(content);
770
- }
771
- }
772
- function loadEnv(envFile) {
773
- config({ path: envFile });
774
- }
775
- async function spawnServer(cmd, args = [], port = 0, env, cwd = process.cwd(), wait = 3e4, stdio = ["ignore", "inherit", "inherit"]) {
776
- if (port <= 0) {
777
- port = await getAvailablePort();
778
- }
779
- if (typeof env === "string") {
780
- env = await parseEnv(env);
781
- }
782
- const proc = cp.spawn(cmd, args, {
783
- cwd,
784
- shell: true,
785
- stdio,
786
- windowsHide: true,
787
- env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
788
- });
789
- const close = () => {
790
- proc.unref();
791
- proc.kill();
792
- };
793
- try {
794
- await Promise.race([waitForError(proc, port), waitForServer(port, wait)]);
795
- } catch (err) {
796
- close();
797
- throw err;
798
- }
799
- return {
800
- port,
801
- close
802
- };
803
- }
804
- async function spawnServerWorker(module, args = [], port = 0, env, wait = true) {
805
- if (port <= 0) {
806
- port = await getAvailablePort();
807
- }
808
- if (typeof env === "string") {
809
- env = await parseEnv(env);
810
- }
811
- const originalExec = cluster.settings.exec;
812
- const originalArgs = cluster.settings.execArgv;
813
- try {
814
- cluster.settings.exec = module;
815
- cluster.settings.execArgv = args;
816
- const worker = cluster.fork({
817
- ...env,
818
- NODE_ENV: "development",
819
- ...process.env,
820
- PORT: `${port}`
821
- });
822
- if (wait) {
823
- return new Promise((resolve) => {
824
- function ready(message) {
825
- if (message === "ready") {
826
- worker.off("message", ready);
827
- resolve(worker);
828
- }
829
- }
830
- worker.on("message", ready);
831
- });
832
- }
833
- return worker;
834
- } finally {
835
- cluster.settings.exec = originalExec;
836
- cluster.settings.execArgv = originalArgs;
837
- }
838
- }
839
- async function waitForError(proc, port) {
840
- return new Promise((_, reject) => {
841
- proc.once("error", reject);
842
- proc.once("exit", (code) => {
843
- reject(
844
- new Error(
845
- `Process exited with code ${code} while waiting for server to start on port "${port}".`
846
- )
847
- );
848
- });
849
- });
850
- }
851
- async function waitForServer(port, wait = 0) {
852
- let remaining = wait > 0 ? wait : Infinity;
853
- let connection;
854
- while (!(connection = await getConnection(port))) {
855
- if (remaining >= 100) {
856
- remaining -= 100;
857
- await sleep(100);
858
- } else {
859
- throw new Error(
860
- `Timeout while wating for server to start on port "${port}".`
861
- );
862
- }
863
- }
864
- return connection;
865
- }
866
- async function waitForWorker(worker, port) {
867
- return new Promise((resolve, reject) => {
868
- function listening(address) {
869
- if (address.port === port) {
870
- worker.off("listening", listening);
871
- resolve();
872
- }
873
- }
874
- worker.on("listening", listening).once("error", reject).once("exit", (code) => {
875
- reject(
876
- new Error(
877
- `Worker exited with code ${code} while waiting for dev server to start on port "${port}".`
878
- )
879
- );
880
- });
881
- });
882
- }
883
- async function getConnection(port) {
884
- return new Promise((resolve) => {
885
- const connection = net.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => {
886
- connection.end();
887
- resolve(null);
888
- }).on("connect", () => {
889
- resolve(connection);
890
- });
891
- });
892
- }
893
- async function isPortInUse(port) {
894
- return Boolean(await getConnection(port));
895
- }
896
- async function getAvailablePort(port) {
897
- if (port && !await isPortInUse(port)) {
898
- return port;
899
- }
900
- return new Promise((resolve) => {
901
- const server = net.createServer().listen(0, () => {
902
- const { port: port2 } = server.address();
903
- server.close(() => resolve(port2));
904
- });
905
- });
906
- }
907
- function sleep(ms) {
908
- return new Promise((resolve) => setTimeout(resolve, ms));
909
- }
910
- function getInspectOptions(args) {
911
- for (const arg of args) {
912
- const match = arg.match(/^--inspect(-brk)?(?:=(?:(.+):)?(.+))?$/);
913
- if (match) {
914
- return {
915
- host: match[2],
916
- port: parseInt(match[3], 10) || void 0,
917
- wait: !!match[1]
918
- };
919
- }
920
- }
921
- }
922
-
923
933
  // src/adapter/index.ts
924
- import { start as explorerStart } from "@marko/run-explorer";
925
934
  import parseNodeArgs from "parse-node-args";
926
935
 
927
936
  // src/vite/constants.ts
@@ -960,13 +969,12 @@ function adapter() {
960
969
  await waitForWorker(nextWorker, port);
961
970
  if (worker) {
962
971
  const prevWorker = worker;
963
- let timeout;
964
972
  worker.once("disconnect", () => {
965
973
  clearTimeout(timeout);
966
974
  });
967
975
  worker.send({ type: "shutdown" });
968
976
  worker.disconnect();
969
- timeout = setTimeout(() => {
977
+ const timeout = setTimeout(() => {
970
978
  prevWorker.kill();
971
979
  }, 2e3);
972
980
  }
@@ -976,7 +984,7 @@ function adapter() {
976
984
  return {
977
985
  port,
978
986
  async close() {
979
- await Promise.all([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
987
+ await Promise.allSettled([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
980
988
  }
981
989
  };
982
990
  }
@@ -986,12 +994,16 @@ function adapter() {
986
994
  if (inspect) {
987
995
  inspector.open(inspect.port, inspect.host, inspect.wait);
988
996
  }
989
- const listen = new Promise((resolve) => {
990
- const listener = devServer.middlewares.listen(port, () => {
991
- resolve(listener.address());
997
+ const listenerPromise = new Promise((resolve) => {
998
+ const listener2 = devServer.middlewares.listen(port, () => {
999
+ resolve(listener2);
992
1000
  });
993
1001
  });
994
- const [explorer, address] = await Promise.all([explorerPromise, listen]);
1002
+ const [explorer, listener] = await Promise.all([
1003
+ explorerPromise,
1004
+ listenerPromise
1005
+ ]);
1006
+ const address = listener.address();
995
1007
  logInfoBox(
996
1008
  `http://localhost:${address.port}`,
997
1009
  explorer && `http://localhost:${explorer.port}`
@@ -999,7 +1011,11 @@ function adapter() {
999
1011
  return {
1000
1012
  port: address.port,
1001
1013
  async close() {
1002
- await Promise.all([devServer.close(), explorer == null ? void 0 : explorer.close()]);
1014
+ await Promise.allSettled([
1015
+ devServer.close(),
1016
+ listener.close(),
1017
+ explorer == null ? void 0 : explorer.close()
1018
+ ]);
1003
1019
  }
1004
1020
  };
1005
1021
  },
@@ -1020,7 +1036,7 @@ function adapter() {
1020
1036
  return explorer ? {
1021
1037
  port: server.port,
1022
1038
  async close() {
1023
- await Promise.all([server.close(), explorer.close()]);
1039
+ await Promise.allSettled([server.close(), explorer.close()]);
1024
1040
  }
1025
1041
  } : server;
1026
1042
  },
@@ -1042,7 +1058,7 @@ function adapter() {
1042
1058
  };
1043
1059
  for (const [name, code] of virtualFiles) {
1044
1060
  let fileName = "";
1045
- let index = name.indexOf(markoRunFilePrefix);
1061
+ const index = name.indexOf(markoRunFilePrefix);
1046
1062
  if (index >= 0) {
1047
1063
  fileName = name.slice(index);
1048
1064
  data.files[fileName] = `${virtualFilePrefix}/${fileName}`;