@evjs/cli 0.0.28 → 0.0.30

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 CHANGED
@@ -7,7 +7,28 @@ import { Command } from "commander";
7
7
  import { build, dev } from "./index.js";
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
  await configure({
10
- sinks: { console: getConsoleSink() },
10
+ sinks: {
11
+ console: getConsoleSink({
12
+ formatter: (record) => {
13
+ const time = new Date(record.timestamp).toLocaleTimeString("en-US", {
14
+ hour12: false,
15
+ });
16
+ const levelColor = record.level === "info"
17
+ ? "\x1b[36m"
18
+ : record.level === "warning"
19
+ ? "\x1b[33m"
20
+ : record.level === "error" || record.level === "fatal"
21
+ ? "\x1b[31m"
22
+ : "\x1b[32m";
23
+ const reset = "\x1b[0m";
24
+ const cat = record.category[1]
25
+ ? `\x1b[90m[${record.category[1]}]\x1b[0m `
26
+ : "";
27
+ const msg = record.message.map(String).join("");
28
+ return `${levelColor}${time}${reset} ${cat}${msg}\n`;
29
+ },
30
+ }),
31
+ },
11
32
  loggers: [
12
33
  { category: ["logtape", "meta"], lowestLevel: "warning" },
13
34
  { category: ["evjs"], sinks: ["console"], lowestLevel: "info" },
package/dist/index.js CHANGED
@@ -99,10 +99,21 @@ export async function dev(userConfig, options) {
99
99
  // Run buildStart hooks
100
100
  await runBuildStartHooks(hooks);
101
101
  const bundler = await getBundlerAdapter(config);
102
+ // Validate HTML files exist
103
+ if (config.pages) {
104
+ for (const [name, page] of Object.entries(config.pages)) {
105
+ if (!fs.existsSync(path.resolve(cwd, page.html))) {
106
+ throw new Error(`[evjs] MPA page "${name}" html template not found: ${page.html}`);
107
+ }
108
+ }
109
+ }
110
+ else if (!fs.existsSync(path.resolve(cwd, config.html))) {
111
+ throw new Error(`[evjs] HTML template not found: ${config.html}`);
112
+ }
102
113
  // Track the running API server process for lifecycle management.
103
114
  let apiProcess = null;
104
115
  let isFirstBuild = true;
105
- const handleServerBundleReady = () => {
116
+ const handleServerBundleReady = async () => {
106
117
  if (!config.serverEnabled)
107
118
  return;
108
119
  const manifestPath = path.resolve(cwd, "dist/server/manifest.json");
@@ -133,13 +144,19 @@ export async function dev(userConfig, options) {
133
144
  // Kill previous process before restarting (handles both first start and restarts)
134
145
  if (apiProcess) {
135
146
  logger.info `Restarting API server...`;
136
- apiProcess.kill();
147
+ const oldProcess = apiProcess;
137
148
  apiProcess = null;
149
+ oldProcess.kill();
150
+ try {
151
+ await Promise.race([
152
+ oldProcess.catch(() => { }),
153
+ new Promise((resolve) => setTimeout(resolve, 3000)),
154
+ ]);
155
+ }
156
+ catch { }
138
157
  }
139
158
  const serverPort = config?.server?.dev?.port ?? CONFIG_DEFAULTS.serverPort;
140
- const runtimeConfig = config?.server?.runtime ?? "node";
141
- const [runtime, ...runtimeExtraArgs] = runtimeConfig.split(/\s+/);
142
- logger.info `Server bundle detected, starting ${runtime} API...`;
159
+ logger.info `Server bundle detected, starting API...`;
143
160
  const bootstrapPath = path.resolve(cwd, "dist/server/_dev_start.cjs");
144
161
  try {
145
162
  const serverBundlePath = path.resolve(cwd, "dist/server", manifest.entry);
@@ -147,22 +164,13 @@ export async function dev(userConfig, options) {
147
164
  fs.mkdirSync(path.dirname(bootstrapPath), { recursive: true });
148
165
  }
149
166
  fs.writeFileSync(bootstrapPath, [
150
- `const bundle = require(${JSON.stringify(serverBundlePath)});`,
151
- `const app = bundle.app || bundle.createApp({ endpoint: ${JSON.stringify(config.server.endpoint)} });`,
167
+ `const handler = require(${JSON.stringify(serverBundlePath)}).default;`,
152
168
  `const { serve } = require("@evjs/server/node");`,
153
- `serve(app, { port: ${serverPort}, https: ${JSON.stringify(config.server.dev.https)} });`,
169
+ `serve({ fetch: handler }, { port: ${serverPort}, https: ${JSON.stringify(config.server.dev.https)} });`,
154
170
  ].join("\n"));
155
- // node gets --watch flags; other runtimes use their own args as-is
156
- const runtimeArgs = runtime === "node"
157
- ? [
158
- "--watch",
159
- "--watch-preserve-output",
160
- ...runtimeExtraArgs,
161
- bootstrapPath,
162
- ]
163
- : [...runtimeExtraArgs, bootstrapPath];
171
+ const runtimeArgs = [bootstrapPath];
164
172
  // Don't await execa here since it's a long-running watch process
165
- const child = execa(runtime, runtimeArgs, {
173
+ const child = execa("node", runtimeArgs, {
166
174
  stdio: "inherit",
167
175
  env: { ...process.env, NODE_ENV: "development" },
168
176
  });
@@ -197,6 +205,17 @@ export async function build(userConfig, options) {
197
205
  // Run buildStart hooks
198
206
  await runBuildStartHooks(hooks);
199
207
  const bundler = await getBundlerAdapter(config);
208
+ // Validate HTML files exist
209
+ if (config.pages) {
210
+ for (const [name, page] of Object.entries(config.pages)) {
211
+ if (!fs.existsSync(path.resolve(cwd, page.html))) {
212
+ throw new Error(`[evjs] MPA page "${name}" html template not found: ${page.html}`);
213
+ }
214
+ }
215
+ }
216
+ else if (!fs.existsSync(path.resolve(cwd, config.html))) {
217
+ throw new Error(`[evjs] HTML template not found: ${config.html}`);
218
+ }
200
219
  await bundler.build(config, cwd, hooks);
201
220
  // Run buildEnd hooks with manifests
202
221
  const buildResult = readBuildResult(cwd, config.serverEnabled, false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evjs/cli",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "CLI and configuration layer for the evjs framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",