@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 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
@@ -24,7 +24,7 @@ export const CONFIG_DEFAULTS = {
24
24
  * dev: { port: 3000 },
25
25
  * },
26
26
  * server: {
27
- * endpoint: "/api/fn",
27
+ * functions: { endpoint: "/api/fn" },
28
28
  * dev: { port: 3001 },
29
29
  * },
30
30
  * });
@@ -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 { fileURLToPath } from "node:url";
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
- * Load config and create webpack configuration object.
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
- logger.info `Using ${evjsConfig ? "ev.config.ts" : "convention-based defaults"}`;
37
- const webpackConfig = createWebpackConfig(evjsConfig, cwd);
38
- return { evjsConfig, webpackConfig };
15
+ return createWebpackConfig(config, cwd);
39
16
  }
40
- program
41
- .command("dev")
42
- .description("Start development server")
43
- .action(async () => {
44
- const cwd = process.cwd();
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 { evjsConfig, webpackConfig } = await resolveWebpackConfig(cwd);
47
- const serverPort = evjsConfig?.server?.dev?.port ?? CONFIG_DEFAULTS.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
- try {
50
- const webpack = esmRequire("webpack");
51
- const WebpackDevServer = esmRequire("webpack-dev-server");
52
- const compiler = webpack(webpackConfig);
53
- const devServerOptions = webpackConfig.devServer ?? {};
54
- const server = new WebpackDevServer(devServerOptions, compiler);
55
- await server.start();
56
- // Background: start Node API when server bundle is ready
57
- let apiStarted = false;
58
- compiler.hooks.done.tap("EvDevServer", async () => {
59
- if (apiStarted)
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
- const manifestPath = path.resolve(cwd, "dist/manifest.json");
62
- const bootstrapPath = path.resolve(cwd, "dist/server/_dev_start.cjs");
63
- if (fs.existsSync(manifestPath)) {
64
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
65
- // Start API server if there's a server entry
66
- if (!manifest.server?.entry)
67
- return;
68
- apiStarted = true;
69
- const backendConfig = evjsConfig?.server?.backend ?? "node";
70
- const [backend, ...backendExtraArgs] = backendConfig.split(/\s+/);
71
- logger.info `Server bundle detected, starting ${backend} API...`;
72
- try {
73
- const serverBundlePath = path.resolve(cwd, "dist/server", manifest.server.entry);
74
- fs.ensureDirSync(path.dirname(bootstrapPath));
75
- fs.writeFileSync(bootstrapPath, [
76
- `const bundle = require(${JSON.stringify(serverBundlePath)});`,
77
- `const app = bundle.app || bundle.createApp({ endpoint: ${JSON.stringify(evjsConfig?.server?.endpoint ?? CONFIG_DEFAULTS.endpoint)} });`,
78
- `const { serve } = require("@evjs/server/node");`,
79
- `serve(app, { port: ${serverPort} });`,
80
- ].join("\n"));
81
- // node gets --watch flags; other runtimes use their own args as-is
82
- const backendArgs = backend === "node"
83
- ? [
84
- "--watch",
85
- "--watch-preserve-output",
86
- ...backendExtraArgs,
87
- bootstrapPath,
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
- catch (err) {
106
- logger.error `Dev server failed to start: ${err}`;
107
- process.exit(1);
108
- }
109
- });
110
- program
111
- .command("build")
112
- .description("Build project for production")
113
- .action(async () => {
114
- const cwd = process.cwd();
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 { webpackConfig } = await resolveWebpackConfig(cwd);
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.1-rc.28",
3
+ "version": "0.0.3",
4
4
  "description": "CLI and configuration layer for the evjs framework",
5
5
  "type": "module",
6
- "main": "./dist/config.js",
7
- "types": "./dist/config.d.ts",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./dist/config.d.ts",
11
- "import": "./dist/config.js"
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/index.js"
18
+ "ev": "dist/cli.js"
19
19
  },
20
20
  "files": [
21
21
  "dist"