generator-mico-cli 0.2.4 → 0.2.5

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.
@@ -13,7 +13,6 @@ import { extractRoutes, getWindowMenus } from './common/menu';
13
13
  import { ensureSsoSession } from './common/request/sso';
14
14
  import {
15
15
  clearMicroAppProps,
16
- getAppNameFromEntry,
17
16
  type IMicroAppProps,
18
17
  setMicroAppProps,
19
18
  } from './common/micro';
@@ -76,74 +75,6 @@ if (typeof window !== 'undefined') {
76
75
  });
77
76
  }
78
77
 
79
- // ==================== 微应用预加载 ====================
80
- // 预加载所有微应用资源,避免快速切换时的竞态条件
81
- // 当资源已预加载时,loadMicroApp 的异步加载会快速完成,减少容器不存在的错误
82
-
83
- /**
84
- * 是否启用微应用预加载
85
- * - 可通过 URL 参数 ?prefetch=false 禁用(方便调试加载时序问题)
86
- * - 可通过 localStorage.setItem('DISABLE_MICRO_APP_PREFETCH', 'true') 禁用
87
- * - 默认启用
88
- */
89
- const isPrefetchEnabled = (): boolean => {
90
- if (typeof window === 'undefined') return false;
91
-
92
- // URL 参数优先级最高
93
- const urlParams = new URLSearchParams(window.location.search);
94
- const prefetchParam = urlParams.get('prefetch');
95
- if (prefetchParam === 'false') {
96
- console.log('[App] Prefetch disabled via URL parameter');
97
- return false;
98
- }
99
-
100
- // localStorage 开关
101
- if (localStorage.getItem('DISABLE_MICRO_APP_PREFETCH') === 'true') {
102
- console.log('[App] Prefetch disabled via localStorage');
103
- return false;
104
- }
105
-
106
- return true;
107
- };
108
-
109
- const prefetchMicroApps = () => {
110
- if (!isPrefetchEnabled()) {
111
- return;
112
- }
113
-
114
- try {
115
- const menus = getWindowMenus();
116
- const routes = extractRoutes(menus);
117
-
118
- // 筛选出所有微应用路由
119
- // 使用 getAppNameFromEntry 生成 name,与 loadMicroApp 保持一致,确保预加载缓存命中
120
- const microApps = routes
121
- .filter((route) => route.loadType === 'microapp' && route.entry)
122
- .map((route) => ({
123
- name: getAppNameFromEntry(route.entry!),
124
- entry: route.entry!,
125
- }));
126
-
127
- if (microApps.length > 0) {
128
- console.log('[App] Prefetching micro apps:', microApps);
129
- prefetchApps(microApps);
130
- }
131
- } catch (error) {
132
- console.warn('[App] Failed to prefetch micro apps:', error);
133
- }
134
- };
135
-
136
- // 在页面加载后预加载微应用
137
- if (typeof window !== 'undefined') {
138
- // 使用 requestIdleCallback 在浏览器空闲时预加载,避免影响首屏渲染
139
- if ('requestIdleCallback' in window) {
140
- window.requestIdleCallback(() => prefetchMicroApps(), { timeout: 3000 });
141
- } else {
142
- // 降级方案:延迟 1 秒后预加载
143
- setTimeout(prefetchMicroApps, 1000);
144
- }
145
- }
146
-
147
78
  // ==================== 微前端共享依赖 ====================
148
79
  // 将公共库暴露到 window,供子应用复用,避免重复打包
149
80
  // 子应用通过 externals 配置引用这些全局变量
@@ -0,0 +1,108 @@
1
+ /**
2
+ * 微应用预加载管理
3
+ *
4
+ * 策略:当前子应用挂载成功后,再逐个预加载其他子应用
5
+ * 避免与当前加载的子应用竞争网络带宽
6
+ */
7
+
8
+ import { prefetchApps } from 'qiankun';
9
+ import { extractRoutes, getWindowMenus } from './menu';
10
+ import { getAppNameFromEntry } from './micro';
11
+
12
+ /**
13
+ * 是否启用微应用预加载
14
+ * - 可通过 URL 参数 ?prefetch=false 禁用(方便调试加载时序问题)
15
+ * - 可通过 localStorage.setItem('DISABLE_MICRO_APP_PREFETCH', 'true') 禁用
16
+ * - 默认启用
17
+ */
18
+ export const isPrefetchEnabled = (): boolean => {
19
+ if (typeof window === 'undefined') return false;
20
+
21
+ // URL 参数优先级最高
22
+ const urlParams = new URLSearchParams(window.location.search);
23
+ const prefetchParam = urlParams.get('prefetch');
24
+ if (prefetchParam === 'false') {
25
+ console.log('[Prefetch] Disabled via URL parameter');
26
+ return false;
27
+ }
28
+
29
+ // localStorage 开关
30
+ if (localStorage.getItem('DISABLE_MICRO_APP_PREFETCH') === 'true') {
31
+ console.log('[Prefetch] Disabled via localStorage');
32
+ return false;
33
+ }
34
+
35
+ return true;
36
+ };
37
+
38
+ /** 已预加载的应用 entry 集合 */
39
+ const prefetchedApps = new Set<string>();
40
+
41
+ /**
42
+ * 获取所有需要预加载的微应用(排除已预加载的)
43
+ */
44
+ export const getMicroAppsForPrefetch = (
45
+ excludeEntry?: string,
46
+ ): Array<{ name: string; entry: string }> => {
47
+ try {
48
+ const menus = getWindowMenus();
49
+ const routes = extractRoutes(menus);
50
+
51
+ return routes
52
+ .filter(
53
+ (route) =>
54
+ route.loadType === 'microapp' &&
55
+ route.entry &&
56
+ route.entry !== excludeEntry &&
57
+ !prefetchedApps.has(route.entry),
58
+ )
59
+ .map((route) => ({
60
+ name: getAppNameFromEntry(route.entry!),
61
+ entry: route.entry!,
62
+ }));
63
+ } catch (error) {
64
+ console.warn('[Prefetch] Failed to get micro apps:', error);
65
+ return [];
66
+ }
67
+ };
68
+
69
+ /**
70
+ * 预加载微应用(低优先级,在浏览器空闲时并发预加载)
71
+ * @param currentEntry 当前正在加载的应用 entry,会被排除
72
+ */
73
+ export const prefetchMicroAppsLowPriority = (currentEntry?: string): void => {
74
+ if (!isPrefetchEnabled()) {
75
+ return;
76
+ }
77
+
78
+ const apps = getMicroAppsForPrefetch(currentEntry);
79
+ if (apps.length === 0) {
80
+ return;
81
+ }
82
+
83
+ // 标记为已预加载,避免重复
84
+ apps.forEach((app) => prefetchedApps.add(app.entry));
85
+
86
+ console.log(
87
+ '[Prefetch] Will prefetch micro apps:',
88
+ apps.map((a) => a.name),
89
+ );
90
+
91
+ // 使用 requestIdleCallback 确保在浏览器空闲时执行,不阻塞当前渲染
92
+ const doPrefetch = () => {
93
+ prefetchApps(apps); // qiankun 会并发预加载所有应用
94
+ };
95
+
96
+ if ('requestIdleCallback' in window) {
97
+ window.requestIdleCallback(doPrefetch, { timeout: 5000 });
98
+ } else {
99
+ setTimeout(doPrefetch, 100);
100
+ }
101
+ };
102
+
103
+ /**
104
+ * 标记应用已加载(避免重复预加载)
105
+ */
106
+ export const markAppAsPrefetched = (entry: string): void => {
107
+ prefetchedApps.add(entry);
108
+ };
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { request as rawRequest } from '@umijs/max';
18
18
  import { setStoredAuthToken } from '../auth/auth-manager';
19
- import { ROUTES } from '../constants';
19
+ import { NO_AUTH_ROUTE_LIST } from '@/constants';
20
20
 
21
21
  // 配置相关
22
22
  import {
@@ -64,7 +64,7 @@ initDefaultInterceptors(isFetchingToken, addToPendingQueue);
64
64
  * 判断当前路由是否跳过认证
65
65
  */
66
66
  const shouldSkipAuth = (): boolean => {
67
- return ROUTES.NO_AUTH_ROUTES.includes(location.pathname);
67
+ return NO_AUTH_ROUTE_LIST.includes(location.pathname);
68
68
  };
69
69
 
70
70
  /**
@@ -57,6 +57,9 @@ let isInUserInteraction = false;
57
57
  /** 交互结束时间(用于 grace period) */
58
58
  let interactionEndTime = 0;
59
59
 
60
+ /** 当前用户交互开始时间(用于判断意图是否在当前交互期间设置的) */
61
+ let currentInteractionStartTime = 0;
62
+
60
63
  /** 调试模式 */
61
64
  const DEBUG = true;
62
65
 
@@ -180,8 +183,33 @@ export function getIntentDebugInfo(): object {
180
183
  * 判断是否应该拦截此次导航
181
184
  */
182
185
  function shouldIntercept(targetPath: string): boolean {
183
- // 1. 在用户交互上下文中,允许导航并更新意图
186
+ const targetBase = getBasePath(targetPath);
187
+
188
+ // 1. 在用户交互上下文中
184
189
  if (isInInteractionContext()) {
190
+ // 检查是否有有效意图,且意图是在当前用户交互期间由 setUserIntent 设置的
191
+ // 只有这种情况才需要检查匹配,以防止微应用在 mount 过程中推送错误的路由
192
+ //
193
+ // 关键区分:
194
+ // - 意图在当前交互之前设置(如页面加载时):允许用户的新导航覆盖旧意图
195
+ // - 意图在当前交互期间由 setUserIntent 设置:正在进行微应用切换,需要保护
196
+ if (isIntentValid() && !currentIntent!.fromInteraction) {
197
+ // 检查意图是否在当前交互期间设置的
198
+ const isIntentFromCurrentInteraction = currentIntent!.timestamp >= currentInteractionStartTime;
199
+ if (isIntentFromCurrentInteraction) {
200
+ const intentBase = getBasePath(currentIntent!.path);
201
+ if (targetBase !== intentBase) {
202
+ warn('❌ 拦截不匹配意图的导航(交互上下文中):', {
203
+ targetPath,
204
+ targetBase,
205
+ intentPath: currentIntent!.path,
206
+ intentBase,
207
+ });
208
+ return true;
209
+ }
210
+ }
211
+ }
212
+ // 目标匹配意图、无有效意图、或意图是旧的,允许导航并更新意图
185
213
  log('用户交互触发导航:', targetPath);
186
214
  currentIntent = {
187
215
  path: targetPath,
@@ -198,7 +226,6 @@ function shouldIntercept(targetPath: string): boolean {
198
226
  }
199
227
 
200
228
  // 3. 有有效意图,检查目标路径是否匹配
201
- const targetBase = getBasePath(targetPath);
202
229
  const intentBase = getBasePath(currentIntent!.path);
203
230
 
204
231
  if (targetBase === intentBase) {
@@ -273,6 +300,8 @@ if (typeof window !== 'undefined') {
273
300
 
274
301
  log('用户交互开始:', event.type);
275
302
  isInUserInteraction = true;
303
+ // 记录交互开始时间,用于判断意图是否在当前交互期间设置的
304
+ currentInteractionStartTime = Date.now();
276
305
 
277
306
  // 在当前事件循环结束后重置标记
278
307
  // 使用 setTimeout 0 确保同步代码执行完毕
@@ -3,7 +3,7 @@
3
3
  * 支持在 localStorage 中存储主题状态,并在页面加载时动态加载对应的主题
4
4
  */
5
5
 
6
- import { THEME } from './constants';
6
+ import { THEME } from '@/constants';
7
7
 
8
8
  export type ThemeMode = 'light' | 'dark';
9
9
 
@@ -3,7 +3,7 @@ import type { UploadProps } from '@arco-design/web-react';
3
3
  import { Message } from '@arco-design/web-react';
4
4
  import type { UploadItem } from '@arco-design/web-react/es/Upload';
5
5
  import SparkMD5 from 'spark-md5';
6
- import type { TDirCategory } from '../constants';
6
+ import type { TDirCategory } from '@/constants';
7
7
  import type {
8
8
  OssUploadError,
9
9
  UploadLifecycleEvent,
@@ -1,4 +1,4 @@
1
- import type { TDirCategory } from '../constants';
1
+ import type { TDirCategory } from '@/constants';
2
2
 
3
3
  export interface UploadLifecycleEvent {
4
4
  stage: 'hashing' | 'signing' | 'uploading';
@@ -1,7 +1,7 @@
1
1
  // ! 这个函数不能放到 ./helpers.ts 中,因为 ./request/index.ts 从 ./helpers.ts 导入了 getFromStorage, safeParseJSON,如果放到 ./helpers.ts 中,会导致循环引入
2
2
  // ! 开发态下,发生循环引入时, mako 不会有编译时报错,但运行时会报错
3
3
 
4
- import type { TDirCategory } from './constants';
4
+ import type { TDirCategory } from '@/constants';
5
5
  import { uploadToOss } from './upload/oss';
6
6
 
7
7
  /** 上传文件到 OSS 并获取 URL */
@@ -14,11 +14,14 @@
14
14
  */
15
15
 
16
16
  import type { MicroApp } from 'qiankun';
17
- import { loadMicroApp, prefetchApps } from 'qiankun';
17
+ import { loadMicroApp } from 'qiankun';
18
18
  import { microAppLogger } from '@/common/logger';
19
19
  // 导入路由守卫(会自动初始化)
20
20
  import { refreshUserIntent, setUserIntent } from '@/common/route-guard';
21
21
 
22
+ // 导入低优先级预加载函数
23
+ import { markAppAsPrefetched, prefetchMicroAppsLowPriority } from '@/common/micro-prefetch';
24
+
22
25
  // ============================================================================
23
26
  // 类型定义
24
27
  // ============================================================================
@@ -171,6 +174,8 @@ class MicroAppManager {
171
174
  if (cached.container.parentElement !== config.target) {
172
175
  activateContainer(cached.container, config.target);
173
176
  }
177
+ // 通知组件当前状态(重要:组件可能在 cleanup 后重新挂载,需要同步状态)
178
+ this.updateState({ loading: false, error: null, mounted: true });
174
179
  }
175
180
  return;
176
181
  }
@@ -273,14 +278,6 @@ class MicroAppManager {
273
278
  this.updateState({ loading: true, error: null, mounted: false });
274
279
 
275
280
  try {
276
- // 预加载资源
277
- if (!this.appCache.has(request.name)) {
278
- try {
279
- prefetchApps([{ name: request.name, entry: request.entry }]);
280
- } catch (error) {
281
- microAppLogger.warn('Prefetch failed:', error);
282
- }
283
- }
284
281
 
285
282
  if (this.shouldAbort(request.name, mySeq)) {
286
283
  console.log('🔍[路由调试] ⚠️ Aborted before load', { name: request.name, mySeq, operationSeq: this.operationSeq });
@@ -317,13 +314,21 @@ class MicroAppManager {
317
314
  console.log('🔍[路由调试] 等待缓存实例 mountPromise...', { name: request.name });
318
315
  await withTimeout(appInstance.microApp.mountPromise, MOUNT_TIMEOUT, '子应用挂载超时');
319
316
  console.log('🔍[路由调试] 缓存实例 mountPromise 完成', { name: request.name, status: appInstance.microApp.getStatus() });
317
+ // 重要:mount 完成后立即更新 props,确保子应用使用最新的 routePath
318
+ // qiankun 的 mount() 使用的是创建实例时的原始 props,可能包含过期的 routePath
319
+ appInstance.microApp.update?.(request.props);
320
+ console.log('🔍[路由调试] 缓存实例 props 已更新(BOOTSTRAPPING 后)', { name: request.name });
320
321
  } else if (status === 'NOT_MOUNTED') {
321
322
  // 实例之前被 unmount 过,需要重新 mount
322
323
  console.log('🔍[路由调试] 开始 mount 缓存实例', { name: request.name });
323
324
  await withTimeout(appInstance.microApp.mount(), MOUNT_TIMEOUT, '子应用挂载超时');
324
325
  console.log('🔍[路由调试] 缓存实例 mount 完成', { name: request.name, status: appInstance.microApp.getStatus() });
326
+ // 重要:mount 完成后立即更新 props,确保子应用使用最新的 routePath
327
+ // qiankun 的 mount() 使用的是创建实例时的原始 props,可能包含过期的 routePath
328
+ appInstance.microApp.update?.(request.props);
329
+ console.log('🔍[路由调试] 缓存实例 props 已更新(NOT_MOUNTED 后)', { name: request.name });
325
330
  }
326
- // 如果 status === 'MOUNTED',则无需操作
331
+ // 如果 status === 'MOUNTED',则无需操作(已在 switchTo 入口处处理)
327
332
 
328
333
  // 刷新意图,保护 mount 成功后的短暂窗口期
329
334
  refreshUserIntent();
@@ -344,6 +349,10 @@ class MicroAppManager {
344
349
  console.log('🔍[路由调试] ✅ 缓存实例挂载成功', { name: request.name, qiankunName: appInstance.qiankunName, status: appInstance.microApp.getStatus() });
345
350
  this.updateState({ loading: false, error: null, mounted: true });
346
351
 
352
+ // 挂载成功后,标记当前应用已加载,并触发其他应用的低优先级预加载
353
+ markAppAsPrefetched(request.entry);
354
+ prefetchMicroAppsLowPriority(request.entry);
355
+
347
356
  } else {
348
357
  // 创建新实例
349
358
  // 使用唯一的 qiankun 实例名称,避免 qiankun 内部状态冲突
@@ -400,6 +409,11 @@ class MicroAppManager {
400
409
  await withTimeout(microApp.mountPromise, MOUNT_TIMEOUT, '子应用挂载超时');
401
410
  console.log('🔍[路由调试] mountPromise 完成', { name: request.name, qiankunName, status: microApp.getStatus() });
402
411
 
412
+ // 重要:mount 完成后调用 update,触发子应用的路由同步
413
+ // 由于子应用 mount 生命周期不再调用 syncRoute,需要通过 update 来同步路由
414
+ microApp.update?.(request.props);
415
+ console.log('🔍[路由调试] 新实例 props 已更新', { name: request.name });
416
+
403
417
  // 刷新意图,保护 mount 成功后的短暂窗口期
404
418
  refreshUserIntent();
405
419
 
@@ -421,6 +435,10 @@ class MicroAppManager {
421
435
  // 这样可以防止被 abort 的子应用在后台执行时修改路由
422
436
  console.log('🔍[路由调试] ✅ 新实例挂载成功', { name: request.name, qiankunName, status: microApp.getStatus() });
423
437
  this.updateState({ loading: false, error: null, mounted: true });
438
+
439
+ // 挂载成功后,标记当前应用已加载,并触发其他应用的低优先级预加载
440
+ markAppAsPrefetched(request.entry);
441
+ prefetchMicroAppsLowPriority(request.entry);
424
442
  }
425
443
 
426
444
  if (this.pendingRequest) {
@@ -1,15 +1,74 @@
1
- export const DEFAULT_NAME = 'Umi Max';
1
+ /**
2
+ * 应用常量定义
3
+ */
2
4
 
3
5
  /**
4
- * 无需认证的路由路径
6
+ * 路由路径常量
5
7
  */
6
- export const NO_AUTH_ROUTES = {
8
+ export const ROUTES = {
9
+ /** 登录页 */
7
10
  LOGIN: '/user/login',
11
+ /** 注册页 */
12
+ REGISTER: '/user/register',
13
+ /** 注册结果页 */
14
+ REGISTER_RESULT: '/user/register-result',
15
+ /** 403 无权限页 */
8
16
  FORBIDDEN: '/403',
17
+ /** 404 未找到页 */
9
18
  NOT_FOUND: '/404',
10
19
  } as const;
11
20
 
12
21
  /**
13
22
  * 无需认证的路由列表
14
23
  */
15
- export const NO_AUTH_ROUTE_LIST = Object.values(NO_AUTH_ROUTES);
24
+ export const NO_AUTH_ROUTE_LIST: string[] = [
25
+ ROUTES.LOGIN,
26
+ ROUTES.REGISTER,
27
+ ROUTES.REGISTER_RESULT,
28
+ ROUTES.FORBIDDEN,
29
+ ROUTES.NOT_FOUND,
30
+ ];
31
+
32
+ /**
33
+ * 主题相关常量
34
+ */
35
+ export const THEME = {
36
+ /** localStorage 存储键 */
37
+ STORAGE_KEY: 'audit-center-theme',
38
+ /** 默认主题 */
39
+ DEFAULT: 'light' as const,
40
+ /** 可选主题值 */
41
+ VALUES: ['light', 'dark'] as const,
42
+ } as const;
43
+
44
+ /**
45
+ * 时区相关常量
46
+ */
47
+ export const TIMEZONE = {
48
+ /** localStorage 存储键(IANA 时区,如 Asia/Shanghai) */
49
+ STORAGE_KEY: 'audit-center-timezone',
50
+ /** localStorage 存储键(用于展示的地区/名称,可选) */
51
+ REGION_STORAGE_KEY: 'audit-center-timezone-region',
52
+ } as const;
53
+
54
+ /**
55
+ * 在线状态相关常量
56
+ */
57
+ export const PRESENCE = {
58
+ /** localStorage 存储键 */
59
+ STORAGE_KEY: 'audit-center-presence-status',
60
+ } as const;
61
+
62
+ /**
63
+ * 存储键常量
64
+ */
65
+ export const STORAGE_KEYS = {
66
+ APP_INFO: 'appInfo',
67
+ IS_SUPERUSER: 'is_superuser',
68
+ GROUPS: 'groups',
69
+ } as const;
70
+
71
+ /**
72
+ * OSS 上传目录分类
73
+ */
74
+ export type TDirCategory = number;
@@ -11,25 +11,6 @@ import { history } from '@umijs/max';
11
11
  import { appLogger } from './common/logger';
12
12
  import { type IMicroAppProps, setMainAppProps } from './common/mainApp';
13
13
 
14
- /**
15
- * @name 独立运行时加载主题
16
- * @description 仅在开发环境且非 qiankun 环境中加载主题样式
17
- *
18
- * 实现原理:
19
- * - 生产构建时 process.env.NODE_ENV !== 'development',整个 if 块被 tree-shake
20
- * - 开发环境独立运行时加载主题,支持本地预览
21
- * - 作为微应用运行时(无论开发还是生产),使用主应用的主题
22
- */
23
- if (process.env.NODE_ENV === 'development') {
24
- // 开发环境:运行时检测是否独立运行
25
- if (typeof window !== 'undefined' && !window.__POWERED_BY_QIANKUN__) {
26
- // 直接导入主题样式(开发环境下会被打包)
27
- import('./styles/theme.less');
28
- appLogger.log('Running standalone in dev mode, theme loaded');
29
- }
30
- }
31
- // 生产环境:作为微应用时,主题由主应用注入,无需加载
32
-
33
14
  /**
34
15
  * @name 路由同步工具
35
16
  * @description 处理主应用与子应用之间的路由同步,支持通配符路由模式
@@ -73,11 +54,10 @@ export const qiankun = {
73
54
  // 保存主应用传递的 props,包括 request 实例
74
55
  setMainAppProps(props);
75
56
 
76
- // 初始路由同步:延迟到下一帧确保 React 组件已初始化
77
- if (props.routePath) {
78
- const routePath = props.routePath;
79
- requestAnimationFrame(() => syncRoute(routePath, 'initial route sync'));
80
- }
57
+ // 注意:不在 mount 中调用 syncRoute
58
+ // 原因:当子应用从缓存复用时,mount 时的 props 可能是旧的(包含过期的 routePath
59
+ // 主应用的 MicroAppManager 会在 mount 完成后立即调用 update() 传递正确的 props
60
+ // 路由同步完全由 update 生命周期处理,避免 mount 中的旧 routePath 覆盖正确的路由
81
61
  },
82
62
 
83
63
  /**
@@ -3,10 +3,10 @@
3
3
  * @description homepage 子应用的全局样式
4
4
  */
5
5
 
6
- // 仅导入 Less 变量(不包含 CSS 变量定义,避免重复打包)
7
- // CSS 变量由主应用(layout)注入到 body 上
8
- // Less 变量通过 var(--xxx) 引用 CSS 变量,自动适配主题
9
- @import '<%= packageScope %>/shared-styles/variables-only';
6
+ // 导入共享样式入口(包含 CSS 变量 + Less 变量 + Arco 覆盖样式)
7
+ // 注意:作为微前端子应用运行时,主应用会先加载这些样式
8
+ // 独立运行时,需要自己加载完整样式(包括 Arco 组件覆盖)
9
+ @import '<%= packageScope %>/shared-styles';
10
10
 
11
11
  * {
12
12
  box-sizing: border-box;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": [
6
6
  "yeoman-generator",