@farris/cli 2.3.7 → 2.3.9

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 (171) hide show
  1. package/lib/commands/add-app.js +5 -5
  2. package/lib/commands/add-app.js.map +1 -1
  3. package/lib/commands/add-lib.js +5 -5
  4. package/lib/commands/add-lib.js.map +1 -1
  5. package/lib/commands/add-micro.js +12 -0
  6. package/lib/commands/add-micro.js.map +1 -0
  7. package/lib/commands/add-project.js +196 -194
  8. package/lib/commands/add-project.js.map +1 -1
  9. package/lib/commands/build-components.js +60 -60
  10. package/lib/commands/build-components.js.map +1 -1
  11. package/lib/commands/build-css.js +38 -38
  12. package/lib/commands/build-css.js.map +1 -1
  13. package/lib/commands/build-lib.js +30 -30
  14. package/lib/commands/build-lib.js.map +1 -1
  15. package/lib/commands/build.js +19 -19
  16. package/lib/commands/build.js.map +1 -1
  17. package/lib/commands/create-app-options.js +85 -74
  18. package/lib/commands/create-app-options.js.map +1 -1
  19. package/lib/commands/create-app.js +131 -131
  20. package/lib/commands/create-app.js.map +1 -1
  21. package/lib/commands/create-options.js +58 -32
  22. package/lib/commands/create-options.js.map +1 -1
  23. package/lib/commands/create.js +341 -331
  24. package/lib/commands/create.js.map +1 -1
  25. package/lib/commands/dev-serve.js +18 -18
  26. package/lib/commands/extract-i18n.js +74 -74
  27. package/lib/commands/extract-i18n.js.map +1 -1
  28. package/lib/commands/generate/api.js +124 -124
  29. package/lib/commands/generate/api.js.map +1 -1
  30. package/lib/commands/generate/common.js +101 -101
  31. package/lib/commands/generate/common.js.map +1 -1
  32. package/lib/commands/generate/component.js +156 -156
  33. package/lib/commands/generate/component.js.map +1 -1
  34. package/lib/commands/generate/view.js +168 -168
  35. package/lib/commands/generate/view.js.map +1 -1
  36. package/lib/commands/preview-serve.js +16 -16
  37. package/lib/commands/workspace/add-app.js +15 -15
  38. package/lib/commands/workspace/add-app.js.map +1 -1
  39. package/lib/commands/workspace/create.js +62 -62
  40. package/lib/commands/workspace/create.js.map +1 -1
  41. package/lib/commands/workspace/inspect.js +30 -30
  42. package/lib/commands/workspace/inspect.js.map +1 -1
  43. package/lib/commands/workspace/verify.js +38 -38
  44. package/lib/commands/workspace/verify.js.map +1 -1
  45. package/lib/common/agents-doc.js +33 -33
  46. package/lib/common/agents-doc.js.map +1 -1
  47. package/lib/common/apply-catalog-deps.js +15 -15
  48. package/lib/common/apply-catalog-deps.js.map +1 -1
  49. package/lib/common/component-file-name.js +3 -3
  50. package/lib/common/constant.js +85 -84
  51. package/lib/common/constant.js.map +1 -1
  52. package/lib/common/create-app-target.js +46 -46
  53. package/lib/common/create-app-target.js.map +1 -1
  54. package/lib/common/generate-app.js +106 -109
  55. package/lib/common/generate-app.js.map +1 -1
  56. package/lib/common/get-dependencies.js +9 -9
  57. package/lib/common/get-farris-config.js +25 -25
  58. package/lib/common/get-farris-config.js.map +1 -1
  59. package/lib/common/get-version.js +6 -6
  60. package/lib/common/get-vite-config.js +192 -192
  61. package/lib/common/get-vite-config.js.map +1 -1
  62. package/lib/common/lib-package-exports.js +24 -24
  63. package/lib/common/lib-package-exports.js.map +1 -1
  64. package/lib/common/list-lib-components.js +23 -23
  65. package/lib/common/list-lib-components.js.map +1 -1
  66. package/lib/common/output.js +164 -164
  67. package/lib/common/output.js.map +1 -1
  68. package/lib/common/project-layout.js +155 -183
  69. package/lib/common/project-layout.js.map +1 -1
  70. package/lib/common/safety.js +172 -173
  71. package/lib/common/safety.js.map +1 -1
  72. package/lib/common/template-manifest.js +18 -14
  73. package/lib/common/template-manifest.js.map +1 -1
  74. package/lib/common/template-renderer.js +114 -114
  75. package/lib/common/template-renderer.js.map +1 -1
  76. package/lib/common/transaction.js +83 -83
  77. package/lib/common/transaction.js.map +1 -1
  78. package/lib/common/verifier.js +187 -201
  79. package/lib/common/verifier.js.map +1 -1
  80. package/lib/common/workspace-contract.js +191 -157
  81. package/lib/common/workspace-contract.js.map +1 -1
  82. package/lib/config/vite-app.js +13 -13
  83. package/lib/config/vite-common.js +20 -20
  84. package/lib/config/vite-common.js.map +1 -1
  85. package/lib/config/vite-component.js +32 -32
  86. package/lib/config/vite-component.js.map +1 -1
  87. package/lib/config/vite-lib.js +26 -26
  88. package/lib/config/vite-lib.js.map +1 -1
  89. package/lib/index.js +261 -238
  90. package/lib/index.js.map +1 -1
  91. package/lib/plugins/create-app-package-json.js +23 -23
  92. package/lib/plugins/create-component-style.js +44 -44
  93. package/lib/plugins/create-package-json.js +48 -48
  94. package/lib/plugins/create-package-json.js.map +1 -1
  95. package/lib/plugins/dts.js +8 -8
  96. package/lib/plugins/html-system.js +9 -9
  97. package/lib/plugins/mock.js +240 -292
  98. package/lib/plugins/mock.js.map +1 -1
  99. package/lib/plugins/msw-adapter.js +141 -0
  100. package/lib/plugins/msw-adapter.js.map +1 -0
  101. package/lib/plugins/replace.js +17 -17
  102. package/lib/plugins/systemjs-bundle.js +15 -15
  103. package/lib/plugins/systemjs-bundle.js.map +1 -1
  104. package/package.json +6 -1
  105. package/templates/create/.gitignore.tpl +28 -8
  106. package/templates/create/AGENTS.md +76 -45
  107. package/templates/create/README.md +44 -11
  108. package/templates/create/package.json +2 -1
  109. package/templates/lib/.gitignore.tpl +31 -1
  110. package/templates/lib/.gitlab-ci.yml +2 -2
  111. package/templates/lib/README.md +24 -1
  112. package/templates/lib/{test → components/__tests__}/index.spec.ts +1 -1
  113. package/templates/lib/{test → components/__tests__}/index.spec.tsx +2 -2
  114. package/templates/lib/farris.config.mjs +2 -2
  115. package/templates/lib/package.json +1 -1
  116. package/templates/lib/tsconfig.json +1 -2
  117. package/templates/lib/vitest.config.ts +4 -2
  118. package/templates/micro/.eslintrc.cjs +15 -0
  119. package/templates/micro/.gitignore.tpl +33 -0
  120. package/templates/micro/.gitlab-ci.yml +59 -0
  121. package/templates/micro/.prettierrc.json +8 -0
  122. package/templates/micro/farris.config.mjs +34 -0
  123. package/templates/micro/index.html +12 -0
  124. package/templates/micro/mock/README.md +53 -0
  125. package/templates/micro/mock/tsconfig.json +10 -0
  126. package/templates/micro/package.json +47 -0
  127. package/templates/micro/src/App.tsx +25 -0
  128. package/templates/micro/src/locales/index.ts +5 -0
  129. package/templates/micro/src/locales/zh-CHS.json +1 -0
  130. package/templates/micro/src/main.ts +47 -0
  131. package/templates/micro/src/router/index.ts +24 -0
  132. package/templates/micro/src/views/AboutView.tsx +12 -0
  133. package/templates/micro/src/views/HomeView.tsx +13 -0
  134. package/templates/micro/src/views/__tests__/AboutView.spec.tsx +11 -0
  135. package/templates/micro/src/views/__tests__/HomeView.spec.tsx +11 -0
  136. package/templates/micro/tsconfig.json +18 -0
  137. package/templates/micro/vitest.config.ts +12 -0
  138. package/templates/mobile/.gitignore.tpl +25 -24
  139. package/templates/mobile/farris.config.mjs +2 -2
  140. package/templates/mobile/mock/README.md +39 -20
  141. package/templates/mobile/mock/tsconfig.json +10 -0
  142. package/templates/mobile/package.json +5 -2
  143. package/templates/mobile/src/main.ts +5 -40
  144. package/templates/mobile/src/views/HomeView.tsx +2 -2
  145. package/templates/mobile/src/views/__tests__/AboutView.spec.tsx +11 -0
  146. package/templates/mobile/src/views/__tests__/HomeView.spec.tsx +11 -0
  147. package/templates/mobile/tsconfig.json +1 -2
  148. package/templates/mobile/vitest.config.ts +4 -2
  149. package/templates/web/.gitignore.tpl +25 -24
  150. package/templates/web/farris.config.mjs +2 -2
  151. package/templates/web/mock/README.md +39 -20
  152. package/templates/web/mock/tsconfig.json +10 -0
  153. package/templates/web/package.json +5 -2
  154. package/templates/web/src/App.tsx +0 -4
  155. package/templates/web/src/main.ts +5 -40
  156. package/templates/web/src/views/HomeView.tsx +2 -2
  157. package/templates/web/src/views/__tests__/AboutView.spec.tsx +11 -0
  158. package/templates/web/src/views/__tests__/HomeView.spec.tsx +11 -0
  159. package/templates/web/tsconfig.json +1 -2
  160. package/templates/web/vitest.config.ts +4 -2
  161. package/templates/mobile/src/components/TheButton.tsx +0 -9
  162. package/templates/mobile/test/src/components/TheButton.spec.ts +0 -15
  163. package/templates/mobile/test/src/components/TheButton.spec.tsx +0 -15
  164. package/templates/web/src/components/TheButton.tsx +0 -9
  165. package/templates/web/src/micro-app.d.ts +0 -20
  166. package/templates/web/src/styles/index.css +0 -0
  167. package/templates/web/test/src/components/TheButton.spec.ts +0 -15
  168. package/templates/web/test/src/components/TheButton.spec.tsx +0 -15
  169. /package/templates/{web → micro}/src/micro/context.ts +0 -0
  170. /package/templates/{mobile → micro}/src/micro-app.d.ts +0 -0
  171. /package/templates/{mobile/src/styles/index.css → micro/src/styles/index.scss} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"template-renderer.js","sourceRoot":"","sources":["../../src/common/template-renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"template-renderer.js","sourceRoot":"","sources":["../../src/common/template-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAW,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAe7D;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,SAA8B;IAClF,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,GAAG,QAAQ,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,SAAiB,EACjB,MAA0C;IAE1C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,SAAS,IAAI,CAAC,UAAkB;QAC9B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAAA,OAAO;QAAA,CAAC;QAEtC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACtE,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;gBAAA,SAAS;YAAA,CAAC;YAEhD,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YACzF,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAsB;IACtD,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAClF,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,UAAU,GAAiD,EAAE,CAAC;IAEpE,SAAS,IAAI,CAAC,UAAkB,EAAE,aAAqB;QACrD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QAExC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAEjE,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,SAAS;YACX,CAAC;YAED,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,aAAa;gBACb,IAAI,cAAc,GAAG,KAAK,CAAC;gBAC3B,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACpC,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC/C,CAAC;gBAED,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;gBAE3D,IAAI,UAAU,CAAC,cAAc,CAAC,IAAI,YAAY,EAAE,CAAC;oBAC/C,SAAS;gBACX,CAAC;gBAED,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAE7D,MAAM,SAAS,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;gBACvD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;wBACtB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;oBAC5D,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;oBACzC,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC1D,CAAC;gBAED,aAAa,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACjD,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAE3B,OAAO;QACL,YAAY;QACZ,sBAAsB,EAAE,UAAU;KACnC,CAAC;AACJ,CAAC"}
@@ -1,84 +1,84 @@
1
- import { existsSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, readdirSync } from 'node:fs';
2
- export class Transaction {
3
- constructor() {
4
- this.createdFiles = new Set();
5
- this.modifiedFiles = new Map(); // path -> original content
6
- this.createdDirs = new Set();
7
- this.committed = false;
8
- }
9
- /**
10
- * 记录新建目录
11
- */
12
- recordCreatedDir(dirPath) {
13
- if (!this.createdDirs.has(dirPath)) {
14
- this.createdDirs.add(dirPath);
15
- }
16
- }
17
- /**
18
- * 记录即将写入/修改的文件
19
- */
20
- prepareWrite(filePath) {
21
- if (this.createdFiles.has(filePath) || this.modifiedFiles.has(filePath)) {
22
- return;
23
- }
24
- if (existsSync(filePath)) {
25
- const original = readFileSync(filePath, 'utf-8');
26
- this.modifiedFiles.set(filePath, original);
27
- }
28
- else {
29
- this.createdFiles.add(filePath);
30
- }
31
- }
32
- /**
33
- * 提交事务
34
- */
35
- commit() {
36
- this.committed = true;
37
- }
38
- /**
39
- * 回滚事务
40
- */
41
- rollback() {
42
- if (this.committed) {
43
- return { rolledBackFiles: [], errors: [] };
44
- }
45
- const rolledBackFiles = [];
46
- const errors = [];
47
- // 恢复修改的文件
48
- for (const [filePath, originalContent] of this.modifiedFiles.entries()) {
49
- try {
50
- writeFileSync(filePath, originalContent, 'utf-8');
51
- rolledBackFiles.push(filePath);
52
- }
53
- catch (err) {
54
- errors.push(`恢复文件失败: ${filePath}, 原因: ${err.message}`);
55
- }
56
- }
57
- // 删除新建的文件
58
- for (const filePath of this.createdFiles) {
59
- try {
60
- if (existsSync(filePath)) {
61
- unlinkSync(filePath);
62
- rolledBackFiles.push(filePath);
63
- }
64
- }
65
- catch (err) {
66
- errors.push(`删除新建文件失败: ${filePath}, 原因: ${err.message}`);
67
- }
68
- }
69
- // 尝试清理新建的空目录(由深到浅排序)
70
- const sortedDirs = Array.from(this.createdDirs).sort((a, b) => b.length - a.length);
71
- for (const dir of sortedDirs) {
72
- try {
73
- if (existsSync(dir) && readdirSync(dir).length === 0) {
74
- rmdirSync(dir);
75
- }
76
- }
77
- catch {
78
- // 忽略非空目录清理异常
79
- }
80
- }
81
- return { rolledBackFiles, errors };
82
- }
83
- }
1
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, readdirSync } from 'node:fs';
2
+ export class Transaction {
3
+ constructor() {
4
+ this.createdFiles = new Set();
5
+ this.modifiedFiles = new Map(); // path -> original content
6
+ this.createdDirs = new Set();
7
+ this.committed = false;
8
+ }
9
+ /**
10
+ * 记录新建目录
11
+ */
12
+ recordCreatedDir(dirPath) {
13
+ if (!this.createdDirs.has(dirPath)) {
14
+ this.createdDirs.add(dirPath);
15
+ }
16
+ }
17
+ /**
18
+ * 记录即将写入/修改的文件
19
+ */
20
+ prepareWrite(filePath) {
21
+ if (this.createdFiles.has(filePath) || this.modifiedFiles.has(filePath)) {
22
+ return;
23
+ }
24
+ if (existsSync(filePath)) {
25
+ const original = readFileSync(filePath, 'utf-8');
26
+ this.modifiedFiles.set(filePath, original);
27
+ }
28
+ else {
29
+ this.createdFiles.add(filePath);
30
+ }
31
+ }
32
+ /**
33
+ * 提交事务
34
+ */
35
+ commit() {
36
+ this.committed = true;
37
+ }
38
+ /**
39
+ * 回滚事务
40
+ */
41
+ rollback() {
42
+ if (this.committed) {
43
+ return { rolledBackFiles: [], errors: [] };
44
+ }
45
+ const rolledBackFiles = [];
46
+ const errors = [];
47
+ // 恢复修改的文件
48
+ for (const [filePath, originalContent] of this.modifiedFiles.entries()) {
49
+ try {
50
+ writeFileSync(filePath, originalContent, 'utf-8');
51
+ rolledBackFiles.push(filePath);
52
+ }
53
+ catch (err) {
54
+ errors.push(`恢复文件失败: ${filePath}, 原因: ${err.message}`);
55
+ }
56
+ }
57
+ // 删除新建的文件
58
+ for (const filePath of this.createdFiles) {
59
+ try {
60
+ if (existsSync(filePath)) {
61
+ unlinkSync(filePath);
62
+ rolledBackFiles.push(filePath);
63
+ }
64
+ }
65
+ catch (err) {
66
+ errors.push(`删除新建文件失败: ${filePath}, 原因: ${err.message}`);
67
+ }
68
+ }
69
+ // 尝试清理新建的空目录(由深到浅排序)
70
+ const sortedDirs = Array.from(this.createdDirs).sort((a, b) => b.length - a.length);
71
+ for (const dir of sortedDirs) {
72
+ try {
73
+ if (existsSync(dir) && readdirSync(dir).length === 0) {
74
+ rmdirSync(dir);
75
+ }
76
+ }
77
+ catch {
78
+ // 忽略非空目录清理异常
79
+ }
80
+ }
81
+ return { rolledBackFiles, errors };
82
+ }
83
+ }
84
84
  //# sourceMappingURL=transaction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/common/transaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/common/transaction.ts"],"names":[],"mappings":"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"}
@@ -1,202 +1,188 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { resolve, join, relative } from 'node:path';
3
- import { findUnreplacedPlaceholders } from './template-renderer.js';
4
- import { LEGACY_CONTAINERS, containerAliases, listProjects, usesNewContainers } from './project-layout.js';
5
- import { CLI_COMMAND_REGISTRY, FORBIDDEN_ROOT_SCRIPTS, ROOT_SCRIPT_CONTRACT, expectedRootScriptValue } from './workspace-contract.js';
6
- /** 任何布局都必须存在的根脚本。 */
7
- const REQUIRED_ROOT_SCRIPTS = ['build', 'typecheck'];
8
- /** 工程类型全集。容器命名一律经 containerAliases 取值,从而兼容历史别名。 */
9
- const CONTAINER_TYPES = ['app', 'lib'];
10
- function readJson(filePath) {
11
- try {
12
- return JSON.parse(readFileSync(filePath, 'utf-8'));
13
- }
14
- catch {
15
- return null;
16
- }
17
- }
18
- function verifyAppProject(project, projectPath, pkg, label, addCheck) {
19
- addCheck(`${label}_catalog_deps`, pkg.dependencies?.['@farris/ui-vue'] === 'catalog:', `工程 ${project.dir} 的 @farris/ui-vue 依赖必须使用 catalog: 协议`);
20
- const indexHtmlPath = join(projectPath, 'index.html');
21
- if (!existsSync(indexHtmlPath)) {
22
- addCheck(`${label}_index_html`, false, `工程 ${project.dir} 缺少 index.html`);
23
- }
24
- else {
25
- const html = readFileSync(indexHtmlPath, 'utf-8');
26
- const hasCorrectEntry = /<script\s+type="module"\s+src="\/src\/main\.ts">\s*<\/script>/.test(html);
27
- const hasWrongEntry = /<script\s+type="module"\s+src="\.\/src\/main\.ts">\s*<\/script>/.test(html);
28
- addCheck(`${label}_html_entry`, hasCorrectEntry && !hasWrongEntry, `工程 ${project.dir} 的 index.html 入口必须为 /src/main.ts,不得写为 ./src/main.ts`);
29
- }
30
- addCheck(`${label}_main_ts`, existsSync(join(projectPath, 'src', 'main.ts')), `工程 ${project.dir} 缺少 src/main.ts`);
31
- const hasAppTsx = existsSync(join(projectPath, 'src', 'App.tsx'));
32
- const hasAppVue = existsSync(join(projectPath, 'src', 'App.vue'));
33
- addCheck(`${label}_app_entry`, hasAppTsx || hasAppVue, `工程 ${project.dir} 缺少 src/App.tsx(或历史兼容的 src/App.vue)`);
34
- const farrisConfigPath = join(projectPath, 'farris.config.mjs');
35
- const configContent = existsSync(farrisConfigPath) ? readFileSync(farrisConfigPath, 'utf-8') : '';
36
- const hasRelativeBase = /base\s*:\s*['"]\.\/?['"]/.test(configContent);
37
- const hasHistoryRouter = /routerMode\s*:\s*['"]history['"]/.test(configContent);
38
- addCheck(`${label}_base_router_compatibility`, !(hasRelativeBase && hasHistoryRouter), `工程 ${project.dir} 配置冲突: 相对路径 base 与 history 路由模式不可同时使用`);
39
- }
40
- function verifyLibProject(project, projectPath, pkg, label, addCheck) {
41
- addCheck(`${label}_components_entry`, existsSync(join(projectPath, 'components', 'index.ts')), `组件库 ${project.dir} 缺少 components/index.ts(发布物唯一入口)`);
42
- addCheck(`${label}_files_whitelist`, Array.isArray(pkg.files) && pkg.files.length > 0, `组件库 ${project.dir} 的 package.json 缺少 files 白名单,误执行 npm publish 会把 src/ 推上去`);
43
- addCheck(`${label}_publish_config`, !!pkg.publishConfig, `组件库 ${project.dir} 的 package.json 缺少 publishConfig`);
44
- }
45
- function verifyProject(wsRoot, project, addCheck) {
46
- const label = `${project.type}_${project.dir.replace(/\//g, '_')}`;
47
- const projectPath = join(wsRoot, project.dir);
48
- const pkgPath = join(projectPath, 'package.json');
49
- const farrisConfigPath = join(projectPath, 'farris.config.mjs');
50
- const tsconfigPath = join(projectPath, 'tsconfig.json');
51
- if (!existsSync(pkgPath)) {
52
- addCheck(`${label}_package_json`, false, `工程 ${project.dir} 缺少 package.json`);
53
- return;
54
- }
55
- const pkg = readJson(pkgPath);
56
- if (!pkg) {
57
- addCheck(`${label}_package_json_valid`, false, `工程 ${project.dir} 的 package.json 解析失败`);
58
- return;
59
- }
60
- addCheck(`${label}_name`, !!pkg.name, `工程 ${project.dir} 的 package.json 缺少 name 字段`);
61
- addCheck(`${label}_farris_config`, existsSync(farrisConfigPath), `工程 ${project.dir} 缺少 farris.config.mjs`);
62
- addCheck(`${label}_tsconfig`, existsSync(tsconfigPath), `工程 ${project.dir} 缺少 tsconfig.json`);
63
- addCheck(`${label}_typecheck_script`, !!pkg.scripts?.typecheck, `工程 ${project.dir} 缺少 typecheck 脚本,根 pnpm typecheck 会静默跳过它`);
64
- if (project.type === 'app') {
65
- verifyAppProject(project, projectPath, pkg, label, addCheck);
66
- }
67
- else {
68
- verifyLibProject(project, projectPath, pkg, label, addCheck);
69
- }
70
- for (const file of [pkgPath, farrisConfigPath, tsconfigPath]) {
71
- if (!existsSync(file)) {
72
- continue;
73
- }
74
- const unreplaced = findUnreplacedPlaceholders(readFileSync(file, 'utf-8'));
75
- addCheck(`${label}_placeholders_${relative(wsRoot, file).replace(/\\/g, '/')}`, unreplaced.length === 0, `文件 ${relative(wsRoot, file)} 存在未替换占位符: ${unreplaced.join(', ')}`);
76
- }
77
- }
78
- /**
79
- * 校验 Workspace 完整性与规范合规性。
80
- *
81
- * 分层结构(pnpm-workspace.yaml 含 application/* 或 library/*,含历史复数别名)走强校验;
82
- * 旧平铺结构(只含 packages/*)只做兼容校验,不因历史模板缺失的项失败。
83
- */
84
- export function verifyWorkspace(targetDir, preservedInputs = []) {
85
- const checks = [];
86
- const errors = [];
87
- const addCheck = (name, passed, message) => {
88
- checks.push({ name, passed, message });
89
- if (!passed && message) {
90
- errors.push(message);
91
- }
92
- };
93
- const resolvedTarget = resolve(process.cwd(), targetDir);
94
- if (!existsSync(resolvedTarget)) {
95
- return {
96
- ok: false,
97
- target: resolvedTarget,
98
- checks: [{ name: 'target_exists', passed: false, message: `目标路径不存在: ${resolvedTarget}` }],
99
- errors: [`目标路径不存在: ${resolvedTarget}`]
100
- };
101
- }
102
- const isNewLayout = usesNewContainers(resolvedTarget);
103
- // 1. 根 package.json
104
- const rootPkgPath = join(resolvedTarget, 'package.json');
105
- if (!existsSync(rootPkgPath)) {
106
- addCheck('root_package_json', false, '缺少根 package.json');
107
- }
108
- else {
109
- const pkg = readJson(rootPkgPath);
110
- if (!pkg) {
111
- addCheck('root_package_json_valid', false, '根 package.json 解析失败');
112
- }
113
- else {
114
- addCheck('root_package_private', pkg.private === true, '根 package.json 必须声明 "private": true');
115
- addCheck('root_package_no_name', !pkg.name, '根 package.json 不应设置 name');
116
- const scripts = (pkg.scripts ?? {});
117
- const missingRootScripts = REQUIRED_ROOT_SCRIPTS.filter((script) => !scripts[script]);
118
- addCheck('root_package_scripts', missingRootScripts.length === 0, `根 package.json 缺少必需脚本: ${missingRootScripts.join(', ')}`);
119
- if (isNewLayout) {
120
- const wrongScripts = ROOT_SCRIPT_CONTRACT.filter((item) => scripts[item.script] !== expectedRootScriptValue(item.script));
121
- addCheck('root_package_scripts_contract', wrongScripts.length === 0, `根脚本必须按契约声明: ${wrongScripts
122
- .map((item) => `${item.script} → ${expectedRootScriptValue(item.script)}`)
123
- .join('; ')}`);
124
- const forbidden = FORBIDDEN_ROOT_SCRIPTS.filter((script) => scripts[script] !== undefined);
125
- addCheck('root_package_no_forbidden_scripts', forbidden.length === 0, `根 package.json 不得声明长驻服务脚本: ${forbidden.join(', ')}`);
126
- addCheck('root_package_cli_dependency', pkg.devDependencies?.['@farris/cli'] === 'catalog:', '根 package.json 必须声明 "@farris/cli": "catalog:",否则根脚本无法解析 farris-cli bin');
127
- }
128
- }
129
- }
130
- // 2. pnpm-workspace.yaml
131
- const wsYamlPath = join(resolvedTarget, 'pnpm-workspace.yaml');
132
- if (!existsSync(wsYamlPath)) {
133
- addCheck('workspace_yaml', false, '缺少 pnpm-workspace.yaml');
134
- }
135
- else {
136
- const yamlContent = readFileSync(wsYamlPath, 'utf-8');
137
- if (isNewLayout) {
138
- const missingContainers = CONTAINER_TYPES.filter((type) => !containerAliases(type).some((container) => yamlContent.includes(`${container}/*`)));
139
- addCheck('workspace_packages_glob', missingContainers.length === 0, `pnpm-workspace.yaml 必须包含新容器 glob: ${missingContainers
140
- .map((type) => `${containerAliases(type)[0]}/*`)
141
- .join(', ')}`);
142
- }
143
- else {
144
- addCheck('workspace_packages_glob', yamlContent.includes('packages/*'), 'pnpm-workspace.yaml 必须包含 "packages/*"');
145
- }
146
- addCheck('workspace_catalog', yamlContent.includes('catalog:'), 'pnpm-workspace.yaml 必须声明 catalog 依赖版本');
147
- }
148
- // 3. 容器目录:懒创建 —— 容器按需生成,只有该类型真的存在工程时才要求容器目录存在
149
- const projects = listProjects(resolvedTarget);
150
- if (isNewLayout) {
151
- for (const type of CONTAINER_TYPES) {
152
- const aliases = containerAliases(type);
153
- const hasProject = projects.some((project) => project.type === type);
154
- const containerPresent = aliases.some((container) => existsSync(join(resolvedTarget, container)));
155
- addCheck(`container_${aliases[0]}`, !hasProject || containerPresent, `存在 ${aliases[0]}/ 下的工程,但容器目录缺失: ${aliases[0]}/`);
156
- }
157
- }
158
- else {
159
- const legacyContainer = LEGACY_CONTAINERS[0];
160
- addCheck(`container_${legacyContainer}`, existsSync(join(resolvedTarget, legacyContainer)), `缺少容器目录: ${legacyContainer}/`);
161
- }
162
- // 4. 逐个工程按类型校验
163
- for (const project of projects) {
164
- verifyProject(resolvedTarget, project, addCheck);
165
- }
166
- // 5. AGENTS.md 体系(仅新结构强校验,见设计文档 §8.3)
167
- if (isNewLayout) {
168
- const agentsPath = join(resolvedTarget, 'AGENTS.md');
169
- if (!existsSync(agentsPath)) {
170
- addCheck('agents_doc_exists', false, '缺少根 AGENTS.md(AI 协作契约的唯一真源)');
171
- }
172
- else {
173
- addCheck('agents_doc_exists', true);
174
- const content = readFileSync(agentsPath, 'utf-8');
175
- const missingDeclaration = CONTAINER_TYPES.filter((type) => !containerAliases(type).some((container) => content.includes(`${container}/`)));
176
- addCheck('agents_doc_containers', missingDeclaration.length === 0, `根 AGENTS.md 未声明容器目录: ${missingDeclaration
177
- .map((type) => containerAliases(type)[0])
178
- .join(', ')}`);
179
- const legacyContainer = LEGACY_CONTAINERS[0];
180
- addCheck('agents_doc_no_legacy_container', !content.includes(`${legacyContainer}/`), `根 AGENTS.md 仍引用旧容器目录 ${legacyContainer}/,与 PROJECT_CONTAINERS 不一致`);
181
- const missingCommands = CLI_COMMAND_REGISTRY.filter((command) => !content.includes(command));
182
- addCheck('agents_doc_commands', missingCommands.length === 0, `根 AGENTS.md 未覆盖命令注册表中的命令: ${missingCommands.join(', ')}`);
183
- }
184
- const claudePath = join(resolvedTarget, 'CLAUDE.md');
185
- if (existsSync(claudePath)) {
186
- const raw = readFileSync(claudePath, 'utf-8');
187
- const lines = raw.trimEnd().split(/\r?\n/);
188
- addCheck('claude_pointer_thin', lines.length <= 3 && raw.includes('AGENTS.md'), 'CLAUDE.md 必须是不含规则正文的薄指针(≤ 3 行且包含 AGENTS.md 字样)');
189
- }
190
- }
191
- // 6. 受保护输入是否依然完好
192
- for (const entry of preservedInputs) {
193
- addCheck(`preserved_input_${entry}`, existsSync(join(resolvedTarget, entry)), `受保护输入文件/目录丢失或被覆盖: ${entry}`);
194
- }
195
- return {
196
- ok: errors.length === 0,
197
- target: resolvedTarget,
198
- checks,
199
- errors
200
- };
201
- }
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { resolve, join, relative } from 'node:path';
3
+ import { findUnreplacedPlaceholders } from './template-renderer.js';
4
+ import { containerFor, listProjects } from './project-layout.js';
5
+ import { CLI_COMMAND_REGISTRY, FORBIDDEN_ROOT_SCRIPTS, ROOT_SCRIPT_CONTRACT, expectedRootScriptValue } from './workspace-contract.js';
6
+ /** 任何布局都必须存在的根脚本。 */
7
+ const REQUIRED_ROOT_SCRIPTS = ['build', 'typecheck'];
8
+ /** 工程类型全集。容器命名一律经 containerFor 取值。 */
9
+ const CONTAINER_TYPES = ['app', 'lib'];
10
+ function readJson(filePath) {
11
+ try {
12
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ function verifyAppProject(project, projectPath, pkg, label, addCheck) {
19
+ addCheck(`${label}_catalog_deps`, pkg.dependencies?.['@farris/ui-vue'] === 'catalog:', `工程 ${project.dir} 的 @farris/ui-vue 依赖必须使用 catalog: 协议`);
20
+ const indexHtmlPath = join(projectPath, 'index.html');
21
+ if (!existsSync(indexHtmlPath)) {
22
+ addCheck(`${label}_index_html`, false, `工程 ${project.dir} 缺少 index.html`);
23
+ }
24
+ else {
25
+ const html = readFileSync(indexHtmlPath, 'utf-8');
26
+ const hasCorrectEntry = /<script\s+type="module"\s+src="\/src\/main\.ts">\s*<\/script>/.test(html);
27
+ const hasWrongEntry = /<script\s+type="module"\s+src="\.\/src\/main\.ts">\s*<\/script>/.test(html);
28
+ addCheck(`${label}_html_entry`, hasCorrectEntry && !hasWrongEntry, `工程 ${project.dir} 的 index.html 入口必须为 /src/main.ts,不得写为 ./src/main.ts`);
29
+ }
30
+ addCheck(`${label}_main_ts`, existsSync(join(projectPath, 'src', 'main.ts')), `工程 ${project.dir} 缺少 src/main.ts`);
31
+ const hasAppTsx = existsSync(join(projectPath, 'src', 'App.tsx'));
32
+ const hasAppVue = existsSync(join(projectPath, 'src', 'App.vue'));
33
+ addCheck(`${label}_app_entry`, hasAppTsx || hasAppVue, `工程 ${project.dir} 缺少 src/App.tsx(或历史兼容的 src/App.vue)`);
34
+ const farrisConfigPath = join(projectPath, 'farris.config.mjs');
35
+ const configContent = existsSync(farrisConfigPath) ? readFileSync(farrisConfigPath, 'utf-8') : '';
36
+ const hasRelativeBase = /base\s*:\s*['"]\.\/?['"]/.test(configContent);
37
+ const hasHistoryRouter = /routerMode\s*:\s*['"]history['"]/.test(configContent);
38
+ addCheck(`${label}_base_router_compatibility`, !(hasRelativeBase && hasHistoryRouter), `工程 ${project.dir} 配置冲突: 相对路径 base 与 history 路由模式不可同时使用`);
39
+ }
40
+ function verifyLibProject(project, projectPath, pkg, label, addCheck) {
41
+ addCheck(`${label}_components_entry`, existsSync(join(projectPath, 'components', 'index.ts')), `组件库 ${project.dir} 缺少 components/index.ts(发布物唯一入口)`);
42
+ addCheck(`${label}_files_whitelist`, Array.isArray(pkg.files) && pkg.files.length > 0, `组件库 ${project.dir} 的 package.json 缺少 files 白名单,误执行 npm publish 会把 src/ 推上去`);
43
+ addCheck(`${label}_publish_config`, !!pkg.publishConfig, `组件库 ${project.dir} 的 package.json 缺少 publishConfig`);
44
+ }
45
+ function verifyProject(wsRoot, project, addCheck) {
46
+ const label = `${project.type}_${project.dir.replace(/\//g, '_')}`;
47
+ const projectPath = join(wsRoot, project.dir);
48
+ const pkgPath = join(projectPath, 'package.json');
49
+ const farrisConfigPath = join(projectPath, 'farris.config.mjs');
50
+ const tsconfigPath = join(projectPath, 'tsconfig.json');
51
+ if (!existsSync(pkgPath)) {
52
+ addCheck(`${label}_package_json`, false, `工程 ${project.dir} 缺少 package.json`);
53
+ return;
54
+ }
55
+ const pkg = readJson(pkgPath);
56
+ if (!pkg) {
57
+ addCheck(`${label}_package_json_valid`, false, `工程 ${project.dir} 的 package.json 解析失败`);
58
+ return;
59
+ }
60
+ addCheck(`${label}_name`, !!pkg.name, `工程 ${project.dir} 的 package.json 缺少 name 字段`);
61
+ addCheck(`${label}_farris_config`, existsSync(farrisConfigPath), `工程 ${project.dir} 缺少 farris.config.mjs`);
62
+ addCheck(`${label}_tsconfig`, existsSync(tsconfigPath), `工程 ${project.dir} 缺少 tsconfig.json`);
63
+ addCheck(`${label}_typecheck_script`, !!pkg.scripts?.typecheck, `工程 ${project.dir} 缺少 typecheck 脚本,根 pnpm typecheck 会静默跳过它`);
64
+ if (project.type === 'lib') {
65
+ verifyLibProject(project, projectPath, pkg, label, addCheck);
66
+ }
67
+ else {
68
+ // app 与 micro 结构一致(micro 的微前端契约由模板守卫保证),都走应用校验
69
+ verifyAppProject(project, projectPath, pkg, label, addCheck);
70
+ }
71
+ for (const file of [pkgPath, farrisConfigPath, tsconfigPath]) {
72
+ if (!existsSync(file)) {
73
+ continue;
74
+ }
75
+ const unreplaced = findUnreplacedPlaceholders(readFileSync(file, 'utf-8'));
76
+ addCheck(`${label}_placeholders_${relative(wsRoot, file).replace(/\\/g, '/')}`, unreplaced.length === 0, `文件 ${relative(wsRoot, file)} 存在未替换占位符: ${unreplaced.join(', ')}`);
77
+ }
78
+ }
79
+ /**
80
+ * 校验 Workspace 完整性与规范合规性。
81
+ *
82
+ * 工作空间必须是 app/ + lib/ 分层结构(容器按需创建);旧平铺结构不再支持。
83
+ */
84
+ export function verifyWorkspace(targetDir, preservedInputs = []) {
85
+ const checks = [];
86
+ const errors = [];
87
+ const addCheck = (name, passed, message) => {
88
+ checks.push({ name, passed, message });
89
+ if (!passed && message) {
90
+ errors.push(message);
91
+ }
92
+ };
93
+ const resolvedTarget = resolve(process.cwd(), targetDir);
94
+ if (!existsSync(resolvedTarget)) {
95
+ return {
96
+ ok: false,
97
+ target: resolvedTarget,
98
+ checks: [{ name: 'target_exists', passed: false, message: `目标路径不存在: ${resolvedTarget}` }],
99
+ errors: [`目标路径不存在: ${resolvedTarget}`]
100
+ };
101
+ }
102
+ // 1. 根 package.json
103
+ const rootPkgPath = join(resolvedTarget, 'package.json');
104
+ if (!existsSync(rootPkgPath)) {
105
+ addCheck('root_package_json', false, '缺少根 package.json');
106
+ }
107
+ else {
108
+ const pkg = readJson(rootPkgPath);
109
+ if (!pkg) {
110
+ addCheck('root_package_json_valid', false, '根 package.json 解析失败');
111
+ }
112
+ else {
113
+ addCheck('root_package_private', pkg.private === true, '根 package.json 必须声明 "private": true');
114
+ addCheck('root_package_no_name', !pkg.name, '根 package.json 不应设置 name');
115
+ const scripts = (pkg.scripts ?? {});
116
+ const missingRootScripts = REQUIRED_ROOT_SCRIPTS.filter((script) => !scripts[script]);
117
+ addCheck('root_package_scripts', missingRootScripts.length === 0, `根 package.json 缺少必需脚本: ${missingRootScripts.join(', ')}`);
118
+ {
119
+ const wrongScripts = ROOT_SCRIPT_CONTRACT.filter((item) => scripts[item.script] !== expectedRootScriptValue(item.script));
120
+ addCheck('root_package_scripts_contract', wrongScripts.length === 0, `根脚本必须按契约声明: ${wrongScripts
121
+ .map((item) => `${item.script} → ${expectedRootScriptValue(item.script)}`)
122
+ .join('; ')}`);
123
+ const forbidden = FORBIDDEN_ROOT_SCRIPTS.filter((script) => scripts[script] !== undefined);
124
+ addCheck('root_package_no_forbidden_scripts', forbidden.length === 0, `根 package.json 不得声明长驻服务脚本: ${forbidden.join(', ')}`);
125
+ addCheck('root_package_cli_dependency', pkg.devDependencies?.['@farris/cli'] === 'catalog:', '根 package.json 必须声明 "@farris/cli": "catalog:",否则根脚本无法解析 farris-cli bin');
126
+ }
127
+ }
128
+ }
129
+ // 2. pnpm-workspace.yaml
130
+ const wsYamlPath = join(resolvedTarget, 'pnpm-workspace.yaml');
131
+ if (!existsSync(wsYamlPath)) {
132
+ addCheck('workspace_yaml', false, '缺少 pnpm-workspace.yaml');
133
+ }
134
+ else {
135
+ const yamlContent = readFileSync(wsYamlPath, 'utf-8');
136
+ const missingContainers = CONTAINER_TYPES.filter((type) => !yamlContent.includes(`${containerFor(type)}/*`));
137
+ addCheck('workspace_packages_glob', missingContainers.length === 0, `pnpm-workspace.yaml 必须包含容器 glob: ${missingContainers
138
+ .map((type) => `${containerFor(type)}/*`)
139
+ .join(', ')}`);
140
+ addCheck('workspace_catalog', yamlContent.includes('catalog:'), 'pnpm-workspace.yaml 必须声明 catalog 依赖版本');
141
+ }
142
+ // 3. 容器目录:懒创建 —— 容器按需生成,只有该类型真的存在工程时才要求容器目录存在
143
+ const projects = listProjects(resolvedTarget);
144
+ for (const type of CONTAINER_TYPES) {
145
+ const container = containerFor(type);
146
+ const hasProject = projects.some((project) => project.type === type);
147
+ const containerPresent = existsSync(join(resolvedTarget, container));
148
+ addCheck(`container_${container}`, !hasProject || containerPresent, `存在 ${container}/ 下的工程,但容器目录缺失: ${container}/`);
149
+ }
150
+ // 4. 逐个工程按类型校验
151
+ for (const project of projects) {
152
+ verifyProject(resolvedTarget, project, addCheck);
153
+ }
154
+ // 5. AGENTS.md 体系(设计文档 §8.3)
155
+ {
156
+ const agentsPath = join(resolvedTarget, 'AGENTS.md');
157
+ if (!existsSync(agentsPath)) {
158
+ addCheck('agents_doc_exists', false, '缺少根 AGENTS.md(AI 协作契约的唯一真源)');
159
+ }
160
+ else {
161
+ addCheck('agents_doc_exists', true);
162
+ const content = readFileSync(agentsPath, 'utf-8');
163
+ const missingDeclaration = CONTAINER_TYPES.filter((type) => !content.includes(`${containerFor(type)}/`));
164
+ addCheck('agents_doc_containers', missingDeclaration.length === 0, `根 AGENTS.md 未声明容器目录: ${missingDeclaration
165
+ .map((type) => containerFor(type))
166
+ .join(', ')}`);
167
+ const missingCommands = CLI_COMMAND_REGISTRY.filter((command) => !content.includes(command));
168
+ addCheck('agents_doc_commands', missingCommands.length === 0, `根 AGENTS.md 未覆盖命令注册表中的命令: ${missingCommands.join(', ')}`);
169
+ }
170
+ const claudePath = join(resolvedTarget, 'CLAUDE.md');
171
+ if (existsSync(claudePath)) {
172
+ const raw = readFileSync(claudePath, 'utf-8');
173
+ const lines = raw.trimEnd().split(/\r?\n/);
174
+ addCheck('claude_pointer_thin', lines.length <= 3 && raw.includes('AGENTS.md'), 'CLAUDE.md 必须是不含规则正文的薄指针(≤ 3 行且包含 AGENTS.md 字样)');
175
+ }
176
+ }
177
+ // 6. 受保护输入是否依然完好
178
+ for (const entry of preservedInputs) {
179
+ addCheck(`preserved_input_${entry}`, existsSync(join(resolvedTarget, entry)), `受保护输入文件/目录丢失或被覆盖: ${entry}`);
180
+ }
181
+ return {
182
+ ok: errors.length === 0,
183
+ target: resolvedTarget,
184
+ checks,
185
+ errors
186
+ };
187
+ }
202
188
  //# sourceMappingURL=verifier.js.map