flu-cli 2.0.5 → 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
@@ -0,0 +1,89 @@
1
+ import chalk from 'chalk'
2
+ import { createInterface } from 'readline'
3
+ import { runInitAiBase, runInitAiBaseWithReport, validateProjectId } from 'flu-cli-core'
4
+ import { buildJsonEnvelope, createNullLogger, printJsonEnvelope } from '../utils/json-output.js'
5
+
6
+ const VALID_STARTERS = new Set(['minimal', 'lite', 'modular', 'clean', 'native', 'custom'])
7
+
8
+ function promptLine(question) {
9
+ const rl = createInterface({ input: process.stdin, output: process.stdout })
10
+ return new Promise((resolve) => {
11
+ rl.question(question, (answer) => {
12
+ rl.close()
13
+ resolve((answer ?? '').trim())
14
+ })
15
+ })
16
+ }
17
+
18
+ /**
19
+ * @param {{ dir?: string, projectId?: string, starter?: string, import?: string }} options
20
+ */
21
+ export async function initAiBaseCli(options) {
22
+ const dir = options.dir || process.cwd()
23
+ const nonInteractive = process.env.FLU_CLI_NON_INTERACTIVE === '1'
24
+ const asJson = options.json === true
25
+
26
+ let projectId = (options.projectId ?? '').trim()
27
+ if (!projectId) {
28
+ if (nonInteractive) {
29
+ console.error(chalk.red('非交互模式下必须提供 --project-id'))
30
+ process.exit(1)
31
+ }
32
+ projectId = await promptLine('projectId(英文/数字/短横线,如 my-app): ')
33
+ }
34
+
35
+ const idErr = validateProjectId(projectId)
36
+ if (idErr) {
37
+ console.error(chalk.red(idErr))
38
+ process.exit(1)
39
+ }
40
+
41
+ let starter = (options.starter || 'minimal').toLowerCase()
42
+ if (!VALID_STARTERS.has(starter)) {
43
+ console.error(chalk.red(`无效的 --starter,可选: ${[...VALID_STARTERS].join(', ')}`))
44
+ process.exit(1)
45
+ }
46
+
47
+ const customImportPath = options.import?.trim()
48
+
49
+ if (starter === 'custom' && !customImportPath && nonInteractive) {
50
+ console.error(chalk.red('非交互模式下 starter=custom 时必须提供 --import <path>'))
51
+ process.exit(1)
52
+ }
53
+
54
+ if (asJson) {
55
+ const nullLogger = createNullLogger()
56
+ const report = await runInitAiBaseWithReport(
57
+ {
58
+ projectDir: dir,
59
+ projectId,
60
+ starter,
61
+ customImportPath: starter === 'custom' ? customImportPath : undefined,
62
+ },
63
+ { logger: nullLogger },
64
+ )
65
+ const diagnostics = [...(report.diagnostics ?? [])]
66
+ if (report.syncRules?.error) diagnostics.push(report.syncRules.error)
67
+ printJsonEnvelope(buildJsonEnvelope('init-ai-base', report.ok, diagnostics, report))
68
+ if (!report.ok) process.exit(1)
69
+ return
70
+ }
71
+
72
+ const result = await runInitAiBase({
73
+ projectDir: dir,
74
+ projectId,
75
+ starter,
76
+ customImportPath: starter === 'custom' ? customImportPath : undefined,
77
+ })
78
+
79
+ for (const d of result.diagnostics) {
80
+ console.log(chalk.gray(d))
81
+ }
82
+
83
+ if (!result.ok) {
84
+ console.error(chalk.red('init-ai-base 失败'))
85
+ process.exit(1)
86
+ }
87
+
88
+ console.log(chalk.green(`✅ 完成: ${dir}/.agent/skills/${result.skillSlug}/SKILL.md`))
89
+ }