@hono/cli 0.1.3 → 0.1.5
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 +162 -115
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -70,114 +70,154 @@ 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
|
-
|
|
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 || []
|
|
73
|
+
async function* buildAndImportApp(filePath, options = {}) {
|
|
74
|
+
let resolveApp;
|
|
75
|
+
let appPromise;
|
|
76
|
+
const preparePromise = () => {
|
|
77
|
+
appPromise = new Promise((resolve4) => {
|
|
78
|
+
resolveApp = resolve4;
|
|
88
79
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
80
|
+
};
|
|
81
|
+
preparePromise();
|
|
82
|
+
const context2 = await esbuild.context({
|
|
83
|
+
entryPoints: [filePath],
|
|
84
|
+
sourcemap: options.sourcemap ?? false,
|
|
85
|
+
sourcesContent: false,
|
|
86
|
+
sourceRoot: process.cwd(),
|
|
87
|
+
bundle: true,
|
|
88
|
+
write: false,
|
|
89
|
+
format: "esm",
|
|
90
|
+
target: "node20",
|
|
91
|
+
jsx: "automatic",
|
|
92
|
+
jsxImportSource: "hono/jsx",
|
|
93
|
+
platform: "node",
|
|
94
|
+
external: options.external || [],
|
|
95
|
+
plugins: [
|
|
96
|
+
{
|
|
97
|
+
name: "watch",
|
|
98
|
+
setup(build2) {
|
|
99
|
+
build2.onEnd(async (result) => {
|
|
100
|
+
try {
|
|
101
|
+
let code = result.outputFiles?.[0]?.text || "";
|
|
102
|
+
if (options.sourcemap) {
|
|
103
|
+
code += `
|
|
104
|
+
//# sourceURL=file://${process.cwd()}/__hono_cli_bundle__.js`;
|
|
105
|
+
}
|
|
106
|
+
const dataUrl = `data:text/javascript;base64,${Buffer.from(code).toString("base64")}`;
|
|
107
|
+
const module = await import(dataUrl);
|
|
108
|
+
const app = module.default;
|
|
109
|
+
if (!app) {
|
|
110
|
+
throw new Error("Failed to build app");
|
|
111
|
+
}
|
|
112
|
+
if (!app || typeof app.request !== "function") {
|
|
113
|
+
throw new Error("No valid Hono app exported from the file");
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
resolveApp(app);
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error("Error building app", error);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
});
|
|
127
|
+
await context2.watch();
|
|
128
|
+
if (!options.watch) {
|
|
129
|
+
await context2.dispose();
|
|
96
130
|
}
|
|
131
|
+
do {
|
|
132
|
+
yield await appPromise;
|
|
133
|
+
preparePromise();
|
|
134
|
+
} while (options.watch);
|
|
97
135
|
}
|
|
98
136
|
|
|
99
137
|
// src/commands/optimize/index.ts
|
|
100
138
|
var DEFAULT_ENTRY_CANDIDATES = ["src/index.ts", "src/index.tsx", "src/index.js", "src/index.jsx"];
|
|
101
139
|
function optimizeCommand(program2) {
|
|
102
|
-
program2.command("optimize").description("Build optimized Hono class").argument("[entry]", "entry file").option("-o, --outfile [outfile]", "output file", "dist/index.js").option("-m, --minify", "minify output file").
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
let routerName;
|
|
115
|
-
let importStatement;
|
|
116
|
-
let assignRouterStatement;
|
|
117
|
-
try {
|
|
118
|
-
const serialized = serializeInitParams(
|
|
119
|
-
buildInitParams({
|
|
120
|
-
paths: app.routes.map(({ path }) => path)
|
|
121
|
-
})
|
|
122
|
-
);
|
|
123
|
-
const hasPreparedRegExpRouter = await new Promise((resolve4) => {
|
|
124
|
-
const child = execFile(process.execPath, [
|
|
125
|
-
"--input-type=module",
|
|
126
|
-
"-e",
|
|
127
|
-
"try { (await import('hono/router/reg-exp-router')).PreparedRegExpRouter && process.exit(0) } finally { process.exit(1) }"
|
|
128
|
-
]);
|
|
129
|
-
child.on("exit", (code) => {
|
|
130
|
-
resolve4(code === 0);
|
|
131
|
-
});
|
|
140
|
+
program2.command("optimize").description("Build optimized Hono class").argument("[entry]", "entry file").option("-o, --outfile [outfile]", "output file", "dist/index.js").option("-m, --minify", "minify output file").option("-t, --target [target]", "environment target (e.g., node24, deno2, es2024)", "node20").action(
|
|
141
|
+
async (entry, options) => {
|
|
142
|
+
if (!entry) {
|
|
143
|
+
entry = DEFAULT_ENTRY_CANDIDATES.find((entry2) => existsSync(entry2)) ?? DEFAULT_ENTRY_CANDIDATES[0];
|
|
144
|
+
}
|
|
145
|
+
const appPath = resolve(process.cwd(), entry);
|
|
146
|
+
if (!existsSync(appPath)) {
|
|
147
|
+
throw new Error(`Entry file ${entry} does not exist`);
|
|
148
|
+
}
|
|
149
|
+
const appFilePath = realpathSync(appPath);
|
|
150
|
+
const buildIterator = buildAndImportApp(appFilePath, {
|
|
151
|
+
external: ["@hono/node-server"]
|
|
132
152
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
153
|
+
const app = (await buildIterator.next()).value;
|
|
154
|
+
let routerName;
|
|
155
|
+
let importStatement;
|
|
156
|
+
let assignRouterStatement;
|
|
157
|
+
try {
|
|
158
|
+
const serialized = serializeInitParams(
|
|
159
|
+
buildInitParams({
|
|
160
|
+
paths: app.routes.map(({ path }) => path)
|
|
161
|
+
})
|
|
162
|
+
);
|
|
163
|
+
const hasPreparedRegExpRouter = await new Promise((resolve4) => {
|
|
164
|
+
const child = execFile(process.execPath, [
|
|
165
|
+
"--input-type=module",
|
|
166
|
+
"-e",
|
|
167
|
+
"try { (await import('hono/router/reg-exp-router')).PreparedRegExpRouter && process.exit(0) } finally { process.exit(1) }"
|
|
168
|
+
]);
|
|
169
|
+
child.on("exit", (code) => {
|
|
170
|
+
resolve4(code === 0);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
if (hasPreparedRegExpRouter) {
|
|
174
|
+
routerName = "PreparedRegExpRouter";
|
|
175
|
+
importStatement = "import { PreparedRegExpRouter } from 'hono/router/reg-exp-router'";
|
|
176
|
+
assignRouterStatement = `const routerParams = ${serialized}
|
|
137
177
|
this.router = new PreparedRegExpRouter(...routerParams)`;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
178
|
+
} else {
|
|
179
|
+
routerName = "RegExpRouter";
|
|
180
|
+
importStatement = "import { RegExpRouter } from 'hono/router/reg-exp-router'";
|
|
181
|
+
assignRouterStatement = "this.router = new RegExpRouter()";
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
routerName = "TrieRouter";
|
|
185
|
+
importStatement = "import { TrieRouter } from 'hono/router/trie-router'";
|
|
186
|
+
assignRouterStatement = "this.router = new TrieRouter()";
|
|
142
187
|
}
|
|
143
|
-
|
|
144
|
-
routerName
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
resolveDir: args.resolveDir
|
|
188
|
+
console.log("[Optimized]");
|
|
189
|
+
console.log(` Router: ${routerName}`);
|
|
190
|
+
const outfile = resolve(process.cwd(), options.outfile);
|
|
191
|
+
await esbuild2.build({
|
|
192
|
+
entryPoints: [appFilePath],
|
|
193
|
+
outfile,
|
|
194
|
+
bundle: true,
|
|
195
|
+
minify: options.minify,
|
|
196
|
+
format: "esm",
|
|
197
|
+
target: options.target,
|
|
198
|
+
platform: "node",
|
|
199
|
+
jsx: "automatic",
|
|
200
|
+
jsxImportSource: "hono/jsx",
|
|
201
|
+
plugins: [
|
|
202
|
+
{
|
|
203
|
+
name: "hono-optimize",
|
|
204
|
+
setup(build2) {
|
|
205
|
+
const honoPseudoImportPath = "hono-optimized-pseudo-import-path";
|
|
206
|
+
build2.onResolve({ filter: /^hono$/ }, async (args) => {
|
|
207
|
+
if (!args.importer) {
|
|
208
|
+
return void 0;
|
|
209
|
+
}
|
|
210
|
+
const resolved = await build2.resolve(args.path, {
|
|
211
|
+
kind: "import-statement",
|
|
212
|
+
resolveDir: args.resolveDir
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
path: join(dirname(resolved.path), honoPseudoImportPath)
|
|
216
|
+
};
|
|
173
217
|
});
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
});
|
|
178
|
-
build3.onLoad({ filter: new RegExp(`/${honoPseudoImportPath}$`) }, async () => {
|
|
179
|
-
return {
|
|
180
|
-
contents: `
|
|
218
|
+
build2.onLoad({ filter: new RegExp(`/${honoPseudoImportPath}$`) }, async () => {
|
|
219
|
+
return {
|
|
220
|
+
contents: `
|
|
181
221
|
import { HonoBase } from 'hono/hono-base'
|
|
182
222
|
${importStatement}
|
|
183
223
|
export class Hono extends HonoBase {
|
|
@@ -187,15 +227,16 @@ export class Hono extends HonoBase {
|
|
|
187
227
|
}
|
|
188
228
|
}
|
|
189
229
|
`
|
|
190
|
-
|
|
191
|
-
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
}
|
|
192
233
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
234
|
+
]
|
|
235
|
+
});
|
|
236
|
+
const outfileStat = statSync(outfile);
|
|
237
|
+
console.log(` Output: ${options.outfile} (${(outfileStat.size / 1024).toFixed(2)} KB)`);
|
|
238
|
+
}
|
|
239
|
+
);
|
|
199
240
|
}
|
|
200
241
|
|
|
201
242
|
// src/commands/request/index.ts
|
|
@@ -203,7 +244,7 @@ import { existsSync as existsSync2, realpathSync as realpathSync2 } from "fs";
|
|
|
203
244
|
import { resolve as resolve2 } from "path";
|
|
204
245
|
var DEFAULT_ENTRY_CANDIDATES2 = ["src/index.ts", "src/index.tsx", "src/index.js", "src/index.jsx"];
|
|
205
246
|
function requestCommand(program2) {
|
|
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(
|
|
247
|
+
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("-w, --watch", "Watch for changes and resend request", false).option(
|
|
207
248
|
"-H, --header <header>",
|
|
208
249
|
"Custom headers",
|
|
209
250
|
(value, previous) => {
|
|
@@ -212,11 +253,15 @@ function requestCommand(program2) {
|
|
|
212
253
|
[]
|
|
213
254
|
).action(async (file, options) => {
|
|
214
255
|
const path = options.path || "/";
|
|
215
|
-
const
|
|
216
|
-
|
|
256
|
+
const watch = options.watch;
|
|
257
|
+
const buildIterator = getBuildIterator(file, watch);
|
|
258
|
+
for await (const app of buildIterator) {
|
|
259
|
+
const result = await executeRequest(app, path, options);
|
|
260
|
+
console.log(JSON.stringify(result, null, 2));
|
|
261
|
+
}
|
|
217
262
|
});
|
|
218
263
|
}
|
|
219
|
-
|
|
264
|
+
function getBuildIterator(appPath, watch) {
|
|
220
265
|
let entry;
|
|
221
266
|
let resolvedAppPath;
|
|
222
267
|
if (appPath) {
|
|
@@ -230,12 +275,13 @@ async function executeRequest(appPath, requestPath, options) {
|
|
|
230
275
|
throw new Error(`Entry file ${entry} does not exist`);
|
|
231
276
|
}
|
|
232
277
|
const appFilePath = realpathSync2(resolvedAppPath);
|
|
233
|
-
|
|
234
|
-
external: ["@hono/node-server"]
|
|
278
|
+
return buildAndImportApp(appFilePath, {
|
|
279
|
+
external: ["@hono/node-server"],
|
|
280
|
+
watch,
|
|
281
|
+
sourcemap: true
|
|
235
282
|
});
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
283
|
+
}
|
|
284
|
+
async function executeRequest(app, requestPath, options) {
|
|
239
285
|
const url = new URL(requestPath, "http://localhost");
|
|
240
286
|
const requestInit = {
|
|
241
287
|
method: options.method || "GET"
|
|
@@ -495,9 +541,10 @@ function serveCommand(program2) {
|
|
|
495
541
|
app = new Hono();
|
|
496
542
|
} else {
|
|
497
543
|
const appFilePath = realpathSync3(appPath);
|
|
498
|
-
|
|
544
|
+
const buildIterator = buildAndImportApp(appFilePath, {
|
|
499
545
|
external: ["@hono/node-server"]
|
|
500
546
|
});
|
|
547
|
+
app = (await buildIterator.next()).value;
|
|
501
548
|
}
|
|
502
549
|
}
|
|
503
550
|
const allFunctions = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hono/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hono": "dist/cli.js"
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@types/node": "^24.7.0",
|
|
44
44
|
"eslint": "^9.37.0",
|
|
45
45
|
"np": "^10.2.0",
|
|
46
|
+
"pkg-pr-new": "^0.0.62",
|
|
46
47
|
"prettier": "^3.6.2",
|
|
47
48
|
"publint": "^0.3.14",
|
|
48
49
|
"tsup": "^8.5.0",
|