flu-cli 2.0.6 → 2.1.0

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +17 -4
  3. package/config/dev.config.js +11 -11
  4. package/config/templates.js +10 -10
  5. package/index.js +554 -102
  6. package/lib/commands/add.js +365 -266
  7. package/lib/commands/assets.js +77 -78
  8. package/lib/commands/cache.js +29 -52
  9. package/lib/commands/completion.js +13 -11
  10. package/lib/commands/config.js +150 -44
  11. package/lib/commands/init-ai-base.js +89 -0
  12. package/lib/commands/newClack.js +269 -178
  13. package/lib/commands/snippets.js +58 -43
  14. package/lib/commands/template.js +98 -58
  15. package/lib/commands/templates.js +101 -57
  16. package/lib/commands/upload.js +313 -0
  17. package/lib/commands/vnext-options.js +206 -0
  18. package/lib/generators/model_generator.js +91 -88
  19. package/lib/generators/page_generator.js +100 -93
  20. package/lib/generators/service_generator.js +44 -39
  21. package/lib/generators/viewmodel_generator.js +25 -29
  22. package/lib/generators/widget_generator.js +30 -35
  23. package/lib/templates/templateCopier.js +14 -15
  24. package/lib/templates/templateManager.js +22 -21
  25. package/lib/utils/config.js +37 -20
  26. package/lib/utils/flutterHelper.js +2 -2
  27. package/lib/utils/i18n.js +3 -3
  28. package/lib/utils/index_updater.js +22 -23
  29. package/lib/utils/json-output.js +59 -0
  30. package/lib/utils/logger.js +17 -17
  31. package/lib/utils/project_detector.js +66 -66
  32. package/lib/utils/snippet_loader.js +21 -19
  33. package/lib/utils/string_helper.js +13 -13
  34. package/lib/utils/templateSelectorEnquirer.js +94 -108
  35. package/locales/en-US.json +1 -1
  36. package/locales/zh-CN.json +2 -2
  37. package/package.json +60 -57
  38. package/scripts/smoke-vnext-generate.mjs +1934 -0
  39. package/scripts/smoke-vnext-params.mjs +92 -0
  40. package/CLI.md +0 -513
  41. package/release.sh +0 -529
  42. package/scripts/e2e-state-tests.js +0 -116
  43. package/scripts/sync-base-to-templates.js +0 -108
  44. package/scripts/workspace-clone-all.sh +0 -101
  45. package/scripts/workspace-status-all.sh +0 -112
@@ -1,38 +1,38 @@
1
- import * as p from '@clack/prompts';
2
- import chalk from 'chalk';
3
- import { join } from 'path';
4
- import { existsSync } from 'fs';
5
- import { AppAssetsManager, ConsoleLogger } from 'flu-cli-core';
6
- import { t } from '../utils/i18n.js';
1
+ import * as p from '@clack/prompts'
2
+ import chalk from 'chalk'
3
+ import { join } from 'path'
4
+ import { existsSync } from 'fs'
5
+ import { AppAssetsManager, ConsoleLogger } from 'flu-cli-core'
6
+ import { t } from '../utils/i18n.js'
7
7
 
8
- const logger = new ConsoleLogger();
8
+ const logger = new ConsoleLogger()
9
9
 
10
10
  /**
11
11
  * 交互式配置应用资源
12
12
  */
13
- export async function configAssets (options) {
14
- const projectPath = options.dir || process.cwd();
13
+ export async function configAssets(options) {
14
+ const projectPath = options.dir || process.cwd()
15
15
 
16
16
  // 检查是否在 Flutter 项目中
17
17
  if (!existsSync(join(projectPath, 'pubspec.yaml'))) {
18
- logger.error(t('assets.not_flutter'));
19
- return;
18
+ logger.error(t('assets.not_flutter'))
19
+ return
20
20
  }
21
21
 
22
- p.intro(chalk.cyan.bold(t('assets.intro')));
22
+ p.intro(chalk.cyan.bold(t('assets.intro')))
23
23
 
24
24
  try {
25
- const assets = {};
25
+ const assets = {}
26
26
 
27
27
  // 1. 配置应用图标
28
28
  const setupIcon = await p.confirm({
29
29
  message: t('assets.setup_icon'),
30
- initialValue: true
31
- });
30
+ initialValue: true,
31
+ })
32
32
 
33
33
  if (p.isCancel(setupIcon)) {
34
- p.cancel(t('common.cancel'));
35
- return;
34
+ p.cancel(t('common.cancel'))
35
+ return
36
36
  }
37
37
 
38
38
  if (setupIcon) {
@@ -40,29 +40,29 @@ export async function configAssets (options) {
40
40
  message: t('assets.icon_path'),
41
41
  placeholder: 'assets/logo.png',
42
42
  validate: (value) => {
43
- if (!value) return '路径不能为空';
43
+ if (!value) return '路径不能为空'
44
44
  if (!existsSync(join(projectPath, value)) && !existsSync(value)) {
45
- return '找不到该文件,请确认路径是否正确';
45
+ return '找不到该文件,请确认路径是否正确'
46
46
  }
47
- }
48
- });
47
+ },
48
+ })
49
49
 
50
50
  if (p.isCancel(iconPath)) {
51
- p.cancel(t('common.cancel'));
52
- return;
51
+ p.cancel(t('common.cancel'))
52
+ return
53
53
  }
54
- assets.appIcon = iconPath;
54
+ assets.appIcon = iconPath
55
55
  }
56
56
 
57
57
  // 2. 配置启动图
58
58
  const setupSplash = await p.confirm({
59
59
  message: t('assets.setup_splash'),
60
- initialValue: true
61
- });
60
+ initialValue: true,
61
+ })
62
62
 
63
63
  if (p.isCancel(setupSplash)) {
64
- p.cancel(t('common.cancel'));
65
- return;
64
+ p.cancel(t('common.cancel'))
65
+ return
66
66
  }
67
67
 
68
68
  if (setupSplash) {
@@ -70,114 +70,113 @@ export async function configAssets (options) {
70
70
  message: t('assets.splash_logo'),
71
71
  placeholder: 'assets/logo.png',
72
72
  validate: (value) => {
73
- if (!value) return '路径不能为空';
73
+ if (!value) return '路径不能为空'
74
74
  if (!existsSync(join(projectPath, value)) && !existsSync(value)) {
75
- return '找不到该文件,请确认路径是否正确';
75
+ return '找不到该文件,请确认路径是否正确'
76
76
  }
77
- }
78
- });
77
+ },
78
+ })
79
79
 
80
80
  if (p.isCancel(splashLogo)) {
81
- p.cancel(t('common.cancel'));
82
- return;
81
+ p.cancel(t('common.cancel'))
82
+ return
83
83
  }
84
- assets.splashLogo = splashLogo;
84
+ assets.splashLogo = splashLogo
85
85
 
86
86
  const bgColor = await p.text({
87
87
  message: t('assets.bg_color'),
88
88
  placeholder: '#FFFFFF',
89
- initialValue: '#FFFFFF'
90
- });
89
+ initialValue: '#FFFFFF',
90
+ })
91
91
 
92
92
  if (p.isCancel(bgColor)) {
93
- p.cancel(t('common.cancel'));
94
- return;
93
+ p.cancel(t('common.cancel'))
94
+ return
95
95
  }
96
- assets.splashBackgroundColor = bgColor;
96
+ assets.splashBackgroundColor = bgColor
97
97
 
98
98
  const useBgImage = await p.confirm({
99
99
  message: t('assets.use_bg_image'),
100
- initialValue: false
101
- });
100
+ initialValue: false,
101
+ })
102
102
 
103
103
  if (p.isCancel(useBgImage)) {
104
- p.cancel(t('common.cancel'));
105
- return;
104
+ p.cancel(t('common.cancel'))
105
+ return
106
106
  }
107
107
 
108
108
  if (useBgImage) {
109
109
  const bgImagePath = await p.text({
110
110
  message: t('assets.bg_image_path'),
111
111
  validate: (value) => {
112
- if (!value) return '路径不能为空';
112
+ if (!value) return '路径不能为空'
113
113
  if (!existsSync(join(projectPath, value)) && !existsSync(value)) {
114
- return '找不到该文件';
114
+ return '找不到该文件'
115
115
  }
116
- }
117
- });
116
+ },
117
+ })
118
118
  if (p.isCancel(bgImagePath)) {
119
- p.cancel(t('common.cancel'));
120
- return;
119
+ p.cancel(t('common.cancel'))
120
+ return
121
121
  }
122
- assets.splashBackground = bgImagePath;
122
+ assets.splashBackground = bgImagePath
123
123
  }
124
124
 
125
125
  // 暗黑模式支持
126
126
  const enableDark = await p.confirm({
127
127
  message: t('assets.setup_dark'),
128
- initialValue: false
129
- });
128
+ initialValue: false,
129
+ })
130
130
 
131
131
  if (p.isCancel(enableDark)) {
132
- p.cancel(t('common.cancel'));
133
- return;
132
+ p.cancel(t('common.cancel'))
133
+ return
134
134
  }
135
135
 
136
136
  if (enableDark) {
137
- assets.enableDarkMode = true;
137
+ assets.enableDarkMode = true
138
138
 
139
139
  const darkBgColor = await p.text({
140
140
  message: t('assets.dark_bg_color'),
141
141
  placeholder: '#000000',
142
- initialValue: '#000000'
143
- });
144
- if (!p.isCancel(darkBgColor)) assets.splashBackgroundColorDark = darkBgColor;
142
+ initialValue: '#000000',
143
+ })
144
+ if (!p.isCancel(darkBgColor)) assets.splashBackgroundColorDark = darkBgColor
145
145
 
146
146
  const useDarkLogo = await p.confirm({
147
147
  message: t('assets.use_dark_logo'),
148
- initialValue: false
149
- });
148
+ initialValue: false,
149
+ })
150
150
  if (useDarkLogo) {
151
151
  const darkLogoPath = await p.text({
152
- message: t('assets.dark_logo_path')
153
- });
154
- if (!p.isCancel(darkLogoPath)) assets.splashLogoDark = darkLogoPath;
152
+ message: t('assets.dark_logo_path'),
153
+ })
154
+ if (!p.isCancel(darkLogoPath)) assets.splashLogoDark = darkLogoPath
155
155
  }
156
156
  }
157
157
  }
158
158
 
159
159
  if (Object.keys(assets).length === 0) {
160
- p.note(t('assets.no_assets'));
161
- p.outro(chalk.gray(t('common.bye')));
162
- return;
160
+ p.note(t('assets.no_assets'))
161
+ p.outro(chalk.gray(t('common.bye')))
162
+ return
163
163
  }
164
164
 
165
- const s = p.spinner();
166
- s.start(t('assets.configuring'));
165
+ const s = p.spinner()
166
+ s.start(t('assets.configuring'))
167
167
 
168
- const assetsManager = new AppAssetsManager();
169
- const success = await assetsManager.setupAppAssets(projectPath, assets, logger);
168
+ const assetsManager = new AppAssetsManager()
169
+ const success = await assetsManager.setupAppAssets(projectPath, assets, logger)
170
170
 
171
171
  if (success) {
172
- s.stop(t('assets.success'));
173
- p.outro(chalk.green.bold(t('assets.done')));
172
+ s.stop(t('assets.success'))
173
+ p.outro(chalk.green.bold(t('assets.done')))
174
174
  } else {
175
- s.stop(t('assets.failed'));
176
- p.outro(chalk.red(t('assets.error_outro')));
175
+ s.stop(t('assets.failed'))
176
+ p.outro(chalk.red(t('assets.error_outro')))
177
177
  }
178
-
179
178
  } catch (error) {
180
- p.cancel(`发生错误: ${error.message}`);
181
- process.exit(1);
179
+ p.cancel(`发生错误: ${error.message}`)
180
+ process.exit(1)
182
181
  }
183
182
  }
@@ -3,97 +3,74 @@
3
3
  * 更新和清理模板缓存
4
4
  */
5
5
 
6
- import { logger } from '../utils/logger.js';
7
- import { getAllTemplates } from '../../config/templates.js';
8
- import { cloneOrUpdateTemplate, getTemplateCachePath, checkTemplateUpdate } from '../templates/templateManager.js';
9
- import fsExtra from 'fs-extra';
10
- import ora from 'ora';
11
-
12
- const { removeSync, existsSync } = fsExtra;
6
+ import { logger } from '../utils/logger.js'
7
+ import { getAllTemplates } from '../../config/templates.js'
8
+ import { TemplateManager } from 'flu-cli-core'
9
+ import { cloneOrUpdateTemplate, checkTemplateUpdate } from '../templates/templateManager.js'
10
+ import ora from 'ora'
13
11
 
14
12
  /**
15
13
  * 更新模板缓存
16
14
  */
17
- export async function updateTemplates (templateName, options = {}) {
18
- logger.title('🔄 更新模板缓存');
15
+ export async function updateTemplates(templateName, options = {}) {
16
+ logger.title('🔄 更新模板缓存')
19
17
 
20
18
  if (templateName) {
21
19
  // 更新指定模板
22
- await updateSingleTemplate(templateName, options);
20
+ await updateSingleTemplate(templateName, options)
23
21
  } else {
24
22
  // 更新所有模板
25
- const templates = getAllTemplates();
23
+ const templates = getAllTemplates()
26
24
 
27
25
  for (const template of templates) {
28
- await updateSingleTemplate(template.name.toLowerCase(), options);
26
+ await updateSingleTemplate(template.name.toLowerCase(), options)
29
27
  }
30
28
  }
31
29
 
32
- logger.newLine();
33
- logger.success('模板更新完成');
30
+ logger.newLine()
31
+ logger.success('模板更新完成')
34
32
  }
35
33
 
36
34
  /**
37
35
  * 更新单个模板
38
36
  */
39
- async function updateSingleTemplate (templateName, options = {}) {
40
- const templates = getAllTemplates();
41
- const template = templates.find(t => t.name.toLowerCase() === templateName);
37
+ async function updateSingleTemplate(templateName, options = {}) {
38
+ const templates = getAllTemplates()
39
+ const template = templates.find((t) => t.name.toLowerCase() === templateName)
42
40
 
43
41
  if (!template) {
44
- logger.error(`模板 "${templateName}" 不存在`);
45
- return;
42
+ logger.error(`模板 "${templateName}" 不存在`)
43
+ return
46
44
  }
47
45
 
48
- logger.info(`检查模板 ${template.displayName}...`);
46
+ logger.info(`检查模板 ${template.displayName}...`)
49
47
 
50
- const updateInfo = await checkTemplateUpdate(templateName);
48
+ const updateInfo = await checkTemplateUpdate(templateName)
51
49
 
52
50
  // 更新模板
53
- const spinner = ora(`更新 ${template.displayName}...`).start();
51
+ const spinner = ora(`更新 ${template.displayName}...`).start()
54
52
 
55
- const result = await cloneOrUpdateTemplate(
56
- templateName,
57
- template.repo,
58
- template.branch,
59
- true
60
- );
53
+ const result = await cloneOrUpdateTemplate(templateName, template.repo, template.branch, true)
61
54
 
62
55
  if (result) {
63
- spinner.succeed(`${template.displayName} 更新成功`);
56
+ spinner.succeed(`${template.displayName} 更新成功`)
64
57
  } else {
65
- spinner.fail(`${template.displayName} 更新失败`);
58
+ spinner.fail(`${template.displayName} 更新失败`)
66
59
  }
67
60
  }
68
61
 
69
62
  /**
70
63
  * 清理缓存
71
64
  */
72
- export async function cleanCache () {
73
- logger.title('🗑️ 清理模板缓存');
74
-
75
- const templates = getAllTemplates();
76
- let cleaned = 0;
77
-
78
- for (const template of templates) {
79
- const templateName = template.name.toLowerCase();
80
- const cachePath = getTemplateCachePath(templateName);
65
+ export async function cleanCache() {
66
+ logger.title('🗑️ 清理模板缓存')
81
67
 
82
- if (existsSync(cachePath)) {
83
- try {
84
- removeSync(cachePath);
85
- logger.success(`已清理: ${template.displayName}`);
86
- cleaned++;
87
- } catch (error) {
88
- logger.error(`清理失败: ${template.displayName} - ${error.message}`);
89
- }
90
- }
91
- }
68
+ const cleaned = await TemplateManager.getInstance().cleanBuiltinTemplateCache(logger)
92
69
 
93
- logger.newLine();
70
+ logger.newLine()
94
71
  if (cleaned > 0) {
95
- logger.success(`已清理 ${cleaned} 个模板缓存`);
72
+ logger.success(`已清理 ${cleaned} 个内置模板缓存`)
96
73
  } else {
97
- logger.info('没有需要清理的缓存');
74
+ logger.info('没有需要清理的缓存')
98
75
  }
99
76
  }
@@ -1,10 +1,7 @@
1
- import chalk from 'chalk';
1
+ import chalk from 'chalk'
2
2
 
3
- /**
4
- * 生成 Shell 自动补全脚本
5
- */
6
- export function completion () {
7
- const script = `
3
+ export function getCompletionScript() {
4
+ return `
8
5
  ###-begin-flu-cli-completion-###
9
6
  #
10
7
  # flu-cli command completion script
@@ -83,10 +80,15 @@ if type compdef &>/dev/null; then
83
80
  fi
84
81
 
85
82
  ###-end-flu-cli-completion-###
86
- `;
83
+ `
84
+ }
87
85
 
88
- console.log(script);
89
- console.error(chalk.green('✅ 补全脚本已生成'));
90
- console.error(chalk.gray('请将其添加到您的 shell 配置文件中 (例如 ~/.zshrc 或 ~/.bashrc)'));
91
- console.error(chalk.gray('用法: flu-cli completion >> ~/.zshrc && source ~/.zshrc'));
86
+ /**
87
+ * 生成 Shell 自动补全脚本
88
+ */
89
+ export function completion() {
90
+ console.log(getCompletionScript())
91
+ console.error(chalk.green('✅ 补全脚本已生成'))
92
+ console.error(chalk.gray('请将其添加到您的 shell 配置文件中 (例如 ~/.zshrc 或 ~/.bashrc)'))
93
+ console.error(chalk.gray('用法: flu-cli completion >> ~/.zshrc && source ~/.zshrc'))
92
94
  }
@@ -3,108 +3,214 @@
3
3
  * 职责:初始化和管理项目配置文件
4
4
  */
5
5
 
6
- import { ProjectConfigManager, detectProjectTemplate, ConfigManager } from 'flu-cli-core';
7
- import { writeFileSync, existsSync } from 'fs';
8
- import { join } from 'path';
9
- import chalk from 'chalk';
6
+ import {
7
+ ProjectConfigManager,
8
+ detectProjectTemplate,
9
+ ConfigManager,
10
+ listGeneratorSelectableOptions,
11
+ } from 'flu-cli-core'
12
+ import { writeFileSync, existsSync } from 'fs'
13
+ import { join } from 'path'
14
+ import chalk from 'chalk'
15
+
16
+ export function initConfigWithReport(options) {
17
+ const diagnostics = []
18
+ try {
19
+ const projectDir = options.dir || process.cwd()
20
+ const configPath = join(projectDir, '.flu-cli.json')
21
+
22
+ if (existsSync(configPath) && !options.force) {
23
+ diagnostics.push('配置文件已存在 (.flu-cli.json),使用 --force 覆盖')
24
+ return { ok: false, diagnostics, configPath, template: null, written: false }
25
+ }
26
+
27
+ const template = detectProjectTemplate(projectDir) || 'custom'
28
+ const config = ProjectConfigManager.getDefaultConfigTemplate(template)
29
+
30
+ try {
31
+ const pageConfig = config.generators && config.generators.page
32
+ if (pageConfig && pageConfig.withBasePage) {
33
+ const possiblePaths = [
34
+ join(projectDir, 'lib/base/base_page.dart'),
35
+ join(projectDir, 'lib/core/base/base_page.dart'),
36
+ join(projectDir, 'lib/core/presentation/base/base_page.dart'),
37
+ ]
38
+
39
+ if (pageConfig.basePageImport && pageConfig.basePageImport.startsWith('lib/')) {
40
+ possiblePaths.unshift(join(projectDir, pageConfig.basePageImport))
41
+ }
42
+
43
+ const basePageExists = possiblePaths.some((p) => existsSync(p))
44
+ if (!basePageExists) {
45
+ diagnostics.push('Smart Init: 未检测到 BasePage 文件,降级为原生模式 (Native Mode)')
46
+ if (config.generators && config.generators.page) {
47
+ config.generators.page.withBasePage = false
48
+ config.generators.page.withViewModel = false
49
+ }
50
+ if (config.generators && config.generators.viewModel) {
51
+ config.generators.viewModel.withBaseViewModel = false
52
+ }
53
+ }
54
+ }
55
+ } catch (e) {
56
+ diagnostics.push(`Smart Init 检查失败: ${e.message || e}`)
57
+ }
58
+
59
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8')
60
+ return { ok: true, diagnostics, configPath, template, written: true }
61
+ } catch (error) {
62
+ return { ok: false, diagnostics: [`初始化配置失败: ${error.message}`], configPath: null }
63
+ }
64
+ }
65
+
66
+ export function setConfigWithReport(key, value) {
67
+ const diagnostics = []
68
+ try {
69
+ const config = ConfigManager.getInstance()
70
+ if (key === 'locale') {
71
+ if (!['zh-CN', 'en-US'].includes(value)) {
72
+ diagnostics.push(`不支持的语言: ${value}`)
73
+ diagnostics.push('支持: zh-CN, en-US')
74
+ return { ok: false, diagnostics, key, value }
75
+ }
76
+ config.setLocale(value)
77
+ return { ok: true, diagnostics, key, value }
78
+ }
79
+ diagnostics.push(`不支持的配置项: ${key}`)
80
+ return { ok: false, diagnostics, key, value }
81
+ } catch (e) {
82
+ return { ok: false, diagnostics: [String(e?.message || e)], key, value }
83
+ }
84
+ }
85
+
86
+ export function getConfigWithReport(key) {
87
+ const config = ConfigManager.getInstance()
88
+ if (key === 'locale') {
89
+ return { ok: true, diagnostics: [], key, value: config.getLocale() }
90
+ }
91
+ if (key) {
92
+ return { ok: false, diagnostics: [`未知配置项: ${key}`], key, value: null }
93
+ }
94
+ return {
95
+ ok: true,
96
+ diagnostics: [],
97
+ key: null,
98
+ value: {
99
+ locale: config.getLocale(),
100
+ author: config.getAuthorName(),
101
+ },
102
+ }
103
+ }
104
+
105
+ export function listGeneratorSelectableOptionsWithReport(options) {
106
+ const projectDir = options.dir || process.cwd()
107
+ const target = options.target || 'page'
108
+ try {
109
+ const report = listGeneratorSelectableOptions(projectDir, target)
110
+ return { ok: true, diagnostics: report.diagnostics ?? [], report }
111
+ } catch (e) {
112
+ return { ok: false, diagnostics: [String(e?.message || e)], report: null }
113
+ }
114
+ }
10
115
 
11
116
  /**
12
117
  * 初始化配置文件
13
118
  */
14
- export function initConfig (options) {
119
+ export function initConfig(options) {
15
120
  try {
16
- const projectDir = options.dir || process.cwd();
17
- const configPath = join(projectDir, '.flu-cli.json');
121
+ const projectDir = options.dir || process.cwd()
122
+ const configPath = join(projectDir, '.flu-cli.json')
18
123
 
19
124
  if (existsSync(configPath) && !options.force) {
20
- console.log(chalk.yellow('⚠️ 配置文件已存在 (.flu-cli.json)'));
21
- console.log(chalk.gray('使用 --force 覆盖'));
22
- return;
125
+ console.log(chalk.yellow('⚠️ 配置文件已存在 (.flu-cli.json)'))
126
+ console.log(chalk.gray('使用 --force 覆盖'))
127
+ return
23
128
  }
24
129
 
25
130
  // 检测当前项目模板,生成对应的默认配置
26
- const template = detectProjectTemplate(projectDir) || 'custom';
27
- let config = ProjectConfigManager.getDefaultConfigTemplate(template);
131
+ const template = detectProjectTemplate(projectDir) || 'custom'
132
+ let config = ProjectConfigManager.getDefaultConfigTemplate(template)
28
133
 
29
134
  // Smart Init: 现实检查,防止默认配置依赖的 BasePage/BaseViewModel 在项目中不存在
30
135
  try {
31
- const pageConfig = config.generators && config.generators.page;
136
+ const pageConfig = config.generators && config.generators.page
32
137
  if (pageConfig && pageConfig.withBasePage) {
33
138
  const possiblePaths = [
34
139
  join(projectDir, 'lib/base/base_page.dart'),
35
140
  join(projectDir, 'lib/core/base/base_page.dart'),
36
- join(projectDir, 'lib/core/presentation/base/base_page.dart')
37
- ];
141
+ join(projectDir, 'lib/core/presentation/base/base_page.dart'),
142
+ ]
38
143
 
39
144
  if (pageConfig.basePageImport && pageConfig.basePageImport.startsWith('lib/')) {
40
- possiblePaths.unshift(join(projectDir, pageConfig.basePageImport));
145
+ possiblePaths.unshift(join(projectDir, pageConfig.basePageImport))
41
146
  }
42
147
 
43
- const basePageExists = possiblePaths.some(p => existsSync(p));
148
+ const basePageExists = possiblePaths.some((p) => existsSync(p))
44
149
 
45
150
  if (!basePageExists) {
46
- console.log(chalk.yellow('Smart Init: 未检测到 BasePage 文件,降级为原生模式 (Native Mode)'));
151
+ console.log(
152
+ chalk.yellow('Smart Init: 未检测到 BasePage 文件,降级为原生模式 (Native Mode)'),
153
+ )
47
154
  if (config.generators && config.generators.page) {
48
- config.generators.page.withBasePage = false;
49
- config.generators.page.withViewModel = false;
155
+ config.generators.page.withBasePage = false
156
+ config.generators.page.withViewModel = false
50
157
  }
51
158
  if (config.generators && config.generators.viewModel) {
52
- config.generators.viewModel.withBaseViewModel = false;
159
+ config.generators.viewModel.withBaseViewModel = false
53
160
  }
54
161
  }
55
162
  }
56
163
  } catch (e) {
57
- console.log(chalk.gray(`Smart Init 检查失败: ${e.message || e}`));
164
+ console.log(chalk.gray(`Smart Init 检查失败: ${e.message || e}`))
58
165
  }
59
166
 
60
- writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
61
-
62
- console.log(chalk.green(`✓ 配置文件已生成: ${configPath}`));
63
- console.log(chalk.cyan(`ℹ️ 基于检测到的模板类型: ${template}`));
64
- console.log(chalk.gray('你可以编辑 .flu-cli.json 来自定义生成规则'));
167
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8')
65
168
 
169
+ console.log(chalk.green(`✓ 配置文件已生成: ${configPath}`))
170
+ console.log(chalk.cyan(`ℹ️ 基于检测到的模板类型: ${template}`))
171
+ console.log(chalk.gray('你可以编辑 .flu-cli.json 来自定义生成规则'))
66
172
  } catch (error) {
67
- console.error(chalk.red(`初始化配置失败: ${error.message}`));
68
- process.exit(1);
173
+ console.error(chalk.red(`初始化配置失败: ${error.message}`))
174
+ process.exit(1)
69
175
  }
70
176
  }
71
177
 
72
178
  /**
73
179
  * 设置全局配置
74
180
  */
75
- export function setConfig (key, value) {
76
- const config = ConfigManager.getInstance();
181
+ export function setConfig(key, value) {
182
+ const config = ConfigManager.getInstance()
77
183
 
78
184
  // 目前只支持 locale
79
185
  if (key === 'locale') {
80
186
  if (!['zh-CN', 'en-US'].includes(value)) {
81
- console.log(chalk.red(`不支持的语言: ${value}`));
82
- console.log(chalk.gray('支持: zh-CN, en-US'));
83
- return;
187
+ console.log(chalk.red(`不支持的语言: ${value}`))
188
+ console.log(chalk.gray('支持: zh-CN, en-US'))
189
+ return
84
190
  }
85
- config.setLocale(value);
86
- console.log(chalk.green(`✓ 全局配置已更新: ${key} = ${value}`));
191
+ config.setLocale(value)
192
+ console.log(chalk.green(`✓ 全局配置已更新: ${key} = ${value}`))
87
193
  } else {
88
- console.log(chalk.yellow(`不支持的配置项: ${key}`));
194
+ console.log(chalk.yellow(`不支持的配置项: ${key}`))
89
195
  }
90
196
  }
91
197
 
92
198
  /**
93
199
  * 获取全局配置
94
200
  */
95
- export function getConfig (key) {
96
- const config = ConfigManager.getInstance();
201
+ export function getConfig(key) {
202
+ const config = ConfigManager.getInstance()
97
203
 
98
204
  if (key === 'locale') {
99
- const val = config.getLocale();
100
- console.log(`${key} = ${val}`);
205
+ const val = config.getLocale()
206
+ console.log(`${key} = ${val}`)
101
207
  } else {
102
208
  // 简单起见,如果 key 未知,显示 list
103
209
  if (key) {
104
- console.log(chalk.yellow(`未知配置项: ${key}`));
210
+ console.log(chalk.yellow(`未知配置项: ${key}`))
105
211
  } else {
106
- console.log(`locale = ${config.getLocale()}`);
107
- console.log(`author = ${config.getAuthorName()}`);
212
+ console.log(`locale = ${config.getLocale()}`)
213
+ console.log(`author = ${config.getAuthorName()}`)
108
214
  }
109
215
  }
110
216
  }