uniky 1.0.12 → 1.0.14

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.
@@ -0,0 +1,233 @@
1
+ # uniky 架构说明
2
+
3
+ ## 📦 混合发布模式
4
+
5
+ 从 v1.0.13 开始,`uniky` 采用**混合发布模式**,结合了源码发布和编译发布的优势。
6
+
7
+ ## 🗂️ 目录结构
8
+
9
+ ```
10
+ uniky/
11
+ ├── src/
12
+ │ ├── lib/ # TypeScript 源码(发布)
13
+ │ │ ├── hook/
14
+ │ │ │ ├── index.ts
15
+ │ │ │ └── useParam.ts
16
+ │ │ ├── http/
17
+ │ │ │ ├── index.ts
18
+ │ │ │ └── ky.ts
19
+ │ │ └── index.ts
20
+ │ │
21
+ │ └── plugin/ # TypeScript 源码(编译)
22
+ │ ├── index.ts
23
+ │ ├── pages.defined.ts
24
+ │ └── global.defined.ts
25
+
26
+ └── dist/
27
+ └── plugin/ # 编译后的 JS(发布)
28
+ ├── index.js
29
+ ├── index.d.ts
30
+ ├── pages.defined.js
31
+ ├── pages.defined.d.ts
32
+ ├── global.defined.js
33
+ └── global.defined.d.ts
34
+ ```
35
+
36
+ ## 📋 发布内容
37
+
38
+ 根据 `package.json` 的 `files` 字段:
39
+
40
+ ```json
41
+ "files": [
42
+ "src/lib", // ← lib 的 TS 源码
43
+ "dist/plugin", // ← plugin 的编译 JS
44
+ "README.md"
45
+ ]
46
+ ```
47
+
48
+ ## 🎯 为什么采用混合模式?
49
+
50
+ ### lib 部分 - TypeScript 源码
51
+
52
+ **原因**:
53
+ - 在运行时被用户代码导入使用
54
+ - 用户的 Vite 构建工具会处理 TS 编译
55
+ - peerDependencies (vue, @dcloudio/uni-app) 由用户项目提供
56
+
57
+ **优势**:
58
+ - ✅ 避免依赖冲突 - 使用项目自己的依赖版本
59
+ - ✅ 更好的类型支持 - 直接使用源码类型定义
60
+ - ✅ 调试更方便 - 可以直接查看和调试源码
61
+ - ✅ 体积更小 - 不包含重复的编译代码
62
+
63
+ **使用示例**:
64
+ ```typescript
65
+ // 在用户项目代码中
66
+ import { useParam } from 'uniky'; // ← 导入 src/lib/hook/useParam.ts
67
+
68
+ const params = useParam();
69
+ ```
70
+
71
+ ### plugin 部分 - 编译后的 JavaScript
72
+
73
+ **原因**:
74
+ - 在 Vite 配置文件中使用
75
+ - Vite 加载配置文件时使用 esbuild
76
+ - esbuild 在某些环境会尝试用 `require()` 加载模块
77
+ - 编译为 JS 可以避免 ESM 兼容性问题
78
+
79
+ **优势**:
80
+ - ✅ 兼容性好 - 支持各种 Node.js 环境
81
+ - ✅ 加载更快 - 无需实时编译
82
+ - ✅ 类型完整 - 包含 `.d.ts` 类型定义
83
+
84
+ **使用示例**:
85
+ ```typescript
86
+ // vite.config.ts
87
+ import { unikyPlugin } from 'uniky/plugin'; // ← 导入 dist/plugin/index.js
88
+
89
+ export default defineConfig({
90
+ plugins: [
91
+ uni(),
92
+ ...unikyPlugin() // ← 编译后的 JS 插件
93
+ ]
94
+ });
95
+ ```
96
+
97
+ ## ⚙️ package.json 配置
98
+
99
+ ```json
100
+ {
101
+ "type": "module",
102
+ "main": "./src/lib/index.ts",
103
+ "module": "./src/lib/index.ts",
104
+ "types": "./src/lib/index.ts",
105
+ "exports": {
106
+ ".": {
107
+ "types": "./src/lib/index.ts",
108
+ "import": "./src/lib/index.ts"
109
+ },
110
+ "./plugin": {
111
+ "types": "./dist/plugin/index.d.ts",
112
+ "import": "./dist/plugin/index.js"
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### 解读
119
+
120
+ - **`"."`** - 主入口(lib)
121
+ - 指向 TypeScript 源码
122
+ - 用户项目构建工具会处理
123
+
124
+ - **`"./plugin"`** - 插件入口
125
+ - 指向编译后的 JavaScript
126
+ - 包含类型定义文件
127
+
128
+ ## 🔧 构建配置
129
+
130
+ ### tsconfig.json
131
+
132
+ ```json
133
+ {
134
+ "compilerOptions": {
135
+ "target": "ES2020",
136
+ "module": "ESNext",
137
+ "outDir": "./dist",
138
+ // ... 其他配置
139
+ },
140
+ "include": ["src/plugin/**/*"], // ← 只编译 plugin
141
+ "exclude": ["src/lib/**/*"] // ← 排除 lib
142
+ }
143
+ ```
144
+
145
+ ### 构建脚本
146
+
147
+ ```json
148
+ {
149
+ "scripts": {
150
+ "build": "tsc", // 只编译 plugin
151
+ "prepublishOnly": "npm run build" // 发布前自动构建
152
+ }
153
+ }
154
+ ```
155
+
156
+ ## 🚀 工作流程
157
+
158
+ ### 开发流程
159
+
160
+ 1. 修改 `src/lib/*` - 无需编译
161
+ 2. 修改 `src/plugin/*` - 需要运行 `npm run build`
162
+ 3. 使用 `npm link` 链接到测试项目
163
+ 4. 清除 Vite 缓存:`rm -rf node_modules/.vite`
164
+
165
+ ### 发布流程
166
+
167
+ ```bash
168
+ # 方式一:自动发布脚本
169
+ npm run publish:auto
170
+
171
+ # 方式二:手动发布
172
+ npm run build # 编译 plugin
173
+ npm publish # 发布到 npm
174
+ ```
175
+
176
+ `prepublishOnly` 钩子确保发布前自动编译。
177
+
178
+ ## 💡 最佳实践
179
+
180
+ ### 对于库用户
181
+
182
+ 1. **使用 lib**:
183
+ ```typescript
184
+ import { useParam } from 'uniky';
185
+ ```
186
+ - 确保项目支持 TypeScript
187
+ - Vite 会自动处理编译
188
+ - 不需要任何特殊配置
189
+
190
+ 2. **使用 plugin**:
191
+ ```typescript
192
+ import { unikyPlugin } from 'uniky/plugin';
193
+ ```
194
+ - 直接使用,无需担心 ESM 问题
195
+ - 已编译为 JS,兼容性好
196
+
197
+ ### 对于库开发者
198
+
199
+ 1. **修改 lib 代码**:
200
+ - 直接修改 `src/lib/**/*`
201
+ - 无需编译
202
+
203
+ 2. **修改 plugin 代码**:
204
+ - 修改 `src/plugin/**/*`
205
+ - 运行 `npm run build`
206
+ - 测试编译后的代码
207
+
208
+ 3. **发布新版本**:
209
+ - 运行 `npm run publish:auto`
210
+ - 自动编译 + 发布
211
+
212
+ ## 🎓 技术要点
213
+
214
+ 1. **ESM 模块系统**
215
+ - `"type": "module"` 声明包为 ESM
216
+ - 所有导入使用 `.js` 扩展名
217
+ - Node.js 内置模块使用 `node:` 前缀
218
+
219
+ 2. **TypeScript 编译**
220
+ - 只编译 plugin 部分
221
+ - 生成 `.js` 和 `.d.ts` 文件
222
+ - 保持 ESM 模块格式
223
+
224
+ 3. **依赖管理**
225
+ - peerDependencies 避免依赖冲突
226
+ - 用户项目提供实际依赖
227
+ - 开发时安装 devDependencies
228
+
229
+ ## 📚 参考资料
230
+
231
+ - [Node.js ESM 文档](https://nodejs.org/api/esm.html)
232
+ - [TypeScript 模块解析](https://www.typescriptlang.org/docs/handbook/module-resolution.html)
233
+ - [Vite 插件开发](https://vitejs.dev/guide/api-plugin.html)
package/CHANGELOG.md ADDED
@@ -0,0 +1,74 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.13] - 2024-01-30
6
+
7
+ ### Changed
8
+ - **重要变更:采用混合发布模式**
9
+ - **lib 部分**:保持 TypeScript 源码(`src/lib/**/*`),由用户项目构建工具处理
10
+ - 避免依赖冲突,使用项目自己的 vue、@dcloudio/uni-app 等依赖
11
+ - 更好的类型支持和调试体验
12
+ - **plugin 部分**:编译为 JavaScript(`dist/plugin/**/*`)
13
+ - 解决 Vite 配置文件加载时的 ESM 兼容性问题
14
+ - 包含完整的类型定义文件(`.d.ts`)
15
+ - 更新 `tsconfig.json`,只编译 `src/plugin` 目录
16
+ - 更新 `package.json` exports 配置,分别指向源码和编译文件
17
+
18
+ ### Fixed
19
+ - **彻底修复 ESM 兼容性问题**
20
+ - 修复了 `uniky/plugin` 在 Vite 配置文件加载时被 `require()` 导致的 ESM 错误
21
+ - 将 Node.js 内置模块导入改为使用 `node:` 前缀 (如 `node:fs`, `node:path`)
22
+ - 在所有相对导入中添加 `.js` 扩展名,确保 ESM 环境下正确解析
23
+ - 验证在 uni-shell 项目中正常运行,无警告
24
+
25
+ ### Added
26
+ - 添加了 `tsconfig.json` 配置文件,提供完整的 TypeScript 编译配置
27
+ - 在 README 中新增"架构说明"章节,详细说明混合发布模式的优势
28
+ - 在 README 中新增"故障排除"章节,包含 7 种常见 ESM 错误的解决方案
29
+ - 在 README 中新增"开发说明"章节,包含本地开发和发布流程
30
+ - 为 uni-shell 项目创建 `UPDATE_UNIKY.md` 更新指南
31
+
32
+ ### 如何更新
33
+
34
+ 在使用 `uniky` 的项目中执行:
35
+
36
+ ```bash
37
+ # 如果是从 npm 安装
38
+ npm update uniky
39
+
40
+ # 如果是本地开发使用 npm link
41
+ cd /path/to/uniky
42
+ npm run build
43
+ npm link
44
+
45
+ cd /path/to/your-project
46
+ npm link uniky
47
+ rm -rf node_modules/.vite # 清除 Vite 缓存
48
+ ```
49
+
50
+ ## [1.0.12] - 2024-01-30
51
+
52
+ ### Changed
53
+ - 全部编译为 JavaScript(已在 1.0.13 中改为混合模式)
54
+
55
+ ## [1.0.11] - 2024-01-30
56
+
57
+ ### Fixed
58
+ - 初步 ESM 兼容性修复(未完全解决)
59
+
60
+ ### Added
61
+ - 添加了基础的 TypeScript 和 ESM 支持
62
+ - 在 README 中新增故障排除章节
63
+
64
+ ### Changed
65
+ - 优化了 `package.json` 配置,添加 `sideEffects: false`
66
+
67
+ ## [1.0.10] - 2024-01-30
68
+
69
+ ### Initial Release
70
+ - 提供 uni-app 常用 hooks
71
+ - 提供 HTTP 请求封装
72
+ - 提供 Vite 插件:
73
+ - `pagesDefinedPlugin`: 从 pages.json 生成类型安全的路由定义
74
+ - `globalDefinedPlugin`: 自动收集并生成全局类型定义
package/README.md CHANGED
@@ -4,10 +4,10 @@ uni-app 开发工具库,提供常用的 hooks、http 请求封装和 vite 插
4
4
 
5
5
  ## 特性
6
6
 
7
- - ✅ 直接使用 TypeScript 源码,无需编译
7
+ - ✅ 混合发布模式:lib 使用 TS 源码,plugin 编译为 JS
8
8
  - ✅ 与用户项目共享依赖,避免冲突
9
9
  - ✅ 完整的类型支持
10
- - ✅ 开箱即用的 Vite 插件
10
+ - ✅ 开箱即用的 Vite 插件,兼容各种构建环境
11
11
 
12
12
  ## 安装
13
13
 
@@ -207,14 +207,26 @@ npm link uniky
207
207
 
208
208
  ## 架构说明
209
209
 
210
- 本库直接发布 TypeScript 源码,不进行编译。这样做的好处:
210
+ 本库采用**混合发布模式**:
211
211
 
212
- 1. **避免依赖冲突**:使用项目自己的 vue、@dcloudio/uni-app 等依赖
213
- 2. **类型支持更好**:直接使用源码类型定义
214
- 3. **调试更方便**:可以直接查看和调试源码
215
- 4. **体积更小**:不包含编译后的代码
212
+ ### lib 部分 - TypeScript 源码
213
+ - 直接发布 TS 源码(`src/lib/**/*`)
214
+ - 由用户项目的构建工具(Vite)处理编译
215
+ - 优势:
216
+ - 避免依赖冲突,使用项目自己的 vue、@dcloudio/uni-app 等依赖
217
+ - 类型支持更好,直接使用源码类型定义
218
+ - 调试更方便,可以直接查看和调试源码
219
+ - 体积更小,不包含编译后的代码
216
220
 
217
- 用户项目的构建工具(如 Vite)会自动处理这些 TypeScript 文件的编译。
221
+ ### plugin 部分 - 编译后的 JavaScript
222
+ - 编译为 JS 文件(`dist/plugin/**/*`)
223
+ - 包含完整的类型定义(`.d.ts` 文件)
224
+ - 原因:
225
+ - Vite 配置文件在加载时使用 esbuild
226
+ - esbuild 在某些环境下会尝试用 `require()` 加载模块
227
+ - 编译为 JS 可以避免 ESM 兼容性问题
228
+
229
+ 这种混合模式结合了两种方式的优势,既保持了库的灵活性,又确保了插件的兼容性。
218
230
 
219
231
  ## 发布
220
232
 
@@ -254,6 +266,41 @@ npm run publish:auto
254
266
  5. 确认后发布到 npm
255
267
  6. 可选自动提交到 git
256
268
 
269
+ ## 开发说明
270
+
271
+ ### 本地开发
272
+
273
+ 1. 克隆仓库
274
+ ```bash
275
+ git clone https://github.com/zhuxietong/uniky.git
276
+ cd uniky
277
+ ```
278
+
279
+ 2. 安装依赖
280
+ ```bash
281
+ npm install
282
+ ```
283
+
284
+ 3. 构建 plugin(仅编译 plugin 部分)
285
+ ```bash
286
+ npm run build
287
+ ```
288
+
289
+ 4. 链接到本地项目
290
+ ```bash
291
+ npm link
292
+ cd /path/to/your-project
293
+ npm link uniky
294
+ ```
295
+
296
+ ### 发布流程
297
+
298
+ ```bash
299
+ npm run publish:auto
300
+ ```
301
+
302
+ 发布前会自动执行 `npm run build`,编译 plugin 部分。
303
+
257
304
  ## License
258
305
 
259
306
  MIT
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from 'vite';
2
+ export default function globalDefinedPlugin(): Plugin;
3
+ //# sourceMappingURL=global.defined.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.defined.d.ts","sourceRoot":"","sources":["../../src/plugin/global.defined.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAWnC,MAAM,CAAC,OAAO,UAAU,mBAAmB,IAAI,MAAM,CA6TpD"}
@@ -0,0 +1,284 @@
1
+ // 该插件用于作为 vite.config.ts 中 作为插件;
2
+ // 该插件用于收集 src/autoGen/global文件夹下的ts文件 所有export 导出的内容, 并将其合并为一个全局定义文件 src/autoGen/global.d.ts 文件 同时,生成一个 /src/autoGen/global.install.ts 文件.
3
+ // 以便在项目中全局使用这些类型定义,避免了手动维护全局类型定义文件的麻烦。
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ export default function globalDefinedPlugin() {
7
+ const globalDir = 'src/autoGen/global';
8
+ const globalDtsPath = 'src/autoGen/global.d.ts';
9
+ const installTsPath = 'src/autoGen/global.install.ts';
10
+ /**
11
+ * 递归获取目录下所有 .ts 文件(排除 .d.ts 和 install.ts)
12
+ */
13
+ function getTsFiles(dir) {
14
+ const files = [];
15
+ if (!fs.existsSync(dir)) {
16
+ return files;
17
+ }
18
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
19
+ for (const entry of entries) {
20
+ const fullPath = path.join(dir, entry.name);
21
+ if (entry.isDirectory()) {
22
+ files.push(...getTsFiles(fullPath));
23
+ }
24
+ else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts') && entry.name !== 'global.install.ts') {
25
+ files.push(fullPath);
26
+ }
27
+ }
28
+ return files;
29
+ }
30
+ /**
31
+ * 解析 TypeScript 文件,提取所有 export 的内容
32
+ */
33
+ function parseExports(filePath) {
34
+ const content = fs.readFileSync(filePath, 'utf-8');
35
+ const exports = [];
36
+ // 匹配 export default
37
+ const defaultExportRegex = /export\s+default\s+(function|class|const|let|var)?\s*([a-zA-Z_$][a-zA-Z0-9_$]*)?/g;
38
+ let match;
39
+ while ((match = defaultExportRegex.exec(content)) !== null) {
40
+ if (match[2]) {
41
+ exports.push({
42
+ name: match[2],
43
+ type: match[1] || 'const',
44
+ isDefault: true,
45
+ filePath
46
+ });
47
+ }
48
+ }
49
+ // 匹配 export function
50
+ const functionRegex = /export\s+(?:async\s+)?function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
51
+ while ((match = functionRegex.exec(content)) !== null) {
52
+ exports.push({
53
+ name: match[1],
54
+ type: 'function',
55
+ isDefault: false,
56
+ filePath
57
+ });
58
+ }
59
+ // 匹配 export const/let/var
60
+ const varRegex = /export\s+(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
61
+ while ((match = varRegex.exec(content)) !== null) {
62
+ exports.push({
63
+ name: match[1],
64
+ type: 'const',
65
+ isDefault: false,
66
+ filePath
67
+ });
68
+ }
69
+ // 匹配 export class
70
+ const classRegex = /export\s+(?:abstract\s+)?class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
71
+ while ((match = classRegex.exec(content)) !== null) {
72
+ exports.push({
73
+ name: match[1],
74
+ type: 'class',
75
+ isDefault: false,
76
+ filePath
77
+ });
78
+ }
79
+ // 匹配 export interface
80
+ const interfaceRegex = /export\s+interface\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
81
+ while ((match = interfaceRegex.exec(content)) !== null) {
82
+ exports.push({
83
+ name: match[1],
84
+ type: 'interface',
85
+ isDefault: false,
86
+ filePath
87
+ });
88
+ }
89
+ // 匹配 export type
90
+ const typeRegex = /export\s+type\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
91
+ while ((match = typeRegex.exec(content)) !== null) {
92
+ exports.push({
93
+ name: match[1],
94
+ type: 'type',
95
+ isDefault: false,
96
+ filePath
97
+ });
98
+ }
99
+ // 匹配 export enum
100
+ const enumRegex = /export\s+(?:const\s+)?enum\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
101
+ while ((match = enumRegex.exec(content)) !== null) {
102
+ exports.push({
103
+ name: match[1],
104
+ type: 'enum',
105
+ isDefault: false,
106
+ filePath
107
+ });
108
+ }
109
+ // 匹配 export { ... }
110
+ const namedExportRegex = /export\s*{([^}]+)}/g;
111
+ while ((match = namedExportRegex.exec(content)) !== null) {
112
+ const names = match[1].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim());
113
+ for (const name of names) {
114
+ if (name) {
115
+ exports.push({
116
+ name,
117
+ type: 'const',
118
+ isDefault: false,
119
+ filePath
120
+ });
121
+ }
122
+ }
123
+ }
124
+ return exports;
125
+ }
126
+ /**
127
+ * 生成 global.d.ts 文件内容
128
+ */
129
+ function generateGlobalDts(allExports) {
130
+ const imports = new Map();
131
+ // 按文件分组导出
132
+ for (const exp of allExports) {
133
+ const relativePath = path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
134
+ if (!imports.has(relativePath)) {
135
+ imports.set(relativePath, new Set());
136
+ }
137
+ if (!exp.isDefault) {
138
+ imports.get(relativePath).add(exp.name);
139
+ }
140
+ }
141
+ let content = '// 自动生成的全局类型定义文件\n';
142
+ content += '// 请勿手动修改\n\n';
143
+ // 生成 import 语句
144
+ for (const [filePath, names] of imports) {
145
+ if (names.size > 0) {
146
+ content += `import type { ${Array.from(names).join(', ')} } from './${filePath}';\n`;
147
+ }
148
+ }
149
+ content += '\n';
150
+ // 生成全局声明
151
+ content += 'declare global {\n';
152
+ // 对于函数、常量、类等,添加到全局
153
+ const globalItems = allExports.filter(exp => !exp.isDefault && exp.type !== 'interface' && exp.type !== 'type');
154
+ if (globalItems.length > 0) {
155
+ for (const exp of globalItems) {
156
+ if (exp.type === 'function') {
157
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
158
+ }
159
+ else if (exp.type === 'const') {
160
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
161
+ }
162
+ else if (exp.type === 'class') {
163
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
164
+ }
165
+ }
166
+ }
167
+ content += '}\n\n';
168
+ content += 'export {};\n';
169
+ return content;
170
+ }
171
+ /**
172
+ * 生成 global.install.ts 文件内容
173
+ */
174
+ function generateInstallTs(allExports) {
175
+ const imports = new Map();
176
+ // 按文件分组导出
177
+ for (const exp of allExports) {
178
+ const relativePath = './global/' + path.relative(path.join('src', 'autoGen', 'global'), exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
179
+ if (!imports.has(relativePath)) {
180
+ imports.set(relativePath, { names: new Set(), hasDefault: false });
181
+ }
182
+ const importInfo = imports.get(relativePath);
183
+ if (exp.isDefault) {
184
+ importInfo.hasDefault = true;
185
+ importInfo.defaultName = exp.name;
186
+ }
187
+ else if (exp.type !== 'interface' && exp.type !== 'type') {
188
+ importInfo.names.add(exp.name);
189
+ }
190
+ }
191
+ let content = '// 自动生成的全局安装文件\n';
192
+ content += '// 请勿手动修改\n\n';
193
+ // 生成 import 语句
194
+ for (const [filePath, info] of imports) {
195
+ if (info.hasDefault && info.names.size > 0) {
196
+ content += `import ${info.defaultName}, { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
197
+ }
198
+ else if (info.hasDefault) {
199
+ content += `import ${info.defaultName} from '${filePath}';\n`;
200
+ }
201
+ else if (info.names.size > 0) {
202
+ content += `import { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
203
+ }
204
+ }
205
+ content += '\n';
206
+ content += '/**\n';
207
+ content += ' * 安装全局定义\n';
208
+ content += ' * 在 main.ts 中调用此函数以注册全局变量\n';
209
+ content += ' */\n';
210
+ content += 'export function installGlobals() {\n';
211
+ // 将导出的内容挂载到 globalThis
212
+ const globalItems = allExports.filter(exp => exp.type !== 'interface' && exp.type !== 'type');
213
+ for (const exp of globalItems) {
214
+ const name = exp.isDefault ? (imports.get('./global/' + path.relative(path.join('src', 'autoGen', 'global'), exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, ''))?.defaultName || exp.name) : exp.name;
215
+ content += ` (globalThis as any).${exp.name} = ${name};\n`;
216
+ }
217
+ content += '}\n';
218
+ return content;
219
+ }
220
+ /**
221
+ * 生成所有文件
222
+ */
223
+ function generate() {
224
+ try {
225
+ const tsFiles = getTsFiles(globalDir);
226
+ if (tsFiles.length === 0) {
227
+ console.log('[globalDefined] 未找到任何 TypeScript 文件');
228
+ return;
229
+ }
230
+ // 收集所有导出
231
+ const allExports = [];
232
+ for (const file of tsFiles) {
233
+ const exports = parseExports(file);
234
+ allExports.push(...exports);
235
+ }
236
+ if (allExports.length === 0) {
237
+ console.log('[globalDefined] 未找到任何导出');
238
+ return;
239
+ }
240
+ // 生成 global.d.ts
241
+ const dtsContent = generateGlobalDts(allExports);
242
+ fs.writeFileSync(globalDtsPath, dtsContent, 'utf-8');
243
+ console.log(`[globalDefined] 已生成 ${globalDtsPath}`);
244
+ // 生成 global.install.ts
245
+ const installContent = generateInstallTs(allExports);
246
+ fs.writeFileSync(installTsPath, installContent, 'utf-8');
247
+ console.log(`[globalDefined] 已生成 ${installTsPath}`);
248
+ console.log(`[globalDefined] 共处理 ${tsFiles.length} 个文件,${allExports.length} 个导出`);
249
+ }
250
+ catch (error) {
251
+ console.error('[globalDefined] 生成失败:', error);
252
+ }
253
+ }
254
+ return {
255
+ name: 'vite-plugin-global-defined',
256
+ buildStart() {
257
+ // 构建开始时生成文件
258
+ generate();
259
+ },
260
+ configureServer(server) {
261
+ // 监听 src/autoGen/global 目录下的文件变化
262
+ server.watcher.add(globalDir);
263
+ server.watcher.on('change', (file) => {
264
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
265
+ console.log(`[globalDefined] 检测到文件变化: ${file}`);
266
+ generate();
267
+ }
268
+ });
269
+ server.watcher.on('add', (file) => {
270
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
271
+ console.log(`[globalDefined] 检测到新文件: ${file}`);
272
+ generate();
273
+ }
274
+ });
275
+ server.watcher.on('unlink', (file) => {
276
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
277
+ console.log(`[globalDefined] 检测到文件删除: ${file}`);
278
+ generate();
279
+ }
280
+ });
281
+ }
282
+ };
283
+ }
284
+ //# sourceMappingURL=global.defined.js.map