@marko/run 0.5.13 → 0.5.15

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) {
@@ -193,275 +553,81 @@ function createMiddleware(fetch2, options) {
193
553
  }
194
554
  break;
195
555
  }
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;
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;
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;
458
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.13"}`;
656
+ message += ` v${"0.5.15"}`;
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 = "";
@@ -628,11 +797,18 @@ B\u2572 \u2572 GG\u203E\u203E\u203E\u203E O\u2571 \u2571 P\u2571 \u2571
628
797
 
629
798
  // src/adapter/dev-server.ts
630
799
  async function createViteDevServer(config2) {
631
- const devServer = await createServer({
800
+ const finalConfig = {
632
801
  ...config2,
633
802
  appType: "custom",
634
803
  server: { ...config2 == null ? void 0 : config2.server, middlewareMode: true }
635
- });
804
+ };
805
+ const { cors } = finalConfig.server;
806
+ if (cors === void 0) {
807
+ finalConfig.server.cors = { preflightContinue: true };
808
+ } else if (typeof cors === "object") {
809
+ cors.preflightContinue ?? (cors.preflightContinue = true);
810
+ }
811
+ const devServer = await createServer(finalConfig);
636
812
  getDevGlobal().addDevServer(devServer);
637
813
  devServer.middlewares.use(logger_default());
638
814
  return devServer;
@@ -720,7 +896,11 @@ function getDevGlobal() {
720
896
  function createErrorMiddleware(devServer) {
721
897
  return function errorMiddleware(error, _req, res, _next) {
722
898
  if (!error.id) {
723
- devServer.config.logger.error(buildErrorMessage(error, [`\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`]));
899
+ devServer.config.logger.error(
900
+ buildErrorMessage(error, [
901
+ `\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`
902
+ ])
903
+ );
724
904
  }
725
905
  res.statusCode = 500;
726
906
  res.end(`
@@ -757,171 +937,7 @@ function createErrorMiddleware(devServer) {
757
937
  };
758
938
  }
759
939
 
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
940
  // src/adapter/index.ts
924
- import { start as explorerStart } from "@marko/run-explorer";
925
941
  import parseNodeArgs from "parse-node-args";
926
942
 
927
943
  // src/vite/constants.ts
@@ -960,13 +976,12 @@ function adapter() {
960
976
  await waitForWorker(nextWorker, port);
961
977
  if (worker) {
962
978
  const prevWorker = worker;
963
- let timeout;
964
979
  worker.once("disconnect", () => {
965
980
  clearTimeout(timeout);
966
981
  });
967
982
  worker.send({ type: "shutdown" });
968
983
  worker.disconnect();
969
- timeout = setTimeout(() => {
984
+ const timeout = setTimeout(() => {
970
985
  prevWorker.kill();
971
986
  }, 2e3);
972
987
  }
@@ -976,7 +991,7 @@ function adapter() {
976
991
  return {
977
992
  port,
978
993
  async close() {
979
- await Promise.all([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
994
+ await Promise.allSettled([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
980
995
  }
981
996
  };
982
997
  }
@@ -986,12 +1001,16 @@ function adapter() {
986
1001
  if (inspect) {
987
1002
  inspector.open(inspect.port, inspect.host, inspect.wait);
988
1003
  }
989
- const listen = new Promise((resolve) => {
990
- const listener = devServer.middlewares.listen(port, () => {
991
- resolve(listener.address());
1004
+ const listenerPromise = new Promise((resolve) => {
1005
+ const listener2 = devServer.middlewares.listen(port, () => {
1006
+ resolve(listener2);
992
1007
  });
993
1008
  });
994
- const [explorer, address] = await Promise.all([explorerPromise, listen]);
1009
+ const [explorer, listener] = await Promise.all([
1010
+ explorerPromise,
1011
+ listenerPromise
1012
+ ]);
1013
+ const address = listener.address();
995
1014
  logInfoBox(
996
1015
  `http://localhost:${address.port}`,
997
1016
  explorer && `http://localhost:${explorer.port}`
@@ -999,7 +1018,11 @@ function adapter() {
999
1018
  return {
1000
1019
  port: address.port,
1001
1020
  async close() {
1002
- await Promise.all([devServer.close(), explorer == null ? void 0 : explorer.close()]);
1021
+ await Promise.allSettled([
1022
+ devServer.close(),
1023
+ listener.close(),
1024
+ explorer == null ? void 0 : explorer.close()
1025
+ ]);
1003
1026
  }
1004
1027
  };
1005
1028
  },
@@ -1020,7 +1043,7 @@ function adapter() {
1020
1043
  return explorer ? {
1021
1044
  port: server.port,
1022
1045
  async close() {
1023
- await Promise.all([server.close(), explorer.close()]);
1046
+ await Promise.allSettled([server.close(), explorer.close()]);
1024
1047
  }
1025
1048
  } : server;
1026
1049
  },
@@ -1042,7 +1065,7 @@ function adapter() {
1042
1065
  };
1043
1066
  for (const [name, code] of virtualFiles) {
1044
1067
  let fileName = "";
1045
- let index = name.indexOf(markoRunFilePrefix);
1068
+ const index = name.indexOf(markoRunFilePrefix);
1046
1069
  if (index >= 0) {
1047
1070
  fileName = name.slice(index);
1048
1071
  data.files[fileName] = `${virtualFilePrefix}/${fileName}`;