@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,516 @@
1
+ /* 空白工作台以留白、细线和深绿建立层次;这里不包含演示统计或客户业务样式。 */
2
+ @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap');
3
+
4
+ :root {
5
+ font-family: 'DM Sans', 'PingFang SC', 'Microsoft YaHei', sans-serif;
6
+ color: #202e29;
7
+ background: #f7f8f4;
8
+ font-synthesis: none;
9
+ -webkit-font-smoothing: antialiased;
10
+ --green: #173e35;
11
+ --muted: #77817b;
12
+ --line: #e2e7df;
13
+ }
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+ body {
18
+ margin: 0;
19
+ min-width: 1024px;
20
+ }
21
+ button,
22
+ input {
23
+ font: inherit;
24
+ }
25
+ button,
26
+ a {
27
+ -webkit-tap-highlight-color: transparent;
28
+ }
29
+ a {
30
+ color: inherit;
31
+ text-decoration: none;
32
+ }
33
+ button,
34
+ .primary {
35
+ cursor: pointer;
36
+ }
37
+ button:disabled {
38
+ cursor: wait;
39
+ opacity: 0.65;
40
+ }
41
+ button:focus-visible,
42
+ a:focus-visible {
43
+ outline: 3px solid #91bca2;
44
+ outline-offset: 4px;
45
+ }
46
+ button {
47
+ transition:
48
+ background 0.18s ease,
49
+ border-color 0.18s ease;
50
+ }
51
+ .brand {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ gap: 10px;
55
+ width: fit-content;
56
+ font-size: 27px;
57
+ font-weight: 700;
58
+ letter-spacing: -1.5px;
59
+ }
60
+ .brand-mark {
61
+ display: grid;
62
+ place-items: center;
63
+ width: 32px;
64
+ height: 34px;
65
+ background: #c5d4ae;
66
+ border-radius: 7px 7px 7px 0;
67
+ font-size: 0;
68
+ }
69
+ .brand-mark::after {
70
+ content: '';
71
+ width: 13px;
72
+ height: 15px;
73
+ border: 2px solid #173e35;
74
+ border-right-color: transparent;
75
+ border-radius: 50%;
76
+ }
77
+ .brand-dot {
78
+ color: #8db798;
79
+ }
80
+ .eyebrow {
81
+ margin: 0 0 18px;
82
+ font-size: 11px;
83
+ font-weight: 600;
84
+ letter-spacing: 2.5px;
85
+ }
86
+ .muted {
87
+ color: var(--muted);
88
+ font-size: 14px;
89
+ line-height: 1.8;
90
+ }
91
+ .primary {
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: space-between;
95
+ gap: 36px;
96
+ min-height: 48px;
97
+ padding: 0 20px;
98
+ border: 1px solid var(--green);
99
+ border-radius: 5px;
100
+ background: var(--green);
101
+ color: #fff;
102
+ font-size: 14px;
103
+ }
104
+ .primary:hover {
105
+ background: #255447;
106
+ }
107
+ .primary span {
108
+ font-size: 19px;
109
+ }
110
+ .error {
111
+ margin: 0;
112
+ padding: 12px 14px;
113
+ border: 1px solid #edd6cc;
114
+ border-radius: 4px;
115
+ background: #fff5ef;
116
+ color: #a04829;
117
+ font-size: 13px;
118
+ line-height: 1.6;
119
+ }
120
+ .status-dot {
121
+ display: inline-block;
122
+ width: 6px;
123
+ height: 6px;
124
+ flex-shrink: 0;
125
+ border-radius: 50%;
126
+ background: #94b999;
127
+ }
128
+
129
+ /* 登录页用安静的品牌叙述与表单分栏,账号密码不预填,也不在页面展示初始化凭证。 */
130
+ .login-layout {
131
+ display: grid;
132
+ grid-template-columns: 49% 51%;
133
+ min-height: 100vh;
134
+ }
135
+ .login-story {
136
+ display: flex;
137
+ flex-direction: column;
138
+ position: relative;
139
+ overflow: hidden;
140
+ padding: 48px 64px 34px;
141
+ background: var(--green);
142
+ color: #f1f3e9;
143
+ }
144
+ .login-story::after {
145
+ content: '';
146
+ position: absolute;
147
+ width: 520px;
148
+ height: 520px;
149
+ right: -300px;
150
+ bottom: -310px;
151
+ border: 1px solid #466253;
152
+ border-radius: 50%;
153
+ box-shadow:
154
+ 0 0 0 70px #ffffff03,
155
+ 0 0 0 140px #ffffff03;
156
+ pointer-events: none;
157
+ }
158
+ .story-copy {
159
+ margin: auto 0;
160
+ padding: 70px 0 90px;
161
+ }
162
+ .story-copy .eyebrow {
163
+ color: #afc3a5;
164
+ }
165
+ .story-copy h1 {
166
+ margin: 0 0 30px;
167
+ font-size: clamp(38px, 3.6vw, 62px);
168
+ line-height: 1.5;
169
+ font-weight: 500;
170
+ letter-spacing: -2px;
171
+ }
172
+ .story-copy h1 span {
173
+ color: #b5ce92;
174
+ }
175
+ .story-description {
176
+ margin: 0;
177
+ color: #bdcbbf;
178
+ font-size: 15px;
179
+ line-height: 2;
180
+ }
181
+ .story-foot {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 9px;
185
+ color: #bfccbf;
186
+ font-size: 11px;
187
+ }
188
+ .edition {
189
+ margin-left: auto;
190
+ font-size: 9px;
191
+ letter-spacing: 1.8px;
192
+ }
193
+ .login-panel {
194
+ position: relative;
195
+ display: grid;
196
+ place-items: center;
197
+ padding: 60px;
198
+ background: #fafbf7;
199
+ }
200
+ .login-form-wrap {
201
+ width: 100%;
202
+ max-width: 350px;
203
+ }
204
+ .section-number {
205
+ color: #82907f;
206
+ font-size: 10px;
207
+ letter-spacing: 2px;
208
+ }
209
+ .login-form-wrap h2 {
210
+ margin: 24px 0 10px;
211
+ font-size: 30px;
212
+ font-weight: 600;
213
+ letter-spacing: -1px;
214
+ }
215
+ .login-form {
216
+ display: flex;
217
+ flex-direction: column;
218
+ gap: 10px;
219
+ margin-top: 35px;
220
+ }
221
+ .login-form label {
222
+ margin-top: 9px;
223
+ font-size: 13px;
224
+ font-weight: 600;
225
+ }
226
+ .login-form input {
227
+ width: 100%;
228
+ height: 48px;
229
+ padding: 0 14px;
230
+ border: 1px solid #dce2d9;
231
+ border-radius: 5px;
232
+ outline: none;
233
+ background: #fff;
234
+ color: #20352c;
235
+ font-size: 14px;
236
+ }
237
+ .login-form input:focus {
238
+ border-color: #638c72;
239
+ box-shadow: 0 0 0 3px #638c7215;
240
+ }
241
+ .login-form input::placeholder {
242
+ color: #a2aba1;
243
+ }
244
+ .login-form .primary {
245
+ margin-top: 17px;
246
+ }
247
+ .login-note {
248
+ margin-top: 22px;
249
+ color: #8d978c;
250
+ font-size: 11px;
251
+ line-height: 1.7;
252
+ }
253
+ .panel-foot {
254
+ position: absolute;
255
+ bottom: 34px;
256
+ color: #9ba398;
257
+ font-size: 11px;
258
+ letter-spacing: 2px;
259
+ }
260
+
261
+ /* 登录后的空状态只说明业务尚未添加;管理员入口由当前账号真实能力决定。 */
262
+ .workspace {
263
+ display: flex;
264
+ min-height: 100vh;
265
+ }
266
+ .sidebar {
267
+ display: flex;
268
+ flex-direction: column;
269
+ width: 232px;
270
+ flex-shrink: 0;
271
+ padding: 30px 20px 24px;
272
+ background: var(--green);
273
+ color: #e8eee4;
274
+ }
275
+ .sidebar .brand {
276
+ margin: 0 14px 60px;
277
+ }
278
+ .sidebar-label {
279
+ margin: 0 14px 14px;
280
+ color: #90a99a;
281
+ font-size: 10px;
282
+ letter-spacing: 2px;
283
+ }
284
+ .nav-item {
285
+ display: flex;
286
+ align-items: center;
287
+ gap: 14px;
288
+ margin-bottom: 8px;
289
+ padding: 13px 14px;
290
+ border: 1px solid transparent;
291
+ border-radius: 5px;
292
+ color: #c8d5c8;
293
+ font-size: 13px;
294
+ }
295
+ .nav-item.active,
296
+ .nav-item:hover {
297
+ border-color: #4c6d5d;
298
+ background: #ffffff09;
299
+ color: #f3f6ed;
300
+ }
301
+ .nav-item > span:first-child {
302
+ font-size: 18px;
303
+ }
304
+ .nav-arrow {
305
+ margin-left: auto;
306
+ color: #91b28f;
307
+ }
308
+ .sidebar-note {
309
+ display: flex;
310
+ align-items: center;
311
+ gap: 8px;
312
+ margin: auto 14px 0;
313
+ padding-top: 40px;
314
+ color: #93ad99;
315
+ font-size: 10px;
316
+ }
317
+ .workspace-body {
318
+ flex: 1;
319
+ min-width: 0;
320
+ }
321
+ .topbar {
322
+ height: 78px;
323
+ display: flex;
324
+ align-items: center;
325
+ justify-content: space-between;
326
+ gap: 30px;
327
+ padding: 0 42px;
328
+ border-bottom: 1px solid var(--line);
329
+ background: #fcfdf9;
330
+ color: #7d887d;
331
+ font-size: 12px;
332
+ }
333
+ .topbar strong {
334
+ color: #344a3d;
335
+ font-weight: 500;
336
+ }
337
+ .breadcrumb-divider {
338
+ margin: 0 15px;
339
+ color: #bcc5b8;
340
+ }
341
+ .account {
342
+ display: flex;
343
+ align-items: center;
344
+ gap: 11px;
345
+ color: #4a5a4c;
346
+ }
347
+ .avatar {
348
+ display: grid;
349
+ place-items: center;
350
+ width: 30px;
351
+ height: 30px;
352
+ border: 1px solid #dce4d5;
353
+ border-radius: 50%;
354
+ background: #eaf0e3;
355
+ font-size: 11px;
356
+ }
357
+ .text-button {
358
+ padding: 5px 0 5px 20px;
359
+ border: 0;
360
+ border-left: 1px solid var(--line);
361
+ margin-left: 9px;
362
+ background: transparent;
363
+ color: #7a867a;
364
+ font-size: 11px;
365
+ }
366
+ .text-button:hover {
367
+ color: var(--green);
368
+ }
369
+ .workspace-content {
370
+ max-width: 1450px;
371
+ margin: 0 auto;
372
+ padding: 48px 42px 24px;
373
+ }
374
+ .page-heading {
375
+ display: flex;
376
+ align-items: center;
377
+ justify-content: space-between;
378
+ margin-bottom: 33px;
379
+ }
380
+ .page-heading .eyebrow {
381
+ margin-bottom: 12px;
382
+ color: #7f8d77;
383
+ font-size: 10px;
384
+ }
385
+ .page-heading h1 {
386
+ margin: 0;
387
+ font-size: 29px;
388
+ letter-spacing: -1px;
389
+ font-weight: 600;
390
+ }
391
+ .page-heading .muted {
392
+ margin: 10px 0 0;
393
+ font-size: 12px;
394
+ }
395
+ .project-tag {
396
+ align-self: flex-start;
397
+ margin-top: 23px;
398
+ padding: 7px 12px;
399
+ border: 1px solid #dce4d5;
400
+ border-radius: 3px;
401
+ background: #f1f5eb;
402
+ color: #64755a;
403
+ font-size: 10px;
404
+ letter-spacing: 1px;
405
+ }
406
+ .empty-state {
407
+ display: flex;
408
+ flex-direction: column;
409
+ align-items: center;
410
+ justify-content: center;
411
+ min-height: 470px;
412
+ padding: 55px 30px;
413
+ border: 1px solid var(--line);
414
+ border-radius: 7px;
415
+ background: #fdfefb;
416
+ text-align: center;
417
+ }
418
+ .empty-state .eyebrow {
419
+ margin: 28px 0 14px;
420
+ color: #87947e;
421
+ font-size: 10px;
422
+ }
423
+ .empty-state h2 {
424
+ margin: 0;
425
+ font-size: 24px;
426
+ font-weight: 500;
427
+ letter-spacing: -0.7px;
428
+ }
429
+ .empty-state > p:not(.eyebrow) {
430
+ margin: 15px 0 26px;
431
+ color: #86917f;
432
+ font-size: 12px;
433
+ line-height: 1.9;
434
+ }
435
+ .manage-link {
436
+ min-height: 42px;
437
+ padding: 0 16px;
438
+ font-size: 12px;
439
+ }
440
+ .empty-illustration {
441
+ position: relative;
442
+ width: 120px;
443
+ height: 104px;
444
+ }
445
+ .sheet {
446
+ position: absolute;
447
+ width: 76px;
448
+ height: 88px;
449
+ border: 1px solid #cedbc6;
450
+ border-radius: 5px;
451
+ background: #f9fcf5;
452
+ }
453
+ .sheet-back {
454
+ top: 2px;
455
+ left: 12px;
456
+ transform: rotate(-12deg);
457
+ background: #edf3e5;
458
+ }
459
+ .sheet-front {
460
+ top: 10px;
461
+ left: 30px;
462
+ padding: 22px 15px;
463
+ transform: rotate(6deg);
464
+ box-shadow: 0 5px 20px #425a2e08;
465
+ }
466
+ .sheet-front > span {
467
+ display: block;
468
+ height: 3px;
469
+ margin-bottom: 8px;
470
+ border-radius: 2px;
471
+ background: #dbe5d2;
472
+ }
473
+ .sheet-front > span:nth-child(2) {
474
+ width: 70%;
475
+ }
476
+ .sheet-front b {
477
+ position: absolute;
478
+ bottom: -11px;
479
+ right: -10px;
480
+ display: grid;
481
+ place-items: center;
482
+ width: 30px;
483
+ height: 30px;
484
+ border: 3px solid #fdfefb;
485
+ border-radius: 50%;
486
+ background: #486840;
487
+ color: #fff;
488
+ font-size: 18px;
489
+ font-weight: 400;
490
+ }
491
+ .workspace-footer {
492
+ display: flex;
493
+ justify-content: space-between;
494
+ margin-top: 24px;
495
+ color: #a0aa99;
496
+ font-size: 10px;
497
+ }
498
+ .session-state {
499
+ display: flex;
500
+ flex-direction: column;
501
+ align-items: center;
502
+ justify-content: center;
503
+ gap: 20px;
504
+ min-height: 100vh;
505
+ color: #6b7b67;
506
+ font-size: 14px;
507
+ }
508
+ .session-state h1 {
509
+ margin: 15px 0 0;
510
+ color: var(--green);
511
+ font-size: 24px;
512
+ font-weight: 500;
513
+ }
514
+ .session-state .primary {
515
+ min-width: 200px;
516
+ }
@@ -0,0 +1,70 @@
1
+ // 应用壳负责导航和账号状态;具体页面通过业务模块的公开入口组合。
2
+ import { useState } from 'react';
3
+ import { useQueryClient } from '@tanstack/react-query';
4
+ import { client, currentUser, useCan } from '@app/contracts';
5
+ import { errorMessages } from '../shared/lib/error-message';
6
+ import { Brand } from '../shared/ui/brand';
7
+ import { HomePage } from '../modules/workspace';
8
+
9
+ export function WorkspaceLayout({ onLogout }: { onLogout: () => void }) {
10
+ // 能力只决定界面入口是否展示;系统管理接口还会再次校验授权。
11
+ const canManage = useCan('User.read');
12
+ const [busy, setBusy] = useState(false);
13
+ const [error, setError] = useState('');
14
+ const user = currentUser();
15
+ const cache = useQueryClient();
16
+
17
+ async function logout() {
18
+ setBusy(true);
19
+ const result = await client.logout();
20
+ setBusy(false);
21
+ if (result.ok) {
22
+ cache.clear();
23
+ onLogout();
24
+ } else setError(errorMessages[result.code]);
25
+ }
26
+
27
+ return (
28
+ <div className="workspace">
29
+ <aside className="sidebar">
30
+ <Brand />
31
+ <span className="sidebar-label">工作空间</span>
32
+ <a className="nav-item active" href="/" aria-current="page">
33
+ <span aria-hidden="true">◫</span>工作台<span className="nav-arrow">↗</span>
34
+ </a>
35
+ {canManage && (
36
+ <a className="nav-item" href="/admin/">
37
+ <span aria-hidden="true">⚙</span>系统管理<span className="nav-arrow">↗</span>
38
+ </a>
39
+ )}
40
+ <div className="sidebar-note">
41
+ <span className="status-dot" />
42
+ 从一个好起点出发
43
+ </div>
44
+ </aside>
45
+ <div className="workspace-body">
46
+ <header className="topbar">
47
+ <span>
48
+ 工作空间<span className="breadcrumb-divider">/</span>
49
+ <strong>工作台</strong>
50
+ </span>
51
+ <div className="account">
52
+ <span className="avatar">{user?.name.slice(0, 1)}</span>
53
+ <span>{user?.name}</span>
54
+ <button className="text-button" onClick={logout} disabled={busy}>
55
+ {busy ? '正在退出…' : '退出登录'}
56
+ </button>
57
+ </div>
58
+ </header>
59
+ <main className="workspace-content">
60
+ {error && (
61
+ <p className="error" role="alert">
62
+ {error}
63
+ </p>
64
+ )}
65
+ <HomePage />
66
+ </main>
67
+ </div>
68
+ </div>
69
+ );
70
+ }
@@ -0,0 +1,13 @@
1
+ // 浏览器入口只负责挂载和全局 Provider。QueryClient 让新增模块可直接使用生成查询 hooks。
2
+ import { createRoot } from 'react-dom/client';
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
+ import { App } from './app/app';
5
+ import './app/styles/global.css';
6
+
7
+ const queryClient = new QueryClient();
8
+
9
+ createRoot(document.getElementById('root')!).render(
10
+ <QueryClientProvider client={queryClient}>
11
+ <App />
12
+ </QueryClientProvider>,
13
+ );
@@ -0,0 +1 @@
1
+ export { LoginPage } from './pages/login-page';
@@ -0,0 +1,87 @@
1
+ // 认证模块拥有登录表单;登录后的导航由 app 组合层处理。
2
+ import { useState, type FormEvent } from 'react';
3
+ import { client } from '@app/contracts';
4
+ import { errorMessages } from '../../../shared/lib/error-message';
5
+ import { Brand } from '../../../shared/ui/brand';
6
+
7
+ export function LoginPage({ onLogin }: { onLogin: () => void }) {
8
+ const [busy, setBusy] = useState(false);
9
+ const [error, setError] = useState('');
10
+
11
+ async function submit(event: FormEvent<HTMLFormElement>) {
12
+ event.preventDefault();
13
+ const form = new FormData(event.currentTarget);
14
+ setBusy(true);
15
+ setError('');
16
+ // SDK 自动处理会话 Cookie、CSRF 与幂等键;成功后同步当前用户和能力列表。
17
+ const result = await client.login(String(form.get('username')), String(form.get('password')));
18
+ setBusy(false);
19
+ if (result.ok) onLogin();
20
+ else setError(errorMessages[result.code]);
21
+ }
22
+
23
+ return (
24
+ <main className="login-layout">
25
+ <section className="login-story">
26
+ <Brand />
27
+ <div className="story-copy">
28
+ <p className="eyebrow">为你的业务,留出空间</p>
29
+ <h1>
30
+ 从这里,
31
+ <br />
32
+ 开始自己的业务<span>。</span>
33
+ </h1>
34
+ <p className="story-description">
35
+ 基础已经就绪。让每一个流程,
36
+ <br />
37
+ 按你的业务方式运转。
38
+ </p>
39
+ </div>
40
+ <div className="story-foot">
41
+ <span className="status-dot" />
42
+ 业务工作台<span className="edition">CAGE / WORKSPACE</span>
43
+ </div>
44
+ </section>
45
+ <section className="login-panel" aria-labelledby="login-title">
46
+ <div className="login-form-wrap">
47
+ <span className="section-number">01 / 欢迎回来</span>
48
+ <h2 id="login-title">登录工作台</h2>
49
+ <p className="muted">使用管理员为你配置的账号继续。</p>
50
+ <form onSubmit={submit} className="login-form">
51
+ <label htmlFor="username">账号</label>
52
+ <input
53
+ id="username"
54
+ name="username"
55
+ autoComplete="username"
56
+ placeholder="请输入账号"
57
+ required
58
+ autoFocus
59
+ disabled={busy}
60
+ />
61
+ <label htmlFor="password">密码</label>
62
+ <input
63
+ id="password"
64
+ name="password"
65
+ type="password"
66
+ autoComplete="current-password"
67
+ placeholder="请输入密码"
68
+ required
69
+ disabled={busy}
70
+ />
71
+ {error && (
72
+ <p className="error" role="alert">
73
+ {error}
74
+ </p>
75
+ )}
76
+ <button className="primary" disabled={busy}>
77
+ {busy ? '正在登录…' : '进入工作台'}
78
+ <span aria-hidden="true">↗</span>
79
+ </button>
80
+ </form>
81
+ <p className="login-note">首次使用的管理员账号,请查看 API 启动终端。</p>
82
+ </div>
83
+ <span className="panel-foot">一个属于你的业务起点</span>
84
+ </section>
85
+ </main>
86
+ );
87
+ }
@@ -0,0 +1 @@
1
+ export { HomePage } from './pages/home-page';