@eggjs/bin 8.0.2-beta.0 → 8.0.2-beta.10
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/README.md +52 -0
- package/dist/baseCommand.d.ts +1 -1
- package/dist/baseCommand.js +20 -4
- package/dist/commands/bundle.d.ts +20 -0
- package/dist/commands/bundle.js +99 -0
- package/dist/commands/cov.d.ts +9 -8
- package/dist/commands/dev.d.ts +5 -5
- package/dist/commands/dev.js +2 -8
- package/dist/commands/manifest.d.ts +22 -0
- package/dist/commands/manifest.js +108 -0
- package/dist/commands/test.d.ts +9 -8
- package/dist/commands/test.js +20 -8
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/scripts/manifest-generate.mjs +59 -0
- package/package.json +14 -8
- package/scripts/manifest-generate.mjs +59 -0
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ Add `egg-bin` to `package.json` scripts:
|
|
|
36
36
|
"test-local": "egg-bin test",
|
|
37
37
|
"test": "npm run lint -- --fix && npm run test-local",
|
|
38
38
|
"cov": "egg-bin cov",
|
|
39
|
+
"bundle": "egg-bin bundle",
|
|
39
40
|
"lint": "eslint .",
|
|
40
41
|
"ci": "npm run lint && npm run cov"
|
|
41
42
|
}
|
|
@@ -183,6 +184,57 @@ You can set `COV_EXCLUDES` env to add glob patterns to exclude from coverage (co
|
|
|
183
184
|
COV_EXCLUDES="app/plugins/c*,app/autocreate/**" egg-bin cov
|
|
184
185
|
```
|
|
185
186
|
|
|
187
|
+
### bundle
|
|
188
|
+
|
|
189
|
+
Bundle an Egg application into a deployable artifact with `@eggjs/egg-bundler`.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
egg-bin bundle
|
|
193
|
+
egg-bin bundle --output ./dist-bundle
|
|
194
|
+
egg-bin bundle --mode development
|
|
195
|
+
egg-bin bundle --framework egg --output ./out
|
|
196
|
+
egg-bin bundle --pack-alias some-package=./node_modules/some-package/index.js
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The command writes the bundle to `./dist-bundle` by default. The generated
|
|
200
|
+
artifact can be started with Node from the output directory:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
cd dist-bundle
|
|
204
|
+
node worker.js
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### bundle options
|
|
208
|
+
|
|
209
|
+
- `--output` / `-o` output directory, default to `./dist-bundle`
|
|
210
|
+
- `--manifest` path to `manifest.json`, default to `<baseDir>/.egg/manifest.json`
|
|
211
|
+
- `--framework` / `-f` framework package specifier, defaulting to
|
|
212
|
+
`package.json#egg.framework` or `egg`. Absolute framework paths are not
|
|
213
|
+
supported by the bundled runtime.
|
|
214
|
+
- `--mode` build mode, `production` or `development`, default to `production`
|
|
215
|
+
- `--force-external` package name to always keep external, supports multiple
|
|
216
|
+
- `--inline-external` package name to force inline, supports multiple
|
|
217
|
+
- `--pack-alias` `@utoo/pack` resolve alias in `<specifier>=<target>` form,
|
|
218
|
+
supports multiple. Dot-relative targets such as `./target.js` and
|
|
219
|
+
`../target.js` are resolved from the application base directory
|
|
220
|
+
|
|
221
|
+
Bundle aliases can also be committed in the application `module.yml`:
|
|
222
|
+
|
|
223
|
+
```yaml
|
|
224
|
+
bundle:
|
|
225
|
+
pack:
|
|
226
|
+
resolve:
|
|
227
|
+
alias:
|
|
228
|
+
some-package: ./node_modules/some-package/index.js
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`module.yml` aliases use the same target resolution rules as `--pack-alias`.
|
|
232
|
+
If the same alias is configured in both places, the explicit CLI
|
|
233
|
+
`--pack-alias` value wins.
|
|
234
|
+
|
|
235
|
+
See [`@eggjs/egg-bundler`](../egg-bundler/README.md) for the programmatic API
|
|
236
|
+
and output structure.
|
|
237
|
+
|
|
186
238
|
## Breaking Changes (v8)
|
|
187
239
|
|
|
188
240
|
### Migrated from Mocha to Vitest
|
package/dist/baseCommand.d.ts
CHANGED
|
@@ -32,7 +32,6 @@ declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
|
32
32
|
protected args: Args$1<T>;
|
|
33
33
|
protected env: {
|
|
34
34
|
[key: string]: string | undefined;
|
|
35
|
-
TZ?: string | undefined;
|
|
36
35
|
};
|
|
37
36
|
protected pkg: Record<string, any>;
|
|
38
37
|
protected isESM: boolean;
|
|
@@ -46,6 +45,7 @@ declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
|
46
45
|
protected formatRequires(): Promise<string[]>;
|
|
47
46
|
protected formatImportModule(modulePath: string): string;
|
|
48
47
|
protected addNodeOptions(options: string): void;
|
|
48
|
+
protected buildRequiresExecArgv(): Promise<string[]>;
|
|
49
49
|
protected forkNode(modulePath: string, forkArgs: string[], options?: ForkNodeOptions): Promise<void>;
|
|
50
50
|
}
|
|
51
51
|
//#endregion
|
package/dist/baseCommand.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getSourceDirname, hasTsConfig, readPackageJSON } from "./utils.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { fork } from "node:child_process";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { pathToFileURL } from "node:url";
|
|
6
7
|
import { debuglog } from "node:util";
|
|
7
|
-
import { importResolve } from "@eggjs/utils";
|
|
8
8
|
import { Command, Flags, Interfaces } from "@oclif/core";
|
|
9
9
|
|
|
10
10
|
//#region src/baseCommand.ts
|
|
@@ -162,20 +162,26 @@ var BaseCommand = class extends Command {
|
|
|
162
162
|
let rootDir = path.dirname(getSourceDirname());
|
|
163
163
|
if (path.basename(rootDir) === "dist") rootDir = path.dirname(rootDir);
|
|
164
164
|
const findPaths = [flags.base, rootDir];
|
|
165
|
+
const cjsResolve = (specifier) => {
|
|
166
|
+
for (const p of findPaths) try {
|
|
167
|
+
return createRequire(path.join(p, "package.json")).resolve(specifier);
|
|
168
|
+
} catch {}
|
|
169
|
+
throw new Error(`Cannot resolve '${specifier}' from ${findPaths.join(", ")}`);
|
|
170
|
+
};
|
|
165
171
|
this.isESM = pkg.type === "module";
|
|
166
172
|
if (typescript) {
|
|
167
173
|
flags.tscompiler = flags.tscompiler ?? "ts-node/register";
|
|
168
|
-
const tsNodeRegister =
|
|
174
|
+
const tsNodeRegister = cjsResolve(flags.tscompiler);
|
|
169
175
|
flags.tscompiler = tsNodeRegister;
|
|
170
176
|
this.addNodeOptions(this.formatImportModule(tsNodeRegister));
|
|
171
177
|
this.env.EGG_TYPESCRIPT = "true";
|
|
172
178
|
process.env.EGG_TYPESCRIPT = "true";
|
|
173
179
|
this.env.TS_NODE_FILES = process.env.TS_NODE_FILES ?? "true";
|
|
174
|
-
const tsConfigPathsRegister =
|
|
180
|
+
const tsConfigPathsRegister = cjsResolve("tsconfig-paths/register");
|
|
175
181
|
this.addNodeOptions(this.formatImportModule(tsConfigPathsRegister));
|
|
176
182
|
}
|
|
177
183
|
if (this.isESM) {
|
|
178
|
-
let esmLoader =
|
|
184
|
+
let esmLoader = cjsResolve("ts-node/esm");
|
|
179
185
|
esmLoader = pathToFileURL(esmLoader).href;
|
|
180
186
|
this.addNodeOptions("--no-warnings");
|
|
181
187
|
this.addNodeOptions(`--loader ${esmLoader}`);
|
|
@@ -235,6 +241,16 @@ var BaseCommand = class extends Command {
|
|
|
235
241
|
if (!this.env.NODE_OPTIONS.includes(options)) this.env.NODE_OPTIONS = `${this.env.NODE_OPTIONS} ${options}`;
|
|
236
242
|
} else this.env.NODE_OPTIONS = options;
|
|
237
243
|
}
|
|
244
|
+
async buildRequiresExecArgv() {
|
|
245
|
+
const requires = await this.formatRequires();
|
|
246
|
+
const execArgv = [];
|
|
247
|
+
for (const r of requires) {
|
|
248
|
+
const module = this.formatImportModule(r);
|
|
249
|
+
const splitIndex = module.indexOf(" ");
|
|
250
|
+
if (splitIndex !== -1) execArgv.push(module.slice(0, splitIndex), module.slice(splitIndex + 2, -1));
|
|
251
|
+
}
|
|
252
|
+
return execArgv;
|
|
253
|
+
}
|
|
238
254
|
async forkNode(modulePath, forkArgs, options = {}) {
|
|
239
255
|
const env = {
|
|
240
256
|
...this.env,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
+
import * as _oclif_core_interfaces18 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/bundle.d.ts
|
|
5
|
+
declare class Bundle extends BaseCommand<typeof Bundle> {
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
output: _oclif_core_interfaces18.OptionFlag<string, _oclif_core_interfaces18.CustomOptions>;
|
|
10
|
+
manifest: _oclif_core_interfaces18.OptionFlag<string | undefined, _oclif_core_interfaces18.CustomOptions>;
|
|
11
|
+
framework: _oclif_core_interfaces18.OptionFlag<string | undefined, _oclif_core_interfaces18.CustomOptions>;
|
|
12
|
+
mode: _oclif_core_interfaces18.OptionFlag<string, _oclif_core_interfaces18.CustomOptions>;
|
|
13
|
+
'force-external': _oclif_core_interfaces18.OptionFlag<string[], _oclif_core_interfaces18.CustomOptions>;
|
|
14
|
+
'inline-external': _oclif_core_interfaces18.OptionFlag<string[], _oclif_core_interfaces18.CustomOptions>;
|
|
15
|
+
'pack-alias': _oclif_core_interfaces18.OptionFlag<string[], _oclif_core_interfaces18.CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Bundle as default };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
import { Flags } from "@oclif/core";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
|
|
7
|
+
//#region src/commands/bundle.ts
|
|
8
|
+
const debug = debuglog("egg/bin/commands/bundle");
|
|
9
|
+
const bundleModes = ["production", "development"];
|
|
10
|
+
function getBundleMode(mode) {
|
|
11
|
+
if (mode === "production" || mode === "development") return mode;
|
|
12
|
+
throw new Error(`Unsupported bundle mode: ${mode}`);
|
|
13
|
+
}
|
|
14
|
+
function parsePackAliases(values, baseDir) {
|
|
15
|
+
if (values.length === 0) return void 0;
|
|
16
|
+
const alias = {};
|
|
17
|
+
for (const value of values) {
|
|
18
|
+
const separator = value.indexOf("=");
|
|
19
|
+
if (separator <= 0 || separator === value.length - 1) throw new Error(`Invalid --pack-alias value: ${value}. Expected <specifier>=<target>.`);
|
|
20
|
+
const specifier = value.slice(0, separator);
|
|
21
|
+
const target = value.slice(separator + 1);
|
|
22
|
+
alias[specifier] = target.startsWith(".") ? path.resolve(baseDir, target) : target;
|
|
23
|
+
}
|
|
24
|
+
return alias;
|
|
25
|
+
}
|
|
26
|
+
async function getBundleFrameworkSpecifier(baseDir, framework) {
|
|
27
|
+
if (framework) return framework;
|
|
28
|
+
const pkgPath = path.join(baseDir, "package.json");
|
|
29
|
+
const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8"));
|
|
30
|
+
return typeof pkg.egg?.framework === "string" && pkg.egg.framework ? pkg.egg.framework : "egg";
|
|
31
|
+
}
|
|
32
|
+
var Bundle = class extends BaseCommand {
|
|
33
|
+
static description = "Bundle an egg app into a deployable artifact using @eggjs/egg-bundler";
|
|
34
|
+
static examples = [
|
|
35
|
+
"<%= config.bin %> <%= command.id %>",
|
|
36
|
+
"<%= config.bin %> <%= command.id %> --output ./dist-bundle",
|
|
37
|
+
"<%= config.bin %> <%= command.id %> --mode development",
|
|
38
|
+
"<%= config.bin %> <%= command.id %> --framework egg --output ./out",
|
|
39
|
+
"<%= config.bin %> <%= command.id %> --pack-alias some-package=./node_modules/some-package/index.js"
|
|
40
|
+
];
|
|
41
|
+
static flags = {
|
|
42
|
+
output: Flags.string({
|
|
43
|
+
char: "o",
|
|
44
|
+
description: "output directory for the bundled artifact",
|
|
45
|
+
default: "./dist-bundle"
|
|
46
|
+
}),
|
|
47
|
+
manifest: Flags.string({ description: "path to manifest.json (defaults to <baseDir>/.egg/manifest.json)" }),
|
|
48
|
+
framework: Flags.string({
|
|
49
|
+
char: "f",
|
|
50
|
+
description: "framework package specifier"
|
|
51
|
+
}),
|
|
52
|
+
mode: Flags.string({
|
|
53
|
+
description: "build mode",
|
|
54
|
+
options: [...bundleModes],
|
|
55
|
+
default: "production"
|
|
56
|
+
}),
|
|
57
|
+
"force-external": Flags.string({
|
|
58
|
+
description: "package name to always mark as external (repeatable)",
|
|
59
|
+
multiple: true,
|
|
60
|
+
default: []
|
|
61
|
+
}),
|
|
62
|
+
"inline-external": Flags.string({
|
|
63
|
+
description: "package name to force-inline even if auto-detected as external (repeatable)",
|
|
64
|
+
multiple: true,
|
|
65
|
+
default: []
|
|
66
|
+
}),
|
|
67
|
+
"pack-alias": Flags.string({
|
|
68
|
+
description: "@utoo/pack resolve alias in <specifier>=<target> form, dot-relative targets resolve from --base",
|
|
69
|
+
multiple: true,
|
|
70
|
+
default: []
|
|
71
|
+
})
|
|
72
|
+
};
|
|
73
|
+
async run() {
|
|
74
|
+
const { flags } = this;
|
|
75
|
+
const baseDir = flags.base;
|
|
76
|
+
const outputDir = path.isAbsolute(flags.output) ? flags.output : path.join(baseDir, flags.output);
|
|
77
|
+
const manifestPath = flags.manifest ? path.isAbsolute(flags.manifest) ? flags.manifest : path.join(baseDir, flags.manifest) : void 0;
|
|
78
|
+
debug("bundle: baseDir=%s, outputDir=%s, framework=%s, mode=%s", baseDir, outputDir, flags.framework, flags.mode);
|
|
79
|
+
const { bundle } = await import("@eggjs/egg-bundler");
|
|
80
|
+
const packAlias = parsePackAliases(flags["pack-alias"], baseDir);
|
|
81
|
+
const result = await bundle({
|
|
82
|
+
baseDir,
|
|
83
|
+
outputDir,
|
|
84
|
+
manifestPath,
|
|
85
|
+
framework: await getBundleFrameworkSpecifier(baseDir, flags.framework),
|
|
86
|
+
mode: getBundleMode(flags.mode),
|
|
87
|
+
externals: {
|
|
88
|
+
force: flags["force-external"],
|
|
89
|
+
inline: flags["inline-external"]
|
|
90
|
+
},
|
|
91
|
+
...packAlias ? { pack: { resolve: { alias: packAlias } } } : {}
|
|
92
|
+
});
|
|
93
|
+
this.log(`bundled to ${result.outputDir} (${result.files.length} files)`);
|
|
94
|
+
this.log(`manifest: ${result.manifestPath}`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
export { Bundle as default };
|
package/dist/commands/cov.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import Test from "./test.js";
|
|
2
2
|
import { InlineConfig } from "vitest/node";
|
|
3
|
-
import * as
|
|
3
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
4
4
|
|
|
5
5
|
//#region src/commands/cov.d.ts
|
|
6
6
|
declare class Cov<T extends typeof Cov> extends Test<T> {
|
|
7
7
|
static description: string;
|
|
8
8
|
static examples: string[];
|
|
9
9
|
static flags: {
|
|
10
|
-
exclude:
|
|
11
|
-
bail:
|
|
12
|
-
timeout:
|
|
13
|
-
'no-timeout':
|
|
14
|
-
grep:
|
|
15
|
-
changed:
|
|
16
|
-
watch:
|
|
10
|
+
exclude: _oclif_core_interfaces0.OptionFlag<string[] | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
11
|
+
bail: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
12
|
+
timeout: _oclif_core_interfaces0.OptionFlag<number, _oclif_core_interfaces0.CustomOptions>;
|
|
13
|
+
'no-timeout': _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
14
|
+
grep: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
15
|
+
changed: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
16
|
+
watch: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
17
|
+
pool: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
17
18
|
};
|
|
18
19
|
protected get defaultCoverageExcludes(): string[];
|
|
19
20
|
/**
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _oclif_core_interfaces32 from "@oclif/core/interfaces";
|
|
3
3
|
|
|
4
4
|
//#region src/commands/dev.d.ts
|
|
5
5
|
declare class Dev<T extends typeof Dev> extends BaseCommand<T> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static examples: string[];
|
|
8
8
|
static flags: {
|
|
9
|
-
port:
|
|
10
|
-
workers:
|
|
11
|
-
framework:
|
|
12
|
-
sticky:
|
|
9
|
+
port: _oclif_core_interfaces32.OptionFlag<number | undefined, _oclif_core_interfaces32.CustomOptions>;
|
|
10
|
+
workers: _oclif_core_interfaces32.OptionFlag<number, _oclif_core_interfaces32.CustomOptions>;
|
|
11
|
+
framework: _oclif_core_interfaces32.OptionFlag<string | undefined, _oclif_core_interfaces32.CustomOptions>;
|
|
12
|
+
sticky: _oclif_core_interfaces32.BooleanFlag<boolean>;
|
|
13
13
|
};
|
|
14
14
|
run(): Promise<void>;
|
|
15
15
|
protected formatEggStartOptions(): Promise<{
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getSourceFilename } from "../utils.js";
|
|
2
2
|
import { BaseCommand } from "../baseCommand.js";
|
|
3
3
|
import { debuglog } from "node:util";
|
|
4
|
-
import { getFrameworkPath } from "@eggjs/utils";
|
|
5
4
|
import { Flags } from "@oclif/core";
|
|
5
|
+
import { getFrameworkPath } from "@eggjs/utils";
|
|
6
6
|
import { detect } from "detect-port";
|
|
7
7
|
|
|
8
8
|
//#region src/commands/dev.ts
|
|
@@ -31,13 +31,7 @@ var Dev = class extends BaseCommand {
|
|
|
31
31
|
const serverBin = getSourceFilename(`../scripts/start-cluster.${this.isESM ? "mjs" : "cjs"}`);
|
|
32
32
|
const eggStartOptions = await this.formatEggStartOptions();
|
|
33
33
|
const args = [JSON.stringify(eggStartOptions)];
|
|
34
|
-
const
|
|
35
|
-
const execArgv = [];
|
|
36
|
-
for (const r of requires) {
|
|
37
|
-
const module = this.formatImportModule(r);
|
|
38
|
-
const splitIndex = module.indexOf(" ");
|
|
39
|
-
if (splitIndex !== -1) execArgv.push(module.slice(0, splitIndex), module.slice(splitIndex + 2, -1));
|
|
40
|
-
}
|
|
34
|
+
const execArgv = await this.buildRequiresExecArgv();
|
|
41
35
|
await this.forkNode(serverBin, args, { execArgv });
|
|
42
36
|
}
|
|
43
37
|
async formatEggStartOptions() {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
2
|
+
import * as _oclif_core_interfaces11 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/manifest.d.ts
|
|
5
|
+
declare class Manifest<T extends typeof Manifest> extends BaseCommand<T> {
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static args: {
|
|
9
|
+
action: _oclif_core_interfaces11.Arg<string, Record<string, unknown>>;
|
|
10
|
+
};
|
|
11
|
+
static flags: {
|
|
12
|
+
framework: _oclif_core_interfaces11.OptionFlag<string | undefined, _oclif_core_interfaces11.CustomOptions>;
|
|
13
|
+
env: _oclif_core_interfaces11.OptionFlag<string, _oclif_core_interfaces11.CustomOptions>;
|
|
14
|
+
scope: _oclif_core_interfaces11.OptionFlag<string, _oclif_core_interfaces11.CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
private runGenerate;
|
|
18
|
+
private runValidate;
|
|
19
|
+
private runClean;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Manifest as default };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { getSourceFilename } from "../utils.js";
|
|
2
|
+
import { BaseCommand } from "../baseCommand.js";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
import { Args, Flags } from "@oclif/core";
|
|
5
|
+
import { getFrameworkPath } from "@eggjs/utils";
|
|
6
|
+
|
|
7
|
+
//#region src/commands/manifest.ts
|
|
8
|
+
const debug = debuglog("egg/bin/commands/manifest");
|
|
9
|
+
var Manifest = class extends BaseCommand {
|
|
10
|
+
static description = "Manage the startup manifest for faster cold starts";
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %> generate",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> generate --env=prod",
|
|
14
|
+
"<%= config.bin %> <%= command.id %> validate --env=prod",
|
|
15
|
+
"<%= config.bin %> <%= command.id %> clean"
|
|
16
|
+
];
|
|
17
|
+
static args = { action: Args.string({
|
|
18
|
+
required: true,
|
|
19
|
+
description: "Action to perform",
|
|
20
|
+
options: [
|
|
21
|
+
"generate",
|
|
22
|
+
"validate",
|
|
23
|
+
"clean"
|
|
24
|
+
]
|
|
25
|
+
}) };
|
|
26
|
+
static flags = {
|
|
27
|
+
framework: Flags.string({ description: "specify framework that can be absolute path or npm package" }),
|
|
28
|
+
env: Flags.string({
|
|
29
|
+
description: "server environment for manifest generation/validation",
|
|
30
|
+
default: "prod"
|
|
31
|
+
}),
|
|
32
|
+
scope: Flags.string({
|
|
33
|
+
description: "server scope for manifest validation",
|
|
34
|
+
default: ""
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
async run() {
|
|
38
|
+
const { action } = this.args;
|
|
39
|
+
switch (action) {
|
|
40
|
+
case "generate":
|
|
41
|
+
await this.runGenerate();
|
|
42
|
+
break;
|
|
43
|
+
case "validate":
|
|
44
|
+
await this.runValidate();
|
|
45
|
+
break;
|
|
46
|
+
case "clean":
|
|
47
|
+
await this.runClean();
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async runGenerate() {
|
|
52
|
+
const { flags } = this;
|
|
53
|
+
const framework = getFrameworkPath({
|
|
54
|
+
framework: flags.framework,
|
|
55
|
+
baseDir: flags.base
|
|
56
|
+
});
|
|
57
|
+
debug("generate manifest: baseDir=%s, framework=%s, env=%s, scope=%s", flags.base, framework, flags.env, flags.scope);
|
|
58
|
+
const options = {
|
|
59
|
+
baseDir: flags.base,
|
|
60
|
+
framework,
|
|
61
|
+
env: flags.env,
|
|
62
|
+
scope: flags.scope
|
|
63
|
+
};
|
|
64
|
+
const serverBin = getSourceFilename("../scripts/manifest-generate.mjs");
|
|
65
|
+
const args = [JSON.stringify(options)];
|
|
66
|
+
const execArgv = await this.buildRequiresExecArgv();
|
|
67
|
+
await this.forkNode(serverBin, args, { execArgv });
|
|
68
|
+
}
|
|
69
|
+
async runValidate() {
|
|
70
|
+
const { flags } = this;
|
|
71
|
+
debug("validate manifest: baseDir=%s, env=%s, scope=%s", flags.base, flags.env, flags.scope);
|
|
72
|
+
const savedEggManifest = process.env.EGG_MANIFEST;
|
|
73
|
+
process.env.EGG_MANIFEST = "true";
|
|
74
|
+
try {
|
|
75
|
+
const { ManifestStore } = await import("@eggjs/core");
|
|
76
|
+
const store = ManifestStore.load(flags.base, flags.env, flags.scope);
|
|
77
|
+
if (!store) {
|
|
78
|
+
console.error("[manifest] Manifest is invalid or does not exist");
|
|
79
|
+
return this.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const { data } = store;
|
|
82
|
+
const resolveCacheCount = Object.keys(data.resolveCache ?? {}).length;
|
|
83
|
+
const fileDiscoveryCount = Object.keys(data.fileDiscovery ?? {}).length;
|
|
84
|
+
const extensionCount = Object.keys(data.extensions ?? {}).length;
|
|
85
|
+
console.log("[manifest] Manifest is valid");
|
|
86
|
+
console.log("[manifest] version: %d", data.version);
|
|
87
|
+
console.log("[manifest] generatedAt: %s", data.generatedAt);
|
|
88
|
+
console.log("[manifest] serverEnv: %s", data.invalidation.serverEnv);
|
|
89
|
+
console.log("[manifest] serverScope: %s", data.invalidation.serverScope);
|
|
90
|
+
console.log("[manifest] resolveCache entries: %d", resolveCacheCount);
|
|
91
|
+
console.log("[manifest] fileDiscovery entries: %d", fileDiscoveryCount);
|
|
92
|
+
console.log("[manifest] extension entries: %d", extensionCount);
|
|
93
|
+
} finally {
|
|
94
|
+
if (savedEggManifest === void 0) delete process.env.EGG_MANIFEST;
|
|
95
|
+
else process.env.EGG_MANIFEST = savedEggManifest;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async runClean() {
|
|
99
|
+
const { flags } = this;
|
|
100
|
+
debug("clean manifest: baseDir=%s", flags.base);
|
|
101
|
+
const { ManifestStore } = await import("@eggjs/core");
|
|
102
|
+
ManifestStore.clean(flags.base);
|
|
103
|
+
console.log("[manifest] Manifest cleaned");
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
export { Manifest as default };
|
package/dist/commands/test.d.ts
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { BaseCommand } from "../baseCommand.js";
|
|
2
2
|
import { InlineConfig } from "vitest/node";
|
|
3
|
-
import * as
|
|
3
|
+
import * as _oclif_core_interfaces39 from "@oclif/core/interfaces";
|
|
4
4
|
|
|
5
5
|
//#region src/commands/test.d.ts
|
|
6
6
|
declare class Test<T extends typeof Test> extends BaseCommand<T> {
|
|
7
7
|
static args: {
|
|
8
|
-
file:
|
|
8
|
+
file: _oclif_core_interfaces39.Arg<string | undefined, Record<string, unknown>>;
|
|
9
9
|
};
|
|
10
10
|
static description: string;
|
|
11
11
|
static examples: string[];
|
|
12
12
|
static flags: {
|
|
13
|
-
bail:
|
|
14
|
-
timeout:
|
|
15
|
-
'no-timeout':
|
|
16
|
-
grep:
|
|
17
|
-
changed:
|
|
18
|
-
watch:
|
|
13
|
+
bail: _oclif_core_interfaces39.BooleanFlag<boolean>;
|
|
14
|
+
timeout: _oclif_core_interfaces39.OptionFlag<number, _oclif_core_interfaces39.CustomOptions>;
|
|
15
|
+
'no-timeout': _oclif_core_interfaces39.BooleanFlag<boolean>;
|
|
16
|
+
grep: _oclif_core_interfaces39.OptionFlag<string | undefined, _oclif_core_interfaces39.CustomOptions>;
|
|
17
|
+
changed: _oclif_core_interfaces39.BooleanFlag<boolean>;
|
|
18
|
+
watch: _oclif_core_interfaces39.BooleanFlag<boolean>;
|
|
19
|
+
pool: _oclif_core_interfaces39.OptionFlag<string, _oclif_core_interfaces39.CustomOptions>;
|
|
19
20
|
};
|
|
20
21
|
run(): Promise<void>;
|
|
21
22
|
protected buildVitestConfig(files: string[]): Promise<InlineConfig>;
|
package/dist/commands/test.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BaseCommand, ForkError } from "../baseCommand.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { debuglog } from "node:util";
|
|
4
|
-
import { EggType, ImportResolveError, detectType, importResolve } from "@eggjs/utils";
|
|
5
4
|
import { Args, Flags } from "@oclif/core";
|
|
6
5
|
import fs from "node:fs/promises";
|
|
6
|
+
import { EggType, ImportResolveError, detectType, importResolve } from "@eggjs/utils";
|
|
7
7
|
import ciParallelVars from "ci-parallel-vars";
|
|
8
8
|
import globby from "globby";
|
|
9
9
|
import { getChangedFilesForRoots } from "jest-changed-files";
|
|
@@ -45,6 +45,11 @@ var Test = class extends BaseCommand {
|
|
|
45
45
|
description: "run tests in watch mode",
|
|
46
46
|
default: false,
|
|
47
47
|
char: "w"
|
|
48
|
+
}),
|
|
49
|
+
pool: Flags.string({
|
|
50
|
+
description: "vitest worker pool type",
|
|
51
|
+
options: ["forks", "threads"],
|
|
52
|
+
default: process.env.EGG_VITEST_POOL ?? "threads"
|
|
48
53
|
})
|
|
49
54
|
};
|
|
50
55
|
async run() {
|
|
@@ -89,6 +94,8 @@ var Test = class extends BaseCommand {
|
|
|
89
94
|
return (path.isAbsolute(f) ? f : path.join(flags.base, f)).replace(/\\/g, "/");
|
|
90
95
|
});
|
|
91
96
|
process.env.EGG_BIN_TIMEOUT = String(flags.timeout);
|
|
97
|
+
process.env.EGG_VITEST_POOL = flags.pool;
|
|
98
|
+
process.env.EGG_VITEST_ISOLATE = process.env.EGG_VITEST_ISOLATE ?? "false";
|
|
92
99
|
debug("run test with vitest, files: %o, flags: %o", files, flags);
|
|
93
100
|
const config = await this.buildVitestConfig(files);
|
|
94
101
|
if (flags["dry-run"]) {
|
|
@@ -120,22 +127,24 @@ var Test = class extends BaseCommand {
|
|
|
120
127
|
setupFiles.push(...requires);
|
|
121
128
|
const eggType = await detectType(flags.base);
|
|
122
129
|
debug("eggType: %s", eggType);
|
|
123
|
-
|
|
130
|
+
const isSelfTestFixture = !!process.env.EGG_BIN_SELF_TEST_FIXTURE;
|
|
131
|
+
if (!isSelfTestFixture && eggType === EggType.application) try {
|
|
124
132
|
const mockSetup = importResolve("@eggjs/mock/setup_vitest", { paths: [flags.base] });
|
|
125
133
|
setupFiles.push(mockSetup);
|
|
126
134
|
debug("auto add @eggjs/mock/setup_vitest: %o", mockSetup);
|
|
127
135
|
} catch (err) {
|
|
128
136
|
if (!(err instanceof ImportResolveError)) throw err;
|
|
129
|
-
debug("skip @eggjs/mock/setup_vitest:
|
|
137
|
+
debug("skip @eggjs/mock/setup_vitest: not resolvable");
|
|
130
138
|
}
|
|
131
139
|
let runner;
|
|
132
|
-
try {
|
|
133
|
-
runner = importResolve("@eggjs/tegg-vitest/runner", { paths: [
|
|
134
|
-
debug("auto use @eggjs/tegg-vitest/runner: %o", runner);
|
|
140
|
+
if (!isSelfTestFixture) for (const resolveFrom of [flags.base, import.meta.dirname]) try {
|
|
141
|
+
runner = importResolve("@eggjs/tegg-vitest/runner", { paths: [resolveFrom] });
|
|
142
|
+
debug("auto use @eggjs/tegg-vitest/runner from %s: %o", resolveFrom, runner);
|
|
143
|
+
break;
|
|
135
144
|
} catch (err) {
|
|
136
145
|
if (!(err instanceof ImportResolveError)) throw err;
|
|
137
|
-
debug("skip @eggjs/tegg-vitest/runner: @eggjs/tegg-vitest not installed");
|
|
138
146
|
}
|
|
147
|
+
if (!runner) debug("skip @eggjs/tegg-vitest/runner: self-test fixture or not resolvable");
|
|
139
148
|
return {
|
|
140
149
|
root: flags.base,
|
|
141
150
|
include: files,
|
|
@@ -145,12 +154,15 @@ var Test = class extends BaseCommand {
|
|
|
145
154
|
"**/node_modules/**"
|
|
146
155
|
],
|
|
147
156
|
testTimeout: flags.timeout,
|
|
157
|
+
hookTimeout: flags.timeout,
|
|
148
158
|
testNamePattern: flags.grep,
|
|
149
159
|
bail: flags.bail ? 1 : 0,
|
|
150
160
|
setupFiles,
|
|
151
161
|
runner,
|
|
152
162
|
reporters: [process.env.TEST_REPORTER ?? "default"],
|
|
153
|
-
pool:
|
|
163
|
+
pool: flags.pool,
|
|
164
|
+
isolate: process.env.EGG_VITEST_ISOLATE !== "false",
|
|
165
|
+
fileParallelism: process.env.EGG_FILE_PARALLELISM === "true",
|
|
154
166
|
execArgv: [...this.globalExecArgv],
|
|
155
167
|
watch: flags.watch,
|
|
156
168
|
globals: true,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { PackageEgg } from "./types.js";
|
|
2
2
|
import { BaseCommand, ForkError, ForkNodeOptions } from "./baseCommand.js";
|
|
3
|
+
import Bundle from "./commands/bundle.js";
|
|
3
4
|
import Test from "./commands/test.js";
|
|
4
5
|
import Cov from "./commands/cov.js";
|
|
5
6
|
import Dev from "./commands/dev.js";
|
|
7
|
+
import Manifest from "./commands/manifest.js";
|
|
6
8
|
export * from "@oclif/core";
|
|
7
|
-
export { BaseCommand, Cov, Dev, ForkError, ForkNodeOptions, PackageEgg, Test };
|
|
9
|
+
export { BaseCommand, Bundle, Cov, Dev, ForkError, ForkNodeOptions, Manifest, PackageEgg, Test };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { BaseCommand, ForkError } from "./baseCommand.js";
|
|
2
|
+
import Bundle from "./commands/bundle.js";
|
|
2
3
|
import Test from "./commands/test.js";
|
|
3
4
|
import Cov from "./commands/cov.js";
|
|
4
5
|
import Dev from "./commands/dev.js";
|
|
6
|
+
import Manifest from "./commands/manifest.js";
|
|
5
7
|
|
|
6
8
|
export * from "@oclif/core"
|
|
7
9
|
|
|
8
|
-
export { BaseCommand, Cov, Dev, ForkError, Test };
|
|
10
|
+
export { BaseCommand, Bundle, Cov, Dev, ForkError, Manifest, Test };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
|
|
3
|
+
import { importModule } from '@eggjs/utils';
|
|
4
|
+
|
|
5
|
+
const debug = debuglog('egg/bin/scripts/manifest-generate');
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
debug('argv: %o', process.argv);
|
|
9
|
+
const options = JSON.parse(process.argv[2]);
|
|
10
|
+
debug('manifest generate options: %o', options);
|
|
11
|
+
|
|
12
|
+
// Set server env/scope before importing framework
|
|
13
|
+
if (options.env) {
|
|
14
|
+
process.env.EGG_SERVER_ENV = options.env;
|
|
15
|
+
}
|
|
16
|
+
if (options.scope) {
|
|
17
|
+
process.env.EGG_SERVER_SCOPE = options.scope;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Clean any existing manifest before generation to ensure the collector
|
|
21
|
+
// captures all lookups (not just cache misses from a stale manifest).
|
|
22
|
+
const { ManifestStore } = await importModule('@eggjs/core', {
|
|
23
|
+
paths: [options.framework],
|
|
24
|
+
});
|
|
25
|
+
ManifestStore.clean(options.baseDir);
|
|
26
|
+
|
|
27
|
+
const framework = await importModule(options.framework);
|
|
28
|
+
const app = await framework.start({
|
|
29
|
+
baseDir: options.baseDir,
|
|
30
|
+
framework: options.framework,
|
|
31
|
+
env: options.env,
|
|
32
|
+
metadataOnly: true,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Generate manifest from collected metadata
|
|
36
|
+
const manifest = app.loader.generateManifest();
|
|
37
|
+
|
|
38
|
+
// Write manifest to .egg/manifest.json
|
|
39
|
+
await ManifestStore.write(options.baseDir, manifest);
|
|
40
|
+
|
|
41
|
+
// Log stats
|
|
42
|
+
const resolveCacheCount = Object.keys(manifest.resolveCache).length;
|
|
43
|
+
const fileDiscoveryCount = Object.keys(manifest.fileDiscovery).length;
|
|
44
|
+
const extensionCount = Object.keys(manifest.extensions).length;
|
|
45
|
+
console.log('[manifest] Generated manifest v%d at %s', manifest.version, manifest.generatedAt);
|
|
46
|
+
console.log('[manifest] resolveCache entries: %d', resolveCacheCount);
|
|
47
|
+
console.log('[manifest] fileDiscovery entries: %d', fileDiscoveryCount);
|
|
48
|
+
console.log('[manifest] extension entries: %d', extensionCount);
|
|
49
|
+
console.log('[manifest] Written to %s/.egg/manifest.json', options.baseDir);
|
|
50
|
+
|
|
51
|
+
// Clean up and exit
|
|
52
|
+
await app.close();
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main().catch((err) => {
|
|
57
|
+
console.error('[manifest] Generation failed:', err);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/bin",
|
|
3
|
-
"version": "8.0.2-beta.
|
|
3
|
+
"version": "8.0.2-beta.10",
|
|
4
4
|
"description": "egg developer tool",
|
|
5
5
|
"homepage": "https://github.com/eggjs/egg/tree/next/tools/egg-bin",
|
|
6
6
|
"bugs": {
|
|
@@ -28,8 +28,10 @@
|
|
|
28
28
|
"exports": {
|
|
29
29
|
".": "./dist/index.js",
|
|
30
30
|
"./baseCommand": "./dist/baseCommand.js",
|
|
31
|
+
"./commands/bundle": "./dist/commands/bundle.js",
|
|
31
32
|
"./commands/cov": "./dist/commands/cov.js",
|
|
32
33
|
"./commands/dev": "./dist/commands/dev.js",
|
|
34
|
+
"./commands/manifest": "./dist/commands/manifest.js",
|
|
33
35
|
"./commands/test": "./dist/commands/test.js",
|
|
34
36
|
"./types": "./dist/types.js",
|
|
35
37
|
"./utils": "./dist/utils.js",
|
|
@@ -49,7 +51,10 @@
|
|
|
49
51
|
"tsconfig-paths": "^4.2.0",
|
|
50
52
|
"utility": "^2.5.0",
|
|
51
53
|
"vitest": "^4.0.15",
|
|
52
|
-
"@eggjs/
|
|
54
|
+
"@eggjs/tegg-vitest": "4.0.2-beta.10",
|
|
55
|
+
"@eggjs/core": "7.0.2-beta.10",
|
|
56
|
+
"@eggjs/utils": "5.0.2-beta.10",
|
|
57
|
+
"@eggjs/egg-bundler": "0.0.1-beta.0"
|
|
53
58
|
},
|
|
54
59
|
"devDependencies": {
|
|
55
60
|
"@swc-node/register": "^1.11.1",
|
|
@@ -63,14 +68,15 @@
|
|
|
63
68
|
"npminstall": "^7.12.0",
|
|
64
69
|
"rimraf": "^6.1.2",
|
|
65
70
|
"runscript": "^2.0.1",
|
|
71
|
+
"sdk-base": "^5.0.1",
|
|
66
72
|
"typescript": "^5.9.3",
|
|
67
|
-
"@eggjs/mock": "7.0.2-beta.
|
|
68
|
-
"@eggjs/supertest": "9.0.2-beta.
|
|
69
|
-
"
|
|
70
|
-
"
|
|
73
|
+
"@eggjs/mock": "7.0.2-beta.10",
|
|
74
|
+
"@eggjs/supertest": "9.0.2-beta.10",
|
|
75
|
+
"egg": "4.1.2-beta.10",
|
|
76
|
+
"@eggjs/tsconfig": "3.1.2-beta.10"
|
|
71
77
|
},
|
|
72
78
|
"peerDependencies": {
|
|
73
|
-
"@eggjs/mock": "7.0.2-beta.
|
|
79
|
+
"@eggjs/mock": "7.0.2-beta.10"
|
|
74
80
|
},
|
|
75
81
|
"peerDependenciesMeta": {
|
|
76
82
|
"@eggjs/mock": {
|
|
@@ -90,8 +96,8 @@
|
|
|
90
96
|
"node": ">=22.18.0"
|
|
91
97
|
},
|
|
92
98
|
"scripts": {
|
|
99
|
+
"build": "tsdown -c tsdown.config.ts",
|
|
93
100
|
"typecheck": "tsgo --noEmit",
|
|
94
|
-
"pretest": "tsdown",
|
|
95
101
|
"test": "vitest run",
|
|
96
102
|
"cov": "vitest run --coverage",
|
|
97
103
|
"ci": "npm run cov"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { debuglog } from 'node:util';
|
|
2
|
+
|
|
3
|
+
import { importModule } from '@eggjs/utils';
|
|
4
|
+
|
|
5
|
+
const debug = debuglog('egg/bin/scripts/manifest-generate');
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
debug('argv: %o', process.argv);
|
|
9
|
+
const options = JSON.parse(process.argv[2]);
|
|
10
|
+
debug('manifest generate options: %o', options);
|
|
11
|
+
|
|
12
|
+
// Set server env/scope before importing framework
|
|
13
|
+
if (options.env) {
|
|
14
|
+
process.env.EGG_SERVER_ENV = options.env;
|
|
15
|
+
}
|
|
16
|
+
if (options.scope) {
|
|
17
|
+
process.env.EGG_SERVER_SCOPE = options.scope;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Clean any existing manifest before generation to ensure the collector
|
|
21
|
+
// captures all lookups (not just cache misses from a stale manifest).
|
|
22
|
+
const { ManifestStore } = await importModule('@eggjs/core', {
|
|
23
|
+
paths: [options.framework],
|
|
24
|
+
});
|
|
25
|
+
ManifestStore.clean(options.baseDir);
|
|
26
|
+
|
|
27
|
+
const framework = await importModule(options.framework);
|
|
28
|
+
const app = await framework.start({
|
|
29
|
+
baseDir: options.baseDir,
|
|
30
|
+
framework: options.framework,
|
|
31
|
+
env: options.env,
|
|
32
|
+
metadataOnly: true,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Generate manifest from collected metadata
|
|
36
|
+
const manifest = app.loader.generateManifest();
|
|
37
|
+
|
|
38
|
+
// Write manifest to .egg/manifest.json
|
|
39
|
+
await ManifestStore.write(options.baseDir, manifest);
|
|
40
|
+
|
|
41
|
+
// Log stats
|
|
42
|
+
const resolveCacheCount = Object.keys(manifest.resolveCache).length;
|
|
43
|
+
const fileDiscoveryCount = Object.keys(manifest.fileDiscovery).length;
|
|
44
|
+
const extensionCount = Object.keys(manifest.extensions).length;
|
|
45
|
+
console.log('[manifest] Generated manifest v%d at %s', manifest.version, manifest.generatedAt);
|
|
46
|
+
console.log('[manifest] resolveCache entries: %d', resolveCacheCount);
|
|
47
|
+
console.log('[manifest] fileDiscovery entries: %d', fileDiscoveryCount);
|
|
48
|
+
console.log('[manifest] extension entries: %d', extensionCount);
|
|
49
|
+
console.log('[manifest] Written to %s/.egg/manifest.json', options.baseDir);
|
|
50
|
+
|
|
51
|
+
// Clean up and exit
|
|
52
|
+
await app.close();
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main().catch((err) => {
|
|
57
|
+
console.error('[manifest] Generation failed:', err);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|