mono-jsx-dom 0.1.4 → 0.1.6
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/bin/build.mjs +20 -18
- package/bin/cli +1 -1
- package/bin/dev.mjs +48 -11
- package/bin/init.mjs +67 -44
- package/package.json +6 -2
- package/server/node-fetch-server.mjs +8 -4
- package/server/node-server-hooks.mjs +17 -0
package/bin/build.mjs
CHANGED
|
@@ -56,15 +56,8 @@ async function ensureDir(path) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// bin/build.ts
|
|
59
|
-
async function run() {
|
|
60
|
-
const flags = parseFlags();
|
|
61
|
-
const start = performance.now();
|
|
62
|
-
const runtime = flags.node ?? "fetch-server";
|
|
63
|
-
await build({ runtime });
|
|
64
|
-
console.log("\x1B[32m\u2728 Build completed.\x1B[0m", "\x1B[90m(%d ms)\x1B[0m", performance.now() - start);
|
|
65
|
-
}
|
|
66
59
|
async function build(options) {
|
|
67
|
-
const workDir = join(cwd(), options?.
|
|
60
|
+
const workDir = join(cwd(), options?.appName ?? ".");
|
|
68
61
|
const outdir = join(workDir, options?.outdir ?? "dist");
|
|
69
62
|
if (!await exists(join(workDir, "index.html"))) {
|
|
70
63
|
console.error("index.html not found");
|
|
@@ -159,7 +152,9 @@ async function build(options) {
|
|
|
159
152
|
for (const file of outputFiles) {
|
|
160
153
|
const contentType = file.path.endsWith(".js") ? "application/javascript" : "text/css";
|
|
161
154
|
const filename = relative(outdir, file.path);
|
|
162
|
-
|
|
155
|
+
if (filename !== tw?.entryCSS) {
|
|
156
|
+
vfs[filename] = await createVFile(indexHTML, filename, file.text, contentType);
|
|
157
|
+
}
|
|
163
158
|
}
|
|
164
159
|
if (tw) {
|
|
165
160
|
const css = await tw.build();
|
|
@@ -173,10 +168,17 @@ async function build(options) {
|
|
|
173
168
|
'import buildJSON$ from "./build.json" with { type: "json" };',
|
|
174
169
|
"server$.setVFS(new Map(Object.entries(buildJSON$)));"
|
|
175
170
|
].join("");
|
|
176
|
-
await buildServerJS(workDir, outdir, options?.
|
|
171
|
+
await buildServerJS(workDir, outdir, options?.serverType, extraJS);
|
|
177
172
|
await dispose();
|
|
178
173
|
}
|
|
179
|
-
async function
|
|
174
|
+
async function run() {
|
|
175
|
+
const flags = parseFlags();
|
|
176
|
+
const start = performance.now();
|
|
177
|
+
const serverType = flags.node ? "node" : "fetch-server";
|
|
178
|
+
await build({ serverType });
|
|
179
|
+
console.log("\x1B[32m\u2728 Build completed.\x1B[0m", "\x1B[90m(" + Math.ceil(performance.now() - start) + " ms)\x1B[0m");
|
|
180
|
+
}
|
|
181
|
+
async function buildServerJS(workDir, outdir, serverType = "fetch-server", extraJS, watch) {
|
|
180
182
|
const stdin2 = {
|
|
181
183
|
sourcefile: join(workDir, "server.js"),
|
|
182
184
|
contents: 'import server from "mono-jsx-dom/server;export default server;',
|
|
@@ -185,11 +187,11 @@ async function buildServerJS(workDir, outdir, runtime = "fetch-server", extraJS,
|
|
|
185
187
|
for (const loader of ["ts", "tsx", "js", "jsx"]) {
|
|
186
188
|
const sourcefile = join(workDir, "server." + loader);
|
|
187
189
|
if (await exists(sourcefile)) {
|
|
188
|
-
if (
|
|
190
|
+
if (serverType === "node") {
|
|
189
191
|
stdin2.sourcefile = join(workDir, "server-node.mjs");
|
|
190
192
|
stdin2.resolveDir = workDir;
|
|
191
193
|
stdin2.contents = [
|
|
192
|
-
'import { serve$ } from "mono-jsx-dom/
|
|
194
|
+
'import { serve as serve$ } from "mono-jsx-dom/node-fetch-server";',
|
|
193
195
|
'import server$ from "./server.' + loader + '";',
|
|
194
196
|
"serve$(server$);"
|
|
195
197
|
].join("\n");
|
|
@@ -213,7 +215,7 @@ async function buildServerJS(workDir, outdir, runtime = "fetch-server", extraJS,
|
|
|
213
215
|
platform: "node",
|
|
214
216
|
format: "esm",
|
|
215
217
|
target: "es2024",
|
|
216
|
-
external: ["mono-jsx-dom/server", "mono-jsx-dom/
|
|
218
|
+
external: ["mono-jsx-dom/server", "mono-jsx-dom/node-fetch-server"]
|
|
217
219
|
};
|
|
218
220
|
if (extraJS) {
|
|
219
221
|
esbOptions.banner = { js: extraJS };
|
|
@@ -235,6 +237,7 @@ async function buildServerJS(workDir, outdir, runtime = "fetch-server", extraJS,
|
|
|
235
237
|
} else {
|
|
236
238
|
await ctx.rebuild();
|
|
237
239
|
await ctx.dispose();
|
|
240
|
+
await esbuild.stop();
|
|
238
241
|
}
|
|
239
242
|
}
|
|
240
243
|
function initTailwindBuilder(workDir, entryCSS) {
|
|
@@ -297,7 +300,7 @@ async function paseIndexHtml(workDir) {
|
|
|
297
300
|
}
|
|
298
301
|
const relativePath = relative(workDir, join(workDir, href));
|
|
299
302
|
entryPoints[relativePath] = relativePath;
|
|
300
|
-
return `<link${attrs}
|
|
303
|
+
return `<link${attrs}href="/${relativePath}">`;
|
|
301
304
|
});
|
|
302
305
|
content = content.replace(/<script(\s[^>]*?)src="([^"]+\.(ts|tsx|js|jsx|mjs))"\s*>/g, (tag, attrs, src) => {
|
|
303
306
|
if (isUrl(src)) {
|
|
@@ -306,7 +309,7 @@ async function paseIndexHtml(workDir) {
|
|
|
306
309
|
const relativePath = relative(workDir, join(workDir, src));
|
|
307
310
|
const resolvedPath = relativePath.slice(0, relativePath.lastIndexOf(".")) + ".js";
|
|
308
311
|
entryPoints[relativePath] = resolvedPath;
|
|
309
|
-
return `<script${attrs}
|
|
312
|
+
return `<script${attrs}src="/${resolvedPath}">`;
|
|
310
313
|
});
|
|
311
314
|
return { content, entryPoints };
|
|
312
315
|
}
|
|
@@ -318,7 +321,7 @@ async function createVFile(indexHTML, filename, content, contentType) {
|
|
|
318
321
|
if (ext !== ".css" && ext !== ".js") {
|
|
319
322
|
filename = filename.slice(0, -ext.length) + ".js";
|
|
320
323
|
}
|
|
321
|
-
indexHTML.content = indexHTML.content.replace('"/' + filename + '"', '"/' + filename + "?hash=" +
|
|
324
|
+
indexHTML.content = indexHTML.content.replace('"/' + filename + '"', '"/' + filename + "?hash=" + contentHash.slice(0, 8) + '"');
|
|
322
325
|
}
|
|
323
326
|
return {
|
|
324
327
|
content,
|
|
@@ -332,6 +335,5 @@ function isUrl(url) {
|
|
|
332
335
|
}
|
|
333
336
|
export {
|
|
334
337
|
build,
|
|
335
|
-
buildServerJS,
|
|
336
338
|
run
|
|
337
339
|
};
|
package/bin/cli
CHANGED
package/bin/dev.mjs
CHANGED
|
@@ -50,9 +50,9 @@ async function exists(filename) {
|
|
|
50
50
|
// bin/dev.ts
|
|
51
51
|
import { build } from "./build.mjs";
|
|
52
52
|
async function dev(options) {
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const workDir = join(cwd(), options?.
|
|
53
|
+
const runtime = "Deno" in globalThis ? "deno" : "Bun" in globalThis ? "bun" : "node";
|
|
54
|
+
const ac = options?.ac ?? new AbortController();
|
|
55
|
+
const workDir = join(cwd(), options?.appName ?? ".");
|
|
56
56
|
const outdir = join(workDir, options?.outdir ?? "dist");
|
|
57
57
|
const port = options?.port ?? 3e3;
|
|
58
58
|
const devServerPort = 8798;
|
|
@@ -77,8 +77,11 @@ async function dev(options) {
|
|
|
77
77
|
});
|
|
78
78
|
await serve({
|
|
79
79
|
port: devServerPort,
|
|
80
|
+
hostname: "localhost",
|
|
80
81
|
idleTimeout: 32,
|
|
81
82
|
// 32 seconds
|
|
83
|
+
onListen: (_localAddress) => {
|
|
84
|
+
},
|
|
82
85
|
fetch: async (req) => {
|
|
83
86
|
const { pathname } = new URL(req.url);
|
|
84
87
|
if (pathname === "/__dev_vfs.json") {
|
|
@@ -162,30 +165,50 @@ async function dev(options) {
|
|
|
162
165
|
}
|
|
163
166
|
});
|
|
164
167
|
const serverScript = await resolveModule(join(workDir, "server"), [".ts", ".mjs", ".js"]) ?? join(workDir, "node_modules/mono-jsx-dom/server/index.mjs");
|
|
168
|
+
const args = ["--watch", serverScript];
|
|
169
|
+
if (runtime === "node") {
|
|
170
|
+
args.unshift("--import", "mono-jsx-dom/node-server-hooks");
|
|
171
|
+
args.push("--port", port.toString());
|
|
172
|
+
} else {
|
|
173
|
+
args.unshift("--port", port.toString());
|
|
174
|
+
}
|
|
175
|
+
if (runtime === "deno") {
|
|
176
|
+
args.unshift("serve", "-A");
|
|
177
|
+
}
|
|
165
178
|
const serverProcess = spawn(
|
|
166
|
-
|
|
167
|
-
|
|
179
|
+
runtime,
|
|
180
|
+
args,
|
|
168
181
|
{
|
|
169
182
|
cwd: workDir,
|
|
170
183
|
env: { ...env, DEV_SERVER: devServerUrl },
|
|
171
184
|
stdio: "inherit"
|
|
172
185
|
}
|
|
173
186
|
);
|
|
174
|
-
|
|
187
|
+
const onClose = () => ac.abort();
|
|
188
|
+
serverProcess.on("close", onClose);
|
|
189
|
+
ac.signal.addEventListener("abort", () => {
|
|
190
|
+
serverProcess.off("close", onClose);
|
|
191
|
+
serverProcess.kill();
|
|
192
|
+
});
|
|
175
193
|
};
|
|
176
194
|
const onError = (error) => {
|
|
177
195
|
console.error(error);
|
|
178
196
|
ac.abort();
|
|
179
197
|
};
|
|
180
|
-
if (
|
|
198
|
+
if (runtime === "node") {
|
|
181
199
|
const [major, minor] = versions.node.split(".").map(Number);
|
|
182
200
|
if (major < 22 || major === 22 && minor < 18) {
|
|
183
201
|
console.error("Node.js version 22.18.0 or higher is required to use the dev command.");
|
|
184
202
|
exit2(1);
|
|
185
203
|
}
|
|
186
204
|
}
|
|
205
|
+
process.on("SIGINT", () => {
|
|
206
|
+
console.log("\x1B[90mShutting down dev server...\x1B[0m");
|
|
207
|
+
ac.abort();
|
|
208
|
+
exit2(0);
|
|
209
|
+
});
|
|
187
210
|
await build({
|
|
188
|
-
|
|
211
|
+
appName: options?.appName,
|
|
189
212
|
outdir: options?.outdir,
|
|
190
213
|
dev: {
|
|
191
214
|
signal: ac.signal,
|
|
@@ -194,9 +217,23 @@ async function dev(options) {
|
|
|
194
217
|
}).catch(onError);
|
|
195
218
|
}
|
|
196
219
|
async function serve(options) {
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
220
|
+
const denoServe = globalThis.Deno?.serve;
|
|
221
|
+
const bunServe = globalThis.Bun?.serve;
|
|
222
|
+
if (denoServe) {
|
|
223
|
+
const { fetch, port, signal, hostname, onListen } = options;
|
|
224
|
+
denoServe(
|
|
225
|
+
{
|
|
226
|
+
port,
|
|
227
|
+
signal,
|
|
228
|
+
hostname,
|
|
229
|
+
onListen: onListen ?? ((localAddress) => {
|
|
230
|
+
console.log(`Server is running on http://${hostname ?? "localhost"}:${localAddress.port}`);
|
|
231
|
+
})
|
|
232
|
+
},
|
|
233
|
+
fetch
|
|
234
|
+
);
|
|
235
|
+
} else if (bunServe) {
|
|
236
|
+
const server = bunServe(options);
|
|
200
237
|
options.signal?.addEventListener("abort", () => server.stop());
|
|
201
238
|
} else {
|
|
202
239
|
await import("../server/node-fetch-server.mjs").then((m) => m.serve(options));
|
package/bin/init.mjs
CHANGED
|
@@ -69,6 +69,7 @@ async function input(prompt, placeholder = "") {
|
|
|
69
69
|
return text;
|
|
70
70
|
} finally {
|
|
71
71
|
stdin.setRawMode(wasRaw ?? false);
|
|
72
|
+
stdin.pause();
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
const rl = createInterface({ input: stdin, output: stdout });
|
|
@@ -89,6 +90,7 @@ async function confirm(prompt) {
|
|
|
89
90
|
stdout.write(hint);
|
|
90
91
|
const wasRaw = stdin.isRaw;
|
|
91
92
|
stdin.setRawMode(true);
|
|
93
|
+
stdin.resume();
|
|
92
94
|
try {
|
|
93
95
|
const yes = await new Promise((resolve) => {
|
|
94
96
|
stdin.once("data", (buf) => {
|
|
@@ -117,6 +119,7 @@ async function confirm(prompt) {
|
|
|
117
119
|
return yes;
|
|
118
120
|
} finally {
|
|
119
121
|
stdin.setRawMode(wasRaw ?? false);
|
|
122
|
+
stdin.pause();
|
|
120
123
|
}
|
|
121
124
|
}
|
|
122
125
|
const rl = createInterface({ input: stdin, output: stdout });
|
|
@@ -163,9 +166,10 @@ var template = {
|
|
|
163
166
|
name: "mono-app",
|
|
164
167
|
version: "0.0.0",
|
|
165
168
|
private: true,
|
|
169
|
+
type: "module",
|
|
166
170
|
scripts: {
|
|
167
|
-
dev: (bun ? "bun --bun" : "") + "
|
|
168
|
-
build: (bun ? "bun --bun" : "") + "
|
|
171
|
+
dev: (bun ? "bun --bun " : "") + "mono-jsx-dom dev",
|
|
172
|
+
build: (bun ? "bun --bun " : "") + "mono-jsx-dom build",
|
|
169
173
|
start: bun ? "bun --bun mono-jsx-dom build && bun dist/server.mjs" : "mono-jsx-dom build --node && node dist/server.mjs"
|
|
170
174
|
}
|
|
171
175
|
},
|
|
@@ -222,17 +226,40 @@ export default {
|
|
|
222
226
|
};
|
|
223
227
|
async function run() {
|
|
224
228
|
const appName = argv2[3] ?? await input("Enter the name of the app", "mono-app");
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
async function init(appName) {
|
|
228
|
-
const appDir = join(cwd(), appName);
|
|
229
|
-
if (await exists(appDir) && !await confirm(`Directory ${appName} already exists. Overwrite?`)) {
|
|
229
|
+
const dir = join(cwd(), appName);
|
|
230
|
+
if (await exists(dir) && !await confirm(`Directory ${appName} already exists. Overwrite?`)) {
|
|
230
231
|
return;
|
|
231
232
|
}
|
|
233
|
+
const tailwindCSS = await confirm("Use TailwindCSS for styling?");
|
|
234
|
+
const wrangler = await confirm("Add Cloudflare Workers integration?");
|
|
235
|
+
const npmCmd = bun ? "bun" : "npm";
|
|
236
|
+
await init({
|
|
237
|
+
dir,
|
|
238
|
+
appName,
|
|
239
|
+
tailwindCSS,
|
|
240
|
+
wrangler,
|
|
241
|
+
onInstall: () => {
|
|
242
|
+
console.log("\x1B[90mInstalling dependencies...\x1B[0m");
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
console.log("");
|
|
246
|
+
console.log("\u2728 \x1B[32mSetup completed.\x1B[0m");
|
|
247
|
+
console.log("You can now start or build the app with the following commands:");
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(`cd ${appName}`);
|
|
250
|
+
console.log(`${npmCmd} run dev \x1B[90m# start the app in development mode.\x1B[0m`);
|
|
251
|
+
if (wrangler) {
|
|
252
|
+
console.log(`${npmCmd} run deploy \x1B[90m# deploy the app to Cloudflare Workers.\x1B[0m`);
|
|
253
|
+
} else {
|
|
254
|
+
console.log(`${npmCmd} run build \x1B[90m# build the app for production.\x1B[0m`);
|
|
255
|
+
console.log(`${npmCmd} run start \x1B[90m# build and start the app in production mode.\x1B[0m`);
|
|
256
|
+
}
|
|
257
|
+
console.log("");
|
|
258
|
+
}
|
|
259
|
+
async function init(options) {
|
|
260
|
+
const { dir, appName, tailwindCSS, wrangler } = options;
|
|
232
261
|
const scaffold = { ...template };
|
|
233
|
-
|
|
234
|
-
const withWrangler = await confirm("Add Cloudflare Workers integration?");
|
|
235
|
-
if (withWrangler) {
|
|
262
|
+
if (wrangler) {
|
|
236
263
|
scaffold["wrangler.jsonc"] = JSON.stringify(
|
|
237
264
|
{
|
|
238
265
|
$schema: "./node_modules/wrangler/config-schema.json",
|
|
@@ -251,17 +278,17 @@ async function init(appName) {
|
|
|
251
278
|
2
|
|
252
279
|
);
|
|
253
280
|
}
|
|
254
|
-
if (!
|
|
281
|
+
if (!tailwindCSS) {
|
|
255
282
|
scaffold["app/style.css"] = "/* app styles */\n";
|
|
256
283
|
}
|
|
257
|
-
await ensureDir(
|
|
284
|
+
await ensureDir(dir);
|
|
258
285
|
await Promise.all(
|
|
259
286
|
Object.entries(scaffold).map(async ([filename, content]) => {
|
|
260
|
-
const filepath = join(
|
|
287
|
+
const filepath = join(dir, filename);
|
|
261
288
|
if (filename === "package.json") {
|
|
262
289
|
const pkg = JSON.parse(content);
|
|
263
290
|
pkg.name = appName;
|
|
264
|
-
if (
|
|
291
|
+
if (wrangler) {
|
|
265
292
|
pkg.scripts.dev = "wrangler dev";
|
|
266
293
|
pkg.scripts.deploy = "wrangler deploy";
|
|
267
294
|
delete pkg.scripts.build;
|
|
@@ -277,7 +304,7 @@ async function init(appName) {
|
|
|
277
304
|
);
|
|
278
305
|
let tsConfig = /* @__PURE__ */ Object.create(null);
|
|
279
306
|
try {
|
|
280
|
-
const data = await readFile(join(
|
|
307
|
+
const data = await readFile(join(dir, "tsconfig.json"), "utf8");
|
|
281
308
|
tsConfig = JSON.parse(data);
|
|
282
309
|
} catch {
|
|
283
310
|
}
|
|
@@ -289,44 +316,40 @@ async function init(appName) {
|
|
|
289
316
|
compilerOptions.noEmit ??= true;
|
|
290
317
|
compilerOptions.jsx = "react-jsx";
|
|
291
318
|
compilerOptions.jsxImportSource = "mono-jsx-dom";
|
|
292
|
-
await writeFile(join(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
console.log("");
|
|
297
|
-
console.log("\u2728 \x1B[32mSetup completed.\x1B[0m");
|
|
298
|
-
console.log("You can now start or build the app with the following commands:");
|
|
299
|
-
console.log("");
|
|
300
|
-
console.log(`cd ${appName}`);
|
|
301
|
-
console.log(`${cmd} dev${isBun ? " " : ""} \x1B[90m# start the app in development mode.\x1B[0m`);
|
|
302
|
-
if (withWrangler) {
|
|
303
|
-
console.log(`${cmd}${isBun ? " run" : ""} deploy \x1B[90m# deploy the app to Cloudflare Workers.\x1B[0m`);
|
|
304
|
-
} else {
|
|
305
|
-
console.log(`${cmd}${isBun ? " run" : ""} build \x1B[90m# build the app for production.\x1B[0m`);
|
|
306
|
-
console.log(`${cmd} start${isBun ? " " : ""} \x1B[90m# build and start the app in production mode.\x1B[0m`);
|
|
307
|
-
}
|
|
308
|
-
console.log("");
|
|
319
|
+
await writeFile(join(dir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2));
|
|
320
|
+
const depsOptions = { tailwindCSS, wrangler };
|
|
321
|
+
options.onInstall?.(depsOptions);
|
|
322
|
+
installDependencies(dir, depsOptions);
|
|
309
323
|
}
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
spawnSync(cmd, ["add", "mono-jsx-dom"], { cwd: cwd2 });
|
|
324
|
+
function installDependencies(cwd2, options) {
|
|
325
|
+
const { tailwindCSS, wrangler, extraDependencies, extraDevDependencies } = options;
|
|
326
|
+
const npmCmd = bun ? "bun" : "npm";
|
|
327
|
+
const deps = ["mono-jsx-dom"];
|
|
316
328
|
const devDeps = ["esbuild"];
|
|
317
|
-
if (
|
|
329
|
+
if (tailwindCSS) {
|
|
318
330
|
devDeps.push("tailwindcss", "oxide-wasm");
|
|
319
331
|
}
|
|
320
|
-
if (
|
|
332
|
+
if (wrangler) {
|
|
321
333
|
devDeps.push("wrangler");
|
|
322
334
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
335
|
+
if (extraDependencies) {
|
|
336
|
+
deps.push(...extraDependencies);
|
|
337
|
+
}
|
|
338
|
+
if (extraDevDependencies) {
|
|
339
|
+
devDeps.push(...extraDevDependencies);
|
|
340
|
+
}
|
|
341
|
+
spawnSync(npmCmd, ["add", ...deps], { cwd: cwd2 });
|
|
342
|
+
spawnSync(npmCmd, ["add", "-D", ...devDeps], { cwd: cwd2 });
|
|
343
|
+
if (wrangler) {
|
|
344
|
+
if (npmCmd === "bun") {
|
|
345
|
+
spawnSync(npmCmd, ["--bun", "wrangler", "types"], { cwd: cwd2 });
|
|
346
|
+
} else {
|
|
347
|
+
spawnSync(npmCmd, ["wrangler", "types"], { cwd: cwd2 });
|
|
348
|
+
}
|
|
326
349
|
}
|
|
327
|
-
return cmd;
|
|
328
350
|
}
|
|
329
351
|
export {
|
|
330
352
|
init,
|
|
353
|
+
installDependencies,
|
|
331
354
|
run
|
|
332
355
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mono-jsx-dom",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A JSX runtime for browsers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jsx",
|
|
@@ -35,9 +35,13 @@
|
|
|
35
35
|
"node": "./server/index.mjs",
|
|
36
36
|
"import": "./server/index.mjs"
|
|
37
37
|
},
|
|
38
|
-
"./
|
|
38
|
+
"./node-fetch-server": {
|
|
39
39
|
"node": "./server/node-fetch-server.mjs",
|
|
40
40
|
"import": "./server/node-fetch-server.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./node-server-hooks": {
|
|
43
|
+
"node": "./server/node-server-hooks.mjs",
|
|
44
|
+
"import": "./server/node-server-hooks.mjs"
|
|
41
45
|
}
|
|
42
46
|
},
|
|
43
47
|
"scripts": {
|
|
@@ -115,12 +115,16 @@ async function sendResponse(res, response) {
|
|
|
115
115
|
res.end();
|
|
116
116
|
}
|
|
117
117
|
function serve(options) {
|
|
118
|
-
const port =
|
|
119
|
-
const server = createServer(createRequestListener(
|
|
118
|
+
const { port = getDefaultPort(), hostname, signal, fetch, onListen } = options;
|
|
119
|
+
const server = createServer(createRequestListener(fetch, options));
|
|
120
120
|
server.listen(port, options?.hostname, () => {
|
|
121
|
-
|
|
121
|
+
if (onListen) {
|
|
122
|
+
onListen({ port });
|
|
123
|
+
} else {
|
|
124
|
+
console.log(`Server is running on http://${hostname ?? "localhost"}:${port}`);
|
|
125
|
+
}
|
|
122
126
|
});
|
|
123
|
-
|
|
127
|
+
signal?.addEventListener("abort", () => {
|
|
124
128
|
server.close();
|
|
125
129
|
});
|
|
126
130
|
return new Promise((resolve, reject) => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// server/node-server-hooks.ts
|
|
2
|
+
import { argv } from "node:process";
|
|
3
|
+
import { registerHooks } from "node:module";
|
|
4
|
+
var serverHook = `
|
|
5
|
+
import { serve as serve$ } from "mono-jsx-dom/node-fetch-server";
|
|
6
|
+
import(import.meta.url).then(m => serve$(m.default));
|
|
7
|
+
`;
|
|
8
|
+
registerHooks({
|
|
9
|
+
load(url, context, nextLoad) {
|
|
10
|
+
const result = nextLoad(url, context);
|
|
11
|
+
if (result.source && "file://" + argv[1] === url) {
|
|
12
|
+
const source = typeof result.source === "string" ? result.source : new TextDecoder().decode(result.source);
|
|
13
|
+
return { ...result, source: source + serverHook };
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
});
|