nitro-nightly 3.1.0-20251028-090722-437659e4 → 3.1.0-20251028-131831-fe9fd554
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.
- package/dist/_build/build.mjs +379 -14
- package/dist/_build/{rollup.mjs → build2.mjs} +218 -68
- package/dist/_build/info.mjs +963 -7
- package/dist/_build/prepare.mjs +1491 -2
- package/dist/_build/snapshot.mjs +155 -31
- package/dist/_build/vite.mjs +43 -2307
- package/dist/_build/vite2.mjs +149 -0
- package/dist/{_deps → _chunks/_deps}/c12.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/giget.mjs +1 -1
- package/dist/_chunks/_deps/klona.mjs +137 -0
- package/dist/{_deps → _chunks/_deps}/knitwork.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/local-pkg.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/mlly.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/nypm.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/pathe.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/pkg-types.mjs +2 -2
- package/dist/{_deps → _chunks/_deps}/rou3.mjs +1 -1
- package/dist/_chunks/_deps/std-env.mjs +3 -0
- package/dist/{_deps → _chunks/_deps}/unimport.mjs +2 -2
- package/dist/{_deps → _chunks/_deps}/unplugin-utils.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/untyped.mjs +1 -1
- package/dist/{_deps → _chunks/_deps}/unwasm.mjs +2 -2
- package/dist/{_presets → _chunks/_presets}/_resolve.mjs +2 -2
- package/dist/{_presets → _chunks/_presets}/_utils.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/azure.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/cloudflare.mjs +4 -4
- package/dist/{_presets → _chunks/_presets}/deno.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/firebase.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/iis.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/index.mjs +1 -1
- package/dist/{_presets → _chunks/_presets}/vercel.mjs +3 -3
- package/dist/{_presets → _chunks/_presets}/zeabur.mjs +1 -1
- package/dist/_chunks/app.mjs +600 -0
- package/dist/_chunks/index.mjs +648 -0
- package/dist/_chunks/server.mjs +256 -0
- package/dist/_cli/build.mjs +2 -2
- package/dist/_cli/dev.mjs +46 -130
- package/dist/_cli/index.mjs +1 -1
- package/dist/_cli/list.mjs +2 -2
- package/dist/_cli/prepare.mjs +2 -2
- package/dist/_cli/run.mjs +2 -2
- package/dist/cli/index.mjs +1 -1
- package/dist/index.mjs +94 -120
- package/dist/node_modules/cookie-es/dist/index.mjs +262 -0
- package/dist/node_modules/cookie-es/package.json +37 -0
- package/dist/node_modules/rendu/dist/index.mjs +380 -0
- package/dist/node_modules/rendu/package.json +47 -0
- package/dist/runtime/internal/task.mjs +1 -2
- package/dist/types/index.d.mts +2 -1
- package/dist/vite.mjs +103 -114
- package/lib/runtime/meta.mjs +18 -25
- package/package.json +9 -10
- package/dist/_build/assets.mjs +0 -235
- package/dist/_build/config.mjs +0 -124
- package/dist/_build/plugins.mjs +0 -1041
- package/dist/_build/rolldown.mjs +0 -494
- package/dist/_build/types.mjs +0 -268
- package/dist/node_modules/klona/dist/index.mjs +0 -81
- package/dist/node_modules/klona/full/index.mjs +0 -53
- package/dist/node_modules/klona/package.json +0 -74
- package/dist/node_modules/std-env/dist/index.mjs +0 -1
- package/dist/node_modules/std-env/package.json +0 -46
- /package/dist/{_deps → _chunks/_deps}/@jridgewell/gen-mapping.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@jridgewell/remapping.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@jridgewell/resolve-uri.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@jridgewell/sourcemap-codec.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@jridgewell/trace-mapping.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@pi0/vite-plugin-fullstack.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-alias.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-commonjs.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-inject.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-json.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-node-resolve.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/plugin-replace.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/@rollup/pluginutils.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/acorn.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/chokidar.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/citty.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/commondir.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/compatx.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/confbox.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/debug.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/deepmerge.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/depd.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/dot-prop.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/dotenv.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/duplexer.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/ee-first.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/encodeurl.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/escape-html.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/escape-string-regexp.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/estree-walker.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/etag.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/exsolve.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/fdir.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/fresh.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/function-bind.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/gzip-size.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/hasown.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/http-errors.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/httpxy.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/inherits.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/is-core-module.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/is-module.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/is-reference.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/js-tokens.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/magic-string.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/mime-db.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/mime-types.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/mime.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/ms.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/node-fetch-native.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/on-finished.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/parseurl.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/path-parse.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/perfect-debounce.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/picomatch.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/pretty-bytes.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/quansync.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/range-parser.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/rc9.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/readdirp.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/resolve.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/send.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/serve-static.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/setprototypeof.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/statuses.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/strip-literal.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/supports-color.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/tinyexec.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/tinyglobby.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/toidentifier.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/ultrahtml.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/unplugin.mjs +0 -0
- /package/dist/{_deps → _chunks/_deps}/webpack-virtual-modules.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/_all.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/_nitro.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/_static.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/_types.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/alwaysdata.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/aws-amplify.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/aws-lambda.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/bun.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/cleavr.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/digitalocean.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/flightcontrol.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/genezio.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/heroku.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/koyeb.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/netlify.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/node.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/platform.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/render.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/standard.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/stormkit.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/winterjs.mjs +0 -0
- /package/dist/{_presets → _chunks/_presets}/zerops.mjs +0 -0
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { rm, readFile } from 'node:fs/promises';
|
|
3
|
+
import { Worker } from 'node:worker_threads';
|
|
4
|
+
import consola from 'consola';
|
|
5
|
+
import { a, T } from './_deps/std-env.mjs';
|
|
6
|
+
import { fromNodeHandler, HTTPError, defineHandler, getRequestIP, getRequestURL, H3, toEventHandler, withBase } from 'h3';
|
|
7
|
+
import { s as serveStatic } from './_deps/serve-static.mjs';
|
|
8
|
+
import { joinURL } from 'ufo';
|
|
9
|
+
import { c as createProxyServer } from './_deps/httpxy.mjs';
|
|
10
|
+
import { Agent } from 'undici';
|
|
11
|
+
import { resolve, dirname } from 'node:path';
|
|
12
|
+
import { ErrorParser } from 'youch-core';
|
|
13
|
+
import { Youch } from 'youch';
|
|
14
|
+
import { SourceMapConsumer } from 'source-map';
|
|
15
|
+
import { FastResponse } from 'srvx';
|
|
16
|
+
|
|
17
|
+
function createHTTPProxy(defaults = {}) {
|
|
18
|
+
const proxy = createProxyServer(defaults);
|
|
19
|
+
proxy.on("proxyReq", (proxyReq, req) => {
|
|
20
|
+
if (!proxyReq.hasHeader("x-forwarded-for")) {
|
|
21
|
+
const address = req.socket.remoteAddress;
|
|
22
|
+
if (address) {
|
|
23
|
+
proxyReq.appendHeader("x-forwarded-for", address);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!proxyReq.hasHeader("x-forwarded-port")) {
|
|
27
|
+
const localPort = req?.socket?.localPort;
|
|
28
|
+
if (localPort) {
|
|
29
|
+
proxyReq.setHeader("x-forwarded-port", req.socket.localPort);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!proxyReq.hasHeader("x-forwarded-Proto")) {
|
|
33
|
+
const encrypted = req?.connection?.encrypted;
|
|
34
|
+
proxyReq.setHeader("x-forwarded-proto", encrypted ? "https" : "http");
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
proxy,
|
|
39
|
+
async handleEvent(event, opts) {
|
|
40
|
+
try {
|
|
41
|
+
return await fromNodeHandler(
|
|
42
|
+
(req, res) => proxy.web(req, res, opts)
|
|
43
|
+
)(event);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
event.res.headers.set("refresh", "3");
|
|
46
|
+
throw new HTTPError({
|
|
47
|
+
status: 503,
|
|
48
|
+
message: "Dev server is unavailable.",
|
|
49
|
+
cause: error
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function fetchAddress(addr, input, inputInit) {
|
|
56
|
+
let url;
|
|
57
|
+
let init;
|
|
58
|
+
if (input instanceof Request) {
|
|
59
|
+
url = new URL(input.url);
|
|
60
|
+
init = {
|
|
61
|
+
method: input.method,
|
|
62
|
+
headers: input.headers,
|
|
63
|
+
body: input.body,
|
|
64
|
+
...inputInit
|
|
65
|
+
};
|
|
66
|
+
} else {
|
|
67
|
+
url = new URL(input);
|
|
68
|
+
init = inputInit;
|
|
69
|
+
}
|
|
70
|
+
init = {
|
|
71
|
+
duplex: "half",
|
|
72
|
+
redirect: "manual",
|
|
73
|
+
...init
|
|
74
|
+
};
|
|
75
|
+
if (addr.socketPath) {
|
|
76
|
+
url.protocol = "http:";
|
|
77
|
+
return fetch(url, {
|
|
78
|
+
...init,
|
|
79
|
+
...fetchSocketOptions(addr.socketPath)
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const origin = `http://${addr.host}${addr.port ? `:${addr.port}` : ""}`;
|
|
83
|
+
const outURL = new URL(url.pathname + url.search, origin);
|
|
84
|
+
return fetch(outURL, init);
|
|
85
|
+
}
|
|
86
|
+
function fetchSocketOptions(socketPath) {
|
|
87
|
+
if ("Bun" in globalThis) {
|
|
88
|
+
return { unix: socketPath };
|
|
89
|
+
}
|
|
90
|
+
if ("Deno" in globalThis) {
|
|
91
|
+
return {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
client: Deno.createHttpClient({
|
|
94
|
+
// @ts-ignore Missing types?
|
|
95
|
+
transport: "unix",
|
|
96
|
+
path: socketPath
|
|
97
|
+
})
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
dispatcher: new Agent({ connect: { socketPath } })
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
class NodeDevWorker {
|
|
106
|
+
closed = false;
|
|
107
|
+
#name;
|
|
108
|
+
#entry;
|
|
109
|
+
#data;
|
|
110
|
+
#hooks;
|
|
111
|
+
#worker;
|
|
112
|
+
#address;
|
|
113
|
+
#proxy;
|
|
114
|
+
#messageListeners;
|
|
115
|
+
constructor(opts) {
|
|
116
|
+
this.#name = opts.name;
|
|
117
|
+
this.#entry = opts.entry;
|
|
118
|
+
this.#data = opts.data;
|
|
119
|
+
this.#hooks = opts.hooks;
|
|
120
|
+
this.#proxy = createHTTPProxy();
|
|
121
|
+
this.#messageListeners = /* @__PURE__ */ new Set();
|
|
122
|
+
this.#initWorker();
|
|
123
|
+
}
|
|
124
|
+
get ready() {
|
|
125
|
+
return Boolean(
|
|
126
|
+
!this.closed && this.#address && this.#proxy && this.#worker
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
// #region Public methods
|
|
130
|
+
async fetch(input, init) {
|
|
131
|
+
for (let i = 0; i < 5 && !(this.#address && this.#proxy); i++) {
|
|
132
|
+
await new Promise((r) => setTimeout(r, 100 * Math.pow(2, i)));
|
|
133
|
+
}
|
|
134
|
+
if (!(this.#address && this.#proxy)) {
|
|
135
|
+
return new Response("Dev worker is unavailable", { status: 503 });
|
|
136
|
+
}
|
|
137
|
+
return fetchAddress(this.#address, input, init);
|
|
138
|
+
}
|
|
139
|
+
upgrade(req, socket, head) {
|
|
140
|
+
if (!this.ready) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
return this.#proxy.proxy.ws(
|
|
144
|
+
req,
|
|
145
|
+
socket,
|
|
146
|
+
{ target: this.#address, xfwd: true },
|
|
147
|
+
head
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
sendMessage(message) {
|
|
151
|
+
if (!this.#worker) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
"Dev worker should be initialized before sending messages."
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
this.#worker.postMessage(message);
|
|
157
|
+
}
|
|
158
|
+
onMessage(listener) {
|
|
159
|
+
this.#messageListeners.add(listener);
|
|
160
|
+
}
|
|
161
|
+
offMessage(listener) {
|
|
162
|
+
this.#messageListeners.delete(listener);
|
|
163
|
+
}
|
|
164
|
+
async close(cause) {
|
|
165
|
+
if (this.closed) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.closed = true;
|
|
169
|
+
this.#hooks.onClose?.(this, cause);
|
|
170
|
+
this.#hooks = {};
|
|
171
|
+
const onError = (error) => consola.error(error);
|
|
172
|
+
await this.#closeWorker().catch(onError);
|
|
173
|
+
await this.#closeProxy().catch(onError);
|
|
174
|
+
await this.#closeSocket().catch(onError);
|
|
175
|
+
}
|
|
176
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
177
|
+
const status = this.closed ? "closed" : this.ready ? "ready" : "pending";
|
|
178
|
+
return `NodeDevWorker#${this.#name}(${status})`;
|
|
179
|
+
}
|
|
180
|
+
// #endregion
|
|
181
|
+
// #region Private methods
|
|
182
|
+
#initWorker() {
|
|
183
|
+
if (!existsSync(this.#entry)) {
|
|
184
|
+
this.close(`worker entry not found in "${this.#entry}".`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const worker = new Worker(this.#entry, {
|
|
188
|
+
env: {
|
|
189
|
+
...process.env
|
|
190
|
+
},
|
|
191
|
+
workerData: {
|
|
192
|
+
name: this.#name,
|
|
193
|
+
...this.#data
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
worker.once("exit", (code) => {
|
|
197
|
+
worker._exitCode = code;
|
|
198
|
+
this.close(`worker exited with code ${code}`);
|
|
199
|
+
});
|
|
200
|
+
worker.once("error", (error) => {
|
|
201
|
+
consola.error(`Worker error:`, error);
|
|
202
|
+
this.close(error);
|
|
203
|
+
});
|
|
204
|
+
worker.on("message", (message) => {
|
|
205
|
+
if (message?.address) {
|
|
206
|
+
this.#address = message.address;
|
|
207
|
+
this.#hooks.onReady?.(this, this.#address);
|
|
208
|
+
}
|
|
209
|
+
for (const listener of this.#messageListeners) {
|
|
210
|
+
listener(message);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
this.#worker = worker;
|
|
214
|
+
}
|
|
215
|
+
async #closeProxy() {
|
|
216
|
+
this.#proxy?.proxy?.close(() => {
|
|
217
|
+
});
|
|
218
|
+
this.#proxy = void 0;
|
|
219
|
+
}
|
|
220
|
+
async #closeSocket() {
|
|
221
|
+
const socketPath = this.#address?.socketPath;
|
|
222
|
+
if (socketPath && socketPath[0] !== "\0" && !socketPath.startsWith(String.raw`\\.\pipe`)) {
|
|
223
|
+
await rm(socketPath).catch(() => {
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
this.#address = void 0;
|
|
227
|
+
}
|
|
228
|
+
async #closeWorker() {
|
|
229
|
+
if (!this.#worker) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
this.#worker.postMessage({ event: "shutdown" });
|
|
233
|
+
if (!this.#worker._exitCode && !a && !T) {
|
|
234
|
+
await new Promise((resolve) => {
|
|
235
|
+
const gracefulShutdownTimeoutMs = Number.parseInt(process.env.NITRO_SHUTDOWN_TIMEOUT || "", 10) || 5e3;
|
|
236
|
+
const timeout = setTimeout(() => {
|
|
237
|
+
if (process.env.DEBUG) {
|
|
238
|
+
consola.warn(`force closing dev worker...`);
|
|
239
|
+
}
|
|
240
|
+
}, gracefulShutdownTimeoutMs);
|
|
241
|
+
this.#worker?.on("message", (message) => {
|
|
242
|
+
if (message.event === "exit") {
|
|
243
|
+
clearTimeout(timeout);
|
|
244
|
+
resolve();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
this.#worker.removeAllListeners();
|
|
250
|
+
await this.#worker.terminate().catch((error) => {
|
|
251
|
+
consola.error(error);
|
|
252
|
+
});
|
|
253
|
+
this.#worker = void 0;
|
|
254
|
+
}
|
|
255
|
+
// #endregion
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function createVFSHandler(nitro) {
|
|
259
|
+
return defineHandler(async (event) => {
|
|
260
|
+
const { socket } = event.runtime?.node?.req || {};
|
|
261
|
+
const isUnixSocket = (
|
|
262
|
+
// No network addresses
|
|
263
|
+
!socket?.remoteAddress && !socket?.localAddress && // Empty address object
|
|
264
|
+
Object.keys(socket?.address?.() || {}).length === 0 && // Socket is readable/writable but has no port info
|
|
265
|
+
socket?.readable && socket?.writable && !socket?.remotePort
|
|
266
|
+
);
|
|
267
|
+
const ip = getRequestIP(event, { xForwardedFor: isUnixSocket });
|
|
268
|
+
const isLocalRequest = ip && /^::1$|^127\.\d+\.\d+\.\d+$/.test(ip);
|
|
269
|
+
if (!isLocalRequest) {
|
|
270
|
+
throw new HTTPError({
|
|
271
|
+
statusText: `Forbidden IP: "${ip || "?"}"`,
|
|
272
|
+
status: 403
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
const vfsEntries = {
|
|
276
|
+
...nitro.vfs,
|
|
277
|
+
...nitro.options.virtual
|
|
278
|
+
};
|
|
279
|
+
const url = event.context.params?._ || "";
|
|
280
|
+
const isJson = url.endsWith(".json") || event.req.headers.get("accept")?.includes("application/json");
|
|
281
|
+
const id = decodeURIComponent(url.replace(/^(\.json)?\/?/, "") || "");
|
|
282
|
+
if (id && !(id in vfsEntries)) {
|
|
283
|
+
throw new HTTPError({ message: "File not found", status: 404 });
|
|
284
|
+
}
|
|
285
|
+
let content = id ? vfsEntries[id] : void 0;
|
|
286
|
+
if (typeof content === "function") {
|
|
287
|
+
content = await content();
|
|
288
|
+
}
|
|
289
|
+
if (isJson) {
|
|
290
|
+
return {
|
|
291
|
+
rootDir: nitro.options.rootDir,
|
|
292
|
+
entries: Object.keys(vfsEntries).map((id2) => ({
|
|
293
|
+
id: id2,
|
|
294
|
+
path: "/_vfs.json/" + encodeURIComponent(id2)
|
|
295
|
+
})),
|
|
296
|
+
current: id ? {
|
|
297
|
+
id,
|
|
298
|
+
content
|
|
299
|
+
} : null
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const directories = { [nitro.options.rootDir]: {} };
|
|
303
|
+
const fpaths = Object.keys(vfsEntries);
|
|
304
|
+
for (const item of fpaths) {
|
|
305
|
+
const segments = item.replace(nitro.options.rootDir, "").split("/").filter(Boolean);
|
|
306
|
+
let currentDir = item.startsWith(nitro.options.rootDir) ? directories[nitro.options.rootDir] : directories;
|
|
307
|
+
for (const segment of segments) {
|
|
308
|
+
if (!currentDir[segment]) {
|
|
309
|
+
currentDir[segment] = {};
|
|
310
|
+
}
|
|
311
|
+
currentDir = currentDir[segment];
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const generateHTML = (directory, path = []) => Object.entries(directory).map(([fname, value = {}]) => {
|
|
315
|
+
const subpath = [...path, fname];
|
|
316
|
+
const key = subpath.join("/");
|
|
317
|
+
const encodedUrl = encodeURIComponent(key);
|
|
318
|
+
const linkClass = url === `/${encodedUrl}` ? "bg-gray-700 text-white" : "hover:bg-gray-800 text-gray-200";
|
|
319
|
+
return Object.keys(value).length === 0 ? `
|
|
320
|
+
<li class="flex flex-nowrap">
|
|
321
|
+
<a href="/_vfs/${encodedUrl}" class="w-full text-sm px-2 py-1 border-b border-gray-10 ${linkClass}">
|
|
322
|
+
${fname}
|
|
323
|
+
</a>
|
|
324
|
+
</li>
|
|
325
|
+
` : `
|
|
326
|
+
<li>
|
|
327
|
+
<details ${url.startsWith(`/${encodedUrl}`) ? "open" : ""}>
|
|
328
|
+
<summary class="w-full text-sm px-2 py-1 border-b border-gray-10 hover:bg-gray-800 text-gray-200">
|
|
329
|
+
${fname}
|
|
330
|
+
</summary>
|
|
331
|
+
<ul class="ml-4">
|
|
332
|
+
${generateHTML(value, subpath)}
|
|
333
|
+
</ul>
|
|
334
|
+
</details>
|
|
335
|
+
</li>
|
|
336
|
+
`;
|
|
337
|
+
}).join("");
|
|
338
|
+
const rootDirectory = directories[nitro.options.rootDir];
|
|
339
|
+
delete directories[nitro.options.rootDir];
|
|
340
|
+
const items = generateHTML(rootDirectory, [nitro.options.rootDir]) + generateHTML(directories);
|
|
341
|
+
const files = `
|
|
342
|
+
<div class="h-full overflow-auto border-r border-gray:10">
|
|
343
|
+
<p class="text-white text-bold text-center py-1 opacity-50">Virtual Files</p>
|
|
344
|
+
<ul class="flex flex-col">${items}</ul>
|
|
345
|
+
</div>
|
|
346
|
+
`;
|
|
347
|
+
const file = id ? editorTemplate({
|
|
348
|
+
readOnly: true,
|
|
349
|
+
language: id.endsWith("html") ? "html" : "javascript",
|
|
350
|
+
theme: "vs-dark",
|
|
351
|
+
value: content,
|
|
352
|
+
wordWrap: "wordWrapColumn",
|
|
353
|
+
wordWrapColumn: 80
|
|
354
|
+
}) : `
|
|
355
|
+
<div class="w-full h-full flex opacity-50">
|
|
356
|
+
<h1 class="text-white m-auto">Select a virtual file to inspect</h1>
|
|
357
|
+
</div>
|
|
358
|
+
`;
|
|
359
|
+
event.res.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
360
|
+
return (
|
|
361
|
+
/* html */
|
|
362
|
+
`
|
|
363
|
+
<!doctype html>
|
|
364
|
+
<html>
|
|
365
|
+
<head>
|
|
366
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css" />
|
|
367
|
+
<link rel="stylesheet" data-name="vs/editor/editor.main" href="${vsUrl}/editor/editor.main.min.css">
|
|
368
|
+
<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"><\/script>
|
|
369
|
+
<style>
|
|
370
|
+
html {
|
|
371
|
+
background: #1E1E1E;
|
|
372
|
+
color: white;
|
|
373
|
+
}
|
|
374
|
+
[un-cloak] {
|
|
375
|
+
display: none;
|
|
376
|
+
}
|
|
377
|
+
</style>
|
|
378
|
+
</head>
|
|
379
|
+
<body class="bg-[#1E1E1E]">
|
|
380
|
+
<div un-cloak class="h-screen grid grid-cols-[300px_1fr]">
|
|
381
|
+
${files}
|
|
382
|
+
${file}
|
|
383
|
+
</div>
|
|
384
|
+
</body>
|
|
385
|
+
</html>`
|
|
386
|
+
);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
const monacoVersion = "0.30.0";
|
|
390
|
+
const monacoUrl = `https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/${monacoVersion}/min`;
|
|
391
|
+
const vsUrl = `${monacoUrl}/vs`;
|
|
392
|
+
const editorTemplate = (options) => `
|
|
393
|
+
<div id="editor" class="min-h-screen w-full h-full"></div>
|
|
394
|
+
<script src="${vsUrl}/loader.min.js"><\/script>
|
|
395
|
+
<script>
|
|
396
|
+
require.config({ paths: { vs: '${vsUrl}' } })
|
|
397
|
+
|
|
398
|
+
const proxy = URL.createObjectURL(new Blob([\`
|
|
399
|
+
self.MonacoEnvironment = { baseUrl: '${monacoUrl}' }
|
|
400
|
+
importScripts('${vsUrl}/base/worker/workerMain.min.js')
|
|
401
|
+
\`], { type: 'text/javascript' }))
|
|
402
|
+
window.MonacoEnvironment = { getWorkerUrl: () => proxy }
|
|
403
|
+
|
|
404
|
+
setTimeout(() => {
|
|
405
|
+
require(['vs/editor/editor.main'], function () {
|
|
406
|
+
monaco.editor.create(document.getElementById('editor'), ${JSON.stringify(
|
|
407
|
+
options
|
|
408
|
+
)})
|
|
409
|
+
})
|
|
410
|
+
}, 0);
|
|
411
|
+
<\/script>
|
|
412
|
+
`;
|
|
413
|
+
|
|
414
|
+
function defineNitroErrorHandler(handler) {
|
|
415
|
+
return handler;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const devErrorHandler = defineNitroErrorHandler(
|
|
419
|
+
async function defaultNitroErrorHandler(error, event) {
|
|
420
|
+
const res = await defaultHandler(error, event);
|
|
421
|
+
return new FastResponse(
|
|
422
|
+
typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2),
|
|
423
|
+
res
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
async function defaultHandler(error, event, opts) {
|
|
428
|
+
const isSensitive = error.unhandled;
|
|
429
|
+
const status = error.status || 500;
|
|
430
|
+
const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true });
|
|
431
|
+
if (status === 404) {
|
|
432
|
+
const baseURL = import.meta.baseURL || "/";
|
|
433
|
+
if (/^\/[^/]/.test(baseURL) && !url.pathname.startsWith(baseURL)) {
|
|
434
|
+
const redirectTo = `${baseURL}${url.pathname.slice(1)}${url.search}`;
|
|
435
|
+
return {
|
|
436
|
+
status: 302,
|
|
437
|
+
statusText: "Found",
|
|
438
|
+
headers: { location: redirectTo },
|
|
439
|
+
body: `Redirecting...`
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
await loadStackTrace(error).catch(consola.error);
|
|
444
|
+
const youch = new Youch();
|
|
445
|
+
if (isSensitive && !opts?.silent) {
|
|
446
|
+
const tags = [error.unhandled && "[unhandled]"].filter(Boolean).join(" ");
|
|
447
|
+
const ansiError = await (await youch.toANSI(error)).replaceAll(process.cwd(), ".");
|
|
448
|
+
consola.error(
|
|
449
|
+
`[request error] ${tags} [${event.req.method}] ${url}
|
|
450
|
+
|
|
451
|
+
`,
|
|
452
|
+
ansiError
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
const useJSON = opts?.json || !event.req.headers.get("accept")?.includes("text/html");
|
|
456
|
+
const headers = {
|
|
457
|
+
"content-type": useJSON ? "application/json" : "text/html",
|
|
458
|
+
// Prevent browser from guessing the MIME types of resources.
|
|
459
|
+
"x-content-type-options": "nosniff",
|
|
460
|
+
// Prevent error page from being embedded in an iframe
|
|
461
|
+
"x-frame-options": "DENY",
|
|
462
|
+
// Prevent browsers from sending the Referer header
|
|
463
|
+
"referrer-policy": "no-referrer",
|
|
464
|
+
// Disable the execution of any js
|
|
465
|
+
"content-security-policy": "script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self';"
|
|
466
|
+
};
|
|
467
|
+
if (status === 404 || !event.res.headers.has("cache-control")) {
|
|
468
|
+
headers["cache-control"] = "no-cache";
|
|
469
|
+
}
|
|
470
|
+
const body = useJSON ? {
|
|
471
|
+
error: true,
|
|
472
|
+
url,
|
|
473
|
+
status,
|
|
474
|
+
statusText: error.statusText,
|
|
475
|
+
message: error.message,
|
|
476
|
+
data: error.data,
|
|
477
|
+
stack: error.stack?.split("\n").map((line) => line.trim())
|
|
478
|
+
} : await youch.toHTML(error, {
|
|
479
|
+
request: {
|
|
480
|
+
url: url.href,
|
|
481
|
+
method: event.req.method,
|
|
482
|
+
headers: Object.fromEntries(event.req.headers.entries())
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
return {
|
|
486
|
+
status,
|
|
487
|
+
statusText: error.statusText,
|
|
488
|
+
headers,
|
|
489
|
+
body
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
async function loadStackTrace(error) {
|
|
493
|
+
if (!(error instanceof Error)) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const parsed = await new ErrorParser().defineSourceLoader(sourceLoader).parse(error);
|
|
497
|
+
const stack = error.message + "\n" + parsed.frames.map((frame) => fmtFrame(frame)).join("\n");
|
|
498
|
+
Object.defineProperty(error, "stack", { value: stack });
|
|
499
|
+
if (error.cause) {
|
|
500
|
+
await loadStackTrace(error.cause).catch(consola.error);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
async function sourceLoader(frame) {
|
|
504
|
+
if (!frame.fileName || frame.fileType !== "fs" || frame.type === "native") {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (frame.type === "app") {
|
|
508
|
+
const rawSourceMap = await readFile(`${frame.fileName}.map`, "utf8").catch(() => {
|
|
509
|
+
});
|
|
510
|
+
if (rawSourceMap) {
|
|
511
|
+
const consumer = await new SourceMapConsumer(rawSourceMap);
|
|
512
|
+
const originalPosition = consumer.originalPositionFor({ line: frame.lineNumber, column: frame.columnNumber });
|
|
513
|
+
if (originalPosition.source && originalPosition.line) {
|
|
514
|
+
frame.fileName = resolve(dirname(frame.fileName), originalPosition.source);
|
|
515
|
+
frame.lineNumber = originalPosition.line;
|
|
516
|
+
frame.columnNumber = originalPosition.column || 0;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const contents = await readFile(frame.fileName, "utf8").catch(() => {
|
|
521
|
+
});
|
|
522
|
+
return contents ? { contents } : void 0;
|
|
523
|
+
}
|
|
524
|
+
function fmtFrame(frame) {
|
|
525
|
+
if (frame.type === "native") {
|
|
526
|
+
return frame.raw;
|
|
527
|
+
}
|
|
528
|
+
const src = `${frame.fileName || ""}:${frame.lineNumber}:${frame.columnNumber})`;
|
|
529
|
+
return frame.functionName ? `at ${frame.functionName} (${src}` : `at ${src}`;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
class NitroDevApp {
|
|
533
|
+
nitro;
|
|
534
|
+
fetch;
|
|
535
|
+
constructor(nitro, catchAllHandler) {
|
|
536
|
+
this.nitro = nitro;
|
|
537
|
+
const app = this.#createApp(catchAllHandler);
|
|
538
|
+
this.fetch = app.fetch.bind(app);
|
|
539
|
+
}
|
|
540
|
+
#createApp(catchAllHandler) {
|
|
541
|
+
const app = new H3({
|
|
542
|
+
debug: true,
|
|
543
|
+
onError: async (error, event) => {
|
|
544
|
+
const errorHandler = this.nitro.options.devErrorHandler || devErrorHandler;
|
|
545
|
+
await loadStackTrace(error).catch(() => {
|
|
546
|
+
});
|
|
547
|
+
return errorHandler(error, event, {
|
|
548
|
+
defaultHandler: defaultHandler
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
for (const h of this.nitro.options.devHandlers) {
|
|
553
|
+
const handler = toEventHandler(h.handler);
|
|
554
|
+
if (!handler) {
|
|
555
|
+
this.nitro.logger.warn("Invalid dev handler:", h);
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
if (h.middleware || !h.route) {
|
|
559
|
+
if (h.route) {
|
|
560
|
+
app.use(h.route, handler, { method: h.method });
|
|
561
|
+
} else {
|
|
562
|
+
app.use(handler, { method: h.method });
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
app.on(h.method || "", h.route, handler, { meta: h.meta });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
app.get("/_vfs/**", createVFSHandler(this.nitro));
|
|
569
|
+
for (const asset of this.nitro.options.publicAssets) {
|
|
570
|
+
const assetRoute = joinURL(
|
|
571
|
+
this.nitro.options.runtimeConfig.app.baseURL,
|
|
572
|
+
asset.baseURL || "/",
|
|
573
|
+
"**"
|
|
574
|
+
);
|
|
575
|
+
let handler = fromNodeHandler(
|
|
576
|
+
// @ts-expect-error (HTTP2 types)
|
|
577
|
+
serveStatic(asset.dir, { dotfiles: "allow" })
|
|
578
|
+
);
|
|
579
|
+
if (asset.baseURL?.length || 0 > 1) {
|
|
580
|
+
handler = withBase(asset.baseURL, handler);
|
|
581
|
+
}
|
|
582
|
+
app.use(assetRoute, handler);
|
|
583
|
+
}
|
|
584
|
+
const routes = Object.keys(this.nitro.options.devProxy).sort().reverse();
|
|
585
|
+
for (const route of routes) {
|
|
586
|
+
let opts = this.nitro.options.devProxy[route];
|
|
587
|
+
if (typeof opts === "string") {
|
|
588
|
+
opts = { target: opts };
|
|
589
|
+
}
|
|
590
|
+
const proxy = createHTTPProxy(opts);
|
|
591
|
+
app.all(route, proxy.handleEvent);
|
|
592
|
+
}
|
|
593
|
+
if (catchAllHandler) {
|
|
594
|
+
app.all("/**", catchAllHandler);
|
|
595
|
+
}
|
|
596
|
+
return app;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export { NitroDevApp as N, NodeDevWorker as a };
|