@evjs/cli 0.0.1-rc.28 → 0.0.3
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 +52 -0
- package/dist/config.js +1 -1
- package/dist/create-webpack-config.js +3 -3
- package/dist/index.js +77 -101
- package/package.json +6 -6
package/dist/cli.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { configure, getConsoleSink } from "@logtape/logtape";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import { build, dev } from "./index.js";
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
await configure({
|
|
10
|
+
sinks: { console: getConsoleSink() },
|
|
11
|
+
loggers: [
|
|
12
|
+
{ category: ["logtape", "meta"], lowestLevel: "warning" },
|
|
13
|
+
{ category: ["evjs"], sinks: ["console"], lowestLevel: "info" },
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
const pkg = fs.readJsonSync(path.resolve(__dirname, "../package.json"));
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name("ev")
|
|
20
|
+
.description("CLI for the evjs framework")
|
|
21
|
+
.version(pkg.version);
|
|
22
|
+
program
|
|
23
|
+
.command("dev")
|
|
24
|
+
.description("Start development server")
|
|
25
|
+
.action(async () => {
|
|
26
|
+
const cwd = process.cwd();
|
|
27
|
+
const { loadConfig } = await import("./load-config.js");
|
|
28
|
+
const config = await loadConfig(cwd);
|
|
29
|
+
try {
|
|
30
|
+
await dev(config ?? undefined, { cwd });
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.error(err);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
program
|
|
38
|
+
.command("build")
|
|
39
|
+
.description("Build project for production")
|
|
40
|
+
.action(async () => {
|
|
41
|
+
const cwd = process.cwd();
|
|
42
|
+
const { loadConfig } = await import("./load-config.js");
|
|
43
|
+
const config = await loadConfig(cwd);
|
|
44
|
+
try {
|
|
45
|
+
await build(config ?? undefined, { cwd });
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error(err);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
program.parse();
|
package/dist/config.js
CHANGED
|
@@ -15,7 +15,7 @@ export function createWebpackConfig(config, cwd) {
|
|
|
15
15
|
const html = client?.html ?? CONFIG_DEFAULTS.html;
|
|
16
16
|
const clientPort = client?.dev?.port ?? CONFIG_DEFAULTS.clientPort;
|
|
17
17
|
const serverPort = server?.dev?.port ?? CONFIG_DEFAULTS.serverPort;
|
|
18
|
-
const endpoint = server?.endpoint ?? CONFIG_DEFAULTS.endpoint;
|
|
18
|
+
const endpoint = server?.functions?.endpoint ?? CONFIG_DEFAULTS.endpoint;
|
|
19
19
|
const isProduction = process.env.NODE_ENV === "production";
|
|
20
20
|
const HtmlWebpackPlugin = esmRequire("html-webpack-plugin");
|
|
21
21
|
const { EvWebpackPlugin } = esmRequire("@evjs/webpack-plugin");
|
|
@@ -74,8 +74,8 @@ export function createWebpackConfig(config, cwd) {
|
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
},
|
|
77
|
-
// Plugin-declared loaders
|
|
78
|
-
...(client?.plugins ?? []).flatMap((plugin) => (plugin.loaders ?? []).map((rule) => {
|
|
77
|
+
// Plugin-declared loaders (client + server)
|
|
78
|
+
...[...(client?.plugins ?? []), ...(server?.plugins ?? [])].flatMap((plugin) => (plugin.loaders ?? []).map((rule) => {
|
|
79
79
|
const entries = Array.isArray(rule.use) ? rule.use : [rule.use];
|
|
80
80
|
return {
|
|
81
81
|
test: rule.test,
|
package/dist/index.js
CHANGED
|
@@ -1,119 +1,96 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { createRequire } from "node:module";
|
|
3
2
|
import path from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
import { configure, getConsoleSink, getLogger } from "@logtape/logtape";
|
|
6
|
-
import { Command } from "commander";
|
|
3
|
+
import { getLogger } from "@logtape/logtape";
|
|
7
4
|
import { execa } from "execa";
|
|
8
5
|
import fs from "fs-extra";
|
|
9
6
|
import { CONFIG_DEFAULTS } from "./config.js";
|
|
7
|
+
export { CONFIG_DEFAULTS, defineConfig } from "./config.js";
|
|
10
8
|
const esmRequire = createRequire(import.meta.url);
|
|
11
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
await configure({
|
|
13
|
-
sinks: { console: getConsoleSink() },
|
|
14
|
-
loggers: [
|
|
15
|
-
{ category: ["logtape", "meta"], lowestLevel: "warning" },
|
|
16
|
-
{ category: ["evjs"], sinks: ["console"], lowestLevel: "info" },
|
|
17
|
-
],
|
|
18
|
-
});
|
|
19
9
|
const logger = getLogger(["evjs", "cli"]);
|
|
20
|
-
const pkg = fs.readJsonSync(path.resolve(__dirname, "../package.json"));
|
|
21
|
-
const program = new Command();
|
|
22
|
-
program
|
|
23
|
-
.name("ev")
|
|
24
|
-
.description("CLI for the evjs framework")
|
|
25
|
-
.version(pkg.version);
|
|
26
10
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* Uses ev.config.ts when present, otherwise falls back to convention-based defaults.
|
|
30
|
-
* No webpack.config.cjs fallback — the meta-framework owns the build config.
|
|
11
|
+
* Create webpack configuration from an EvConfig object.
|
|
31
12
|
*/
|
|
32
|
-
async function resolveWebpackConfig(cwd) {
|
|
33
|
-
const { loadConfig } = await import("./load-config.js");
|
|
34
|
-
const evjsConfig = await loadConfig(cwd);
|
|
13
|
+
async function resolveWebpackConfig(config, cwd) {
|
|
35
14
|
const { createWebpackConfig } = await import("./create-webpack-config.js");
|
|
36
|
-
|
|
37
|
-
const webpackConfig = createWebpackConfig(evjsConfig, cwd);
|
|
38
|
-
return { evjsConfig, webpackConfig };
|
|
15
|
+
return createWebpackConfig(config, cwd);
|
|
39
16
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Start the development server programmatically.
|
|
19
|
+
*
|
|
20
|
+
* @param config - evjs configuration object (from `defineConfig`)
|
|
21
|
+
* @param options - additional options like `cwd`
|
|
22
|
+
*/
|
|
23
|
+
export async function dev(config, options) {
|
|
24
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
45
25
|
process.env.NODE_ENV ??= "development";
|
|
46
|
-
const
|
|
47
|
-
const serverPort =
|
|
26
|
+
const webpackConfig = await resolveWebpackConfig(config, cwd);
|
|
27
|
+
const serverPort = config?.server?.dev?.port ?? CONFIG_DEFAULTS.serverPort;
|
|
48
28
|
logger.info `Starting development server...`;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
29
|
+
const webpack = esmRequire("webpack");
|
|
30
|
+
const WebpackDevServer = esmRequire("webpack-dev-server");
|
|
31
|
+
const compiler = webpack(webpackConfig);
|
|
32
|
+
const devServerOptions = webpackConfig.devServer ?? {};
|
|
33
|
+
const server = new WebpackDevServer(devServerOptions, compiler);
|
|
34
|
+
await server.start();
|
|
35
|
+
// Background: start Node API when server bundle is ready
|
|
36
|
+
let apiStarted = false;
|
|
37
|
+
compiler.hooks.done.tap("EvDevServer", async () => {
|
|
38
|
+
if (apiStarted)
|
|
39
|
+
return;
|
|
40
|
+
const manifestPath = path.resolve(cwd, "dist/manifest.json");
|
|
41
|
+
const bootstrapPath = path.resolve(cwd, "dist/server/_dev_start.cjs");
|
|
42
|
+
if (fs.existsSync(manifestPath)) {
|
|
43
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
44
|
+
// Start API server if there's a server entry
|
|
45
|
+
if (!manifest.server?.entry)
|
|
60
46
|
return;
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
]
|
|
89
|
-
: [...backendExtraArgs, bootstrapPath];
|
|
90
|
-
// Don't await execa here since it's a long-running watch process
|
|
91
|
-
execa(backend, backendArgs, {
|
|
92
|
-
stdio: "inherit",
|
|
93
|
-
env: { ...process.env, NODE_ENV: "development" },
|
|
94
|
-
}).catch(() => {
|
|
95
|
-
apiStarted = false;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
logger.error `Server backend failed: ${err}`;
|
|
47
|
+
apiStarted = true;
|
|
48
|
+
const backendConfig = config?.server?.backend ?? "node";
|
|
49
|
+
const [backend, ...backendExtraArgs] = backendConfig.split(/\s+/);
|
|
50
|
+
logger.info `Server bundle detected, starting ${backend} API...`;
|
|
51
|
+
try {
|
|
52
|
+
const serverBundlePath = path.resolve(cwd, "dist/server", manifest.server.entry);
|
|
53
|
+
fs.ensureDirSync(path.dirname(bootstrapPath));
|
|
54
|
+
fs.writeFileSync(bootstrapPath, [
|
|
55
|
+
`const bundle = require(${JSON.stringify(serverBundlePath)});`,
|
|
56
|
+
`const app = bundle.app || bundle.createApp({ endpoint: ${JSON.stringify(config?.server?.functions?.endpoint ?? CONFIG_DEFAULTS.endpoint)} });`,
|
|
57
|
+
`const { serve } = require("@evjs/server/node");`,
|
|
58
|
+
`serve(app, { port: ${serverPort}, https: ${Boolean(config?.server?.dev?.https)} });`,
|
|
59
|
+
].join("\n"));
|
|
60
|
+
// node gets --watch flags; other runtimes use their own args as-is
|
|
61
|
+
const backendArgs = backend === "node"
|
|
62
|
+
? [
|
|
63
|
+
"--watch",
|
|
64
|
+
"--watch-preserve-output",
|
|
65
|
+
...backendExtraArgs,
|
|
66
|
+
bootstrapPath,
|
|
67
|
+
]
|
|
68
|
+
: [...backendExtraArgs, bootstrapPath];
|
|
69
|
+
// Don't await execa here since it's a long-running watch process
|
|
70
|
+
execa(backend, backendArgs, {
|
|
71
|
+
stdio: "inherit",
|
|
72
|
+
env: { ...process.env, NODE_ENV: "development" },
|
|
73
|
+
}).catch(() => {
|
|
100
74
|
apiStarted = false;
|
|
101
|
-
}
|
|
75
|
+
});
|
|
102
76
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
77
|
+
catch (err) {
|
|
78
|
+
logger.error `Server backend failed: ${err}`;
|
|
79
|
+
apiStarted = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Run a production build programmatically.
|
|
86
|
+
*
|
|
87
|
+
* @param config - evjs configuration object (from `defineConfig`)
|
|
88
|
+
* @param options - additional options like `cwd`
|
|
89
|
+
*/
|
|
90
|
+
export async function build(config, options) {
|
|
91
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
115
92
|
process.env.NODE_ENV ??= "production";
|
|
116
|
-
const
|
|
93
|
+
const webpackConfig = await resolveWebpackConfig(config, cwd);
|
|
117
94
|
logger.info `Building for production...`;
|
|
118
95
|
const webpack = esmRequire("webpack");
|
|
119
96
|
const compiler = webpack(webpackConfig);
|
|
@@ -135,5 +112,4 @@ program
|
|
|
135
112
|
});
|
|
136
113
|
});
|
|
137
114
|
logger.info `Build complete!`;
|
|
138
|
-
}
|
|
139
|
-
program.parse();
|
|
115
|
+
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evjs/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "CLI and configuration layer for the evjs framework",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/
|
|
7
|
-
"types": "./dist/
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"types": "./dist/
|
|
11
|
-
"import": "./dist/
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
17
|
"bin": {
|
|
18
|
-
"ev": "dist/
|
|
18
|
+
"ev": "dist/cli.js"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist"
|