uniky 1.0.14 → 1.0.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniky",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "uni-app 开发工具库,包含 hooks、http 请求和 vite 插件",
5
5
  "type": "module",
6
6
  "main": "./src/lib/index.ts",
@@ -12,21 +12,19 @@
12
12
  "import": "./src/lib/index.ts"
13
13
  },
14
14
  "./plugin": {
15
- "types": "./dist/plugin/index.d.ts",
16
- "import": "./dist/plugin/index.js"
15
+ "types": "./src/plugin/index.ts",
16
+ "import": "./src/plugin/index.ts"
17
17
  }
18
18
  },
19
19
  "sideEffects": false,
20
20
  "files": [
21
21
  "src/lib",
22
- "dist/plugin",
23
- "README.md",
24
- "CHANGELOG.md",
25
- "ARCHITECTURE.md"
22
+ "src/plugin",
23
+ "scripts",
24
+ "README.md"
26
25
  ],
27
26
  "scripts": {
28
- "build": "tsc",
29
- "prepublishOnly": "npm run build",
27
+ "postinstall": "node scripts/postinstall.js",
30
28
  "publish:auto": "bash publish.sh"
31
29
  },
32
30
  "keywords": [
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ import { copyFileSync, mkdirSync, existsSync, writeFileSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ function findProjectRoot() {
10
+ let currentDir = process.cwd();
11
+ const maxDepth = 10;
12
+ let depth = 0;
13
+
14
+ while (depth < maxDepth) {
15
+ const packageJsonPath = join(currentDir, 'package.json');
16
+ if (existsSync(packageJsonPath)) {
17
+ const nodeModulesPath = join(currentDir, 'node_modules');
18
+ if (existsSync(nodeModulesPath)) {
19
+ return currentDir;
20
+ }
21
+ }
22
+ const parentDir = dirname(currentDir);
23
+ if (parentDir === currentDir) break;
24
+ currentDir = parentDir;
25
+ depth++;
26
+ }
27
+
28
+ return process.cwd();
29
+ }
30
+
31
+ function installPluginFiles() {
32
+ try {
33
+ const projectRoot = findProjectRoot();
34
+ const unikyDir = join(projectRoot, '.uniky');
35
+ const pluginDir = join(unikyDir, 'plugin');
36
+
37
+ if (!existsSync(unikyDir)) {
38
+ mkdirSync(unikyDir, { recursive: true });
39
+ }
40
+
41
+ if (!existsSync(pluginDir)) {
42
+ mkdirSync(pluginDir, { recursive: true });
43
+ }
44
+
45
+ const sourceDir = join(__dirname, '..', 'src', 'plugin');
46
+ const filesToCopy = [
47
+ 'pages.defined.ts',
48
+ 'global.defined.ts',
49
+ 'lib.defined.ts',
50
+ 'index.ts'
51
+ ];
52
+
53
+ let copiedCount = 0;
54
+ filesToCopy.forEach(file => {
55
+ const sourcePath = join(sourceDir, file);
56
+ const targetPath = join(pluginDir, file);
57
+
58
+ if (existsSync(sourcePath)) {
59
+ copyFileSync(sourcePath, targetPath);
60
+ copiedCount++;
61
+ }
62
+ });
63
+
64
+ const indexContent = `// created by zhuxietong on 2026-01-30 16:37
65
+ export * from './plugin/index.js';
66
+ `;
67
+
68
+ writeFileSync(join(unikyDir, 'index.ts'), indexContent, 'utf-8');
69
+
70
+ console.log(`[uniky] 插件文件已安装到 ${unikyDir} (${copiedCount} 个文件)`);
71
+ } catch (error) {
72
+ console.warn('[uniky] 插件文件安装失败,将在 vite 启动时自动安装:', error.message);
73
+ }
74
+ }
75
+
76
+ installPluginFiles();
@@ -0,0 +1,333 @@
1
+ // 该插件用于作为 vite.config.ts 中 作为插件;
2
+ // 该插件用于收集 src/autoGen/global文件夹下的ts文件 所有export 导出的内容, 并将其合并为一个全局定义文件 src/autoGen/global.d.ts 文件 同时,生成一个 /src/autoGen/global.install.ts 文件.
3
+ // 以便在项目中全局使用这些类型定义,避免了手动维护全局类型定义文件的麻烦。
4
+
5
+ import type { Plugin } from 'vite';
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+
9
+ interface ExportInfo {
10
+ name: string;
11
+ type: 'function' | 'const' | 'class' | 'interface' | 'type' | 'enum';
12
+ isDefault: boolean;
13
+ filePath: string;
14
+ }
15
+
16
+ export default function globalDefinedPlugin(): Plugin {
17
+ const globalDir = 'src/autoGen/global';
18
+ const globalDtsPath = 'src/autoGen/global.d.ts';
19
+ const installTsPath = 'src/autoGen/global.install.ts';
20
+
21
+ /**
22
+ * 递归获取目录下所有 .ts 文件(排除 .d.ts 和 install.ts)
23
+ */
24
+ function getTsFiles(dir: string): string[] {
25
+ const files: string[] = [];
26
+
27
+ if (!fs.existsSync(dir)) {
28
+ return files;
29
+ }
30
+
31
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
32
+
33
+ for (const entry of entries) {
34
+ const fullPath = path.join(dir, entry.name);
35
+
36
+ if (entry.isDirectory()) {
37
+ files.push(...getTsFiles(fullPath));
38
+ } else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts') && entry.name !== 'global.install.ts') {
39
+ files.push(fullPath);
40
+ }
41
+ }
42
+
43
+ return files;
44
+ }
45
+
46
+ /**
47
+ * 解析 TypeScript 文件,提取所有 export 的内容
48
+ */
49
+ function parseExports(filePath: string): ExportInfo[] {
50
+ const content = fs.readFileSync(filePath, 'utf-8');
51
+ const exports: ExportInfo[] = [];
52
+
53
+ // 匹配 export default
54
+ const defaultExportRegex = /export\s+default\s+(function|class|const|let|var)?\s*([a-zA-Z_$][a-zA-Z0-9_$]*)?/g;
55
+ let match;
56
+
57
+ while ((match = defaultExportRegex.exec(content)) !== null) {
58
+ if (match[2]) {
59
+ exports.push({
60
+ name: match[2],
61
+ type: (match[1] as any) || 'const',
62
+ isDefault: true,
63
+ filePath
64
+ });
65
+ }
66
+ }
67
+
68
+ // 匹配 export function
69
+ const functionRegex = /export\s+(?:async\s+)?function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
70
+ while ((match = functionRegex.exec(content)) !== null) {
71
+ exports.push({
72
+ name: match[1],
73
+ type: 'function',
74
+ isDefault: false,
75
+ filePath
76
+ });
77
+ }
78
+
79
+ // 匹配 export const/let/var
80
+ const varRegex = /export\s+(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
81
+ while ((match = varRegex.exec(content)) !== null) {
82
+ exports.push({
83
+ name: match[1],
84
+ type: 'const',
85
+ isDefault: false,
86
+ filePath
87
+ });
88
+ }
89
+
90
+ // 匹配 export class
91
+ const classRegex = /export\s+(?:abstract\s+)?class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
92
+ while ((match = classRegex.exec(content)) !== null) {
93
+ exports.push({
94
+ name: match[1],
95
+ type: 'class',
96
+ isDefault: false,
97
+ filePath
98
+ });
99
+ }
100
+
101
+ // 匹配 export interface
102
+ const interfaceRegex = /export\s+interface\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
103
+ while ((match = interfaceRegex.exec(content)) !== null) {
104
+ exports.push({
105
+ name: match[1],
106
+ type: 'interface',
107
+ isDefault: false,
108
+ filePath
109
+ });
110
+ }
111
+
112
+ // 匹配 export type
113
+ const typeRegex = /export\s+type\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
114
+ while ((match = typeRegex.exec(content)) !== null) {
115
+ exports.push({
116
+ name: match[1],
117
+ type: 'type',
118
+ isDefault: false,
119
+ filePath
120
+ });
121
+ }
122
+
123
+ // 匹配 export enum
124
+ const enumRegex = /export\s+(?:const\s+)?enum\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
125
+ while ((match = enumRegex.exec(content)) !== null) {
126
+ exports.push({
127
+ name: match[1],
128
+ type: 'enum',
129
+ isDefault: false,
130
+ filePath
131
+ });
132
+ }
133
+
134
+ // 匹配 export { ... }
135
+ const namedExportRegex = /export\s*{([^}]+)}/g;
136
+ while ((match = namedExportRegex.exec(content)) !== null) {
137
+ const names = match[1].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim());
138
+ for (const name of names) {
139
+ if (name) {
140
+ exports.push({
141
+ name,
142
+ type: 'const',
143
+ isDefault: false,
144
+ filePath
145
+ });
146
+ }
147
+ }
148
+ }
149
+
150
+ return exports;
151
+ }
152
+
153
+ /**
154
+ * 生成 global.d.ts 文件内容
155
+ */
156
+ function generateGlobalDts(allExports: ExportInfo[]): string {
157
+ const imports = new Map<string, Set<string>>();
158
+
159
+ // 按文件分组导出
160
+ for (const exp of allExports) {
161
+ const relativePath = path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
162
+ if (!imports.has(relativePath)) {
163
+ imports.set(relativePath, new Set());
164
+ }
165
+ if (!exp.isDefault) {
166
+ imports.get(relativePath)!.add(exp.name);
167
+ }
168
+ }
169
+
170
+ let content = '// 自动生成的全局类型定义文件\n';
171
+ content += '// 请勿手动修改\n\n';
172
+
173
+ // 生成 import 语句
174
+ for (const [filePath, names] of imports) {
175
+ if (names.size > 0) {
176
+ content += `import type { ${Array.from(names).join(', ')} } from './${filePath}';\n`;
177
+ }
178
+ }
179
+
180
+ content += '\n';
181
+
182
+ // 生成全局声明
183
+ content += 'declare global {\n';
184
+
185
+ // 对于函数、常量、类等,添加到全局
186
+ const globalItems = allExports.filter(exp => !exp.isDefault && exp.type !== 'interface' && exp.type !== 'type');
187
+ if (globalItems.length > 0) {
188
+ for (const exp of globalItems) {
189
+ if (exp.type === 'function') {
190
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
191
+ } else if (exp.type === 'const') {
192
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
193
+ } else if (exp.type === 'class') {
194
+ content += ` const ${exp.name}: typeof import('./${path.relative('src/autoGen', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
195
+ }
196
+ }
197
+ }
198
+
199
+ content += '}\n\n';
200
+ content += 'export {};\n';
201
+
202
+ return content;
203
+ }
204
+
205
+ /**
206
+ * 生成 global.install.ts 文件内容
207
+ */
208
+ function generateInstallTs(allExports: ExportInfo[]): string {
209
+ const imports = new Map<string, { names: Set<string>; hasDefault: boolean; defaultName?: string }>();
210
+
211
+ // 按文件分组导出
212
+ for (const exp of allExports) {
213
+ const relativePath = './global/' + path.relative(path.join('src', 'autoGen', 'global'), exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
214
+ if (!imports.has(relativePath)) {
215
+ imports.set(relativePath, { names: new Set(), hasDefault: false });
216
+ }
217
+ const importInfo = imports.get(relativePath)!;
218
+ if (exp.isDefault) {
219
+ importInfo.hasDefault = true;
220
+ importInfo.defaultName = exp.name;
221
+ } else if (exp.type !== 'interface' && exp.type !== 'type') {
222
+ importInfo.names.add(exp.name);
223
+ }
224
+ }
225
+
226
+ let content = '// 自动生成的全局安装文件\n';
227
+ content += '// 请勿手动修改\n\n';
228
+
229
+ // 生成 import 语句
230
+ for (const [filePath, info] of imports) {
231
+ if (info.hasDefault && info.names.size > 0) {
232
+ content += `import ${info.defaultName}, { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
233
+ } else if (info.hasDefault) {
234
+ content += `import ${info.defaultName} from '${filePath}';\n`;
235
+ } else if (info.names.size > 0) {
236
+ content += `import { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
237
+ }
238
+ }
239
+
240
+ content += '\n';
241
+ content += '/**\n';
242
+ content += ' * 安装全局定义\n';
243
+ content += ' * 在 main.ts 中调用此函数以注册全局变量\n';
244
+ content += ' */\n';
245
+ content += 'export function installGlobals() {\n';
246
+
247
+ // 将导出的内容挂载到 globalThis
248
+ const globalItems = allExports.filter(exp => exp.type !== 'interface' && exp.type !== 'type');
249
+ for (const exp of globalItems) {
250
+ 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;
251
+ content += ` (globalThis as any).${exp.name} = ${name};\n`;
252
+ }
253
+
254
+ content += '}\n';
255
+
256
+ return content;
257
+ }
258
+
259
+ /**
260
+ * 生成所有文件
261
+ */
262
+ function generate() {
263
+ try {
264
+ const tsFiles = getTsFiles(globalDir);
265
+
266
+ if (tsFiles.length === 0) {
267
+ console.log('[globalDefined] 未找到任何 TypeScript 文件');
268
+ return;
269
+ }
270
+
271
+ // 收集所有导出
272
+ const allExports: ExportInfo[] = [];
273
+ for (const file of tsFiles) {
274
+ const exports = parseExports(file);
275
+ allExports.push(...exports);
276
+ }
277
+
278
+ if (allExports.length === 0) {
279
+ console.log('[globalDefined] 未找到任何导出');
280
+ return;
281
+ }
282
+
283
+ // 生成 global.d.ts
284
+ const dtsContent = generateGlobalDts(allExports);
285
+ fs.writeFileSync(globalDtsPath, dtsContent, 'utf-8');
286
+ console.log(`[globalDefined] 已生成 ${globalDtsPath}`);
287
+
288
+ // 生成 global.install.ts
289
+ const installContent = generateInstallTs(allExports);
290
+ fs.writeFileSync(installTsPath, installContent, 'utf-8');
291
+ console.log(`[globalDefined] 已生成 ${installTsPath}`);
292
+
293
+ console.log(`[globalDefined] 共处理 ${tsFiles.length} 个文件,${allExports.length} 个导出`);
294
+ } catch (error) {
295
+ console.error('[globalDefined] 生成失败:', error);
296
+ }
297
+ }
298
+
299
+ return {
300
+ name: 'vite-plugin-global-defined',
301
+
302
+ buildStart() {
303
+ // 构建开始时生成文件
304
+ generate();
305
+ },
306
+
307
+ configureServer(server) {
308
+ // 监听 src/autoGen/global 目录下的文件变化
309
+ server.watcher.add(globalDir);
310
+
311
+ server.watcher.on('change', (file) => {
312
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
313
+ console.log(`[globalDefined] 检测到文件变化: ${file}`);
314
+ generate();
315
+ }
316
+ });
317
+
318
+ server.watcher.on('add', (file) => {
319
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
320
+ console.log(`[globalDefined] 检测到新文件: ${file}`);
321
+ generate();
322
+ }
323
+ });
324
+
325
+ server.watcher.on('unlink', (file) => {
326
+ if (file.includes('src/autoGen/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
327
+ console.log(`[globalDefined] 检测到文件删除: ${file}`);
328
+ generate();
329
+ }
330
+ });
331
+ }
332
+ };
333
+ }
@@ -0,0 +1,32 @@
1
+ // created by zhuxietong on 2026-01-30 16:37
2
+ import type { Plugin } from 'vite';
3
+
4
+ import pagesDefinedPlugin from './pages.defined';
5
+ import globalDefinedPlugin from './global.defined';
6
+
7
+
8
+
9
+ export interface UnikyPluginOptions {
10
+ enablePages?: boolean;
11
+ enableGlobal?: boolean;
12
+ }
13
+
14
+ export function unikyPlugin(options: UnikyPluginOptions = {}): Plugin[] {
15
+ const { enablePages = true, enableGlobal = true } = options;
16
+
17
+ const plugins: Plugin[] = [];
18
+
19
+ if (enablePages) {
20
+ plugins.push(pagesDefinedPlugin());
21
+ }
22
+
23
+ if (enableGlobal) {
24
+ plugins.push(globalDefinedPlugin());
25
+ }
26
+
27
+ return plugins;
28
+ }
29
+
30
+ export { pagesDefinedPlugin, globalDefinedPlugin };
31
+
32
+ export default unikyPlugin;
@@ -0,0 +1,2 @@
1
+
2
+ export { }