@hono/cli 0.1.1 → 0.1.2
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/cli.js +51 -77
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -70,61 +70,30 @@ import { dirname, join, resolve } from "path";
|
|
|
70
70
|
|
|
71
71
|
// src/utils/build.ts
|
|
72
72
|
import * as esbuild from "esbuild";
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
import { extname } from "path";
|
|
74
|
+
import { pathToFileURL } from "url";
|
|
75
|
+
async function buildAndImportApp(filePath, options = {}) {
|
|
76
|
+
const ext = extname(filePath);
|
|
77
|
+
if ([".ts", ".tsx", ".jsx"].includes(ext)) {
|
|
78
|
+
const result = await esbuild.build({
|
|
79
|
+
entryPoints: [filePath],
|
|
80
|
+
bundle: true,
|
|
81
|
+
write: false,
|
|
82
|
+
format: "esm",
|
|
83
|
+
target: "node20",
|
|
84
|
+
jsx: "automatic",
|
|
85
|
+
jsxImportSource: "hono/jsx",
|
|
86
|
+
platform: "node",
|
|
87
|
+
external: options.external || []
|
|
79
88
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
target: "node20",
|
|
88
|
-
jsx: "automatic",
|
|
89
|
-
jsxImportSource: "hono/jsx",
|
|
90
|
-
platform: "node",
|
|
91
|
-
external: options.external || [],
|
|
92
|
-
plugins: [
|
|
93
|
-
{
|
|
94
|
-
name: "watch",
|
|
95
|
-
setup(build2) {
|
|
96
|
-
build2.onEnd(async (result) => {
|
|
97
|
-
try {
|
|
98
|
-
const code = result.outputFiles?.[0]?.text || "";
|
|
99
|
-
const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
|
|
100
|
-
const module = await import(dataUrl);
|
|
101
|
-
const app = module.default;
|
|
102
|
-
if (!app) {
|
|
103
|
-
throw new Error("Failed to build app");
|
|
104
|
-
}
|
|
105
|
-
if (!app || typeof app.request !== "function") {
|
|
106
|
-
throw new Error("No valid Hono app exported from the file");
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
resolveApp(app);
|
|
110
|
-
} catch {
|
|
111
|
-
}
|
|
112
|
-
} catch (error) {
|
|
113
|
-
console.error("Error building app", error);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
});
|
|
120
|
-
await context2.watch();
|
|
121
|
-
if (!options.watch) {
|
|
122
|
-
await context2.dispose();
|
|
89
|
+
const code = result.outputFiles[0].text;
|
|
90
|
+
const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
|
|
91
|
+
const module = await import(dataUrl);
|
|
92
|
+
return module.default;
|
|
93
|
+
} else {
|
|
94
|
+
const module = await import(pathToFileURL(filePath).href);
|
|
95
|
+
return module.default;
|
|
123
96
|
}
|
|
124
|
-
do {
|
|
125
|
-
yield await appPromise;
|
|
126
|
-
preparePromise();
|
|
127
|
-
} while (options.watch);
|
|
128
97
|
}
|
|
129
98
|
|
|
130
99
|
// src/commands/optimize/index.ts
|
|
@@ -139,10 +108,9 @@ function optimizeCommand(program2) {
|
|
|
139
108
|
throw new Error(`Entry file ${entry} does not exist`);
|
|
140
109
|
}
|
|
141
110
|
const appFilePath = realpathSync(appPath);
|
|
142
|
-
const
|
|
111
|
+
const app = await buildAndImportApp(appFilePath, {
|
|
143
112
|
external: ["@hono/node-server"]
|
|
144
113
|
});
|
|
145
|
-
const app = (await buildIterator.next()).value;
|
|
146
114
|
let routerName;
|
|
147
115
|
let importStatement;
|
|
148
116
|
let assignRouterStatement;
|
|
@@ -193,13 +161,13 @@ function optimizeCommand(program2) {
|
|
|
193
161
|
plugins: [
|
|
194
162
|
{
|
|
195
163
|
name: "hono-optimize",
|
|
196
|
-
setup(
|
|
164
|
+
setup(build3) {
|
|
197
165
|
const honoPseudoImportPath = "hono-optimized-pseudo-import-path";
|
|
198
|
-
|
|
166
|
+
build3.onResolve({ filter: /^hono$/ }, async (args) => {
|
|
199
167
|
if (!args.importer) {
|
|
200
168
|
return void 0;
|
|
201
169
|
}
|
|
202
|
-
const resolved = await
|
|
170
|
+
const resolved = await build3.resolve(args.path, {
|
|
203
171
|
kind: "import-statement",
|
|
204
172
|
resolveDir: args.resolveDir
|
|
205
173
|
});
|
|
@@ -207,7 +175,7 @@ function optimizeCommand(program2) {
|
|
|
207
175
|
path: join(dirname(resolved.path), honoPseudoImportPath)
|
|
208
176
|
};
|
|
209
177
|
});
|
|
210
|
-
|
|
178
|
+
build3.onLoad({ filter: new RegExp(`/${honoPseudoImportPath}$`) }, async () => {
|
|
211
179
|
return {
|
|
212
180
|
contents: `
|
|
213
181
|
import { HonoBase } from 'hono/hono-base'
|
|
@@ -235,7 +203,7 @@ import { existsSync as existsSync2, realpathSync as realpathSync2 } from "fs";
|
|
|
235
203
|
import { resolve as resolve2 } from "path";
|
|
236
204
|
var DEFAULT_ENTRY_CANDIDATES2 = ["src/index.ts", "src/index.tsx", "src/index.js", "src/index.jsx"];
|
|
237
205
|
function requestCommand(program2) {
|
|
238
|
-
program2.command("request").description("Send request to Hono app using app.request()").argument("[file]", "Path to the Hono app file").option("-P, --path <path>", "Request path", "/").option("-X, --method <method>", "HTTP method", "GET").option("-d, --data <data>", "Request body data").option(
|
|
206
|
+
program2.command("request").description("Send request to Hono app using app.request()").argument("[file]", "Path to the Hono app file").option("-P, --path <path>", "Request path", "/").option("-X, --method <method>", "HTTP method", "GET").option("-d, --data <data>", "Request body data").option(
|
|
239
207
|
"-H, --header <header>",
|
|
240
208
|
"Custom headers",
|
|
241
209
|
(value, previous) => {
|
|
@@ -244,15 +212,11 @@ function requestCommand(program2) {
|
|
|
244
212
|
[]
|
|
245
213
|
).action(async (file, options) => {
|
|
246
214
|
const path = options.path || "/";
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
for await (const app of buildIterator) {
|
|
250
|
-
const result = await executeRequest(app, path, options);
|
|
251
|
-
console.log(JSON.stringify(result, null, 2));
|
|
252
|
-
}
|
|
215
|
+
const result = await executeRequest(file, path, options);
|
|
216
|
+
console.log(JSON.stringify(result, null, 2));
|
|
253
217
|
});
|
|
254
218
|
}
|
|
255
|
-
function
|
|
219
|
+
async function executeRequest(appPath, requestPath, options) {
|
|
256
220
|
let entry;
|
|
257
221
|
let resolvedAppPath;
|
|
258
222
|
if (appPath) {
|
|
@@ -266,12 +230,12 @@ function getBuildIterator(appPath, watch) {
|
|
|
266
230
|
throw new Error(`Entry file ${entry} does not exist`);
|
|
267
231
|
}
|
|
268
232
|
const appFilePath = realpathSync2(resolvedAppPath);
|
|
269
|
-
|
|
270
|
-
external: ["@hono/node-server"]
|
|
271
|
-
watch
|
|
233
|
+
const app = await buildAndImportApp(appFilePath, {
|
|
234
|
+
external: ["@hono/node-server"]
|
|
272
235
|
});
|
|
273
|
-
|
|
274
|
-
|
|
236
|
+
if (!app || typeof app.request !== "function") {
|
|
237
|
+
throw new Error("No valid Hono app exported from the file");
|
|
238
|
+
}
|
|
275
239
|
const url = new URL(requestPath, "http://localhost");
|
|
276
240
|
const requestInit = {
|
|
277
241
|
method: options.method || "GET"
|
|
@@ -307,7 +271,11 @@ async function executeRequest(app, requestPath, options) {
|
|
|
307
271
|
function searchCommand(program2) {
|
|
308
272
|
program2.command("search").argument("<query>", "Search query for Hono documentation").option("-l, --limit <number>", "Number of results to show (default: 5)", (value) => {
|
|
309
273
|
const parsed = parseInt(value, 10);
|
|
310
|
-
if (isNaN(parsed) || parsed < 1
|
|
274
|
+
if (isNaN(parsed) || parsed < 1) {
|
|
275
|
+
throw new Error(`Limit must be a number between 1 and 20. Received: ${value}
|
|
276
|
+
`);
|
|
277
|
+
}
|
|
278
|
+
if (parsed > 20) {
|
|
311
279
|
console.warn("Limit must be a number between 1 and 20\n");
|
|
312
280
|
return 5;
|
|
313
281
|
}
|
|
@@ -502,7 +470,14 @@ var builtinMap = {
|
|
|
502
470
|
}
|
|
503
471
|
});
|
|
504
472
|
function serveCommand(program2) {
|
|
505
|
-
program2.command("serve").description("Start server").argument("[entry]", "entry file").option("-p, --port <port>", "port number"
|
|
473
|
+
program2.command("serve").description("Start server").argument("[entry]", "entry file").option("-p, --port <port>", "port number", (value) => {
|
|
474
|
+
const parsed = parseInt(value, 10);
|
|
475
|
+
if (!/^\d+$/.test(value) || parsed < 0 || parsed > 65535) {
|
|
476
|
+
throw new Error(`Port must be a number between 0 and 65535. Received: ${value}
|
|
477
|
+
`);
|
|
478
|
+
}
|
|
479
|
+
return parsed;
|
|
480
|
+
}).option("--show-routes", "show registered routes").option(
|
|
506
481
|
"--use <middleware>",
|
|
507
482
|
"use middleware",
|
|
508
483
|
(value, previous) => {
|
|
@@ -520,10 +495,9 @@ function serveCommand(program2) {
|
|
|
520
495
|
app = new Hono();
|
|
521
496
|
} else {
|
|
522
497
|
const appFilePath = realpathSync3(appPath);
|
|
523
|
-
|
|
498
|
+
app = await buildAndImportApp(appFilePath, {
|
|
524
499
|
external: ["@hono/node-server"]
|
|
525
500
|
});
|
|
526
|
-
app = (await buildIterator.next()).value;
|
|
527
501
|
}
|
|
528
502
|
}
|
|
529
503
|
const allFunctions = {};
|
|
@@ -556,7 +530,7 @@ function serveCommand(program2) {
|
|
|
556
530
|
serve(
|
|
557
531
|
{
|
|
558
532
|
fetch: baseApp.fetch,
|
|
559
|
-
port: options.port
|
|
533
|
+
port: options.port ?? 7070
|
|
560
534
|
},
|
|
561
535
|
(info) => {
|
|
562
536
|
console.log(`Listening on http://localhost:${info.port}`);
|