@yss123/cage-cli 0.0.0-stage → 0.2.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 (499) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -2
  3. package/bin/cage.js +6 -0
  4. package/bin/create-cage-app.js +6 -0
  5. package/dist/analyze.d.ts +18 -0
  6. package/dist/analyze.js +28 -0
  7. package/dist/analyze.js.map +1 -0
  8. package/dist/baseline.d.ts +5 -0
  9. package/dist/baseline.js +50 -0
  10. package/dist/baseline.js.map +1 -0
  11. package/dist/budget.d.ts +7 -0
  12. package/dist/budget.js +52 -0
  13. package/dist/budget.js.map +1 -0
  14. package/dist/config.d.ts +30 -0
  15. package/dist/config.js +46 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/context.d.ts +72 -0
  18. package/dist/context.js +202 -0
  19. package/dist/context.js.map +1 -0
  20. package/dist/create-prompt.d.ts +5 -0
  21. package/dist/create-prompt.js +50 -0
  22. package/dist/create-prompt.js.map +1 -0
  23. package/dist/create.d.ts +18 -0
  24. package/dist/create.js +64 -0
  25. package/dist/create.js.map +1 -0
  26. package/dist/derive.d.ts +14 -0
  27. package/dist/derive.js +163 -0
  28. package/dist/derive.js.map +1 -0
  29. package/dist/dev.d.ts +2 -0
  30. package/dist/dev.js +116 -0
  31. package/dist/dev.js.map +1 -0
  32. package/dist/env.d.ts +1 -0
  33. package/dist/env.js +15 -0
  34. package/dist/env.js.map +1 -0
  35. package/dist/findings.d.ts +11 -0
  36. package/dist/findings.js +13 -0
  37. package/dist/findings.js.map +1 -0
  38. package/dist/gen/contracts.d.ts +6 -0
  39. package/dist/gen/contracts.js +188 -0
  40. package/dist/gen/contracts.js.map +1 -0
  41. package/dist/gen/index.d.ts +19 -0
  42. package/dist/gen/index.js +177 -0
  43. package/dist/gen/index.js.map +1 -0
  44. package/dist/gen/zod-code.d.ts +7 -0
  45. package/dist/gen/zod-code.js +163 -0
  46. package/dist/gen/zod-code.js.map +1 -0
  47. package/dist/graph-command.d.ts +11 -0
  48. package/dist/graph-command.js +67 -0
  49. package/dist/graph-command.js.map +1 -0
  50. package/dist/graph-model.d.ts +21 -0
  51. package/dist/graph-model.js +101 -0
  52. package/dist/graph-model.js.map +1 -0
  53. package/dist/graph-presentation.d.ts +11 -0
  54. package/dist/graph-presentation.js +25 -0
  55. package/dist/graph-presentation.js.map +1 -0
  56. package/dist/graph-query.d.ts +171 -0
  57. package/dist/graph-query.js +242 -0
  58. package/dist/graph-query.js.map +1 -0
  59. package/dist/graph-relations.d.ts +14 -0
  60. package/dist/graph-relations.js +142 -0
  61. package/dist/graph-relations.js.map +1 -0
  62. package/dist/graph-search.d.ts +21 -0
  63. package/dist/graph-search.js +63 -0
  64. package/dist/graph-search.js.map +1 -0
  65. package/dist/graph-snapshot.d.ts +11 -0
  66. package/dist/graph-snapshot.js +29 -0
  67. package/dist/graph-snapshot.js.map +1 -0
  68. package/dist/graph.d.ts +11 -0
  69. package/dist/graph.js +105 -0
  70. package/dist/graph.js.map +1 -0
  71. package/dist/impact.d.ts +34 -0
  72. package/dist/impact.js +235 -0
  73. package/dist/impact.js.map +1 -0
  74. package/dist/index.d.ts +20 -0
  75. package/dist/index.js +22 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/init.d.ts +6 -0
  78. package/dist/init.js +131 -0
  79. package/dist/init.js.map +1 -0
  80. package/dist/load.d.ts +6 -0
  81. package/dist/load.js +17 -0
  82. package/dist/load.js.map +1 -0
  83. package/dist/main.d.ts +1 -0
  84. package/dist/main.js +221 -0
  85. package/dist/main.js.map +1 -0
  86. package/dist/migrate.d.ts +4 -0
  87. package/dist/migrate.js +30 -0
  88. package/dist/migrate.js.map +1 -0
  89. package/dist/ontology.d.ts +43 -0
  90. package/dist/ontology.js +280 -0
  91. package/dist/ontology.js.map +1 -0
  92. package/dist/process.d.ts +6 -0
  93. package/dist/process.js +39 -0
  94. package/dist/process.js.map +1 -0
  95. package/dist/project-structure.d.ts +8 -0
  96. package/dist/project-structure.js +94 -0
  97. package/dist/project-structure.js.map +1 -0
  98. package/dist/rules.d.ts +23 -0
  99. package/dist/rules.js +251 -0
  100. package/dist/rules.js.map +1 -0
  101. package/dist/static-check.d.ts +23 -0
  102. package/dist/static-check.js +222 -0
  103. package/dist/static-check.js.map +1 -0
  104. package/dist/sync.d.ts +5 -0
  105. package/dist/sync.js +118 -0
  106. package/dist/sync.js.map +1 -0
  107. package/dist/upgrade.d.ts +10 -0
  108. package/dist/upgrade.js +81 -0
  109. package/dist/upgrade.js.map +1 -0
  110. package/dist/verify.d.ts +7 -0
  111. package/dist/verify.js +88 -0
  112. package/dist/verify.js.map +1 -0
  113. package/dist/version.d.ts +4 -0
  114. package/dist/version.js +6 -0
  115. package/dist/version.js.map +1 -0
  116. package/graph-ui/app.js +1103 -0
  117. package/graph-ui/graph-model.js +100 -0
  118. package/graph-ui/graph-relations.js +141 -0
  119. package/graph-ui/graph-search.js +62 -0
  120. package/graph-ui/index.html +197 -0
  121. package/graph-ui/model.js +83 -0
  122. package/graph-ui/relations.js +2 -0
  123. package/graph-ui/structure.js +77 -0
  124. package/graph-ui/style.css +1719 -0
  125. package/package.json +60 -3
  126. package/templates/app/.dockerignore +10 -0
  127. package/templates/app/.env.example +61 -0
  128. package/templates/app/.github/workflows/cage.yml +44 -0
  129. package/templates/app/AGENTS.md +96 -0
  130. package/templates/app/Dockerfile +25 -0
  131. package/templates/app/README.md +88 -0
  132. package/templates/app/_gitignore +8 -0
  133. package/templates/app/apps/api/package.json +16 -0
  134. package/templates/app/apps/api/src/main.ts +10 -0
  135. package/templates/app/apps/api/src/worker.ts +14 -0
  136. package/templates/app/apps/api/tsconfig.json +5 -0
  137. package/templates/app/apps/web/index.html +13 -0
  138. package/templates/app/apps/web/package.json +22 -0
  139. package/templates/app/apps/web/src/app/app.tsx +18 -0
  140. package/templates/app/apps/web/src/app/styles/global.css +663 -0
  141. package/templates/app/apps/web/src/app/workspace-layout.tsx +70 -0
  142. package/templates/app/apps/web/src/main.tsx +13 -0
  143. package/templates/app/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +20 -0
  144. package/templates/app/apps/web/src/modules/approval/index.ts +2 -0
  145. package/templates/app/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +54 -0
  146. package/templates/app/apps/web/src/modules/auth/index.ts +1 -0
  147. package/templates/app/apps/web/src/modules/auth/pages/login-page.tsx +59 -0
  148. package/templates/app/apps/web/src/modules/inventory/index.ts +1 -0
  149. package/templates/app/apps/web/src/modules/inventory/pages/inventory-page.tsx +74 -0
  150. package/templates/app/apps/web/src/modules/purchase/components/purchase-order-form.tsx +60 -0
  151. package/templates/app/apps/web/src/modules/purchase/index.ts +2 -0
  152. package/templates/app/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +210 -0
  153. package/templates/app/apps/web/src/shared/hooks/use-command.ts +29 -0
  154. package/templates/app/apps/web/src/shared/lib/error-message.ts +15 -0
  155. package/templates/app/apps/web/src/shared/ui/notice.tsx +13 -0
  156. package/templates/app/apps/web/src/shared/ui/page-heading.tsx +28 -0
  157. package/templates/app/apps/web/tsconfig.json +11 -0
  158. package/templates/app/apps/web/vite.config.ts +19 -0
  159. package/templates/app/cage.config.json +114 -0
  160. package/templates/app/db/migrations/0001_init.sql +112 -0
  161. package/templates/app/docs/ai/README.md +77 -0
  162. package/templates/app/docs/ai/architecture.md +122 -0
  163. package/templates/app/docs/ai/ontology-context.md +117 -0
  164. package/templates/app/docs/ai/primitives.md +249 -0
  165. package/templates/app/docs/ai/project-structure.md +123 -0
  166. package/templates/app/docs/ai/purchase-example.md +97 -0
  167. package/templates/app/docs/ai/recipes.md +81 -0
  168. package/templates/app/docs/ai/relations.md +160 -0
  169. package/templates/app/docs/ai/transfers.md +92 -0
  170. package/templates/app/docs/ai/troubleshooting.md +60 -0
  171. package/templates/app/docs/ai/workflow.md +139 -0
  172. package/templates/app/docs/errors/CAGE-APPR-001.md +47 -0
  173. package/templates/app/docs/errors/CAGE-APPR-002.md +47 -0
  174. package/templates/app/docs/errors/CAGE-APPR-003.md +47 -0
  175. package/templates/app/docs/errors/CAGE-APPR-004.md +47 -0
  176. package/templates/app/docs/errors/CAGE-APPR-005.md +47 -0
  177. package/templates/app/docs/errors/CAGE-APPR-006.md +47 -0
  178. package/templates/app/docs/errors/CAGE-APPR-007.md +50 -0
  179. package/templates/app/docs/errors/CAGE-APPR-010.md +48 -0
  180. package/templates/app/docs/errors/CAGE-AUTH-001.md +47 -0
  181. package/templates/app/docs/errors/CAGE-BUDGET-001.md +47 -0
  182. package/templates/app/docs/errors/CAGE-BUDGET-002.md +47 -0
  183. package/templates/app/docs/errors/CAGE-BUDGET-003.md +47 -0
  184. package/templates/app/docs/errors/CAGE-CMD-002.md +47 -0
  185. package/templates/app/docs/errors/CAGE-CMD-003.md +47 -0
  186. package/templates/app/docs/errors/CAGE-CONN-001.md +47 -0
  187. package/templates/app/docs/errors/CAGE-CONN-002.md +47 -0
  188. package/templates/app/docs/errors/CAGE-CONN-003.md +47 -0
  189. package/templates/app/docs/errors/CAGE-CONN-004.md +47 -0
  190. package/templates/app/docs/errors/CAGE-CONN-005.md +47 -0
  191. package/templates/app/docs/errors/CAGE-CONN-006.md +47 -0
  192. package/templates/app/docs/errors/CAGE-CONN-007.md +47 -0
  193. package/templates/app/docs/errors/CAGE-CONN-008.md +47 -0
  194. package/templates/app/docs/errors/CAGE-CONN-009.md +47 -0
  195. package/templates/app/docs/errors/CAGE-CONN-010.md +47 -0
  196. package/templates/app/docs/errors/CAGE-CONN-011.md +47 -0
  197. package/templates/app/docs/errors/CAGE-CONN-012.md +47 -0
  198. package/templates/app/docs/errors/CAGE-CREATE-001.md +52 -0
  199. package/templates/app/docs/errors/CAGE-DECL-001.md +48 -0
  200. package/templates/app/docs/errors/CAGE-DECL-002.md +47 -0
  201. package/templates/app/docs/errors/CAGE-DECL-003.md +47 -0
  202. package/templates/app/docs/errors/CAGE-DECL-004.md +47 -0
  203. package/templates/app/docs/errors/CAGE-DEP-001.md +48 -0
  204. package/templates/app/docs/errors/CAGE-DEP-002.md +47 -0
  205. package/templates/app/docs/errors/CAGE-DEP-003.md +47 -0
  206. package/templates/app/docs/errors/CAGE-DEP-004.md +47 -0
  207. package/templates/app/docs/errors/CAGE-DEP-005.md +47 -0
  208. package/templates/app/docs/errors/CAGE-DLQ-001.md +48 -0
  209. package/templates/app/docs/errors/CAGE-ENV-001.md +52 -0
  210. package/templates/app/docs/errors/CAGE-EVENT-001.md +47 -0
  211. package/templates/app/docs/errors/CAGE-EVENT-002.md +50 -0
  212. package/templates/app/docs/errors/CAGE-FIELD-001.md +47 -0
  213. package/templates/app/docs/errors/CAGE-FIELD-002.md +47 -0
  214. package/templates/app/docs/errors/CAGE-FIELD-003.md +47 -0
  215. package/templates/app/docs/errors/CAGE-FIELD-004.md +47 -0
  216. package/templates/app/docs/errors/CAGE-GEN-001.md +48 -0
  217. package/templates/app/docs/errors/CAGE-GEN-002.md +47 -0
  218. package/templates/app/docs/errors/CAGE-GRANT-001.md +49 -0
  219. package/templates/app/docs/errors/CAGE-GRANT-002.md +48 -0
  220. package/templates/app/docs/errors/CAGE-GRANT-003.md +47 -0
  221. package/templates/app/docs/errors/CAGE-IMPACT-001.md +48 -0
  222. package/templates/app/docs/errors/CAGE-INIT-001.md +47 -0
  223. package/templates/app/docs/errors/CAGE-INIT-002.md +49 -0
  224. package/templates/app/docs/errors/CAGE-INIT-003.md +48 -0
  225. package/templates/app/docs/errors/CAGE-INIT-004.md +48 -0
  226. package/templates/app/docs/errors/CAGE-JOB-001.md +47 -0
  227. package/templates/app/docs/errors/CAGE-JOB-002.md +47 -0
  228. package/templates/app/docs/errors/CAGE-JOB-003.md +47 -0
  229. package/templates/app/docs/errors/CAGE-LINT-001.md +47 -0
  230. package/templates/app/docs/errors/CAGE-MIG-001.md +47 -0
  231. package/templates/app/docs/errors/CAGE-MIG-002.md +47 -0
  232. package/templates/app/docs/errors/CAGE-MIG-003.md +5 -0
  233. package/templates/app/docs/errors/CAGE-MIG-004.md +5 -0
  234. package/templates/app/docs/errors/CAGE-MIG-005.md +47 -0
  235. package/templates/app/docs/errors/CAGE-NAME-001.md +47 -0
  236. package/templates/app/docs/errors/CAGE-NAME-002.md +47 -0
  237. package/templates/app/docs/errors/CAGE-NAME-003.md +47 -0
  238. package/templates/app/docs/errors/CAGE-NAME-004.md +47 -0
  239. package/templates/app/docs/errors/CAGE-NAME-005.md +47 -0
  240. package/templates/app/docs/errors/CAGE-NAME-006.md +47 -0
  241. package/templates/app/docs/errors/CAGE-ORG-001.md +49 -0
  242. package/templates/app/docs/errors/CAGE-PAIR-002.md +50 -0
  243. package/templates/app/docs/errors/CAGE-QUERY-001.md +47 -0
  244. package/templates/app/docs/errors/CAGE-QUERY-002.md +47 -0
  245. package/templates/app/docs/errors/CAGE-QUERY-003.md +49 -0
  246. package/templates/app/docs/errors/CAGE-REACT-001.md +47 -0
  247. package/templates/app/docs/errors/CAGE-REACT-002.md +47 -0
  248. package/templates/app/docs/errors/CAGE-READS-001.md +47 -0
  249. package/templates/app/docs/errors/CAGE-REG-001.md +53 -0
  250. package/templates/app/docs/errors/CAGE-REG-002.md +48 -0
  251. package/templates/app/docs/errors/CAGE-REG-003.md +47 -0
  252. package/templates/app/docs/errors/CAGE-REL-001.md +64 -0
  253. package/templates/app/docs/errors/CAGE-ROUTE-001.md +47 -0
  254. package/templates/app/docs/errors/CAGE-SCOPE-001.md +47 -0
  255. package/templates/app/docs/errors/CAGE-SCOPE-002.md +47 -0
  256. package/templates/app/docs/errors/CAGE-SECRET-001.md +48 -0
  257. package/templates/app/docs/errors/CAGE-SECRET-002.md +47 -0
  258. package/templates/app/docs/errors/CAGE-SENS-001.md +48 -0
  259. package/templates/app/docs/errors/CAGE-SQL-001.md +47 -0
  260. package/templates/app/docs/errors/CAGE-SQL-002.md +47 -0
  261. package/templates/app/docs/errors/CAGE-STATE-001.md +49 -0
  262. package/templates/app/docs/errors/CAGE-STATE-002.md +47 -0
  263. package/templates/app/docs/errors/CAGE-STATE-003.md +47 -0
  264. package/templates/app/docs/errors/CAGE-STATE-004.md +47 -0
  265. package/templates/app/docs/errors/CAGE-STATE-005.md +48 -0
  266. package/templates/app/docs/errors/CAGE-STATE-010.md +48 -0
  267. package/templates/app/docs/errors/CAGE-STATE-011.md +48 -0
  268. package/templates/app/docs/errors/CAGE-STRUCT-001.md +51 -0
  269. package/templates/app/docs/errors/CAGE-STRUCT-002.md +51 -0
  270. package/templates/app/docs/errors/CAGE-SYNC-001.md +48 -0
  271. package/templates/app/docs/errors/CAGE-TEST-001.md +47 -0
  272. package/templates/app/docs/errors/CAGE-UNSAFE-001.md +48 -0
  273. package/templates/app/docs/errors/CAGE-UPGRADE-001.md +48 -0
  274. package/templates/app/docs/errors/README.md +307 -0
  275. package/templates/app/docs/errors/runtime.md +50 -0
  276. package/templates/app/package.json +22 -0
  277. package/templates/app/packages/contracts/package.json +16 -0
  278. package/templates/app/packages/contracts/src/aggregates/dept/index.ts +74 -0
  279. package/templates/app/packages/contracts/src/aggregates/inventory/index.ts +57 -0
  280. package/templates/app/packages/contracts/src/aggregates/inventory-lock/index.ts +52 -0
  281. package/templates/app/packages/contracts/src/aggregates/purchase-order/index.ts +72 -0
  282. package/templates/app/packages/contracts/src/aggregates/role/index.ts +85 -0
  283. package/templates/app/packages/contracts/src/aggregates/user/index.ts +89 -0
  284. package/templates/app/packages/contracts/src/index.ts +81 -0
  285. package/templates/app/packages/contracts/src/queries/index.ts +17 -0
  286. package/templates/app/packages/contracts/tsconfig.json +5 -0
  287. package/templates/app/packages/domain/package.json +23 -0
  288. package/templates/app/packages/domain/src/index.ts +6 -0
  289. package/templates/app/packages/domain/src/integrations/erp.ts +36 -0
  290. package/templates/app/packages/domain/src/modules/inventory/index.ts +2 -0
  291. package/templates/app/packages/domain/src/modules/inventory/inventory.ts +43 -0
  292. package/templates/app/packages/domain/src/modules/purchase/approvals.ts +18 -0
  293. package/templates/app/packages/domain/src/modules/purchase/index.ts +6 -0
  294. package/templates/app/packages/domain/src/modules/purchase/jobs.ts +13 -0
  295. package/templates/app/packages/domain/src/modules/purchase/purchase-order.test.ts +137 -0
  296. package/templates/app/packages/domain/src/modules/purchase/purchase-order.ts +122 -0
  297. package/templates/app/packages/domain/src/modules/purchase/queries.ts +10 -0
  298. package/templates/app/packages/domain/src/workflows/purchase-inventory.ts +24 -0
  299. package/templates/app/packages/domain/tsconfig.json +5 -0
  300. package/templates/app/pnpm-workspace.yaml +10 -0
  301. package/templates/app/renovate.json +5 -0
  302. package/templates/app/tsconfig.base.json +8 -0
  303. package/templates/blank/.dockerignore +10 -0
  304. package/templates/blank/.env.example +61 -0
  305. package/templates/blank/.github/workflows/cage.yml +44 -0
  306. package/templates/blank/AGENTS.md +96 -0
  307. package/templates/blank/Dockerfile +25 -0
  308. package/templates/blank/README.md +37 -0
  309. package/templates/blank/_gitignore +8 -0
  310. package/templates/blank/apps/api/package.json +15 -0
  311. package/templates/blank/apps/api/src/main.ts +11 -0
  312. package/templates/blank/apps/api/src/worker.ts +8 -0
  313. package/templates/blank/apps/api/tsconfig.json +5 -0
  314. package/templates/blank/apps/web/index.html +13 -0
  315. package/templates/blank/apps/web/package.json +22 -0
  316. package/templates/blank/apps/web/src/app/app.tsx +44 -0
  317. package/templates/blank/apps/web/src/app/styles/global.css +516 -0
  318. package/templates/blank/apps/web/src/app/workspace-layout.tsx +70 -0
  319. package/templates/blank/apps/web/src/main.tsx +13 -0
  320. package/templates/blank/apps/web/src/modules/auth/index.ts +1 -0
  321. package/templates/blank/apps/web/src/modules/auth/pages/login-page.tsx +87 -0
  322. package/templates/blank/apps/web/src/modules/workspace/index.ts +1 -0
  323. package/templates/blank/apps/web/src/modules/workspace/pages/home-page.tsx +45 -0
  324. package/templates/blank/apps/web/src/shared/lib/error-message.ts +11 -0
  325. package/templates/blank/apps/web/src/shared/ui/brand.tsx +11 -0
  326. package/templates/blank/apps/web/tsconfig.json +11 -0
  327. package/templates/blank/apps/web/vite.config.ts +19 -0
  328. package/templates/blank/cage.config.json +14 -0
  329. package/templates/blank/db/migrations/0001_init.sql +63 -0
  330. package/templates/blank/docs/ai/README.md +77 -0
  331. package/templates/blank/docs/ai/architecture.md +122 -0
  332. package/templates/blank/docs/ai/ontology-context.md +117 -0
  333. package/templates/blank/docs/ai/primitives.md +249 -0
  334. package/templates/blank/docs/ai/project-structure.md +123 -0
  335. package/templates/blank/docs/ai/purchase-example.md +97 -0
  336. package/templates/blank/docs/ai/recipes.md +81 -0
  337. package/templates/blank/docs/ai/relations.md +160 -0
  338. package/templates/blank/docs/ai/transfers.md +92 -0
  339. package/templates/blank/docs/ai/troubleshooting.md +60 -0
  340. package/templates/blank/docs/ai/workflow.md +139 -0
  341. package/templates/blank/docs/errors/CAGE-APPR-001.md +47 -0
  342. package/templates/blank/docs/errors/CAGE-APPR-002.md +47 -0
  343. package/templates/blank/docs/errors/CAGE-APPR-003.md +47 -0
  344. package/templates/blank/docs/errors/CAGE-APPR-004.md +47 -0
  345. package/templates/blank/docs/errors/CAGE-APPR-005.md +47 -0
  346. package/templates/blank/docs/errors/CAGE-APPR-006.md +47 -0
  347. package/templates/blank/docs/errors/CAGE-APPR-007.md +50 -0
  348. package/templates/blank/docs/errors/CAGE-APPR-010.md +48 -0
  349. package/templates/blank/docs/errors/CAGE-AUTH-001.md +47 -0
  350. package/templates/blank/docs/errors/CAGE-BUDGET-001.md +47 -0
  351. package/templates/blank/docs/errors/CAGE-BUDGET-002.md +47 -0
  352. package/templates/blank/docs/errors/CAGE-BUDGET-003.md +47 -0
  353. package/templates/blank/docs/errors/CAGE-CMD-002.md +47 -0
  354. package/templates/blank/docs/errors/CAGE-CMD-003.md +47 -0
  355. package/templates/blank/docs/errors/CAGE-CONN-001.md +47 -0
  356. package/templates/blank/docs/errors/CAGE-CONN-002.md +47 -0
  357. package/templates/blank/docs/errors/CAGE-CONN-003.md +47 -0
  358. package/templates/blank/docs/errors/CAGE-CONN-004.md +47 -0
  359. package/templates/blank/docs/errors/CAGE-CONN-005.md +47 -0
  360. package/templates/blank/docs/errors/CAGE-CONN-006.md +47 -0
  361. package/templates/blank/docs/errors/CAGE-CONN-007.md +47 -0
  362. package/templates/blank/docs/errors/CAGE-CONN-008.md +47 -0
  363. package/templates/blank/docs/errors/CAGE-CONN-009.md +47 -0
  364. package/templates/blank/docs/errors/CAGE-CONN-010.md +47 -0
  365. package/templates/blank/docs/errors/CAGE-CONN-011.md +47 -0
  366. package/templates/blank/docs/errors/CAGE-CONN-012.md +47 -0
  367. package/templates/blank/docs/errors/CAGE-CREATE-001.md +52 -0
  368. package/templates/blank/docs/errors/CAGE-DECL-001.md +48 -0
  369. package/templates/blank/docs/errors/CAGE-DECL-002.md +47 -0
  370. package/templates/blank/docs/errors/CAGE-DECL-003.md +47 -0
  371. package/templates/blank/docs/errors/CAGE-DECL-004.md +47 -0
  372. package/templates/blank/docs/errors/CAGE-DEP-001.md +48 -0
  373. package/templates/blank/docs/errors/CAGE-DEP-002.md +47 -0
  374. package/templates/blank/docs/errors/CAGE-DEP-003.md +47 -0
  375. package/templates/blank/docs/errors/CAGE-DEP-004.md +47 -0
  376. package/templates/blank/docs/errors/CAGE-DEP-005.md +47 -0
  377. package/templates/blank/docs/errors/CAGE-DLQ-001.md +48 -0
  378. package/templates/blank/docs/errors/CAGE-ENV-001.md +52 -0
  379. package/templates/blank/docs/errors/CAGE-EVENT-001.md +47 -0
  380. package/templates/blank/docs/errors/CAGE-EVENT-002.md +50 -0
  381. package/templates/blank/docs/errors/CAGE-FIELD-001.md +47 -0
  382. package/templates/blank/docs/errors/CAGE-FIELD-002.md +47 -0
  383. package/templates/blank/docs/errors/CAGE-FIELD-003.md +47 -0
  384. package/templates/blank/docs/errors/CAGE-FIELD-004.md +47 -0
  385. package/templates/blank/docs/errors/CAGE-GEN-001.md +48 -0
  386. package/templates/blank/docs/errors/CAGE-GEN-002.md +47 -0
  387. package/templates/blank/docs/errors/CAGE-GRANT-001.md +49 -0
  388. package/templates/blank/docs/errors/CAGE-GRANT-002.md +48 -0
  389. package/templates/blank/docs/errors/CAGE-GRANT-003.md +47 -0
  390. package/templates/blank/docs/errors/CAGE-IMPACT-001.md +48 -0
  391. package/templates/blank/docs/errors/CAGE-INIT-001.md +47 -0
  392. package/templates/blank/docs/errors/CAGE-INIT-002.md +49 -0
  393. package/templates/blank/docs/errors/CAGE-INIT-003.md +48 -0
  394. package/templates/blank/docs/errors/CAGE-INIT-004.md +48 -0
  395. package/templates/blank/docs/errors/CAGE-JOB-001.md +47 -0
  396. package/templates/blank/docs/errors/CAGE-JOB-002.md +47 -0
  397. package/templates/blank/docs/errors/CAGE-JOB-003.md +47 -0
  398. package/templates/blank/docs/errors/CAGE-LINT-001.md +47 -0
  399. package/templates/blank/docs/errors/CAGE-MIG-001.md +47 -0
  400. package/templates/blank/docs/errors/CAGE-MIG-002.md +47 -0
  401. package/templates/blank/docs/errors/CAGE-MIG-003.md +5 -0
  402. package/templates/blank/docs/errors/CAGE-MIG-004.md +5 -0
  403. package/templates/blank/docs/errors/CAGE-MIG-005.md +47 -0
  404. package/templates/blank/docs/errors/CAGE-NAME-001.md +47 -0
  405. package/templates/blank/docs/errors/CAGE-NAME-002.md +47 -0
  406. package/templates/blank/docs/errors/CAGE-NAME-003.md +47 -0
  407. package/templates/blank/docs/errors/CAGE-NAME-004.md +47 -0
  408. package/templates/blank/docs/errors/CAGE-NAME-005.md +47 -0
  409. package/templates/blank/docs/errors/CAGE-NAME-006.md +47 -0
  410. package/templates/blank/docs/errors/CAGE-ORG-001.md +49 -0
  411. package/templates/blank/docs/errors/CAGE-PAIR-002.md +50 -0
  412. package/templates/blank/docs/errors/CAGE-QUERY-001.md +47 -0
  413. package/templates/blank/docs/errors/CAGE-QUERY-002.md +47 -0
  414. package/templates/blank/docs/errors/CAGE-QUERY-003.md +49 -0
  415. package/templates/blank/docs/errors/CAGE-REACT-001.md +47 -0
  416. package/templates/blank/docs/errors/CAGE-REACT-002.md +47 -0
  417. package/templates/blank/docs/errors/CAGE-READS-001.md +47 -0
  418. package/templates/blank/docs/errors/CAGE-REG-001.md +53 -0
  419. package/templates/blank/docs/errors/CAGE-REG-002.md +48 -0
  420. package/templates/blank/docs/errors/CAGE-REG-003.md +47 -0
  421. package/templates/blank/docs/errors/CAGE-REL-001.md +64 -0
  422. package/templates/blank/docs/errors/CAGE-ROUTE-001.md +47 -0
  423. package/templates/blank/docs/errors/CAGE-SCOPE-001.md +47 -0
  424. package/templates/blank/docs/errors/CAGE-SCOPE-002.md +47 -0
  425. package/templates/blank/docs/errors/CAGE-SECRET-001.md +48 -0
  426. package/templates/blank/docs/errors/CAGE-SECRET-002.md +47 -0
  427. package/templates/blank/docs/errors/CAGE-SENS-001.md +48 -0
  428. package/templates/blank/docs/errors/CAGE-SQL-001.md +47 -0
  429. package/templates/blank/docs/errors/CAGE-SQL-002.md +47 -0
  430. package/templates/blank/docs/errors/CAGE-STATE-001.md +49 -0
  431. package/templates/blank/docs/errors/CAGE-STATE-002.md +47 -0
  432. package/templates/blank/docs/errors/CAGE-STATE-003.md +47 -0
  433. package/templates/blank/docs/errors/CAGE-STATE-004.md +47 -0
  434. package/templates/blank/docs/errors/CAGE-STATE-005.md +48 -0
  435. package/templates/blank/docs/errors/CAGE-STATE-010.md +48 -0
  436. package/templates/blank/docs/errors/CAGE-STATE-011.md +48 -0
  437. package/templates/blank/docs/errors/CAGE-STRUCT-001.md +51 -0
  438. package/templates/blank/docs/errors/CAGE-STRUCT-002.md +51 -0
  439. package/templates/blank/docs/errors/CAGE-SYNC-001.md +48 -0
  440. package/templates/blank/docs/errors/CAGE-TEST-001.md +47 -0
  441. package/templates/blank/docs/errors/CAGE-UNSAFE-001.md +48 -0
  442. package/templates/blank/docs/errors/CAGE-UPGRADE-001.md +48 -0
  443. package/templates/blank/docs/errors/README.md +307 -0
  444. package/templates/blank/docs/errors/runtime.md +50 -0
  445. package/templates/blank/docs/examples/purchase-admin/README.md +5 -0
  446. package/templates/blank/docs/examples/purchase-admin/apps/api/src/main.ts +10 -0
  447. package/templates/blank/docs/examples/purchase-admin/apps/api/src/worker.ts +14 -0
  448. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/app.tsx +18 -0
  449. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/styles/global.css +663 -0
  450. package/templates/blank/docs/examples/purchase-admin/apps/web/src/app/workspace-layout.tsx +70 -0
  451. package/templates/blank/docs/examples/purchase-admin/apps/web/src/main.tsx +13 -0
  452. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/hooks/use-approval-tasks.ts +20 -0
  453. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/index.ts +2 -0
  454. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/approval/pages/approval-tasks-page.tsx +54 -0
  455. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/index.ts +1 -0
  456. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/auth/pages/login-page.tsx +59 -0
  457. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/index.ts +1 -0
  458. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/inventory/pages/inventory-page.tsx +74 -0
  459. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/components/purchase-order-form.tsx +60 -0
  460. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/index.ts +2 -0
  461. package/templates/blank/docs/examples/purchase-admin/apps/web/src/modules/purchase/pages/purchase-orders-page.tsx +210 -0
  462. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/hooks/use-command.ts +29 -0
  463. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/lib/error-message.ts +15 -0
  464. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/notice.tsx +13 -0
  465. package/templates/blank/docs/examples/purchase-admin/apps/web/src/shared/ui/page-heading.tsx +28 -0
  466. package/templates/blank/docs/examples/purchase-admin/cage.config.json +114 -0
  467. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/dept/index.ts +74 -0
  468. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory/index.ts +57 -0
  469. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/inventory-lock/index.ts +52 -0
  470. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/purchase-order/index.ts +72 -0
  471. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/role/index.ts +85 -0
  472. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/aggregates/user/index.ts +89 -0
  473. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/index.ts +81 -0
  474. package/templates/blank/docs/examples/purchase-admin/packages/contracts/src/queries/index.ts +17 -0
  475. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/index.ts +6 -0
  476. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/integrations/erp.ts +36 -0
  477. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/index.ts +2 -0
  478. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/inventory/inventory.ts +43 -0
  479. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/approvals.ts +18 -0
  480. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/index.ts +6 -0
  481. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/jobs.ts +13 -0
  482. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.test.ts +137 -0
  483. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/purchase-order.ts +122 -0
  484. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/modules/purchase/queries.ts +10 -0
  485. package/templates/blank/docs/examples/purchase-admin/packages/domain/src/workflows/purchase-inventory.ts +24 -0
  486. package/templates/blank/package.json +22 -0
  487. package/templates/blank/packages/contracts/package.json +16 -0
  488. package/templates/blank/packages/contracts/src/aggregates/dept/index.ts +74 -0
  489. package/templates/blank/packages/contracts/src/aggregates/role/index.ts +85 -0
  490. package/templates/blank/packages/contracts/src/aggregates/user/index.ts +89 -0
  491. package/templates/blank/packages/contracts/src/index.ts +55 -0
  492. package/templates/blank/packages/contracts/src/queries/index.ts +13 -0
  493. package/templates/blank/packages/contracts/tsconfig.json +5 -0
  494. package/templates/blank/packages/domain/package.json +23 -0
  495. package/templates/blank/packages/domain/src/index.ts +4 -0
  496. package/templates/blank/packages/domain/tsconfig.json +5 -0
  497. package/templates/blank/pnpm-workspace.yaml +10 -0
  498. package/templates/blank/renovate.json +5 -0
  499. package/templates/blank/tsconfig.base.json +8 -0
@@ -0,0 +1,307 @@
1
+ # 错误码册
2
+
3
+ 这是本业务项目自带的离线诊断手册。先使用错误码、声明位置、reason/fix 定位;不需要克隆框架仓库。
4
+
5
+ - [HTTP 运行时错误与业务码](runtime.md):401/403/404、状态冲突、约束拒绝、DOMAIN_ERROR 等。
6
+ - [业务排错顺序](../ai/troubleshooting.md):启动、权限、审批人、worker、死信与导入导出。
7
+ - CAGE-* 是声明、工具链或内部运行诊断;HTTP code 与业务 domainCode 是另一层,不要混为一谈。
8
+
9
+ 每页包含触发阶段、具体原因、修复步骤、正反例、验证方法与当前版实现位置。例子为局部说明,不能替代完整业务输入。
10
+
11
+ ## 审批
12
+
13
+ | 诊断码 | 含义 |
14
+ | --- | --- |
15
+ | [CAGE-APPR-001](CAGE-APPR-001.md) | 可路由字段不存在 |
16
+ | [CAGE-APPR-002](CAGE-APPR-002.md) | 审批结论落到其他聚合 |
17
+ | [CAGE-APPR-003](CAGE-APPR-003.md) | 审批结论未允许流程调用 |
18
+ | [CAGE-APPR-004](CAGE-APPR-004.md) | 路由没有对应审批绑定 |
19
+ | [CAGE-APPR-005](CAGE-APPR-005.md) | 流程名称格式错误 |
20
+ | [CAGE-APPR-006](CAGE-APPR-006.md) | 流程没有步骤 |
21
+ | [CAGE-APPR-007](CAGE-APPR-007.md) | 找不到审批人 |
22
+ | [CAGE-APPR-010](CAGE-APPR-010.md) | 流程专用命令没有调用者 |
23
+
24
+ ## 登录认证
25
+
26
+ | 诊断码 | 含义 |
27
+ | --- | --- |
28
+ | [CAGE-AUTH-001](CAGE-AUTH-001.md) | OIDC 发现文档获取失败 |
29
+
30
+ ## 体积与逃生口预算
31
+
32
+ | 诊断码 | 含义 |
33
+ | --- | --- |
34
+ | [CAGE-BUDGET-001](CAGE-BUDGET-001.md) | 内核超出体积预算 |
35
+ | [CAGE-BUDGET-002](CAGE-BUDGET-002.md) | 公共原语超过词汇预算 |
36
+ | [CAGE-BUDGET-003](CAGE-BUDGET-003.md) | 新增未经基线认可的 unsafe |
37
+
38
+ ## 命令
39
+
40
+ | 诊断码 | 含义 |
41
+ | --- | --- |
42
+ | [CAGE-CMD-002](CAGE-CMD-002.md) | 已有记录命令缺少 id |
43
+ | [CAGE-CMD-003](CAGE-CMD-003.md) | 新建命令没有目标状态 |
44
+
45
+ ## 第三方连接器
46
+
47
+ | 诊断码 | 含义 |
48
+ | --- | --- |
49
+ | [CAGE-CONN-001](CAGE-CONN-001.md) | 连接器名称格式错误 |
50
+ | [CAGE-CONN-002](CAGE-CONN-002.md) | 外部操作路径格式错误 |
51
+ | [CAGE-CONN-003](CAGE-CONN-003.md) | 地址白名单包含协议或路径 |
52
+ | [CAGE-CONN-004](CAGE-CONN-004.md) | 只读操作被用作出站写映射 |
53
+ | [CAGE-CONN-005](CAGE-CONN-005.md) | 入站事件名称格式错误 |
54
+ | [CAGE-CONN-006](CAGE-CONN-006.md) | 回调命令未允许 external |
55
+ | [CAGE-CONN-007](CAGE-CONN-007.md) | 当前环境没有连接器地址 |
56
+ | [CAGE-CONN-008](CAGE-CONN-008.md) | 外部请求发生网络错误或超时 |
57
+ | [CAGE-CONN-009](CAGE-CONN-009.md) | 外部服务返回非成功状态 |
58
+ | [CAGE-CONN-010](CAGE-CONN-010.md) | 外部响应不符合 schema |
59
+ | [CAGE-CONN-011](CAGE-CONN-011.md) | 出站永久失败进入死信 |
60
+ | [CAGE-CONN-012](CAGE-CONN-012.md) | 外部专用命令没有声明调用者 |
61
+
62
+ ## 创建应用
63
+
64
+ | 诊断码 | 含义 |
65
+ | --- | --- |
66
+ | [CAGE-CREATE-001](CAGE-CREATE-001.md) | 项目创建参数或模板资源有误 |
67
+
68
+ ## 可抽取声明
69
+
70
+ | 诊断码 | 含义 |
71
+ | --- | --- |
72
+ | [CAGE-DECL-001](CAGE-DECL-001.md) | 声明不在可抽取的顶层常量 |
73
+ | [CAGE-DECL-002](CAGE-DECL-002.md) | 声明没有从 domain 入口导出 |
74
+ | [CAGE-DECL-003](CAGE-DECL-003.md) | 声明不是 export const |
75
+ | [CAGE-DECL-004](CAGE-DECL-004.md) | 跨文件导出名冲突 |
76
+
77
+ ## 依赖边界
78
+
79
+ | 诊断码 | 含义 |
80
+ | --- | --- |
81
+ | [CAGE-DEP-001](CAGE-DEP-001.md) | 领域声明直接依赖 IO |
82
+ | [CAGE-DEP-002](CAGE-DEP-002.md) | 适配器绕过命令写库 |
83
+ | [CAGE-DEP-003](CAGE-DEP-003.md) | 前端依赖服务端实现 |
84
+ | [CAGE-DEP-004](CAGE-DEP-004.md) | 声明或 handler 直接发请求/动态导入 |
85
+ | [CAGE-DEP-005](CAGE-DEP-005.md) | domain 反向依赖生成物 |
86
+
87
+ ## 工程目录与模块依赖
88
+
89
+ | 诊断码 | 含义 |
90
+ | --- | --- |
91
+ | [CAGE-STRUCT-001](CAGE-STRUCT-001.md) | 业务源码目录不符合模块约定 |
92
+ | [CAGE-STRUCT-002](CAGE-STRUCT-002.md) | 源码依赖越过模块边界 |
93
+
94
+ ## 死信操作
95
+
96
+ | 诊断码 | 含义 |
97
+ | --- | --- |
98
+ | [CAGE-DLQ-001](CAGE-DLQ-001.md) | 死信不存在或已经处理 |
99
+
100
+ ## 运行配置
101
+
102
+ | 诊断码 | 含义 |
103
+ | --- | --- |
104
+ | [CAGE-ENV-001](CAGE-ENV-001.md) | 缺少数据库连接配置 |
105
+
106
+ ## 事件载荷与兼容性
107
+
108
+ | 诊断码 | 含义 |
109
+ | --- | --- |
110
+ | [CAGE-EVENT-001](CAGE-EVENT-001.md) | 事件载荷不满足声明 |
111
+ | [CAGE-EVENT-002](CAGE-EVENT-002.md) | 事件变更不向后兼容 |
112
+
113
+ ## 字段
114
+
115
+ | 诊断码 | 含义 |
116
+ | --- | --- |
117
+ | [CAGE-FIELD-001](CAGE-FIELD-001.md) | 敏感字段种类不存在 |
118
+ | [CAGE-FIELD-002](CAGE-FIELD-002.md) | 引用目标为空 |
119
+ | [CAGE-FIELD-003](CAGE-FIELD-003.md) | 字段不是字段原语 |
120
+ | [CAGE-FIELD-004](CAGE-FIELD-004.md) | 覆盖系统保留列 |
121
+
122
+ ## 关系字段
123
+
124
+ | 诊断码 | 含义 |
125
+ | --- | --- |
126
+ | [CAGE-REL-001](CAGE-REL-001.md) | 关系字段声明无效 |
127
+
128
+ ## 生成一致性
129
+
130
+ | 诊断码 | 含义 |
131
+ | --- | --- |
132
+ | [CAGE-GEN-001](CAGE-GEN-001.md) | 契约等生成结果过期 |
133
+ | [CAGE-GEN-002](CAGE-GEN-002.md) | 声明结构没有对应迁移 |
134
+
135
+ ## 角色授权与防提权
136
+
137
+ | 诊断码 | 含义 |
138
+ | --- | --- |
139
+ | [CAGE-GRANT-001](CAGE-GRANT-001.md) | 授予超出自己的能力或额度 |
140
+ | [CAGE-GRANT-002](CAGE-GRANT-002.md) | 授予超出自己的数据范围 |
141
+ | [CAGE-GRANT-003](CAGE-GRANT-003.md) | 能力不在代码目录中 |
142
+
143
+ ## 影响分析
144
+
145
+ | 诊断码 | 含义 |
146
+ | --- | --- |
147
+ | [CAGE-IMPACT-001](CAGE-IMPACT-001.md) | 影响分析没有可用基线 |
148
+
149
+ ## 账号初始化
150
+
151
+ | 诊断码 | 含义 |
152
+ | --- | --- |
153
+ | [CAGE-INIT-001](CAGE-INIT-001.md) | 管理员 URL 没有数据库名 |
154
+ | [CAGE-INIT-002](CAGE-INIT-002.md) | 集群已有账号但缺少原凭证 |
155
+ | [CAGE-INIT-003](CAGE-INIT-003.md) | 三种连接身份或目标不一致 |
156
+ | [CAGE-INIT-004](CAGE-INIT-004.md) | 账号已创建但 .env 替换失败 |
157
+
158
+ ## 定时任务
159
+
160
+ | 诊断码 | 含义 |
161
+ | --- | --- |
162
+ | [CAGE-JOB-001](CAGE-JOB-001.md) | 定时表达式不合法 |
163
+ | [CAGE-JOB-002](CAGE-JOB-002.md) | 任务调用了未声明的命令 |
164
+ | [CAGE-JOB-003](CAGE-JOB-003.md) | 任务读取了未声明的聚合 |
165
+
166
+ ## 通用 lint
167
+
168
+ | 诊断码 | 含义 |
169
+ | --- | --- |
170
+ | [CAGE-LINT-001](CAGE-LINT-001.md) | lint 语法或规则错误 |
171
+
172
+ ## 结构迁移与安全层
173
+
174
+ | 诊断码 | 含义 |
175
+ | --- | --- |
176
+ | [CAGE-MIG-001](CAGE-MIG-001.md) | 迁移事务执行失败 |
177
+ | [CAGE-MIG-002](CAGE-MIG-002.md) | 安全层重建失败 |
178
+ | [CAGE-MIG-005](CAGE-MIG-005.md) | 已执行迁移内容被修改 |
179
+
180
+ ## 名称
181
+
182
+ | 诊断码 | 含义 |
183
+ | --- | --- |
184
+ | [CAGE-NAME-001](CAGE-NAME-001.md) | 聚合名必须大驼峰 |
185
+ | [CAGE-NAME-002](CAGE-NAME-002.md) | 字段名必须小驼峰 |
186
+ | [CAGE-NAME-003](CAGE-NAME-003.md) | 事件名必须大驼峰 |
187
+ | [CAGE-NAME-004](CAGE-NAME-004.md) | 命令名必须小驼峰 |
188
+ | [CAGE-NAME-005](CAGE-NAME-005.md) | 查询名必须小驼峰 |
189
+ | [CAGE-NAME-006](CAGE-NAME-006.md) | 任务名必须小驼峰 |
190
+
191
+ ## 组织模型
192
+
193
+ | 诊断码 | 含义 |
194
+ | --- | --- |
195
+ | [CAGE-ORG-001](CAGE-ORG-001.md) | 业务入口遗漏组织模型 |
196
+
197
+ ## 资源配对
198
+
199
+ | 诊断码 | 含义 |
200
+ | --- | --- |
201
+ | [CAGE-PAIR-002](CAGE-PAIR-002.md) | 离开持有资源状态却没有释放 |
202
+
203
+ ## 安全查询
204
+
205
+ | 诊断码 | 含义 |
206
+ | --- | --- |
207
+ | [CAGE-QUERY-001](CAGE-QUERY-001.md) | 查询必须选择一种实现 |
208
+ | [CAGE-QUERY-002](CAGE-QUERY-002.md) | 自定义查询直接访问基表 |
209
+ | [CAGE-QUERY-003](CAGE-QUERY-003.md) | 查询读取范围与声明不一致 |
210
+
211
+ ## 跨聚合反应
212
+
213
+ | 诊断码 | 含义 |
214
+ | --- | --- |
215
+ | [CAGE-REACT-001](CAGE-REACT-001.md) | 反应目标与命令聚合不一致 |
216
+ | [CAGE-REACT-002](CAGE-REACT-002.md) | 同事务反应链嵌套过深 |
217
+
218
+ ## 显式读依赖
219
+
220
+ | 诊断码 | 含义 |
221
+ | --- | --- |
222
+ | [CAGE-READS-001](CAGE-READS-001.md) | handler 使用了未声明读依赖 |
223
+
224
+ ## 运行时注册表
225
+
226
+ | 诊断码 | 含义 |
227
+ | --- | --- |
228
+ | [CAGE-REG-001](CAGE-REG-001.md) | 注册表缺少被引用声明 |
229
+ | [CAGE-REG-002](CAGE-REG-002.md) | 聚合或查询注册重名 |
230
+ | [CAGE-REG-003](CAGE-REG-003.md) | 命令能力点重复 |
231
+
232
+ ## 自动路由
233
+
234
+ | 诊断码 | 含义 |
235
+ | --- | --- |
236
+ | [CAGE-ROUTE-001](CAGE-ROUTE-001.md) | 业务项目手写 HTTP 路由 |
237
+
238
+ ## 数据范围
239
+
240
+ | 诊断码 | 含义 |
241
+ | --- | --- |
242
+ | [CAGE-SCOPE-001](CAGE-SCOPE-001.md) | 范围组合子未知 |
243
+ | [CAGE-SCOPE-002](CAGE-SCOPE-002.md) | 范围字段没有声明 |
244
+
245
+ ## 密钥边界
246
+
247
+ | 诊断码 | 含义 |
248
+ | --- | --- |
249
+ | [CAGE-SECRET-001](CAGE-SECRET-001.md) | 运行环境缺少密钥 |
250
+ | [CAGE-SECRET-002](CAGE-SECRET-002.md) | 源码疑似包含密钥字面量 |
251
+
252
+ ## 敏感字段
253
+
254
+ | 诊断码 | 含义 |
255
+ | --- | --- |
256
+ | [CAGE-SENS-001](CAGE-SENS-001.md) | 敏感字段未标注就进入事件 |
257
+
258
+ ## SQL 参数化
259
+
260
+ | 诊断码 | 含义 |
261
+ | --- | --- |
262
+ | [CAGE-SQL-001](CAGE-SQL-001.md) | SQL 拼接用户值 |
263
+ | [CAGE-SQL-002](CAGE-SQL-002.md) | sql.raw 接收动态表达式 |
264
+
265
+ ## 状态与可达性
266
+
267
+ | 诊断码 | 含义 |
268
+ | --- | --- |
269
+ | [CAGE-STATE-001](CAGE-STATE-001.md) | 引用了未声明状态 |
270
+ | [CAGE-STATE-002](CAGE-STATE-002.md) | 状态集合为空 |
271
+ | [CAGE-STATE-003](CAGE-STATE-003.md) | 状态名称格式错误 |
272
+ | [CAGE-STATE-004](CAGE-STATE-004.md) | 状态名称重复 |
273
+ | [CAGE-STATE-005](CAGE-STATE-005.md) | 状态声明位置冲突 |
274
+ | [CAGE-STATE-010](CAGE-STATE-010.md) | 状态不可达 |
275
+ | [CAGE-STATE-011](CAGE-STATE-011.md) | 非终态没有后续操作 |
276
+
277
+ ## AI 托管区
278
+
279
+ | 诊断码 | 含义 |
280
+ | --- | --- |
281
+ | [CAGE-SYNC-001](CAGE-SYNC-001.md) | AGENTS 托管区过期或标记损坏 |
282
+
283
+ ## 测试报告
284
+
285
+ | 诊断码 | 含义 |
286
+ | --- | --- |
287
+ | [CAGE-TEST-001](CAGE-TEST-001.md) | 测试进程没有生成结果报告 |
288
+
289
+ ## 逃生口
290
+
291
+ | 诊断码 | 含义 |
292
+ | --- | --- |
293
+ | [CAGE-UNSAFE-001](CAGE-UNSAFE-001.md) | 逃生口缺少原因或负责人 |
294
+
295
+ ## 升级
296
+
297
+ | 诊断码 | 含义 |
298
+ | --- | --- |
299
+ | [CAGE-UPGRADE-001](CAGE-UPGRADE-001.md) | 升级版本或 codemod 有歧义 |
300
+
301
+ ## 历史流程
302
+
303
+ [CAGE-MIG-003](CAGE-MIG-003.md)、[CAGE-MIG-004](CAGE-MIG-004.md) 属于旧版初始化流程,当前使用 init + migrate;保留页面供历史诊断。
304
+
305
+ 手册随创建项目时的 CLI 版本分发。cage sync 仅更新 AGENTS 托管区;升级后需要按该版本的资料核对差异。
306
+
307
+ 框架维护者:修改 scripts/error-catalog.ts 后运行 pnpm docs:errors;不要只手改生成的逐码页面。
@@ -0,0 +1,50 @@
1
+ # HTTP 运行时错误与业务码
2
+
3
+ [返回错误码册](README.md) · [排错方法](../ai/troubleshooting.md)
4
+
5
+ 框架诊断分三层:`CAGE-APPR-007` 等内部/工具码、HTTP 响应的通用 `code`、业务拒绝的 `domainCode`。同一次失败可以同时涉及几层;例如审批人配置问题出现在 worker 死信,前端提交此前可能已成功。
6
+
7
+ ## 接口错误
8
+
9
+ | code | HTTP | 含义 | 业务前端/AI 应怎么做 |
10
+ | --- | --- | --- | --- |
11
+ | UNAUTHENTICATED | 401 | 会话不存在/失效或认证未通过 | 重新登录;回调先核对验签,不跳过认证 |
12
+ | FORBIDDEN | 403 | 无能力、身份不允许,或 CSRF 拒绝等 | 看 detail 与当前授权;不能只因有按钮就认为有权。客户端会刷新过期 CSRF 令牌重试 |
13
+ | NOT_FOUND | 404 | 记录不存在或超出范围 | 用当前用户检查 id/租户/范围,不泄漏范围外数据 |
14
+ | INVALID_INPUT | 400 | Zod/协议输入错误、外键或检查约束等 | 按输入 schema 修正字段和格式,不直接扩大 schema |
15
+ | INVALID_TRANSITION | 409 | 当前状态不允许该命令 | 刷新记录,按真实生命周期显示允许操作 |
16
+ | CONSTRAINT_VIOLATED | 403 | 职责分离、额度、二次认证、防提权等拒绝 | 看约束原因,调整业务操作或由有权管理员配置;不删除约束 |
17
+ | INVARIANT_VIOLATED | 409 | 命令结果不满足聚合不变量 | 修正输入或 handler,保持合法结果 |
18
+ | CONFLICT | 409 | 版本、唯一性、数据库串行化/死锁等冲突 | 看 detail、重新读取再决定是否重试;不要盲目重复创建 |
19
+ | DOMAIN_ERROR | 422 | handler 返回 fail | 读取 domainCode,展示业务文案和必要 detail |
20
+ | RATE_LIMITED | 429 | 请求超过限流 | 按提示等待,避免页面无限重试 |
21
+ | INTERNAL | 500 | 未分类内部错误 | 用 requestId 查服务端日志,向用户显示通用失败;不返回堆栈/密钥 |
22
+ | NETWORK(仅客户端) | 0 | 请求未取得可用网络响应 | 检查连接与服务状态;保留同次操作幂等键,避免误认为服务端一定未执行 |
23
+
24
+ 网络失败和超时不证明服务端事务未提交。通用重试与人工重试都需考虑幂等与当前状态,不能先写 SQL 回滚业务再重发。
25
+
26
+ ## 业务码用法
27
+
28
+ 领域 handler 返回:
29
+
30
+ ```ts
31
+ return fail('STOCK_SHORT', ['A-01']);
32
+ ```
33
+
34
+ HTTP 响应形状为:
35
+
36
+ ```json
37
+ { "code": "DOMAIN_ERROR", "domainCode": "STOCK_SHORT", "detail": ["A-01"] }
38
+ ```
39
+
40
+ 客户端方法返回可区分结果,先判断 `result.ok`;失败时看 `result.code`,业务错误再看 `result.domainCode`。不要假设 code 直接等于 STOCK_SHORT,也不要把所有 403 当作“请重新登录”。
41
+
42
+ 业务码由项目定义并在页面翻译;字段 schema、不变量、硬约束和业务 fail 各有职责。正常业务拒绝不要伪装成普通异常导致 INTERNAL。
43
+
44
+ ## 异步任务与死信
45
+
46
+ 导入/导出 HTTP 202 只表示任务已接受,任务详情另有 queued/processing/retrying/completed/failed/expired。检查 task.errorCode/result 和导入报告,完成后才提供成功提示或下载。
47
+
48
+ outbox 消费失败可能重试或进死信;修复内层错误后重放,查看同一聚合后续消息是否继续。使用管理接口处理,不直接更新 sys.outbox 或业务状态。
49
+
50
+ 当前实现定义位于框架源码 `packages/kernel/src/errors.ts` 与客户端包;实际 API 响应为准。生成契约会列出命令可能的通用错误与能抽取到的业务码,但不代表任何错误都已被实际测试覆盖。
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@app/purchase-admin",
3
+ "private": true,
4
+ "type": "module",
5
+ "packageManager": "pnpm@10.14.0",
6
+ "scripts": {
7
+ "dev": "cage dev",
8
+ "migrate": "cage migrate",
9
+ "verify": "cage verify",
10
+ "gen": "cage gen",
11
+ "build:app": "pnpm --filter @app/domain build && pnpm --filter @app/api build && pnpm --filter @app/web build"
12
+ },
13
+ "devDependencies": {
14
+ "@yss123/cage-cli": "0.2.0",
15
+ "@yss123/cage-testkit": "0.2.0",
16
+ "@yss123/cage-lint": "0.2.0",
17
+ "@types/node": "^24.3.0",
18
+ "typescript": "~5.9.3",
19
+ "vitest": "^4.1.12",
20
+ "tsx": "^4.20.5"
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@app/contracts",
3
+ "private": true,
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc -p tsconfig.json",
10
+ "typecheck": "tsc -p tsconfig.json --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@yss123/cage-client": "0.2.0",
14
+ "zod": "^4.1.5"
15
+ }
16
+ }
@@ -0,0 +1,74 @@
1
+ // 生成物:由 cage gen 从 domain 声明生成,不要手改。
2
+ /* eslint-disable */
3
+
4
+ import { z } from 'zod';
5
+ import { client, useCageList, useCageQuery, type TransferTask } from '@yss123/cage-client';
6
+
7
+ /** 部门:读侧快照(敏感字段是按权限掩码后的值) */
8
+ export const DeptSchema = z.object({
9
+ id: z.string().uuid(),
10
+ name: z.string(),
11
+ code: z.string().nullable().optional(),
12
+ parentId: z.string().uuid().nullable().optional(),
13
+ ancestors: z.string(),
14
+ leaderId: z.string().uuid().nullable().optional(),
15
+ status: z.enum(["active", "archived"]),
16
+ version: z.number().int(),
17
+ createdAt: z.string(),
18
+ updatedAt: z.string(),
19
+ });
20
+ export type Dept = z.infer<typeof DeptSchema>;
21
+ export type DeptStatus = Dept['status'];
22
+ export const DeptStates = ['active', 'archived'] as const;
23
+
24
+ /** 命令输入:和后端命令的输入校验完全一致 */
25
+ export const DeptInputs = {
26
+ archive: z.object({ id: z.string().uuid() }),
27
+ create: z.object({ name: z.string().min(1).max(100), code: z.string().max(64).optional(), parentId: z.string().uuid().nullable().optional(), leaderId: z.string().uuid().nullable().optional() }),
28
+ update: z.object({ id: z.string().uuid(), name: z.string().min(1).max(100).optional(), code: z.string().max(64).nullable().optional(), leaderId: z.string().uuid().nullable().optional() }),
29
+ };
30
+
31
+ /** Dept.archive 可能返回的错误码 */
32
+ export type DeptArchiveError = 'CONFLICT' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT' | 'INVALID_TRANSITION' | 'NOT_FOUND';
33
+ /** Dept.create 可能返回的错误码 */
34
+ export type DeptCreateError = 'CONFLICT' | 'CONSTRAINT_VIOLATED' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT';
35
+ /** Dept.update 可能返回的错误码 */
36
+ export type DeptUpdateError = 'CONFLICT' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT' | 'INVALID_TRANSITION' | 'NOT_FOUND';
37
+
38
+ export type DeptSortKey = 'createdAt' | 'updatedAt' | 'name' | 'code' | 'parentId' | 'ancestors' | 'leaderId';
39
+ export interface DeptListParams {
40
+ page?: number;
41
+ pageSize?: number;
42
+ /** 排序:字段名,前面加 - 表示倒序 */
43
+ sort?: DeptSortKey | `-${DeptSortKey}`;
44
+ /** 可以逗号分隔多个状态 */
45
+ status?: string;
46
+ createdAfter?: string;
47
+ createdBefore?: string;
48
+ name?: string | number | boolean;
49
+ code?: string | number | boolean;
50
+ parentId?: string | number | boolean;
51
+ ancestors?: string | number | boolean;
52
+ leaderId?: string | number | boolean;
53
+ }
54
+
55
+ /** 调用方法:每个命令一个;client 自动生成并附带幂等键和 CSRF 令牌 */
56
+ export const dept = {
57
+ /** 停用部门(没有在职用户和下级部门时) */
58
+ archive: (id: string, expectedVersion?: number) => client.post<Dept, DeptArchiveError>(`/api/dept/${encodeURIComponent(id)}/archive`, { expectedVersion }),
59
+ /** 新建部门 */
60
+ create: (input: z.input<typeof DeptInputs.create>) => client.post<Dept, DeptCreateError>('/api/dept/create', input),
61
+ /** 修改部门名称、编码、负责人 */
62
+ update: (id: string, input: Omit<z.input<typeof DeptInputs.update>, 'id'>, expectedVersion?: number) => client.post<Dept, DeptUpdateError>(`/api/dept/${encodeURIComponent(id)}/update`, { ...input, expectedVersion }),
63
+ /** 异步导出 CSV:返回任务,使用 client.transfer(id) 查状态,完成后下载。需要 Dept.export 能力。 */
64
+ export: (params: DeptListParams = {}, options: { idempotencyKey?: string } = {}) => client.post<TransferTask, 'CONFLICT'>('/api/dept/export', params, options),
65
+ get: (id: string) => client.get<Dept>(`/api/dept/${encodeURIComponent(id)}`),
66
+ list: (params: DeptListParams = {}) => client.get<{ items: Dept[]; total: number; page: number; pageSize: number }>('/api/dept', params as Record<string, unknown>),
67
+ };
68
+
69
+ /** 详情查询 hook:响应也用 schema 校验;范围外返回 NOT_FOUND */
70
+ export const useDept = (id: string) => useCageQuery(['dept', id], `/api/dept/${encodeURIComponent(id)}`, DeptSchema, { enabled: !!id });
71
+ /** 列表查询 hook:走读侧账号与安全视图 */
72
+ export const useDeptList = (params: DeptListParams = {}) => useCageList(['dept'], '/api/dept', params as Record<string, unknown>, DeptSchema);
73
+ /** 查询缓存键前缀:命令成功后让它失效 */
74
+ export const deptKeys = { all: ['dept'] as const, one: (id: string) => ['dept', id] as const };
@@ -0,0 +1,57 @@
1
+ // 生成物:由 cage gen 从 domain 声明生成,不要手改。
2
+ /* eslint-disable */
3
+
4
+ import { z } from 'zod';
5
+ import { client, useCageList, useCageQuery, type TransferTask } from '@yss123/cage-client';
6
+
7
+ /** Inventory:读侧快照(敏感字段是按权限掩码后的值) */
8
+ export const InventorySchema = z.object({
9
+ id: z.string().uuid(),
10
+ sku: z.string(),
11
+ available: z.number().int(),
12
+ status: z.enum(["active", "deleted"]),
13
+ version: z.number().int(),
14
+ createdAt: z.string(),
15
+ updatedAt: z.string(),
16
+ });
17
+ export type Inventory = z.infer<typeof InventorySchema>;
18
+ export type InventoryStatus = Inventory['status'];
19
+ export const InventoryStates = ['active', 'deleted'] as const;
20
+
21
+ /** 命令输入:和后端命令的输入校验完全一致 */
22
+ export const InventoryInputs = {
23
+ create: z.object({ sku: z.string(), available: z.number().int().min(-9007199254740991).max(9007199254740991) }),
24
+ };
25
+
26
+ /** Inventory.create 可能返回的错误码 */
27
+ export type InventoryCreateError = 'CONFLICT' | 'CONSTRAINT_VIOLATED' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT';
28
+
29
+ export type InventorySortKey = 'createdAt' | 'updatedAt' | 'sku' | 'available';
30
+ export interface InventoryListParams {
31
+ page?: number;
32
+ pageSize?: number;
33
+ /** 排序:字段名,前面加 - 表示倒序 */
34
+ sort?: InventorySortKey | `-${InventorySortKey}`;
35
+ /** 可以逗号分隔多个状态 */
36
+ status?: string;
37
+ createdAfter?: string;
38
+ createdBefore?: string;
39
+ sku?: string | number | boolean;
40
+ available?: string | number | boolean;
41
+ }
42
+
43
+ /** 调用方法:每个命令一个;client 自动生成并附带幂等键和 CSRF 令牌 */
44
+ export const inventory = {
45
+ create: (input: z.input<typeof InventoryInputs.create>) => client.post<Inventory, InventoryCreateError>('/api/inventory/create', input),
46
+ /** 异步导出 CSV:返回任务,使用 client.transfer(id) 查状态,完成后下载。需要 Inventory.export 能力。 */
47
+ export: (params: InventoryListParams = {}, options: { idempotencyKey?: string } = {}) => client.post<TransferTask, 'CONFLICT'>('/api/inventory/export', params, options),
48
+ get: (id: string) => client.get<Inventory>(`/api/inventory/${encodeURIComponent(id)}`),
49
+ list: (params: InventoryListParams = {}) => client.get<{ items: Inventory[]; total: number; page: number; pageSize: number }>('/api/inventory', params as Record<string, unknown>),
50
+ };
51
+
52
+ /** 详情查询 hook:响应也用 schema 校验;范围外返回 NOT_FOUND */
53
+ export const useInventory = (id: string) => useCageQuery(['inventory', id], `/api/inventory/${encodeURIComponent(id)}`, InventorySchema, { enabled: !!id });
54
+ /** 列表查询 hook:走读侧账号与安全视图 */
55
+ export const useInventoryList = (params: InventoryListParams = {}) => useCageList(['inventory'], '/api/inventory', params as Record<string, unknown>, InventorySchema);
56
+ /** 查询缓存键前缀:命令成功后让它失效 */
57
+ export const inventoryKeys = { all: ['inventory'] as const, one: (id: string) => ['inventory', id] as const };
@@ -0,0 +1,52 @@
1
+ // 生成物:由 cage gen 从 domain 声明生成,不要手改。
2
+ /* eslint-disable */
3
+
4
+ import { z } from 'zod';
5
+ import { client, useCageList, useCageQuery, type TransferTask } from '@yss123/cage-client';
6
+
7
+ /** InventoryLock:读侧快照(敏感字段是按权限掩码后的值) */
8
+ export const InventoryLockSchema = z.object({
9
+ id: z.string().uuid(),
10
+ orderId: z.string().uuid(),
11
+ items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),
12
+ status: z.enum(["held", "released"]),
13
+ version: z.number().int(),
14
+ createdAt: z.string(),
15
+ updatedAt: z.string(),
16
+ });
17
+ export type InventoryLock = z.infer<typeof InventoryLockSchema>;
18
+ export type InventoryLockStatus = InventoryLock['status'];
19
+ export const InventoryLockStates = ['held', 'released'] as const;
20
+
21
+ /** 命令输入:和后端命令的输入校验完全一致 */
22
+ export const InventoryLockInputs = {
23
+ };
24
+
25
+
26
+ export type InventoryLockSortKey = 'createdAt' | 'updatedAt' | 'orderId';
27
+ export interface InventoryLockListParams {
28
+ page?: number;
29
+ pageSize?: number;
30
+ /** 排序:字段名,前面加 - 表示倒序 */
31
+ sort?: InventoryLockSortKey | `-${InventoryLockSortKey}`;
32
+ /** 可以逗号分隔多个状态 */
33
+ status?: string;
34
+ createdAfter?: string;
35
+ createdBefore?: string;
36
+ orderId?: string | number | boolean;
37
+ }
38
+
39
+ /** 调用方法:每个命令一个;client 自动生成并附带幂等键和 CSRF 令牌 */
40
+ export const inventoryLock = {
41
+ /** 异步导出 CSV:返回任务,使用 client.transfer(id) 查状态,完成后下载。需要 InventoryLock.export 能力。 */
42
+ export: (params: InventoryLockListParams = {}, options: { idempotencyKey?: string } = {}) => client.post<TransferTask, 'CONFLICT'>('/api/inventory-lock/export', params, options),
43
+ get: (id: string) => client.get<InventoryLock>(`/api/inventory-lock/${encodeURIComponent(id)}`),
44
+ list: (params: InventoryLockListParams = {}) => client.get<{ items: InventoryLock[]; total: number; page: number; pageSize: number }>('/api/inventory-lock', params as Record<string, unknown>),
45
+ };
46
+
47
+ /** 详情查询 hook:响应也用 schema 校验;范围外返回 NOT_FOUND */
48
+ export const useInventoryLock = (id: string) => useCageQuery(['inventory-lock', id], `/api/inventory-lock/${encodeURIComponent(id)}`, InventoryLockSchema, { enabled: !!id });
49
+ /** 列表查询 hook:走读侧账号与安全视图 */
50
+ export const useInventoryLockList = (params: InventoryLockListParams = {}) => useCageList(['inventory-lock'], '/api/inventory-lock', params as Record<string, unknown>, InventoryLockSchema);
51
+ /** 查询缓存键前缀:命令成功后让它失效 */
52
+ export const inventoryLockKeys = { all: ['inventory-lock'] as const, one: (id: string) => ['inventory-lock', id] as const };
@@ -0,0 +1,72 @@
1
+ // 生成物:由 cage gen 从 domain 声明生成,不要手改。
2
+ /* eslint-disable */
3
+
4
+ import { z } from 'zod';
5
+ import { client, useCageList, useCageQuery, type TransferTask } from '@yss123/cage-client';
6
+
7
+ /** PurchaseOrder:读侧快照(敏感字段是按权限掩码后的值) */
8
+ export const PurchaseOrderSchema = z.object({
9
+ id: z.string().uuid(),
10
+ deptId: z.string().uuid(),
11
+ createdBy: z.string().uuid(),
12
+ supplierPhone: z.string().nullable().optional(),
13
+ amount: z.string(),
14
+ items: z.array(z.object({ sku: z.string(), qty: z.number().int() })),
15
+ erpNo: z.string().nullable().optional(),
16
+ status: z.enum(["draft", "pending_approval", "approved", "received", "rejected", "cancelled"]),
17
+ version: z.number().int(),
18
+ createdAt: z.string(),
19
+ updatedAt: z.string(),
20
+ });
21
+ export type PurchaseOrder = z.infer<typeof PurchaseOrderSchema>;
22
+ export type PurchaseOrderStatus = PurchaseOrder['status'];
23
+ export const PurchaseOrderStates = ['draft', 'pending_approval', 'approved', 'received', 'rejected', 'cancelled'] as const;
24
+
25
+ /** 命令输入:和后端命令的输入校验完全一致 */
26
+ export const PurchaseOrderInputs = {
27
+ cancel: z.object({ id: z.string().uuid() }),
28
+ create: z.object({ amount: z.string(), items: z.array(z.object({ sku: z.string(), qty: z.number().int().max(9007199254740991).gt(0) })).min(1), supplierPhone: z.string().optional(), deptId: z.string().uuid().optional() }),
29
+ submit: z.object({ id: z.string().uuid() }),
30
+ };
31
+
32
+ /** PurchaseOrder.cancel 可能返回的错误码 */
33
+ export type PurchaseOrderCancelError = 'CONFLICT' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT' | 'INVALID_TRANSITION' | 'INVARIANT_VIOLATED' | 'NOT_FOUND';
34
+ /** PurchaseOrder.create 可能返回的错误码 */
35
+ export type PurchaseOrderCreateError = 'CONFLICT' | 'CONSTRAINT_VIOLATED' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT' | 'INVARIANT_VIOLATED';
36
+ /** PurchaseOrder.submit 可能返回的错误码;业务码(domainCode):NO_ITEMS */
37
+ export type PurchaseOrderSubmitError = 'CONFLICT' | 'DOMAIN_ERROR' | 'FORBIDDEN' | 'INVALID_INPUT' | 'INVALID_TRANSITION' | 'INVARIANT_VIOLATED' | 'NOT_FOUND';
38
+ export type PurchaseOrderSubmitDomainCode = 'NO_ITEMS';
39
+
40
+ export type PurchaseOrderSortKey = 'createdAt' | 'updatedAt' | 'deptId' | 'createdBy' | 'supplierPhone' | 'amount' | 'erpNo';
41
+ export interface PurchaseOrderListParams {
42
+ page?: number;
43
+ pageSize?: number;
44
+ /** 排序:字段名,前面加 - 表示倒序 */
45
+ sort?: PurchaseOrderSortKey | `-${PurchaseOrderSortKey}`;
46
+ /** 可以逗号分隔多个状态 */
47
+ status?: string;
48
+ createdAfter?: string;
49
+ createdBefore?: string;
50
+ deptId?: string | number | boolean;
51
+ createdBy?: string | number | boolean;
52
+ amount?: string | number | boolean;
53
+ erpNo?: string | number | boolean;
54
+ }
55
+
56
+ /** 调用方法:每个命令一个;client 自动生成并附带幂等键和 CSRF 令牌 */
57
+ export const purchaseOrder = {
58
+ cancel: (id: string, expectedVersion?: number) => client.post<PurchaseOrder, PurchaseOrderCancelError>(`/api/purchase-order/${encodeURIComponent(id)}/cancel`, { expectedVersion }),
59
+ create: (input: z.input<typeof PurchaseOrderInputs.create>) => client.post<PurchaseOrder, PurchaseOrderCreateError>('/api/purchase-order/create', input),
60
+ submit: (id: string, expectedVersion?: number) => client.post<PurchaseOrder, PurchaseOrderSubmitError>(`/api/purchase-order/${encodeURIComponent(id)}/submit`, { expectedVersion }),
61
+ /** 异步导出 CSV:返回任务,使用 client.transfer(id) 查状态,完成后下载。需要 PurchaseOrder.export 能力。 */
62
+ export: (params: PurchaseOrderListParams = {}, options: { idempotencyKey?: string } = {}) => client.post<TransferTask, 'CONFLICT'>('/api/purchase-order/export', params, options),
63
+ get: (id: string) => client.get<PurchaseOrder>(`/api/purchase-order/${encodeURIComponent(id)}`),
64
+ list: (params: PurchaseOrderListParams = {}) => client.get<{ items: PurchaseOrder[]; total: number; page: number; pageSize: number }>('/api/purchase-order', params as Record<string, unknown>),
65
+ };
66
+
67
+ /** 详情查询 hook:响应也用 schema 校验;范围外返回 NOT_FOUND */
68
+ export const usePurchaseOrder = (id: string) => useCageQuery(['purchase-order', id], `/api/purchase-order/${encodeURIComponent(id)}`, PurchaseOrderSchema, { enabled: !!id });
69
+ /** 列表查询 hook:走读侧账号与安全视图 */
70
+ export const usePurchaseOrderList = (params: PurchaseOrderListParams = {}) => useCageList(['purchase-order'], '/api/purchase-order', params as Record<string, unknown>, PurchaseOrderSchema);
71
+ /** 查询缓存键前缀:命令成功后让它失效 */
72
+ export const purchaseOrderKeys = { all: ['purchase-order'] as const, one: (id: string) => ['purchase-order', id] as const };