@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.
@@ -43,20 +43,381 @@ var import_url = require("url");
43
43
  var __importMetaURL = (0, import_url.pathToFileURL)(__filename);
44
44
 
45
45
  // src/adapter/index.ts
46
- var import_path2 = __toESM(require("path"), 1);
46
+ var import_run_explorer = require("@marko/run-explorer");
47
47
  var import_fs2 = __toESM(require("fs"), 1);
48
48
  var import_inspector2 = __toESM(require("inspector"), 1);
49
+ var import_path2 = __toESM(require("path"), 1);
49
50
  var import_url2 = require("url");
50
51
 
51
- // src/adapter/dev-server.ts
52
- var import_path = __toESM(require("path"), 1);
53
- var import_vite = require("vite");
52
+ // src/vite/utils/server.ts
53
+ var import_child_process = __toESM(require("child_process"), 1);
54
+ var import_cluster = __toESM(require("cluster"), 1);
55
+ var import_dotenv = require("dotenv");
56
+ var import_fs = __toESM(require("fs"), 1);
57
+ var import_net = __toESM(require("net"), 1);
58
+ async function parseEnv(envFile) {
59
+ if (import_fs.default.existsSync(envFile)) {
60
+ const content = await import_fs.default.promises.readFile(envFile, "utf8");
61
+ return (0, import_dotenv.parse)(content);
62
+ }
63
+ }
64
+ function loadEnv(envFile) {
65
+ (0, import_dotenv.config)({ path: envFile });
66
+ }
67
+ async function spawnServer(cmd, args = [], port = 0, env, cwd = process.cwd(), wait = 3e4, stdio = ["ignore", "inherit", "inherit"]) {
68
+ if (port <= 0) {
69
+ port = await getAvailablePort();
70
+ }
71
+ if (typeof env === "string") {
72
+ env = await parseEnv(env);
73
+ }
74
+ const proc = import_child_process.default.spawn(cmd, args, {
75
+ cwd,
76
+ shell: true,
77
+ stdio,
78
+ windowsHide: true,
79
+ env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
80
+ });
81
+ const close = () => {
82
+ proc.unref();
83
+ proc.kill();
84
+ };
85
+ try {
86
+ await Promise.race([waitForError(proc, port), waitForServer(port, wait)]);
87
+ } catch (err) {
88
+ close();
89
+ throw err;
90
+ }
91
+ return {
92
+ port,
93
+ close
94
+ };
95
+ }
96
+ async function spawnServerWorker(module2, args = [], port = 0, env, wait = true) {
97
+ if (port <= 0) {
98
+ port = await getAvailablePort();
99
+ }
100
+ if (typeof env === "string") {
101
+ env = await parseEnv(env);
102
+ }
103
+ const originalExec = import_cluster.default.settings.exec;
104
+ const originalArgs = import_cluster.default.settings.execArgv;
105
+ try {
106
+ import_cluster.default.settings.exec = module2;
107
+ import_cluster.default.settings.execArgv = args;
108
+ const worker = import_cluster.default.fork({
109
+ ...env,
110
+ NODE_ENV: "development",
111
+ ...process.env,
112
+ PORT: `${port}`
113
+ });
114
+ if (wait) {
115
+ return new Promise((resolve) => {
116
+ function ready(message) {
117
+ if (message === "ready") {
118
+ worker.off("message", ready);
119
+ resolve(worker);
120
+ }
121
+ }
122
+ worker.on("message", ready);
123
+ });
124
+ }
125
+ return worker;
126
+ } finally {
127
+ import_cluster.default.settings.exec = originalExec;
128
+ import_cluster.default.settings.execArgv = originalArgs;
129
+ }
130
+ }
131
+ async function waitForError(proc, port) {
132
+ return new Promise((_, reject) => {
133
+ proc.once("error", reject);
134
+ proc.once("exit", (code) => {
135
+ reject(
136
+ new Error(
137
+ `Process exited with code ${code} while waiting for server to start on port "${port}".`
138
+ )
139
+ );
140
+ });
141
+ });
142
+ }
143
+ async function waitForServer(port, wait = 0) {
144
+ let remaining = wait > 0 ? wait : Infinity;
145
+ let connection;
146
+ while (!(connection = await getConnection(port))) {
147
+ if (remaining >= 100) {
148
+ remaining -= 100;
149
+ await sleep(100);
150
+ } else {
151
+ throw new Error(
152
+ `Timeout while wating for server to start on port "${port}".`
153
+ );
154
+ }
155
+ }
156
+ return connection;
157
+ }
158
+ async function waitForWorker(worker, port) {
159
+ return new Promise((resolve, reject) => {
160
+ function listening(address) {
161
+ if (address.port === port) {
162
+ worker.off("listening", listening);
163
+ resolve();
164
+ }
165
+ }
166
+ worker.on("listening", listening).once("error", reject).once("exit", (code) => {
167
+ reject(
168
+ new Error(
169
+ `Worker exited with code ${code} while waiting for dev server to start on port "${port}".`
170
+ )
171
+ );
172
+ });
173
+ });
174
+ }
175
+ async function getConnection(port) {
176
+ return new Promise((resolve) => {
177
+ const connection = import_net.default.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => {
178
+ connection.end();
179
+ resolve(null);
180
+ }).on("connect", () => {
181
+ resolve(connection);
182
+ });
183
+ });
184
+ }
185
+ async function isPortInUse(port) {
186
+ return Boolean(await getConnection(port));
187
+ }
188
+ async function getAvailablePort(port) {
189
+ if (port && !await isPortInUse(port)) {
190
+ return port;
191
+ }
192
+ return new Promise((resolve) => {
193
+ const server = import_net.default.createServer().listen(0, () => {
194
+ const { port: port2 } = server.address();
195
+ server.close(() => resolve(port2));
196
+ });
197
+ });
198
+ }
199
+ function sleep(ms) {
200
+ return new Promise((resolve) => setTimeout(resolve, ms));
201
+ }
202
+ function getInspectOptions(args) {
203
+ for (const arg of args) {
204
+ const match = arg.match(/^--inspect(-brk)?(?:=(?:(.+):)?(.+))?$/);
205
+ if (match) {
206
+ return {
207
+ host: match[2],
208
+ port: parseInt(match[3], 10) || void 0,
209
+ wait: !!match[1]
210
+ };
211
+ }
212
+ }
213
+ }
214
+
215
+ // src/adapter/dev-server.ts
216
+ var import_path = __toESM(require("path"), 1);
217
+ var import_vite = require("vite");
218
+
219
+ // src/adapter/logger.ts
220
+ var import_draftlog = __toESM(require("draftlog"), 1);
221
+ var import_human_format = __toESM(require("human-format"), 1);
222
+ var import_inspector = __toESM(require("inspector"), 1);
223
+ var import_kleur = __toESM(require("kleur"), 1);
224
+ if (!import_inspector.default.url()) {
225
+ import_draftlog.default.into(console);
226
+ import_draftlog.default.defaults.canReWrite = false;
227
+ }
228
+ var HttpStatusColors = [
229
+ "",
230
+ // Unused
231
+ "green",
232
+ // 1xx
233
+ "green",
234
+ // 2xx
235
+ "cyan",
236
+ // 3xx
237
+ "yellow",
238
+ // 4xx
239
+ "red"
240
+ // 5xx
241
+ ];
242
+ var IdChars = [
243
+ "",
244
+ import_kleur.default.cyan("\xB9"),
245
+ import_kleur.default.magenta("\xB2"),
246
+ import_kleur.default.green("\xB3"),
247
+ import_kleur.default.red("\u2074"),
248
+ import_kleur.default.cyan("\u2075"),
249
+ import_kleur.default.magenta("\u2076"),
250
+ import_kleur.default.green("\u2077"),
251
+ import_kleur.default.red("\u2078"),
252
+ import_kleur.default.cyan("\u2079"),
253
+ import_kleur.default.red("\u207A")
254
+ ];
255
+ var ArrowSteps = [" ", " \u25C0", " \u25C0\u2501", "\u25C0\u2501\u2501", "\u2501\u2501 ", "\u2501 ", " "];
256
+ function logger_default(_options = {}) {
257
+ let inFlight = 0;
258
+ return function logger(req, res, next) {
259
+ const startTime = Date.now();
260
+ const handleFinish = () => done("finish");
261
+ const handleClose = () => done("close");
262
+ res.on("finish", handleFinish);
263
+ res.on("close", handleClose);
264
+ const bitMask = ~inFlight & inFlight + 1;
265
+ const index = Math.log2(bitMask);
266
+ const id = IdChars[index];
267
+ if (index < IdChars.length) {
268
+ inFlight |= bitMask;
269
+ }
270
+ const finalizeLog = logRequest(id, req);
271
+ let bodyLength = 0;
272
+ const _write = res.write;
273
+ const _end = res.end;
274
+ res.write = (...args) => {
275
+ if (args[0]) {
276
+ if (typeof args[1] !== "function") {
277
+ bodyLength += Buffer.byteLength(args[0], args[1]);
278
+ } else {
279
+ bodyLength += args[0].length;
280
+ }
281
+ }
282
+ return _write.apply(res, args);
283
+ };
284
+ res.end = (...args) => {
285
+ if (args[0] && typeof args[0] !== "function") {
286
+ if (typeof args[1] !== "function") {
287
+ bodyLength += Buffer.byteLength(args[0], args[1]);
288
+ } else {
289
+ bodyLength += args[0].length;
290
+ }
291
+ }
292
+ return _end.apply(res, args);
293
+ };
294
+ next == null ? void 0 : next();
295
+ function done(event) {
296
+ res.off("finish", handleFinish);
297
+ res.off("close", handleClose);
298
+ finalizeLog();
299
+ if (index < 10) {
300
+ inFlight ^= bitMask;
301
+ }
302
+ let contentLength = res.getHeader("content-length") || 0;
303
+ if (Array.isArray(contentLength)) {
304
+ contentLength = parseInt(contentLength[0], 10) || 0;
305
+ } else if (typeof contentLength === "string") {
306
+ contentLength = parseInt(contentLength, 10) || 0;
307
+ }
308
+ logResponse(
309
+ id,
310
+ req,
311
+ res,
312
+ startTime,
313
+ contentLength || bodyLength,
314
+ event === "finish"
315
+ );
316
+ }
317
+ };
318
+ }
319
+ var spinners;
320
+ function logRequest(id, req) {
321
+ const info = id + " " + import_kleur.default.bold(req.method) + " " + import_kleur.default.dim(req.url);
322
+ const final = import_kleur.default.dim(requestArrow(id)) + info;
323
+ if (console.draft) {
324
+ spinners ?? (spinners = createAnimationManager({ steps: ArrowSteps.length }));
325
+ const update = console.draft();
326
+ const stop = spinners.add((step) => {
327
+ update(import_kleur.default.cyan(requestArrow(id, step)) + info);
328
+ });
329
+ return () => {
330
+ stop();
331
+ update(final);
332
+ };
333
+ }
334
+ console.log(final);
335
+ return () => {
336
+ };
337
+ }
338
+ function logResponse(id, req, res, startTime, contentLength, success) {
339
+ const status = res.statusCode;
340
+ const color = HttpStatusColors[status / 100 | 0] || "red";
341
+ let length;
342
+ if (req.method === "HEAD" || [204, 205, 304].includes(status)) {
343
+ length = "";
344
+ } else if (!contentLength) {
345
+ length = import_kleur.default.dim("-");
346
+ } else {
347
+ length = formatMeasurement(bytes(contentLength));
348
+ }
349
+ let arrow = id ? "\u2501" : "\u2501\u2501";
350
+ if (success) {
351
+ arrow = import_kleur.default.dim(arrow + "\u25B6");
352
+ } else {
353
+ arrow = import_kleur.default.red(import_kleur.default.dim(arrow) + import_kleur.default.bold("x"));
354
+ }
355
+ console.log(
356
+ arrow + id + " " + import_kleur.default.bold(req.method) + " " + import_kleur.default.dim(req.url) + " " + import_kleur.default[color](status) + " " + formatMeasurement(time(startTime)) + " " + length
357
+ );
358
+ }
359
+ function requestArrow(id, step = 3) {
360
+ const arrow = ArrowSteps[step];
361
+ return id ? arrow.slice(0, -1) : arrow;
362
+ }
363
+ function time(start) {
364
+ const delta = Date.now() - start;
365
+ return delta < 5e3 ? [delta, "ms"] : [(delta / 1e3).toFixed(1), "s"];
366
+ }
367
+ function bytes(size) {
368
+ const { value, prefix } = import_human_format.default.raw(size, { maxDecimals: 2, unit: "b" });
369
+ return [value.toFixed(2), (prefix + "b").toLowerCase()];
370
+ }
371
+ function formatMeasurement([value, unit]) {
372
+ return import_kleur.default.dim(value + import_kleur.default.yellow(import_kleur.default.bold(unit)));
373
+ }
374
+ function createAnimationManager(options = {}) {
375
+ const { steps = 1e4, ms = 100 } = options;
376
+ const fns = /* @__PURE__ */ new Set();
377
+ let step = 0;
378
+ let isRunning = false;
379
+ let interval;
380
+ function start() {
381
+ step = 0;
382
+ isRunning = true;
383
+ interval = setInterval(() => {
384
+ if (isRunning) {
385
+ for (const fn of fns) {
386
+ fn(step);
387
+ }
388
+ step = (step + 1) % steps;
389
+ }
390
+ }, ms);
391
+ }
392
+ function stop() {
393
+ isRunning = false;
394
+ clearInterval(interval);
395
+ }
396
+ return {
397
+ add(fn) {
398
+ fns.add(fn);
399
+ if (!isRunning) {
400
+ start();
401
+ }
402
+ fn(step);
403
+ return () => {
404
+ fns.delete(fn);
405
+ if (!fns.size) {
406
+ stop();
407
+ }
408
+ };
409
+ }
410
+ };
411
+ }
412
+
413
+ // src/adapter/middleware.ts
414
+ var import_node_stream = require("node:stream");
54
415
 
55
416
  // src/adapter/polyfill.ts
56
- var webStream = __toESM(require("stream/web"), 1);
57
417
  var import_crypto = require("crypto");
58
- var undici = __toESM(require("undici"), 1);
59
418
  var import_http = require("http");
419
+ var webStream = __toESM(require("stream/web"), 1);
420
+ var undici = __toESM(require("undici"), 1);
60
421
  globalThis.crypto ?? (globalThis.crypto = import_crypto.webcrypto);
61
422
  globalThis.fetch ?? (globalThis.fetch = undici.fetch);
62
423
  globalThis.Response ?? (globalThis.Response = undici.Response);
@@ -121,7 +482,6 @@ function getSetCookie_fallback(headers) {
121
482
  }
122
483
 
123
484
  // src/adapter/middleware.ts
124
- var import_node_stream = require("node:stream");
125
485
  function getForwardedHeader(req, name) {
126
486
  const value = req.headers["x-forwarded-" + name];
127
487
  if (value) {
@@ -232,277 +592,83 @@ function createMiddleware(fetch2, options) {
232
592
  } else {
233
593
  body = req;
234
594
  }
235
- break;
236
- }
237
- const request = new Request(url, {
238
- method: req.method,
239
- headers: req.headers,
240
- body,
241
- // @ts-expect-error: Node requires this for streams
242
- duplex: "half",
243
- signal
244
- });
245
- const platform = createPlatform({
246
- request: req,
247
- response: res
248
- });
249
- let response;
250
- try {
251
- response = await fetch2(request, platform);
252
- } catch (err) {
253
- normalizeError(err);
254
- if (next) {
255
- next(err);
256
- } else {
257
- console.error(err);
258
- }
259
- return;
260
- }
261
- if (!response) {
262
- if (next) {
263
- next();
264
- }
265
- return;
266
- }
267
- res.statusCode = response.status;
268
- copyResponseHeaders(res, response.headers);
269
- if (!response.body) {
270
- if (!response.headers.has("content-length")) {
271
- res.setHeader("content-length", "0");
272
- }
273
- res.end();
274
- return;
275
- } else if (res.destroyed) {
276
- controller.abort(new Error("Response stream destroyed"));
277
- return;
278
- }
279
- writeResponse(response.body.getReader(), res, controller);
280
- };
281
- }
282
- async function writeResponse(reader, res, controller) {
283
- try {
284
- while (!controller.signal.aborted) {
285
- const { done, value } = await reader.read();
286
- if (done) {
287
- res.end();
288
- return;
289
- }
290
- res.write(value);
291
- if (res.flush) {
292
- res.flush();
293
- }
294
- }
295
- } catch (err) {
296
- controller.abort(err);
297
- }
298
- }
299
- var bodyConsumedErrorStream = new ReadableStream({
300
- pull(controller) {
301
- controller.error(
302
- new Error(
303
- "The request body stream has been destroyed or consumed by something before Marko Run."
304
- )
305
- );
306
- }
307
- });
308
-
309
- // src/adapter/logger.ts
310
- var import_kleur = __toESM(require("kleur"), 1);
311
- var import_draftlog = __toESM(require("draftlog"), 1);
312
- var import_human_format = __toESM(require("human-format"), 1);
313
- var import_inspector = __toESM(require("inspector"), 1);
314
- if (!import_inspector.default.url()) {
315
- import_draftlog.default.into(console);
316
- import_draftlog.default.defaults.canReWrite = false;
317
- }
318
- var HttpStatusColors = [
319
- "",
320
- // Unused
321
- "green",
322
- // 1xx
323
- "green",
324
- // 2xx
325
- "cyan",
326
- // 3xx
327
- "yellow",
328
- // 4xx
329
- "red"
330
- // 5xx
331
- ];
332
- var IdChars = [
333
- "",
334
- import_kleur.default.cyan("\xB9"),
335
- import_kleur.default.magenta("\xB2"),
336
- import_kleur.default.green("\xB3"),
337
- import_kleur.default.red("\u2074"),
338
- import_kleur.default.cyan("\u2075"),
339
- import_kleur.default.magenta("\u2076"),
340
- import_kleur.default.green("\u2077"),
341
- import_kleur.default.red("\u2078"),
342
- import_kleur.default.cyan("\u2079"),
343
- import_kleur.default.red("\u207A")
344
- ];
345
- var ArrowSteps = [" ", " \u25C0", " \u25C0\u2501", "\u25C0\u2501\u2501", "\u2501\u2501 ", "\u2501 ", " "];
346
- function logger_default(_options = {}) {
347
- let inFlight = 0;
348
- return function logger(req, res, next) {
349
- let startTime = Date.now();
350
- const handleFinish = () => done("finish");
351
- const handleClose = () => done("close");
352
- res.on("finish", handleFinish);
353
- res.on("close", handleClose);
354
- const bitMask = ~inFlight & inFlight + 1;
355
- const index = Math.log2(bitMask);
356
- const id = IdChars[index];
357
- if (index < IdChars.length) {
358
- inFlight |= bitMask;
359
- }
360
- const finalizeLog = logRequest(id, req);
361
- let bodyLength = 0;
362
- const _write = res.write;
363
- const _end = res.end;
364
- res.write = (...args) => {
365
- if (args[0]) {
366
- if (typeof args[1] !== "function") {
367
- bodyLength += Buffer.byteLength(args[0], args[1]);
368
- } else {
369
- bodyLength += args[0].length;
370
- }
371
- }
372
- return _write.apply(res, args);
373
- };
374
- res.end = (...args) => {
375
- if (args[0] && typeof args[0] !== "function") {
376
- if (typeof args[1] !== "function") {
377
- bodyLength += Buffer.byteLength(args[0], args[1]);
378
- } else {
379
- bodyLength += args[0].length;
380
- }
381
- }
382
- return _end.apply(res, args);
383
- };
384
- next == null ? void 0 : next();
385
- function done(event) {
386
- res.off("finish", handleFinish);
387
- res.off("close", handleClose);
388
- finalizeLog();
389
- if (index < 10) {
390
- inFlight ^= bitMask;
391
- }
392
- let contentLength = res.getHeader("content-length") || 0;
393
- if (Array.isArray(contentLength)) {
394
- contentLength = parseInt(contentLength[0], 10) || 0;
395
- } else if (typeof contentLength === "string") {
396
- contentLength = parseInt(contentLength, 10) || 0;
397
- }
398
- logResponse(
399
- id,
400
- req,
401
- res,
402
- startTime,
403
- contentLength || bodyLength,
404
- event === "finish"
405
- );
406
- }
407
- };
408
- }
409
- var spinners;
410
- function logRequest(id, req) {
411
- const info = id + " " + import_kleur.default.bold(req.method) + " " + import_kleur.default.dim(req.url);
412
- const final = import_kleur.default.dim(requestArrow(id)) + info;
413
- if (console.draft) {
414
- spinners ?? (spinners = createAnimationManager({ steps: ArrowSteps.length }));
415
- const update = console.draft();
416
- const stop = spinners.add((step) => {
417
- update(import_kleur.default.cyan(requestArrow(id, step)) + info);
418
- });
419
- return () => {
420
- stop();
421
- update(final);
422
- };
423
- }
424
- console.log(final);
425
- return () => {
426
- };
427
- }
428
- function logResponse(id, req, res, startTime, contentLength, success) {
429
- const status = res.statusCode;
430
- const color = HttpStatusColors[status / 100 | 0] || "red";
431
- let length;
432
- if (req.method === "HEAD" || [204, 205, 304].includes(status)) {
433
- length = "";
434
- } else if (!contentLength) {
435
- length = import_kleur.default.dim("-");
436
- } else {
437
- length = formatMeasurement(bytes(contentLength));
438
- }
439
- let arrow = id ? "\u2501" : "\u2501\u2501";
440
- if (success) {
441
- arrow = import_kleur.default.dim(arrow + "\u25B6");
442
- } else {
443
- arrow = import_kleur.default.red(import_kleur.default.dim(arrow) + import_kleur.default.bold("x"));
444
- }
445
- console.log(
446
- arrow + id + " " + import_kleur.default.bold(req.method) + " " + import_kleur.default.dim(req.url) + " " + import_kleur.default[color](status) + " " + formatMeasurement(time(startTime)) + " " + length
447
- );
448
- }
449
- function requestArrow(id, step = 3) {
450
- const arrow = ArrowSteps[step];
451
- return id ? arrow.slice(0, -1) : arrow;
452
- }
453
- function time(start) {
454
- const delta = Date.now() - start;
455
- return delta < 5e3 ? [delta, "ms"] : [(delta / 1e3).toFixed(1), "s"];
456
- }
457
- function bytes(size) {
458
- const { value, prefix } = import_human_format.default.raw(size, { maxDecimals: 2, unit: "b" });
459
- return [value.toFixed(2), (prefix + "b").toLowerCase()];
460
- }
461
- function formatMeasurement([value, unit]) {
462
- return import_kleur.default.dim(value + import_kleur.default.yellow(import_kleur.default.bold(unit)));
463
- }
464
- function createAnimationManager(options = {}) {
465
- const { steps = 1e4, ms = 100 } = options;
466
- const fns = /* @__PURE__ */ new Set();
467
- let step = 0;
468
- let isRunning = false;
469
- let interval;
470
- function start() {
471
- step = 0;
472
- isRunning = true;
473
- interval = setInterval(() => {
474
- if (isRunning) {
475
- for (const fn of fns) {
476
- fn(step);
477
- }
478
- step = (step + 1) % steps;
595
+ break;
596
+ }
597
+ const request = new Request(url, {
598
+ method: req.method,
599
+ headers: req.headers,
600
+ body,
601
+ // @ts-expect-error: Node requires this for streams
602
+ duplex: "half",
603
+ signal
604
+ });
605
+ const platform = createPlatform({
606
+ request: req,
607
+ response: res
608
+ });
609
+ let response;
610
+ try {
611
+ response = await fetch2(request, platform);
612
+ } catch (err) {
613
+ normalizeError(err);
614
+ if (next) {
615
+ next(err);
616
+ } else {
617
+ console.error(err);
479
618
  }
480
- }, ms);
481
- }
482
- function stop() {
483
- isRunning = false;
484
- clearInterval(interval);
485
- }
486
- return {
487
- add(fn) {
488
- fns.add(fn);
489
- if (!isRunning) {
490
- start();
619
+ return;
620
+ }
621
+ if (!response) {
622
+ if (next) {
623
+ next();
491
624
  }
492
- fn(step);
493
- return () => {
494
- fns.delete(fn);
495
- if (!fns.size) {
496
- stop();
497
- }
498
- };
625
+ return;
626
+ }
627
+ res.statusCode = response.status;
628
+ copyResponseHeaders(res, response.headers);
629
+ if (!response.body) {
630
+ if (!response.headers.has("content-length")) {
631
+ res.setHeader("content-length", "0");
632
+ }
633
+ res.end();
634
+ return;
635
+ } else if (res.destroyed) {
636
+ controller.abort(new Error("Response stream destroyed"));
637
+ return;
499
638
  }
639
+ writeResponse(response.body.getReader(), res, controller);
500
640
  };
501
641
  }
642
+ async function writeResponse(reader, res, controller) {
643
+ try {
644
+ while (!controller.signal.aborted) {
645
+ const { done, value } = await reader.read();
646
+ if (done) {
647
+ res.end();
648
+ return;
649
+ }
650
+ res.write(value);
651
+ if (res.flush) {
652
+ res.flush();
653
+ }
654
+ }
655
+ } catch (err) {
656
+ controller.abort(err);
657
+ }
658
+ }
659
+ var bodyConsumedErrorStream = new ReadableStream({
660
+ pull(controller) {
661
+ controller.error(
662
+ new Error(
663
+ "The request body stream has been destroyed or consumed by something before Marko Run."
664
+ )
665
+ );
666
+ }
667
+ });
502
668
 
503
669
  // src/adapter/utils.ts
504
- var import_supports_color = __toESM(require("supports-color"), 1);
505
670
  var import_kleur2 = __toESM(require("kleur"), 1);
671
+ var import_supports_color = __toESM(require("supports-color"), 1);
506
672
  function stripAnsi(string) {
507
673
  return string.replace(
508
674
  /([\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><])/g,
@@ -528,7 +694,7 @@ function logInfoBox(address, explorer) {
528
694
  const color = !!import_supports_color.default.stdout;
529
695
  let message = import_kleur2.default.bold("Marko Run");
530
696
  if (true) {
531
- message += ` v${"0.5.12"}`;
697
+ message += ` v${"0.5.14"}`;
532
698
  }
533
699
  message += "\n\n";
534
700
  message += import_kleur2.default.dim("Server listening at");
@@ -575,7 +741,7 @@ function drawMarkoBox(message, options) {
575
741
  }
576
742
  line += textPadding;
577
743
  if (i >= textStartLine && i < textEndLine) {
578
- let index = i - textStartLine;
744
+ const index = i - textStartLine;
579
745
  line += textLines[index];
580
746
  line += " ".repeat(textWidth - textWidths[index]);
581
747
  } else {
@@ -610,13 +776,16 @@ B\u2572 \u2572 GG\u203E\u203E\u203E\u203E O\u2571 \u2571 P\u2571 \u2571
610
776
  O: "#ff9500",
611
777
  R: "#f3154d",
612
778
  P: "#ce176c"
613
- }).reduce((acc, [key, hex]) => {
614
- const r = parseInt(hex.slice(1, 3), 16);
615
- const g = parseInt(hex.slice(3, 5), 16);
616
- const b = parseInt(hex.slice(5, 7), 16);
617
- acc[key] = `\x1B[38;2;${r};${g};${b}m`;
618
- return acc;
619
- }, {});
779
+ }).reduce(
780
+ (acc, [key, hex]) => {
781
+ const r = parseInt(hex.slice(1, 3), 16);
782
+ const g = parseInt(hex.slice(3, 5), 16);
783
+ const b = parseInt(hex.slice(5, 7), 16);
784
+ acc[key] = `\x1B[38;2;${r};${g};${b}m`;
785
+ return acc;
786
+ },
787
+ {}
788
+ );
620
789
  const lines = [];
621
790
  const lineWidths = [];
622
791
  let line = "";
@@ -761,7 +930,11 @@ function getDevGlobal() {
761
930
  function createErrorMiddleware(devServer) {
762
931
  return function errorMiddleware(error, _req, res, _next) {
763
932
  if (!error.id) {
764
- devServer.config.logger.error((0, import_vite.buildErrorMessage)(error, [`\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`]));
933
+ devServer.config.logger.error(
934
+ (0, import_vite.buildErrorMessage)(error, [
935
+ `\x1B[31;1mRequest failed with error: ${error.message}\x1B[0m`
936
+ ])
937
+ );
765
938
  }
766
939
  res.statusCode = 500;
767
940
  res.end(`
@@ -798,171 +971,7 @@ function createErrorMiddleware(devServer) {
798
971
  };
799
972
  }
800
973
 
801
- // src/vite/utils/server.ts
802
- var import_net = __toESM(require("net"), 1);
803
- var import_child_process = __toESM(require("child_process"), 1);
804
- var import_dotenv = require("dotenv");
805
- var import_fs = __toESM(require("fs"), 1);
806
- var import_cluster = __toESM(require("cluster"), 1);
807
- async function parseEnv(envFile) {
808
- if (import_fs.default.existsSync(envFile)) {
809
- const content = await import_fs.default.promises.readFile(envFile, "utf8");
810
- return (0, import_dotenv.parse)(content);
811
- }
812
- }
813
- function loadEnv(envFile) {
814
- (0, import_dotenv.config)({ path: envFile });
815
- }
816
- async function spawnServer(cmd, args = [], port = 0, env, cwd = process.cwd(), wait = 3e4, stdio = ["ignore", "inherit", "inherit"]) {
817
- if (port <= 0) {
818
- port = await getAvailablePort();
819
- }
820
- if (typeof env === "string") {
821
- env = await parseEnv(env);
822
- }
823
- const proc = import_child_process.default.spawn(cmd, args, {
824
- cwd,
825
- shell: true,
826
- stdio,
827
- windowsHide: true,
828
- env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
829
- });
830
- const close = () => {
831
- proc.unref();
832
- proc.kill();
833
- };
834
- try {
835
- await Promise.race([waitForError(proc, port), waitForServer(port, wait)]);
836
- } catch (err) {
837
- close();
838
- throw err;
839
- }
840
- return {
841
- port,
842
- close
843
- };
844
- }
845
- async function spawnServerWorker(module2, args = [], port = 0, env, wait = true) {
846
- if (port <= 0) {
847
- port = await getAvailablePort();
848
- }
849
- if (typeof env === "string") {
850
- env = await parseEnv(env);
851
- }
852
- const originalExec = import_cluster.default.settings.exec;
853
- const originalArgs = import_cluster.default.settings.execArgv;
854
- try {
855
- import_cluster.default.settings.exec = module2;
856
- import_cluster.default.settings.execArgv = args;
857
- const worker = import_cluster.default.fork({
858
- ...env,
859
- NODE_ENV: "development",
860
- ...process.env,
861
- PORT: `${port}`
862
- });
863
- if (wait) {
864
- return new Promise((resolve) => {
865
- function ready(message) {
866
- if (message === "ready") {
867
- worker.off("message", ready);
868
- resolve(worker);
869
- }
870
- }
871
- worker.on("message", ready);
872
- });
873
- }
874
- return worker;
875
- } finally {
876
- import_cluster.default.settings.exec = originalExec;
877
- import_cluster.default.settings.execArgv = originalArgs;
878
- }
879
- }
880
- async function waitForError(proc, port) {
881
- return new Promise((_, reject) => {
882
- proc.once("error", reject);
883
- proc.once("exit", (code) => {
884
- reject(
885
- new Error(
886
- `Process exited with code ${code} while waiting for server to start on port "${port}".`
887
- )
888
- );
889
- });
890
- });
891
- }
892
- async function waitForServer(port, wait = 0) {
893
- let remaining = wait > 0 ? wait : Infinity;
894
- let connection;
895
- while (!(connection = await getConnection(port))) {
896
- if (remaining >= 100) {
897
- remaining -= 100;
898
- await sleep(100);
899
- } else {
900
- throw new Error(
901
- `Timeout while wating for server to start on port "${port}".`
902
- );
903
- }
904
- }
905
- return connection;
906
- }
907
- async function waitForWorker(worker, port) {
908
- return new Promise((resolve, reject) => {
909
- function listening(address) {
910
- if (address.port === port) {
911
- worker.off("listening", listening);
912
- resolve();
913
- }
914
- }
915
- worker.on("listening", listening).once("error", reject).once("exit", (code) => {
916
- reject(
917
- new Error(
918
- `Worker exited with code ${code} while waiting for dev server to start on port "${port}".`
919
- )
920
- );
921
- });
922
- });
923
- }
924
- async function getConnection(port) {
925
- return new Promise((resolve) => {
926
- const connection = import_net.default.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => {
927
- connection.end();
928
- resolve(null);
929
- }).on("connect", () => {
930
- resolve(connection);
931
- });
932
- });
933
- }
934
- async function isPortInUse(port) {
935
- return Boolean(await getConnection(port));
936
- }
937
- async function getAvailablePort(port) {
938
- if (port && !await isPortInUse(port)) {
939
- return port;
940
- }
941
- return new Promise((resolve) => {
942
- const server = import_net.default.createServer().listen(0, () => {
943
- const { port: port2 } = server.address();
944
- server.close(() => resolve(port2));
945
- });
946
- });
947
- }
948
- function sleep(ms) {
949
- return new Promise((resolve) => setTimeout(resolve, ms));
950
- }
951
- function getInspectOptions(args) {
952
- for (const arg of args) {
953
- const match = arg.match(/^--inspect(-brk)?(?:=(?:(.+):)?(.+))?$/);
954
- if (match) {
955
- return {
956
- host: match[2],
957
- port: parseInt(match[3], 10) || void 0,
958
- wait: !!match[1]
959
- };
960
- }
961
- }
962
- }
963
-
964
974
  // src/adapter/index.ts
965
- var import_run_explorer = require("@marko/run-explorer");
966
975
  var import_parse_node_args = __toESM(require("parse-node-args"), 1);
967
976
 
968
977
  // src/vite/constants.ts
@@ -1001,13 +1010,12 @@ function adapter() {
1001
1010
  await waitForWorker(nextWorker, port);
1002
1011
  if (worker) {
1003
1012
  const prevWorker = worker;
1004
- let timeout;
1005
1013
  worker.once("disconnect", () => {
1006
1014
  clearTimeout(timeout);
1007
1015
  });
1008
1016
  worker.send({ type: "shutdown" });
1009
1017
  worker.disconnect();
1010
- timeout = setTimeout(() => {
1018
+ const timeout = setTimeout(() => {
1011
1019
  prevWorker.kill();
1012
1020
  }, 2e3);
1013
1021
  }
@@ -1017,7 +1025,7 @@ function adapter() {
1017
1025
  return {
1018
1026
  port,
1019
1027
  async close() {
1020
- await Promise.all([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
1028
+ await Promise.allSettled([worker.kill(), explorer2 == null ? void 0 : explorer2.close()]);
1021
1029
  }
1022
1030
  };
1023
1031
  }
@@ -1027,12 +1035,16 @@ function adapter() {
1027
1035
  if (inspect) {
1028
1036
  import_inspector2.default.open(inspect.port, inspect.host, inspect.wait);
1029
1037
  }
1030
- const listen = new Promise((resolve) => {
1031
- const listener = devServer.middlewares.listen(port, () => {
1032
- resolve(listener.address());
1038
+ const listenerPromise = new Promise((resolve) => {
1039
+ const listener2 = devServer.middlewares.listen(port, () => {
1040
+ resolve(listener2);
1033
1041
  });
1034
1042
  });
1035
- const [explorer, address] = await Promise.all([explorerPromise, listen]);
1043
+ const [explorer, listener] = await Promise.all([
1044
+ explorerPromise,
1045
+ listenerPromise
1046
+ ]);
1047
+ const address = listener.address();
1036
1048
  logInfoBox(
1037
1049
  `http://localhost:${address.port}`,
1038
1050
  explorer && `http://localhost:${explorer.port}`
@@ -1040,7 +1052,11 @@ function adapter() {
1040
1052
  return {
1041
1053
  port: address.port,
1042
1054
  async close() {
1043
- await Promise.all([devServer.close(), explorer == null ? void 0 : explorer.close()]);
1055
+ await Promise.allSettled([
1056
+ devServer.close(),
1057
+ listener.close(),
1058
+ explorer == null ? void 0 : explorer.close()
1059
+ ]);
1044
1060
  }
1045
1061
  };
1046
1062
  },
@@ -1061,7 +1077,7 @@ function adapter() {
1061
1077
  return explorer ? {
1062
1078
  port: server.port,
1063
1079
  async close() {
1064
- await Promise.all([server.close(), explorer.close()]);
1080
+ await Promise.allSettled([server.close(), explorer.close()]);
1065
1081
  }
1066
1082
  } : server;
1067
1083
  },
@@ -1083,7 +1099,7 @@ function adapter() {
1083
1099
  };
1084
1100
  for (const [name, code] of virtualFiles) {
1085
1101
  let fileName = "";
1086
- let index = name.indexOf(markoRunFilePrefix);
1102
+ const index = name.indexOf(markoRunFilePrefix);
1087
1103
  if (index >= 0) {
1088
1104
  fileName = name.slice(index);
1089
1105
  data.files[fileName] = `${virtualFilePrefix}/${fileName}`;