@evjs/cli 0.0.16 → 0.0.17
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 +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +80 -5
- package/dist/load-config.d.ts +2 -5
- package/dist/load-config.js +2 -22
- package/package.json +2 -4
package/dist/cli.js
CHANGED
|
@@ -26,7 +26,7 @@ program
|
|
|
26
26
|
.action(async () => {
|
|
27
27
|
const cwd = process.cwd();
|
|
28
28
|
const { loadConfig } = await import("./load-config.js");
|
|
29
|
-
const config = await loadConfig(cwd
|
|
29
|
+
const config = await loadConfig(cwd);
|
|
30
30
|
try {
|
|
31
31
|
await dev(config ?? undefined, { cwd });
|
|
32
32
|
}
|
|
@@ -41,7 +41,7 @@ program
|
|
|
41
41
|
.action(async () => {
|
|
42
42
|
const cwd = process.cwd();
|
|
43
43
|
const { loadConfig } = await import("./load-config.js");
|
|
44
|
-
const config = await loadConfig(cwd
|
|
44
|
+
const config = await loadConfig(cwd);
|
|
45
45
|
try {
|
|
46
46
|
await build(config ?? undefined, { cwd });
|
|
47
47
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CONFIG_DEFAULTS, defineConfig, type EvBundlerCtx, type EvConfig, type
|
|
2
|
-
export { CONFIG_DEFAULTS, type EvConfig, type
|
|
1
|
+
import { CONFIG_DEFAULTS, defineConfig, type EvBuildResult, type EvBundlerCtx, type EvConfig, type EvPlugin, type EvPluginContext, type EvPluginHooks, type ResolvedEvConfig, resolveConfig } from "@evjs/shared";
|
|
2
|
+
export { CONFIG_DEFAULTS, type EvConfig, type EvBuildResult, type EvBundlerCtx, type EvPlugin, type EvPluginContext, type EvPluginHooks, type ResolvedEvConfig, resolveConfig, defineConfig, };
|
|
3
3
|
export interface DevOptions {
|
|
4
4
|
cwd?: string;
|
|
5
5
|
}
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,60 @@ async function getBundlerAdapter(config) {
|
|
|
16
16
|
}
|
|
17
17
|
throw new Error(`Bundler '${bundlerName}' is not supported yet.`);
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Run plugin setup() hooks and collect lifecycle hooks.
|
|
21
|
+
*/
|
|
22
|
+
async function collectPluginHooks(plugins, ctx) {
|
|
23
|
+
const allHooks = [];
|
|
24
|
+
for (const plugin of plugins) {
|
|
25
|
+
if (plugin.setup) {
|
|
26
|
+
const hooks = await plugin.setup(ctx);
|
|
27
|
+
if (hooks) {
|
|
28
|
+
allHooks.push(hooks);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return allHooks;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run all buildStart hooks sequentially.
|
|
36
|
+
*/
|
|
37
|
+
async function runBuildStartHooks(hooks) {
|
|
38
|
+
for (const h of hooks) {
|
|
39
|
+
if (h.buildStart) {
|
|
40
|
+
await h.buildStart();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run all buildEnd hooks sequentially.
|
|
46
|
+
*/
|
|
47
|
+
async function runBuildEndHooks(hooks, result) {
|
|
48
|
+
for (const h of hooks) {
|
|
49
|
+
if (h.buildEnd) {
|
|
50
|
+
await h.buildEnd(result);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Read build manifests from disk.
|
|
56
|
+
*/
|
|
57
|
+
function readBuildResult(cwd, serverEnabled, isRebuild) {
|
|
58
|
+
const clientManifestPath = serverEnabled
|
|
59
|
+
? path.resolve(cwd, "dist/client/manifest.json")
|
|
60
|
+
: path.resolve(cwd, "dist/manifest.json");
|
|
61
|
+
if (!fs.existsSync(clientManifestPath))
|
|
62
|
+
return null;
|
|
63
|
+
const clientManifest = JSON.parse(fs.readFileSync(clientManifestPath, "utf-8"));
|
|
64
|
+
let serverManifest;
|
|
65
|
+
if (serverEnabled) {
|
|
66
|
+
const serverManifestPath = path.resolve(cwd, "dist/server/manifest.json");
|
|
67
|
+
if (fs.existsSync(serverManifestPath)) {
|
|
68
|
+
serverManifest = JSON.parse(fs.readFileSync(serverManifestPath, "utf-8"));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { clientManifest, serverManifest, isRebuild };
|
|
72
|
+
}
|
|
19
73
|
/**
|
|
20
74
|
* Start the development server programmatically.
|
|
21
75
|
*
|
|
@@ -26,10 +80,15 @@ export async function dev(userConfig, options) {
|
|
|
26
80
|
const config = resolveConfig(userConfig);
|
|
27
81
|
const cwd = options?.cwd ?? process.cwd();
|
|
28
82
|
process.env.NODE_ENV ??= "development";
|
|
83
|
+
// Collect plugin hooks
|
|
84
|
+
const pluginCtx = { mode: "development", config };
|
|
85
|
+
const hooks = await collectPluginHooks(config.plugins, pluginCtx);
|
|
86
|
+
// Run buildStart hooks
|
|
87
|
+
await runBuildStartHooks(hooks);
|
|
29
88
|
const bundler = await getBundlerAdapter(config);
|
|
30
89
|
// Track the running API server process for lifecycle management.
|
|
31
|
-
// Using a reference instead of a boolean allows proper restart on crash.
|
|
32
90
|
let apiProcess = null;
|
|
91
|
+
let isFirstBuild = true;
|
|
33
92
|
const handleServerBundleReady = () => {
|
|
34
93
|
if (!config.serverEnabled)
|
|
35
94
|
return;
|
|
@@ -43,6 +102,14 @@ export async function dev(userConfig, options) {
|
|
|
43
102
|
}
|
|
44
103
|
if (!manifest.entry)
|
|
45
104
|
return;
|
|
105
|
+
// Run buildEnd hooks with manifests
|
|
106
|
+
const buildResult = readBuildResult(cwd, config.serverEnabled, !isFirstBuild);
|
|
107
|
+
if (buildResult) {
|
|
108
|
+
runBuildEndHooks(hooks, buildResult).catch((err) => {
|
|
109
|
+
logger.error `Plugin buildEnd hook failed: ${err}`;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
isFirstBuild = false;
|
|
46
113
|
// Kill previous process before restarting (handles both first start and restarts)
|
|
47
114
|
if (apiProcess) {
|
|
48
115
|
logger.info `Restarting API server...`;
|
|
@@ -92,9 +159,7 @@ export async function dev(userConfig, options) {
|
|
|
92
159
|
apiProcess = null;
|
|
93
160
|
}
|
|
94
161
|
};
|
|
95
|
-
await bundler.dev(config, cwd, {
|
|
96
|
-
onServerBundleReady: handleServerBundleReady,
|
|
97
|
-
});
|
|
162
|
+
await bundler.dev(config, cwd, { onServerBundleReady: handleServerBundleReady }, hooks);
|
|
98
163
|
}
|
|
99
164
|
/**
|
|
100
165
|
* Run a production build programmatically.
|
|
@@ -106,6 +171,16 @@ export async function build(userConfig, options) {
|
|
|
106
171
|
const config = resolveConfig(userConfig);
|
|
107
172
|
const cwd = options?.cwd ?? process.cwd();
|
|
108
173
|
process.env.NODE_ENV ??= "production";
|
|
174
|
+
// Collect plugin hooks
|
|
175
|
+
const pluginCtx = { mode: "production", config };
|
|
176
|
+
const hooks = await collectPluginHooks(config.plugins, pluginCtx);
|
|
177
|
+
// Run buildStart hooks
|
|
178
|
+
await runBuildStartHooks(hooks);
|
|
109
179
|
const bundler = await getBundlerAdapter(config);
|
|
110
|
-
await bundler.build(config, cwd);
|
|
180
|
+
await bundler.build(config, cwd, hooks);
|
|
181
|
+
// Run buildEnd hooks with manifests
|
|
182
|
+
const buildResult = readBuildResult(cwd, config.serverEnabled, false);
|
|
183
|
+
if (buildResult) {
|
|
184
|
+
await runBuildEndHooks(hooks, buildResult);
|
|
185
|
+
}
|
|
111
186
|
}
|
package/dist/load-config.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type { EvConfig
|
|
1
|
+
import type { EvConfig } from "@evjs/shared";
|
|
2
2
|
/**
|
|
3
3
|
* Load evjs config from the project root.
|
|
4
4
|
*
|
|
5
5
|
* Looks for `ev.config.ts`, `.js`, or `.mjs` in the given directory.
|
|
6
6
|
* Returns undefined if no config file is found.
|
|
7
|
-
*
|
|
8
|
-
* After loading, all plugin `config` hooks are executed in order.
|
|
9
|
-
* If a plugin injects new plugins, their hooks are also executed.
|
|
10
7
|
*/
|
|
11
|
-
export declare function loadConfig(cwd: string
|
|
8
|
+
export declare function loadConfig(cwd: string): Promise<EvConfig | undefined>;
|
package/dist/load-config.js
CHANGED
|
@@ -6,33 +6,13 @@ const CONFIG_FILES = ["ev.config.ts", "ev.config.js", "ev.config.mjs"];
|
|
|
6
6
|
*
|
|
7
7
|
* Looks for `ev.config.ts`, `.js`, or `.mjs` in the given directory.
|
|
8
8
|
* Returns undefined if no config file is found.
|
|
9
|
-
*
|
|
10
|
-
* After loading, all plugin `config` hooks are executed in order.
|
|
11
|
-
* If a plugin injects new plugins, their hooks are also executed.
|
|
12
9
|
*/
|
|
13
|
-
export async function loadConfig(cwd
|
|
10
|
+
export async function loadConfig(cwd) {
|
|
14
11
|
for (const filename of CONFIG_FILES) {
|
|
15
12
|
const configPath = path.resolve(cwd, filename);
|
|
16
13
|
if (fs.existsSync(configPath)) {
|
|
17
14
|
const mod = await import(configPath);
|
|
18
|
-
|
|
19
|
-
// Execute plugin config hooks
|
|
20
|
-
const currentCtx = ctx ?? { mode: "development" };
|
|
21
|
-
const executedConfigHooks = new Set();
|
|
22
|
-
let hasNewPlugins = true;
|
|
23
|
-
while (hasNewPlugins) {
|
|
24
|
-
hasNewPlugins = false;
|
|
25
|
-
const allPlugins = config.plugins ?? [];
|
|
26
|
-
for (const plugin of allPlugins) {
|
|
27
|
-
if (plugin.config && !executedConfigHooks.has(plugin.name)) {
|
|
28
|
-
config = plugin.config(config, currentCtx) ?? config;
|
|
29
|
-
executedConfigHooks.add(plugin.name);
|
|
30
|
-
hasNewPlugins = true;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return config;
|
|
15
|
+
return mod.default ?? mod;
|
|
36
16
|
}
|
|
37
17
|
}
|
|
38
18
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evjs/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "CLI and configuration layer for the evjs framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,9 +32,7 @@
|
|
|
32
32
|
"@evjs/shared": "*",
|
|
33
33
|
"@logtape/logtape": "^2.0.4",
|
|
34
34
|
"commander": "^12.1.0",
|
|
35
|
-
"execa": "^9.6.1"
|
|
36
|
-
"glob": "^13.0.6",
|
|
37
|
-
"picocolors": "^1.1.1"
|
|
35
|
+
"execa": "^9.6.1"
|
|
38
36
|
},
|
|
39
37
|
"devDependencies": {
|
|
40
38
|
"@types/node": "^22.19.15",
|