@esmx/core 3.0.0-rc.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 +29 -0
- package/dist/app.d.ts +84 -0
- package/dist/app.mjs +34 -0
- package/dist/cli/cli.d.ts +2 -0
- package/dist/cli/cli.mjs +73 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.mjs +3 -0
- package/dist/gez.d.ts +703 -0
- package/dist/gez.mjs +842 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +19 -0
- package/dist/manifest-json.d.ts +48 -0
- package/dist/manifest-json.mjs +21 -0
- package/dist/module-config.d.ts +185 -0
- package/dist/module-config.mjs +79 -0
- package/dist/pack-config.d.ts +251 -0
- package/dist/pack-config.mjs +26 -0
- package/dist/render-context.d.ts +1212 -0
- package/dist/render-context.mjs +1010 -0
- package/dist/utils/cache.d.ts +49 -0
- package/dist/utils/cache.mjs +16 -0
- package/dist/utils/import-map.d.ts +8 -0
- package/dist/utils/import-map.mjs +32 -0
- package/dist/utils/middleware.d.ts +57 -0
- package/dist/utils/middleware.mjs +51 -0
- package/dist/utils/path-without-index.d.ts +1 -0
- package/dist/utils/path-without-index.mjs +9 -0
- package/dist/utils/resolve-path.d.ts +2 -0
- package/dist/utils/resolve-path.mjs +4 -0
- package/dist/utils/static-import-lexer.d.ts +26 -0
- package/dist/utils/static-import-lexer.mjs +43 -0
- package/package.json +103 -0
- package/src/app.ts +144 -0
- package/src/cli/cli.ts +99 -0
- package/src/cli/index.ts +5 -0
- package/src/gez.ts +1026 -0
- package/src/index.ts +38 -0
- package/src/manifest-json.ts +80 -0
- package/src/module-config.ts +282 -0
- package/src/pack-config.ts +301 -0
- package/src/render-context.ts +1326 -0
- package/src/utils/cache.ts +68 -0
- package/src/utils/import-map.ts +47 -0
- package/src/utils/middleware.ts +118 -0
- package/src/utils/path-without-index.ts +9 -0
- package/src/utils/resolve-path.ts +33 -0
- package/src/utils/static-import-lexer.ts +85 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { type EsmxOptions, type COMMAND, type RuntimeTarget, type ImportMap, type SpecifierMap, type ScopesMap, Esmx } from './esmx';
|
|
2
|
+
export { PathType, type ModuleConfig, type ParsedModuleConfig, parseModuleConfig } from './module-config';
|
|
3
|
+
export { type PackConfig, type ParsedPackConfig, parsePackConfig } from './pack-config';
|
|
4
|
+
export { type App, createApp } from './app';
|
|
5
|
+
export { type RenderContextOptions, type ServerRenderHandle, type RenderFiles, RenderContext } from './render-context';
|
|
6
|
+
export { isImmutableFile, type Middleware, createMiddleware, mergeMiddlewares } from './utils/middleware';
|
|
7
|
+
export type { ManifestJson, ManifestJsonChunkSizes, ManifestJsonChunks } from './manifest-json';
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export {
|
|
2
|
+
Esmx
|
|
3
|
+
} from "./esmx";
|
|
4
|
+
export {
|
|
5
|
+
PathType,
|
|
6
|
+
parseModuleConfig
|
|
7
|
+
} from "./module-config.mjs";
|
|
8
|
+
export {
|
|
9
|
+
parsePackConfig
|
|
10
|
+
} from "./pack-config.mjs";
|
|
11
|
+
export { createApp } from "./app.mjs";
|
|
12
|
+
export {
|
|
13
|
+
RenderContext
|
|
14
|
+
} from "./render-context.mjs";
|
|
15
|
+
export {
|
|
16
|
+
isImmutableFile,
|
|
17
|
+
createMiddleware,
|
|
18
|
+
mergeMiddlewares
|
|
19
|
+
} from "./utils/middleware.mjs";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { RuntimeTarget } from './esmx';
|
|
2
|
+
import type { ParsedModuleConfig } from './module-config';
|
|
3
|
+
export interface ManifestJsonChunks {
|
|
4
|
+
/**
|
|
5
|
+
* 当前编译的 JS 文件。
|
|
6
|
+
*/
|
|
7
|
+
js: string;
|
|
8
|
+
/**
|
|
9
|
+
* 当前编译的 CSS 文件。
|
|
10
|
+
*/
|
|
11
|
+
css: string[];
|
|
12
|
+
/**
|
|
13
|
+
* 其它的资源文件。
|
|
14
|
+
*/
|
|
15
|
+
resources: string[];
|
|
16
|
+
/**
|
|
17
|
+
* 构建产物的大小。
|
|
18
|
+
*/
|
|
19
|
+
sizes: ManifestJsonChunkSizes;
|
|
20
|
+
}
|
|
21
|
+
export interface ManifestJsonChunkSizes {
|
|
22
|
+
js: number;
|
|
23
|
+
css: number;
|
|
24
|
+
resource: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ManifestJson {
|
|
27
|
+
/**
|
|
28
|
+
* 服务名字,来自于:EsmxOptions.name
|
|
29
|
+
*/
|
|
30
|
+
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* 对外导出的文件
|
|
33
|
+
*/
|
|
34
|
+
exports: Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* 构建的全部文件清单
|
|
37
|
+
*/
|
|
38
|
+
buildFiles: string[];
|
|
39
|
+
/**
|
|
40
|
+
* 编译的文件信息
|
|
41
|
+
* 类型:Record<源文件, 编译信息>
|
|
42
|
+
*/
|
|
43
|
+
chunks: Record<string, ManifestJsonChunks>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 获取服务清单文件
|
|
47
|
+
*/
|
|
48
|
+
export declare function getManifestList(target: RuntimeTarget, moduleConfig: ParsedModuleConfig): Promise<ManifestJson[]>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
async function readJson(filename) {
|
|
4
|
+
return JSON.parse(await fsp.readFile(filename, "utf-8"));
|
|
5
|
+
}
|
|
6
|
+
export async function getManifestList(target, moduleConfig) {
|
|
7
|
+
return Promise.all(
|
|
8
|
+
moduleConfig.links.map(async (item) => {
|
|
9
|
+
const filename = path.resolve(item.root, target, "manifest.json");
|
|
10
|
+
try {
|
|
11
|
+
const data = await readJson(filename);
|
|
12
|
+
data.name = item.name;
|
|
13
|
+
return data;
|
|
14
|
+
} catch (e) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`'${item.name}' service '${target}/manifest.json' file read error`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
export declare enum PathType {
|
|
2
|
+
npm = "npm:",
|
|
3
|
+
root = "root:"
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 模块配置接口。
|
|
7
|
+
* 用于定义服务的导出、导入和外部依赖配置。
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // entry.node.ts
|
|
12
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
13
|
+
*
|
|
14
|
+
* export default {
|
|
15
|
+
* modules: {
|
|
16
|
+
* // 导出配置
|
|
17
|
+
* exports: [
|
|
18
|
+
* 'root:src/components/button.vue', // 导出源码文件
|
|
19
|
+
* 'root:src/utils/format.ts',
|
|
20
|
+
* 'npm:vue', // 导出第三方依赖
|
|
21
|
+
* 'npm:vue-router'
|
|
22
|
+
* ],
|
|
23
|
+
*
|
|
24
|
+
* // 导入配置
|
|
25
|
+
* links: {
|
|
26
|
+
* // 源码安装方式:需要指向 dist 目录
|
|
27
|
+
* 'ssr-remote': 'root:./node_modules/ssr-remote/dist',
|
|
28
|
+
* // 软件包安装方式:直接指向包目录
|
|
29
|
+
* 'other-remote': 'root:./node_modules/other-remote'
|
|
30
|
+
* },
|
|
31
|
+
*
|
|
32
|
+
* // 外部依赖配置
|
|
33
|
+
* imports: {
|
|
34
|
+
* 'vue': 'ssr-remote/npm/vue',
|
|
35
|
+
* 'vue-router': 'ssr-remote/npm/vue-router'
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* } satisfies EsmxOptions;
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export interface ModuleConfig {
|
|
42
|
+
/**
|
|
43
|
+
* 导出配置列表。
|
|
44
|
+
* 将服务中的特定代码单元(如组件、工具函数等)以 ESM 格式对外暴露。
|
|
45
|
+
*
|
|
46
|
+
* 支持两种类型:
|
|
47
|
+
* - root:* - 导出源码文件,如:'root:src/components/button.vue'
|
|
48
|
+
* - npm:* - 导出第三方依赖,如:'npm:vue'
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* exports: [
|
|
53
|
+
* // 导出源码文件
|
|
54
|
+
* 'root:src/components/button.vue',
|
|
55
|
+
* 'root:src/utils/format.ts',
|
|
56
|
+
* // 导出第三方依赖
|
|
57
|
+
* 'npm:vue',
|
|
58
|
+
* 'npm:vue-router'
|
|
59
|
+
* ]
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
exports?: string[];
|
|
63
|
+
/**
|
|
64
|
+
* 导入配置映射。
|
|
65
|
+
* 配置需要导入的远程模块及其本地路径。
|
|
66
|
+
*
|
|
67
|
+
* 安装方式不同,配置也不同:
|
|
68
|
+
* - 源码安装(Workspace、Git):需要指向 dist 目录
|
|
69
|
+
* - 软件包安装(Link、静态服务器、私有镜像源、File):直接指向包目录
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* links: {
|
|
74
|
+
* // 源码安装方式:需要指向 dist 目录
|
|
75
|
+
* 'ssr-remote': 'root:./node_modules/ssr-remote/dist',
|
|
76
|
+
* // 软件包安装方式:直接指向包目录
|
|
77
|
+
* 'other-remote': 'root:./node_modules/other-remote'
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
links?: Record<string, string>;
|
|
82
|
+
/**
|
|
83
|
+
* 外部依赖映射。
|
|
84
|
+
* 配置要使用的外部依赖,通常是使用远程模块中的依赖。
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* imports: {
|
|
89
|
+
* // 使用远程模块中的依赖
|
|
90
|
+
* 'vue': 'ssr-remote/npm/vue',
|
|
91
|
+
* 'vue-router': 'ssr-remote/npm/vue-router'
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
imports?: Record<string, string>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 解析后的模块配置。
|
|
99
|
+
* 将原始的模块配置转换为标准化的内部格式,用于模块的加载和解析。
|
|
100
|
+
*/
|
|
101
|
+
export interface ParsedModuleConfig {
|
|
102
|
+
/**
|
|
103
|
+
* 当前服务的名称。
|
|
104
|
+
* 用于标识模块和生成导入路径。
|
|
105
|
+
*/
|
|
106
|
+
name: string;
|
|
107
|
+
/**
|
|
108
|
+
* 当前服务的根目录路径。
|
|
109
|
+
* 用于解析相对路径和构建产物的存放。
|
|
110
|
+
*/
|
|
111
|
+
root: string;
|
|
112
|
+
/**
|
|
113
|
+
* 导出配置列表。
|
|
114
|
+
* 定义了当前服务对外暴露的模块。
|
|
115
|
+
*/
|
|
116
|
+
exports: {
|
|
117
|
+
/**
|
|
118
|
+
* 原始导出路径。
|
|
119
|
+
* 例如:'npm:vue' 或 'root:src/components'
|
|
120
|
+
*/
|
|
121
|
+
name: string;
|
|
122
|
+
/**
|
|
123
|
+
* 路径类型。
|
|
124
|
+
* - npm: node_modules 中的依赖
|
|
125
|
+
* - root: 项目根目录下的文件
|
|
126
|
+
*/
|
|
127
|
+
type: PathType;
|
|
128
|
+
/**
|
|
129
|
+
* 导入名称。
|
|
130
|
+
* 格式:'${serviceName}/${type}/${path}'
|
|
131
|
+
* 例如:'your-app-name/npm/vue' 或 'your-app-name/src/components'
|
|
132
|
+
*/
|
|
133
|
+
importName: string;
|
|
134
|
+
/**
|
|
135
|
+
* 导出路径。
|
|
136
|
+
* 相对于服务根目录的路径。
|
|
137
|
+
* 例如:'./npm/vue' 或 './src/components'
|
|
138
|
+
*/
|
|
139
|
+
exportName: string;
|
|
140
|
+
/**
|
|
141
|
+
* 实际的文件路径。
|
|
142
|
+
* 例如:'vue' 或 './src/components.ts'
|
|
143
|
+
*/
|
|
144
|
+
exportPath: string;
|
|
145
|
+
/**
|
|
146
|
+
* 外部依赖名称。
|
|
147
|
+
* 用于其他服务导入此模块时的标识。
|
|
148
|
+
* 例如:'vue' 或 'your-app-name/src/components'
|
|
149
|
+
*/
|
|
150
|
+
externalName: string;
|
|
151
|
+
}[];
|
|
152
|
+
/**
|
|
153
|
+
* 导入配置列表。
|
|
154
|
+
* 定义了当前服务需要导入的外部模块。
|
|
155
|
+
*/
|
|
156
|
+
links: Array<{
|
|
157
|
+
/**
|
|
158
|
+
* 软包名称
|
|
159
|
+
*/
|
|
160
|
+
name: string;
|
|
161
|
+
/**
|
|
162
|
+
* 软件包根目录
|
|
163
|
+
*/
|
|
164
|
+
root: string;
|
|
165
|
+
}>;
|
|
166
|
+
/**
|
|
167
|
+
* 外部依赖映射。
|
|
168
|
+
* 将模块的导入路径映射到实际的模块位置。
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* {
|
|
173
|
+
* 'vue': {
|
|
174
|
+
* match: /^vue$/, // 匹配导入语句
|
|
175
|
+
* import: 'your-app-name/npm/vue' // 实际的模块路径
|
|
176
|
+
* }
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
imports: Record<string, {
|
|
181
|
+
match: RegExp;
|
|
182
|
+
import?: string;
|
|
183
|
+
}>;
|
|
184
|
+
}
|
|
185
|
+
export declare function parseModuleConfig(name: string, root: string, config?: ModuleConfig): ParsedModuleConfig;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export var PathType = /* @__PURE__ */ ((PathType2) => {
|
|
3
|
+
PathType2["npm"] = "npm:";
|
|
4
|
+
PathType2["root"] = "root:";
|
|
5
|
+
return PathType2;
|
|
6
|
+
})(PathType || {});
|
|
7
|
+
export function parseModuleConfig(name, root, config = {}) {
|
|
8
|
+
const exports = [];
|
|
9
|
+
if (config.exports) {
|
|
10
|
+
config.exports.forEach((key) => {
|
|
11
|
+
if (key.startsWith("npm:" /* npm */)) {
|
|
12
|
+
const exportName = key.substring("npm:" /* npm */.length);
|
|
13
|
+
exports.push({
|
|
14
|
+
name: key,
|
|
15
|
+
type: "npm:" /* npm */,
|
|
16
|
+
importName: `${name}/npm/${exportName}`,
|
|
17
|
+
exportName: `./npm/${exportName}`,
|
|
18
|
+
exportPath: exportName,
|
|
19
|
+
externalName: exportName
|
|
20
|
+
});
|
|
21
|
+
} else if (key.startsWith("root:" /* root */)) {
|
|
22
|
+
const exportName = key.substring("root:" /* root */.length);
|
|
23
|
+
const exportNameNoSuffix = exportName.replace(/\.(ts|js)$/, "");
|
|
24
|
+
exports.push({
|
|
25
|
+
name: key,
|
|
26
|
+
type: "root:" /* root */,
|
|
27
|
+
importName: `${name}/${exportNameNoSuffix}`,
|
|
28
|
+
exportName: `./${exportNameNoSuffix}`,
|
|
29
|
+
exportPath: `./${exportName}`,
|
|
30
|
+
externalName: `${name}/${exportNameNoSuffix}`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const links = [];
|
|
36
|
+
if (config.links) {
|
|
37
|
+
const getLocalPath = (dir) => {
|
|
38
|
+
if (dir.startsWith("root:" /* root */)) {
|
|
39
|
+
return path.resolve(root, dir.substring("root:" /* root */.length));
|
|
40
|
+
} else if (path.isAbsolute(dir)) {
|
|
41
|
+
return dir;
|
|
42
|
+
}
|
|
43
|
+
return path.resolve(process.cwd(), dir);
|
|
44
|
+
};
|
|
45
|
+
const _links = config.links;
|
|
46
|
+
Object.keys(config.links).forEach((key) => {
|
|
47
|
+
const value = _links[key].trim();
|
|
48
|
+
links.push({
|
|
49
|
+
name: key,
|
|
50
|
+
root: getLocalPath(value)
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const imports = {};
|
|
55
|
+
exports.forEach(({ importName, externalName }) => {
|
|
56
|
+
imports[externalName] = {
|
|
57
|
+
match: new RegExp(`^${externalName}$`),
|
|
58
|
+
import: importName
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
links.forEach(({ name: name2 }) => {
|
|
62
|
+
imports[name2] = {
|
|
63
|
+
match: new RegExp(`^${[name2]}/`)
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
if (config.imports) {
|
|
67
|
+
Object.entries(config.imports).forEach(([key, value]) => {
|
|
68
|
+
imports[key] = {
|
|
69
|
+
import: value,
|
|
70
|
+
match: new RegExp(`^${key}$`)
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
links.push({
|
|
75
|
+
name,
|
|
76
|
+
root: path.resolve(root, "dist")
|
|
77
|
+
});
|
|
78
|
+
return { name, root, exports, links, imports };
|
|
79
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import type { Esmx } from './esmx';
|
|
2
|
+
/**
|
|
3
|
+
* 软件包打包配置接口。
|
|
4
|
+
* 用于将服务的构建产物打包成标准的 npm .tgz 格式软件包。
|
|
5
|
+
*
|
|
6
|
+
* 特点:
|
|
7
|
+
* - **标准化**:使用 npm 标准的 .tgz 打包格式
|
|
8
|
+
* - **完整性**:包含模块的源代码、类型声明和配置文件等所有必要文件
|
|
9
|
+
* - **兼容性**:与 npm 生态系统完全兼容,支持标准的包管理工作流
|
|
10
|
+
*
|
|
11
|
+
* 使用场景:
|
|
12
|
+
* - 模块打包发布
|
|
13
|
+
* - 版本发布管理
|
|
14
|
+
* - CI/CD 流程集成
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // entry.node.ts
|
|
19
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
20
|
+
*
|
|
21
|
+
* export default {
|
|
22
|
+
* modules: {
|
|
23
|
+
* // 配置需要导出的模块
|
|
24
|
+
* exports: [
|
|
25
|
+
* 'root:src/components/button.vue',
|
|
26
|
+
* 'root:src/utils/format.ts',
|
|
27
|
+
* 'npm:vue',
|
|
28
|
+
* 'npm:vue-router'
|
|
29
|
+
* ]
|
|
30
|
+
* },
|
|
31
|
+
* // 打包配置
|
|
32
|
+
* pack: {
|
|
33
|
+
* // 启用打包功能
|
|
34
|
+
* enable: true,
|
|
35
|
+
*
|
|
36
|
+
* // 同时输出多个版本
|
|
37
|
+
* outputs: [
|
|
38
|
+
* 'dist/versions/latest.tgz',
|
|
39
|
+
* 'dist/versions/1.0.0.tgz'
|
|
40
|
+
* ],
|
|
41
|
+
*
|
|
42
|
+
* // 自定义 package.json
|
|
43
|
+
* packageJson: async (esmx, pkg) => {
|
|
44
|
+
* pkg.name = '@your-scope/your-app';
|
|
45
|
+
* pkg.version = '1.0.0';
|
|
46
|
+
* // 添加构建脚本
|
|
47
|
+
* pkg.scripts = {
|
|
48
|
+
* "prepare": "npm run build",
|
|
49
|
+
* "build": "npm run build:dts && npm run build:ssr",
|
|
50
|
+
* "build:ssr": "esmx build",
|
|
51
|
+
* "build:dts": "tsc --declaration --emitDeclarationOnly --outDir dist/src"
|
|
52
|
+
* };
|
|
53
|
+
* return pkg;
|
|
54
|
+
* },
|
|
55
|
+
*
|
|
56
|
+
* // 打包前准备
|
|
57
|
+
* onBefore: async (esmx, pkg) => {
|
|
58
|
+
* // 添加必要文件
|
|
59
|
+
* await fs.writeFile('dist/README.md', '# Your App\n\n模块导出说明...');
|
|
60
|
+
* // 执行类型检查
|
|
61
|
+
* await runTypeCheck();
|
|
62
|
+
* },
|
|
63
|
+
*
|
|
64
|
+
* // 打包后处理
|
|
65
|
+
* onAfter: async (esmx, pkg, file) => {
|
|
66
|
+
* // 发布到私有 npm 镜像源
|
|
67
|
+
* await publishToRegistry(file, {
|
|
68
|
+
* registry: 'https://npm.your-registry.com/'
|
|
69
|
+
* });
|
|
70
|
+
* // 或部署到静态服务器
|
|
71
|
+
* await uploadToServer(file, 'https://static.example.com/packages');
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* } satisfies EsmxOptions;
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export interface PackConfig {
|
|
78
|
+
/**
|
|
79
|
+
* 是否启用打包功能。
|
|
80
|
+
* 启用后会将构建产物打包成标准的 npm .tgz 格式软件包。
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
enable?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* 指定输出的软件包文件路径。
|
|
86
|
+
* 支持以下配置方式:
|
|
87
|
+
* - string: 单个输出路径,如 'dist/versions/my-app.tgz'
|
|
88
|
+
* - string[]: 多个输出路径,用于同时生成多个版本
|
|
89
|
+
* - boolean: true 时使用默认路径 'dist/client/versions/latest.tgz'
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* // 单个输出
|
|
94
|
+
* outputs: 'dist/app.tgz'
|
|
95
|
+
*
|
|
96
|
+
* // 多个版本
|
|
97
|
+
* outputs: [
|
|
98
|
+
* 'dist/versions/latest.tgz',
|
|
99
|
+
* 'dist/versions/1.0.0.tgz'
|
|
100
|
+
* ]
|
|
101
|
+
*
|
|
102
|
+
* // 使用默认路径
|
|
103
|
+
* outputs: true
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @default 'dist/client/versions/latest.tgz'
|
|
107
|
+
*/
|
|
108
|
+
outputs?: string | string[] | boolean;
|
|
109
|
+
/**
|
|
110
|
+
* package.json 处理函数。
|
|
111
|
+
* 在打包前调用,用于自定义 package.json 的内容。
|
|
112
|
+
*
|
|
113
|
+
* 常见用途:
|
|
114
|
+
* - 修改包名和版本号
|
|
115
|
+
* - 添加或更新依赖项
|
|
116
|
+
* - 添加自定义字段
|
|
117
|
+
* - 配置发布相关信息
|
|
118
|
+
*
|
|
119
|
+
* @param esmx - Esmx 实例
|
|
120
|
+
* @param pkgJson - 原始的 package.json 内容
|
|
121
|
+
* @returns 处理后的 package.json 内容
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* packageJson: async (esmx, pkg) => {
|
|
126
|
+
* // 设置包信息
|
|
127
|
+
* pkg.name = 'my-app';
|
|
128
|
+
* pkg.version = '1.0.0';
|
|
129
|
+
* pkg.description = '我的应用';
|
|
130
|
+
*
|
|
131
|
+
* // 添加依赖
|
|
132
|
+
* pkg.dependencies = {
|
|
133
|
+
* 'vue': '^3.0.0',
|
|
134
|
+
* 'express': '^4.17.1'
|
|
135
|
+
* };
|
|
136
|
+
*
|
|
137
|
+
* // 添加发布配置
|
|
138
|
+
* pkg.publishConfig = {
|
|
139
|
+
* registry: 'https://registry.example.com'
|
|
140
|
+
* };
|
|
141
|
+
*
|
|
142
|
+
* return pkg;
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
packageJson?: (esmx: Esmx, pkgJson: Record<string, any>) => Promise<Record<string, any>>;
|
|
147
|
+
/**
|
|
148
|
+
* 打包前的钩子函数。
|
|
149
|
+
* 在生成 .tgz 文件之前调用,用于执行准备工作。
|
|
150
|
+
*
|
|
151
|
+
* 常见用途:
|
|
152
|
+
* - 添加额外的文件(README、LICENSE 等)
|
|
153
|
+
* - 执行测试或构建验证
|
|
154
|
+
* - 生成文档或元数据
|
|
155
|
+
* - 清理临时文件
|
|
156
|
+
*
|
|
157
|
+
* @param esmx - Esmx 实例
|
|
158
|
+
* @param pkgJson - 处理后的 package.json 内容
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* onBefore: async (esmx, pkg) => {
|
|
163
|
+
* // 添加文档
|
|
164
|
+
* await fs.writeFile('dist/README.md', '# My App');
|
|
165
|
+
* await fs.writeFile('dist/LICENSE', 'MIT License');
|
|
166
|
+
*
|
|
167
|
+
* // 执行测试
|
|
168
|
+
* await runTests();
|
|
169
|
+
*
|
|
170
|
+
* // 生成文档
|
|
171
|
+
* await generateDocs();
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
onBefore?: (esmx: Esmx, pkgJson: Record<string, any>) => Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* 打包后的钩子函数。
|
|
178
|
+
* 在 .tgz 文件生成后调用,用于处理打包产物。
|
|
179
|
+
*
|
|
180
|
+
* 常见用途:
|
|
181
|
+
* - 发布到 npm 仓库(公共或私有)
|
|
182
|
+
* - 上传到静态资源服务器
|
|
183
|
+
* - 执行版本管理
|
|
184
|
+
* - 触发 CI/CD 流程
|
|
185
|
+
*
|
|
186
|
+
* @param esmx - Esmx 实例
|
|
187
|
+
* @param pkgJson - 最终的 package.json 内容
|
|
188
|
+
* @param file - 生成的 .tgz 文件内容
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* onAfter: async (esmx, pkg, file) => {
|
|
193
|
+
* // 发布到 npm 私有仓库
|
|
194
|
+
* await publishToRegistry(file, {
|
|
195
|
+
* registry: 'https://registry.example.com'
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* // 上传到静态资源服务器
|
|
199
|
+
* await uploadToServer(file, 'https://assets.example.com/packages');
|
|
200
|
+
*
|
|
201
|
+
* // 创建版本标签
|
|
202
|
+
* await createGitTag(pkg.version);
|
|
203
|
+
*
|
|
204
|
+
* // 触发部署流程
|
|
205
|
+
* await triggerDeploy(pkg.version);
|
|
206
|
+
* }
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
onAfter?: (esmx: Esmx, pkgJson: Record<string, any>, file: Buffer) => Promise<void>;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* PackConfig 配置解析后的内部接口。
|
|
213
|
+
* 将用户配置标准化,设置默认值,便于框架内部使用。
|
|
214
|
+
*
|
|
215
|
+
* 主要处理:
|
|
216
|
+
* - 确保所有可选字段都有默认值
|
|
217
|
+
* - 统一输出路径格式
|
|
218
|
+
* - 标准化回调函数
|
|
219
|
+
*/
|
|
220
|
+
export interface ParsedPackConfig {
|
|
221
|
+
/**
|
|
222
|
+
* 是否启用打包功能。
|
|
223
|
+
* 解析后总是有确定的布尔值。
|
|
224
|
+
* @default false
|
|
225
|
+
*/
|
|
226
|
+
enable: boolean;
|
|
227
|
+
/**
|
|
228
|
+
* 解析后的输出文件路径列表。
|
|
229
|
+
* 将所有输出格式统一转换为字符串数组:
|
|
230
|
+
* - 布尔值 true → ['dist/client/versions/latest.tgz']
|
|
231
|
+
* - 字符串 → [输入的字符串]
|
|
232
|
+
* - 字符串数组 → 保持不变
|
|
233
|
+
*/
|
|
234
|
+
outputs: string[];
|
|
235
|
+
/**
|
|
236
|
+
* 标准化的 package.json 处理函数。
|
|
237
|
+
* 未配置时使用默认函数,保持原始内容不变。
|
|
238
|
+
*/
|
|
239
|
+
packageJson: (esmx: Esmx, pkgJson: Record<string, any>) => Promise<Record<string, any>>;
|
|
240
|
+
/**
|
|
241
|
+
* 标准化的打包前钩子函数。
|
|
242
|
+
* 未配置时使用空函数。
|
|
243
|
+
*/
|
|
244
|
+
onBefore: (esmx: Esmx, pkgJson: Record<string, any>) => Promise<void>;
|
|
245
|
+
/**
|
|
246
|
+
* 标准化的打包后钩子函数。
|
|
247
|
+
* 未配置时使用空函数。
|
|
248
|
+
*/
|
|
249
|
+
onAfter: (esmx: Esmx, pkgJson: Record<string, any>, file: Buffer) => Promise<void>;
|
|
250
|
+
}
|
|
251
|
+
export declare function parsePackConfig(config?: PackConfig): ParsedPackConfig;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function parsePackConfig(config = {}) {
|
|
2
|
+
const outputs = [];
|
|
3
|
+
if (typeof config.outputs === "string") {
|
|
4
|
+
outputs.push(config.outputs);
|
|
5
|
+
} else if (Array.isArray(config.outputs)) {
|
|
6
|
+
outputs.push(...config.outputs);
|
|
7
|
+
} else if (config.outputs !== false) {
|
|
8
|
+
outputs.push("dist/client/versions/latest.tgz");
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
enable: config.enable ?? false,
|
|
12
|
+
outputs,
|
|
13
|
+
async packageJson(esmx, pkgJson) {
|
|
14
|
+
if (config.packageJson) {
|
|
15
|
+
pkgJson = await config.packageJson(esmx, pkgJson);
|
|
16
|
+
}
|
|
17
|
+
return pkgJson;
|
|
18
|
+
},
|
|
19
|
+
async onBefore(esmx, pkgJson) {
|
|
20
|
+
await config.onBefore?.(esmx, pkgJson);
|
|
21
|
+
},
|
|
22
|
+
async onAfter(esmx, pkgJson, file) {
|
|
23
|
+
await config.onAfter?.(esmx, pkgJson, file);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|