@oj-module/cli 0.2.1 → 0.2.5

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 (231) hide show
  1. package/devkit/README.md +14 -3
  2. package/devkit/SKILL.md +16 -4
  3. package/devkit/framework-dev.md +8 -6
  4. package/devkit/manual.md +243 -23
  5. package/package.json +2 -2
  6. package/shell-dist/assets/runtime.js +143 -8
  7. package/shell-dist/index.html +2 -2
  8. package/shell-dist/versions.json +3 -3
  9. package/src/args.ts +67 -0
  10. package/src/build.ts +11 -3
  11. package/src/bundle.ts +197 -0
  12. package/src/contract/__tests__/handler-scan.test.ts +82 -0
  13. package/src/contract/check.ts +2 -1
  14. package/src/contract/handler-scan.ts +32 -0
  15. package/src/deterministic-tar.ts +120 -0
  16. package/src/dev.ts +4 -2
  17. package/src/enable.ts +28 -0
  18. package/src/index.ts +63 -2
  19. package/src/info.ts +3 -2
  20. package/src/init.ts +147 -14
  21. package/src/install.ts +268 -0
  22. package/src/keygen.ts +88 -0
  23. package/src/layout.ts +31 -0
  24. package/src/lifecycle/__tests__/authoring.test.ts +109 -0
  25. package/src/lifecycle/__tests__/bundle.test.ts +150 -0
  26. package/src/lifecycle/__tests__/deterministic-tar.test.ts +145 -0
  27. package/src/lifecycle/__tests__/fixtures/README.md +59 -0
  28. package/src/lifecycle/__tests__/fixtures/fixture-invalid/EXPECTED-VIOLATIONS.md +27 -0
  29. package/src/lifecycle/__tests__/fixtures/fixture-invalid/api/src/Demo/manifest.yaml +6 -0
  30. package/src/lifecycle/__tests__/fixtures/fixture-invalid/manifest.yaml +40 -0
  31. package/src/lifecycle/__tests__/fixtures/fixture-invalid/web/src/Demo/entry.ts +14 -0
  32. package/src/lifecycle/__tests__/fixtures/fixture-invalid/web/src/Demo/locales/en-US.json +12 -0
  33. package/src/lifecycle/__tests__/fixtures/fixture-invalid/web/src/Demo/locales/zh-CN.json +12 -0
  34. package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/manifest.yaml +9 -0
  35. package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/migrations/0001__init.sql +6 -0
  36. package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/ping/api.ts +9 -0
  37. package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/schema.yaml +9 -0
  38. package/src/lifecycle/__tests__/fixtures/fixture-valid/manifest.yaml +96 -0
  39. package/src/lifecycle/__tests__/fixtures/fixture-valid/web/src/demo-solution/entry.ts +23 -0
  40. package/src/lifecycle/__tests__/fixtures/fixture-valid/web/src/demo-solution/locales/en-US.json +29 -0
  41. package/src/lifecycle/__tests__/fixtures/fixture-valid/web/src/demo-solution/locales/zh-CN.json +29 -0
  42. package/src/lifecycle/__tests__/fixtures/sig/demo-solution-0.2.0.tgz +0 -0
  43. package/src/lifecycle/__tests__/fixtures/sig/demo-solution-0.2.0.tgz.bad.sig +7 -0
  44. package/src/lifecycle/__tests__/fixtures/sig/demo-solution-0.2.0.tgz.sig +7 -0
  45. package/src/lifecycle/__tests__/fixtures/sig/demo-solution-0.2.0.tgz.unknown.sig +7 -0
  46. package/src/lifecycle/__tests__/fixtures/sig/gen-signed-fixtures.d.mts +21 -0
  47. package/src/lifecycle/__tests__/fixtures/sig/gen-signed-fixtures.mjs +196 -0
  48. package/src/lifecycle/__tests__/helpers.ts +78 -0
  49. package/src/lifecycle/__tests__/install.test.ts +514 -0
  50. package/src/lifecycle/__tests__/keygen.test.ts +61 -0
  51. package/src/lifecycle/__tests__/manifest-contract.test.ts +228 -0
  52. package/src/lifecycle/__tests__/publish.test.ts +80 -0
  53. package/src/lifecycle/__tests__/sig-fixtures.test.ts +100 -0
  54. package/src/lifecycle/__tests__/sign.test.ts +131 -0
  55. package/src/lifecycle/__tests__/smoke.test.ts +61 -0
  56. package/src/lifecycle/__tests__/trust.test.ts +177 -0
  57. package/src/lifecycle/__tests__/uninstall.test.ts +87 -0
  58. package/src/lifecycle/keygen.ts +40 -0
  59. package/src/lifecycle/sign.ts +74 -0
  60. package/src/manifest-contract.ts +696 -0
  61. package/src/oj-cert.ts +19 -0
  62. package/src/oj-cmd.ts +3 -3
  63. package/src/preview.ts +2 -2
  64. package/src/publish.ts +150 -0
  65. package/src/sign.ts +128 -0
  66. package/src/site.ts +146 -0
  67. package/src/trust.ts +116 -0
  68. package/src/uninstall.ts +29 -0
  69. package/src/usage.ts +35 -1
  70. package/templates/README.md +46 -7
  71. package/templates/api/config.yaml +47 -0
  72. package/templates/api/seed.mysql.sql +1 -1
  73. package/templates/api/seed.pg.sql +1 -1
  74. package/templates/api/src/_platform/_lifecycle/atomic.ts +98 -0
  75. package/templates/api/src/_platform/_lifecycle/history.ts +31 -0
  76. package/templates/api/src/_platform/_lifecycle/installer.ts +1080 -0
  77. package/templates/api/src/_platform/_lifecycle/lock.ts +148 -0
  78. package/templates/api/src/_platform/_lifecycle/semver.ts +61 -0
  79. package/templates/api/src/_platform/_lifecycle/sha384.ts +187 -0
  80. package/templates/api/src/_platform/_lifecycle/state.ts +256 -0
  81. package/templates/api/src/_platform/_lifecycle/steps/deploy-web.ts +182 -0
  82. package/templates/api/src/_platform/_lifecycle/steps/download.ts +90 -0
  83. package/templates/api/src/_platform/_lifecycle/steps/extract.ts +239 -0
  84. package/templates/api/src/_platform/_lifecycle/steps/migrate.ts +363 -0
  85. package/templates/api/src/_platform/_lifecycle/steps/preflight.ts +590 -0
  86. package/templates/api/src/_platform/_lifecycle/steps/register.ts +211 -0
  87. package/templates/api/src/_platform/_lifecycle/steps/reload.ts +81 -0
  88. package/templates/api/src/_platform/_lifecycle/steps/smoke.ts +216 -0
  89. package/templates/api/src/_platform/_lifecycle/steps/verify.ts +207 -0
  90. package/templates/api/src/_platform/_lifecycle/tasks.ts +119 -0
  91. package/templates/api/src/_platform/_lifecycle/text-edit.ts +110 -0
  92. package/templates/api/src/_platform/_lifecycle/tgz-guard.ts +41 -0
  93. package/templates/api/src/_platform/_lifecycle/trust.ts +229 -0
  94. package/templates/api/src/_platform/_lifecycle/types.ts +94 -0
  95. package/templates/api/src/_platform/_lifecycle/uninstall.ts +283 -0
  96. package/templates/api/src/_platform/_lifecycle/verify-checks.ts +228 -0
  97. package/templates/api/src/_platform/_lifecycle/verify-report.ts +92 -0
  98. package/templates/api/src/_platform/_shared/service/access.ts +2 -2
  99. package/templates/api/src/_platform/_shared/service/settings.ts +10 -1
  100. package/templates/api/src/_platform/_shared/service/solution-perms.ts +14 -7
  101. package/templates/api/src/_platform/_shared/site-facade.ts +44 -0
  102. package/templates/api/src/_platform/manifest.yaml +1 -0
  103. package/templates/api/src/_platform/market/api.ts +883 -0
  104. package/templates/api/src/_platform/market/bootstrap.ts +39 -0
  105. package/templates/api/src/_platform/migrations/0010__sys_solution_route.mysql.sql +17 -0
  106. package/templates/api/src/_platform/migrations/0010__sys_solution_route.pg.sql +16 -0
  107. package/templates/api/src/_platform/migrations/0010__sys_solution_route.sql +18 -0
  108. package/templates/api/src/_platform/migrations/0011__sys_setting_group_label.mysql.sql +2 -0
  109. package/templates/api/src/_platform/migrations/0011__sys_setting_group_label.sql +4 -0
  110. package/templates/api/src/_platform/migrations/0012__market_history.mysql.sql +13 -0
  111. package/templates/api/src/_platform/migrations/0012__market_history.pg.sql +12 -0
  112. package/templates/api/src/_platform/migrations/0012__market_history.sql +14 -0
  113. package/templates/api/src/_platform/schema.yaml +21 -4
  114. package/templates/api/src/_platform/seed.sql +2 -2
  115. package/templates/api/src/_platform/solutions/api.ts +212 -0
  116. package/templates/api/src/demo/manifest.yaml +5 -0
  117. package/templates/api/src/demo/migrations/0001__create_todos.sql +9 -0
  118. package/templates/api/src/demo/schema.yaml +11 -0
  119. package/templates/api/src/demo/seed.sql +5 -0
  120. package/templates/api/src/demo/todos/api.ts +59 -0
  121. package/templates/api/src/home/line/api.ts +57 -0
  122. package/templates/api/src/home/manifest.yaml +6 -0
  123. package/templates/api/src/home/migrations/0001__create_home_tables.sql +13 -0
  124. package/templates/api/src/home/pie/api.ts +40 -0
  125. package/templates/api/src/home/schema.yaml +14 -0
  126. package/templates/api/src/home/seed.sql +70 -0
  127. package/templates/api/src/system/oplog/api.ts +44 -2
  128. package/templates/api/tests/fixture.ts +16 -0
  129. package/templates/api/tests/lifecycle/atomic-state.spec.ts +183 -0
  130. package/templates/api/tests/lifecycle/bootstrap.spec.ts +116 -0
  131. package/templates/api/tests/lifecycle/deploy-smoke.spec.ts +492 -0
  132. package/templates/api/tests/lifecycle/installer.spec.ts +1218 -0
  133. package/templates/api/tests/lifecycle/market-api.spec.ts +971 -0
  134. package/templates/api/tests/lifecycle/migrate.spec.ts +575 -0
  135. package/templates/api/tests/lifecycle/preflight.spec.ts +255 -0
  136. package/templates/api/tests/lifecycle/register.spec.ts +194 -0
  137. package/templates/api/tests/lifecycle/semver.spec.ts +43 -0
  138. package/templates/api/tests/lifecycle/sha384.spec.ts +48 -0
  139. package/templates/api/tests/lifecycle/sig-fixtures.spec.ts +65 -0
  140. package/templates/api/tests/lifecycle/solutions-api.spec.ts +98 -0
  141. package/templates/api/tests/lifecycle/steps-fs.spec.ts +623 -0
  142. package/templates/api/tests/lifecycle/text-edit.spec.ts +177 -0
  143. package/templates/api/tests/lifecycle/tgz-guard.spec.ts +103 -0
  144. package/templates/api/tests/lifecycle/trust.spec.ts +310 -0
  145. package/templates/api/tests/lifecycle/uninstall.spec.ts +386 -0
  146. package/templates/api/tests/lifecycle/verify-checks.spec.ts +385 -0
  147. package/templates/api/tests/lifecycle/verify-report.spec.ts +290 -0
  148. package/templates/api/tests/rbac-settings.spec.ts +8 -0
  149. package/templates/init.include.yaml +56 -0
  150. package/templates/openapi.json +527 -0
  151. package/templates/package.json +52 -0
  152. package/templates/web/src/_platform/__client/api.schemas.ts +8 -0
  153. package/templates/web/src/_platform/__client/api.ts +335 -0
  154. package/templates/web/src/about/entry.ts +42 -0
  155. package/templates/web/src/about/locales/en-US.json +16 -0
  156. package/templates/web/src/about/locales/zh-CN.json +16 -0
  157. package/templates/web/src/about/pages/constants.ts +20 -0
  158. package/templates/web/src/about/pages/index.tsx +135 -0
  159. package/templates/web/src/access/entry.ts +74 -0
  160. package/templates/web/src/access/locales/en-US.json +46 -0
  161. package/templates/web/src/access/locales/zh-CN.json +46 -0
  162. package/templates/web/src/access/pages/access-mode/index.tsx +16 -0
  163. package/templates/web/src/access/pages/admin-visible/index.tsx +16 -0
  164. package/templates/web/src/access/pages/button-control/index.tsx +181 -0
  165. package/templates/web/src/access/pages/common-visible/index.tsx +16 -0
  166. package/templates/web/src/access/pages/page-control/index.tsx +142 -0
  167. package/templates/web/src/demo/__client/api.schemas.ts +20 -0
  168. package/templates/web/src/demo/__client/api.ts +89 -0
  169. package/templates/web/src/exception/entry.ts +80 -0
  170. package/templates/web/src/exception/locales/en-US.json +13 -0
  171. package/templates/web/src/exception/locales/zh-CN.json +13 -0
  172. package/templates/web/src/exception/pages/403/index.tsx +30 -0
  173. package/templates/web/src/exception/pages/404/index.tsx +30 -0
  174. package/templates/web/src/exception/pages/500/index.tsx +30 -0
  175. package/templates/web/src/exception/pages/unknown-component/index.tsx +38 -0
  176. package/templates/web/src/home/__client/api.schemas.ts +22 -0
  177. package/templates/web/src/home/__client/api.ts +113 -0
  178. package/templates/web/src/login/locales/en-US.json +6 -0
  179. package/templates/web/src/login/locales/zh-CN.json +6 -0
  180. package/templates/web/src/login/pages/login.tsx +67 -18
  181. package/templates/web/src/oj-market/__tests__/CardGrid.test.tsx +93 -0
  182. package/templates/web/src/oj-market/__tests__/HistoryDrawer.test.tsx +28 -0
  183. package/templates/web/src/oj-market/__tests__/InstallDialog.test.tsx +69 -0
  184. package/templates/web/src/oj-market/__tests__/RollbackDialog.test.tsx +43 -0
  185. package/templates/web/src/oj-market/__tests__/UninstallConfirm.test.tsx +30 -0
  186. package/templates/web/src/oj-market/__tests__/marketClient.fake.ts +70 -0
  187. package/templates/web/src/oj-market/__tests__/poll.test.ts +24 -0
  188. package/templates/web/src/oj-market/__tests__/render.tsx +14 -0
  189. package/templates/web/src/oj-market/__tests__/runtime-stub.ts +14 -0
  190. package/templates/web/src/oj-market/__tests__/semver.test.ts +26 -0
  191. package/templates/web/src/oj-market/api/MarketClientProvider.tsx +12 -0
  192. package/templates/web/src/oj-market/api/client.ts +135 -0
  193. package/templates/web/src/oj-market/api/context.ts +11 -0
  194. package/templates/web/src/oj-market/api/defaultClient.ts +7 -0
  195. package/templates/web/src/oj-market/components/CardGrid.tsx +76 -0
  196. package/templates/web/src/oj-market/components/CardItem.tsx +102 -0
  197. package/templates/web/src/oj-market/components/DetailDrawer.tsx +53 -0
  198. package/templates/web/src/oj-market/components/HistoryDrawer.tsx +75 -0
  199. package/templates/web/src/oj-market/components/InstallDialog.tsx +112 -0
  200. package/templates/web/src/oj-market/components/RollbackDialog.tsx +79 -0
  201. package/templates/web/src/oj-market/components/UninstallConfirm.tsx +74 -0
  202. package/templates/web/src/oj-market/entry.ts +27 -0
  203. package/templates/web/src/oj-market/hooks/useMarket.ts +91 -0
  204. package/templates/web/src/oj-market/locales/en-US.json +100 -0
  205. package/templates/web/src/oj-market/locales/zh-CN.json +100 -0
  206. package/templates/web/src/oj-market/pages/MarketApp.tsx +136 -0
  207. package/templates/web/src/oj-market/types.ts +84 -0
  208. package/templates/web/src/oj-market/utils/poll.ts +36 -0
  209. package/templates/web/src/oj-market/utils/semver.ts +14 -0
  210. package/templates/web/src/outside/entry.ts +80 -0
  211. package/templates/web/src/outside/locales/en-US.json +10 -0
  212. package/templates/web/src/outside/locales/zh-CN.json +10 -0
  213. package/templates/web/src/personal-center/entry.ts +1 -10
  214. package/templates/web/src/personal-center/locales/en-US.json +1 -5
  215. package/templates/web/src/personal-center/locales/zh-CN.json +1 -5
  216. package/templates/web/src/route-nest/entry.ts +73 -0
  217. package/templates/web/src/route-nest/locales/en-US.json +9 -0
  218. package/templates/web/src/route-nest/locales/zh-CN.json +9 -0
  219. package/templates/web/src/route-nest/pages/menu1/menu1-1/index.tsx +5 -0
  220. package/templates/web/src/route-nest/pages/menu1/menu1-2/index.tsx +5 -0
  221. package/templates/web/src/route-nest/pages/menu2/index.tsx +5 -0
  222. package/templates/web/src/system/__client/api.schemas.ts +162 -0
  223. package/templates/web/src/system/__client/api.ts +382 -0
  224. package/templates/web/src/system/pages/oplog/index.tsx +1 -1
  225. package/templates/web/src/system/pages/roles/index.tsx +1 -0
  226. package/templates/web/src/system/pages/settings/index.tsx +1 -1
  227. package/templates/web/src/system/pages/users/index.tsx +1 -1
  228. package/templates/web.config.ts +32 -40
  229. package/vendor/host-versions.json +3 -3
  230. package/templates/pnpm-workspace.yaml +0 -14
  231. package/templates/web/src/personal-center/pages/settings/index.tsx +0 -5
@@ -0,0 +1,162 @@
1
+ /* eslint-disable */
2
+ // 生成物:ojm api 从契约生成,勿手改(改动请改契约文件后重跑 ojm api)
3
+ // AC-D15:仅供 DEV 校验动态 import,生产构建不进产物
4
+ import { z } from "@oj-module/runtime";
5
+
6
+ export const schemas = {
7
+ "systemLoginMethodsGet": {
8
+ data: z.object({
9
+ "methods": z.array(z.string())
10
+ }),
11
+ },
12
+ "systemOplogGet": {
13
+ query: z.object({
14
+ "action": z.string().optional(),
15
+ "username": z.string().optional(),
16
+ "module": z.string().optional(),
17
+ "limit": z.number().min(1).max(200).optional()
18
+ }),
19
+ data: z.object({
20
+ "list": z.array(z.object({
21
+ "id": z.number(),
22
+ "create_time": z.number(),
23
+ "user_id": z.number(),
24
+ "username": z.string(),
25
+ "action": z.string(),
26
+ "module": z.string(),
27
+ "version": z.string().nullable(),
28
+ "target": z.string().nullable(),
29
+ "detail": z.string().nullable(),
30
+ "level": z.number()
31
+ })),
32
+ "total": z.number(),
33
+ "truncated": z.boolean()
34
+ }),
35
+ },
36
+ "systemOplogPost": {
37
+ body: z.object({
38
+ "action": z.string().min(1),
39
+ "module": z.string().min(1),
40
+ "version": z.string().optional(),
41
+ "target": z.string().optional(),
42
+ "level": z.number().optional()
43
+ }),
44
+ data: z.object({
45
+ "ok": z.boolean()
46
+ }),
47
+ },
48
+ "systemPermissionsGet": {
49
+ data: z.array(z.object({
50
+ "code": z.string(),
51
+ "module": z.string(),
52
+ "title_key": z.string().nullable(),
53
+ "deprecated": z.boolean()
54
+ })),
55
+ },
56
+ "systemRolesGet": {
57
+ data: z.array(z.object({
58
+ "name": z.string(),
59
+ "module": z.string(),
60
+ "title": z.string().nullable(),
61
+ "description": z.string().nullable(),
62
+ "builtin": z.boolean(),
63
+ "deprecated": z.boolean(),
64
+ "holders": z.number(),
65
+ "permissions": z.array(z.string())
66
+ })),
67
+ },
68
+ "systemRolesPost": {
69
+ body: z.object({
70
+ "name": // @oj-warn: pattern="^custom\\.[a-z0-9][a-z0-9-]*$" 为 Rust regex,未在前端执行(跨语言语义漂移/ReDoS 风险)
71
+ z.string(),
72
+ "title": z.string().min(1),
73
+ "permissions": z.array(z.string()).optional()
74
+ }),
75
+ data: z.object({
76
+ "name": z.string(),
77
+ "module": z.string()
78
+ }),
79
+ },
80
+ "systemRolesDelete": {
81
+ query: z.object({
82
+ "name": z.string().min(1)
83
+ }),
84
+ },
85
+ "systemRolesBindingsPut": {
86
+ query: z.object({
87
+ "name": z.string().min(1)
88
+ }),
89
+ body: z.object({
90
+ "permissions": z.array(z.string())
91
+ }),
92
+ },
93
+ "systemSettingsGet": {
94
+ data: z.array(z.object({
95
+ "group": z.string(),
96
+ "items": z.array(z.object({
97
+ "key": z.string(),
98
+ "module": z.string(),
99
+ "group": z.string(),
100
+ "type": z.string(),
101
+ "value": z.string().nullable(),
102
+ "default_value": z.string().nullable(),
103
+ "label_key": z.string().nullable(),
104
+ "options": z.string().nullable(),
105
+ "secret": z.boolean(),
106
+ "update_time": z.number()
107
+ }))
108
+ })),
109
+ },
110
+ "systemSettingsPut": {
111
+ body: z.object({
112
+ "key": z.string().min(1),
113
+ "value": z.string()
114
+ }),
115
+ },
116
+ "systemUsersGet": {
117
+ data: z.array(z.object({
118
+ "id": z.number(),
119
+ "username": z.string(),
120
+ "display_name": z.string().nullable(),
121
+ "email": z.string().nullable(),
122
+ "is_forbidden": z.boolean(),
123
+ "must_change": z.boolean(),
124
+ "roles": z.array(z.string())
125
+ })),
126
+ },
127
+ "systemUsersPost": {
128
+ body: z.object({
129
+ "username": z.string().min(1),
130
+ "password": z.string().min(6),
131
+ "displayName": z.string().optional(),
132
+ "email": z.string().optional()
133
+ }),
134
+ data: z.object({
135
+ "id": z.number()
136
+ }),
137
+ },
138
+ "systemUsersForbiddenPut": {
139
+ query: z.object({
140
+ "uid": z.number()
141
+ }),
142
+ body: z.object({
143
+ "forbidden": z.boolean()
144
+ }),
145
+ },
146
+ "systemUsersPasswordPut": {
147
+ query: z.object({
148
+ "uid": z.number()
149
+ }),
150
+ body: z.object({
151
+ "password": z.string().min(6)
152
+ }),
153
+ },
154
+ "systemUsersRolesPut": {
155
+ query: z.object({
156
+ "uid": z.number()
157
+ }),
158
+ body: z.object({
159
+ "roles": z.array(z.string())
160
+ }),
161
+ },
162
+ };
@@ -0,0 +1,382 @@
1
+ /* eslint-disable */
2
+ // 生成物:ojm api 从契约生成,勿手改(改动请改契约文件后重跑 ojm api)
3
+ import { ContractApiError } from "@oj-module/runtime/contract/errors";
4
+ import type { ScopedRequestLike } from "@oj-module/runtime/contract/errors";
5
+ import type { ModuleContext } from "@oj-module/runtime";
6
+ import type { z } from "@oj-module/runtime";
7
+ import type { schemas } from "./api.schemas";
8
+
9
+ /** oj 信封(AC-D16):code=0 成功;非 0 时 HTTP status=code,由 toApiError 归一为 ContractApiError */
10
+ interface OjEnvelope<T> { code: number, msg?: string, data?: T }
11
+
12
+ let req: ScopedRequestLike | undefined;
13
+
14
+ /** 线上 API 前缀(ojm api 从契约抽取,唯一真源,勿手改):请求基址 + 前缀登记用 */
15
+ export const API_PREFIX = "/system";
16
+
17
+ /** 认领身份前缀(契约 apiPrefix,字面等于模块目录名):跨模块认领护栏对比基准 */
18
+ export const MODULE_PREFIX = "/system";
19
+
20
+ /**
21
+ * 模块 entry 的 onInit 里一行创建(构造即 install):完成 apiPrefix 登记 +
22
+ * scoped request 绑定,返回绑好前缀的端点函数集合。一模块一 client;
23
+ * 重复构造幂等安全(前缀重复登记同值、request 重绑同值)。
24
+ */
25
+ export function createSystemClient(ctx: ModuleContext) {
26
+ // 跨模块认领护栏(DEV):工厂知道自己该属于谁(MODULE_PREFIX = 契约 apiPrefix),
27
+ // ctx 又带 module.name——名实不符说明别的模块在替本模块创建 client,会共享 request
28
+ // 单槽、卸载互相耦合;跨模块需求应由本模块创建后经 provider 暴露。
29
+ // 注意对比基准是 MODULE_PREFIX(目录名)而非 API_PREFIX——D-M8 映射时线上前缀
30
+ // 属于别的命名空间,认领身份仍按目录名。
31
+ if (import.meta.env.DEV && ctx.module.name !== MODULE_PREFIX.slice(1)) {
32
+ console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${MODULE_PREFIX.slice(1)}" 模块在自身 onInit 创建,跨模块需求经 provider 暴露。`);
33
+ }
34
+ ctx.register.apiPrefix(API_PREFIX);
35
+ bindRequest(ctx.utils.request);
36
+ return { systemLoginMethodsGet, systemOplogGet, systemOplogPost, systemPermissionsGet, systemRolesGet, systemRolesPost, systemRolesDelete, systemRolesBindingsPut, systemSettingsGet, systemSettingsPut, systemUsersGet, systemUsersPost, systemUsersForbiddenPut, systemUsersPasswordPut, systemUsersRolesPut };
37
+ }
38
+
39
+ /**
40
+ * @deprecated 请改用 createSystemClient(ctx)——工厂构造即完成
41
+ * 前缀登记 + request 绑定,不会出现「登记了前缀没绑 request」的半接线状态。
42
+ */
43
+ export function bindRequest(r: ScopedRequestLike): void {
44
+ req = r;
45
+ }
46
+
47
+ function ensureReq(): ScopedRequestLike {
48
+ if (!req)
49
+ throw new ContractApiError(-1, "[ojm-api] 请求未绑定——请在模块 entry.ts 的 onInit 里调用 createSystemClient(ctx)(或 bindRequest(ctx.utils.request))。");
50
+ return req;
51
+ }
52
+
53
+ /** ky HTTPError → ContractApiError(错误体为信封时取 code/msg);契约违例与原错误原样透传 */
54
+ async function toApiError(e: unknown): Promise<unknown> {
55
+ if (e instanceof ContractApiError)
56
+ return e;
57
+ // ky 2.x 构造 HTTPError 时已用 getReader() 消费掉原 response 体(res.clone().json() 按规范抛 TypeError,
58
+ // 体方法一律失效),解析好的错误体在公开字段 error.data——故读 error.data,勿改回 clone().json()。
59
+ const err = e as { data?: { code?: unknown, msg?: string }, response?: Response } | null;
60
+ const res = err?.response;
61
+ const d = err?.data;
62
+ if (res instanceof Response && d && typeof d.code === "number")
63
+ return new ContractApiError(d.code, d.msg ?? res.statusText);
64
+ return e;
65
+ }
66
+
67
+ export type SystemLoginMethodsGetData = z.infer<(typeof schemas)["systemLoginMethodsGet"]["data"]>;
68
+
69
+ export async function systemLoginMethodsGet(): Promise<SystemLoginMethodsGetData> {
70
+ const client = ensureReq();
71
+ try {
72
+ const env = await client.get(`system/login-methods`).json<OjEnvelope<SystemLoginMethodsGetData>>();
73
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
74
+ if (typeof env.code === "number" && env.code !== 0)
75
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
76
+ const data = env.data as SystemLoginMethodsGetData;
77
+ if (import.meta.env.DEV) {
78
+ const { schemas } = await import("./api.schemas");
79
+ const r = schemas["systemLoginMethodsGet"].data.safeParse(data);
80
+ if (!r.success)
81
+ throw new ContractApiError(-1, `[契约违例] systemLoginMethodsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
82
+ }
83
+ return data;
84
+ }
85
+ catch (e) {
86
+ throw await toApiError(e);
87
+ }
88
+ }
89
+
90
+ export type SystemOplogGetQuery = z.input<(typeof schemas)["systemOplogGet"]["query"]>;
91
+ export type SystemOplogGetData = z.infer<(typeof schemas)["systemOplogGet"]["data"]>;
92
+
93
+ export async function systemOplogGet(query: SystemOplogGetQuery): Promise<SystemOplogGetData> {
94
+ const client = ensureReq();
95
+ try {
96
+ const env = await client.get(`system/oplog`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<SystemOplogGetData>>();
97
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
98
+ if (typeof env.code === "number" && env.code !== 0)
99
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
100
+ const data = env.data as SystemOplogGetData;
101
+ if (import.meta.env.DEV) {
102
+ const { schemas } = await import("./api.schemas");
103
+ const r = schemas["systemOplogGet"].data.safeParse(data);
104
+ if (!r.success)
105
+ throw new ContractApiError(-1, `[契约违例] systemOplogGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
106
+ }
107
+ return data;
108
+ }
109
+ catch (e) {
110
+ throw await toApiError(e);
111
+ }
112
+ }
113
+
114
+ export type SystemOplogPostBody = z.input<(typeof schemas)["systemOplogPost"]["body"]>;
115
+ export type SystemOplogPostData = z.infer<(typeof schemas)["systemOplogPost"]["data"]>;
116
+
117
+ export async function systemOplogPost(body: SystemOplogPostBody): Promise<SystemOplogPostData> {
118
+ const client = ensureReq();
119
+ try {
120
+ const env = await client.post(`system/oplog`, { json: body }).json<OjEnvelope<SystemOplogPostData>>();
121
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
122
+ if (typeof env.code === "number" && env.code !== 0)
123
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
124
+ const data = env.data as SystemOplogPostData;
125
+ if (import.meta.env.DEV) {
126
+ const { schemas } = await import("./api.schemas");
127
+ const r = schemas["systemOplogPost"].data.safeParse(data);
128
+ if (!r.success)
129
+ throw new ContractApiError(-1, `[契约违例] systemOplogPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
130
+ }
131
+ return data;
132
+ }
133
+ catch (e) {
134
+ throw await toApiError(e);
135
+ }
136
+ }
137
+
138
+ export type SystemPermissionsGetData = z.infer<(typeof schemas)["systemPermissionsGet"]["data"]>;
139
+
140
+ export async function systemPermissionsGet(): Promise<SystemPermissionsGetData> {
141
+ const client = ensureReq();
142
+ try {
143
+ const env = await client.get(`system/permissions`).json<OjEnvelope<SystemPermissionsGetData>>();
144
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
145
+ if (typeof env.code === "number" && env.code !== 0)
146
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
147
+ const data = env.data as SystemPermissionsGetData;
148
+ if (import.meta.env.DEV) {
149
+ const { schemas } = await import("./api.schemas");
150
+ const r = schemas["systemPermissionsGet"].data.safeParse(data);
151
+ if (!r.success)
152
+ throw new ContractApiError(-1, `[契约违例] systemPermissionsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
153
+ }
154
+ return data;
155
+ }
156
+ catch (e) {
157
+ throw await toApiError(e);
158
+ }
159
+ }
160
+
161
+ export type SystemRolesGetData = z.infer<(typeof schemas)["systemRolesGet"]["data"]>;
162
+
163
+ export async function systemRolesGet(): Promise<SystemRolesGetData> {
164
+ const client = ensureReq();
165
+ try {
166
+ const env = await client.get(`system/roles`).json<OjEnvelope<SystemRolesGetData>>();
167
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
168
+ if (typeof env.code === "number" && env.code !== 0)
169
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
170
+ const data = env.data as SystemRolesGetData;
171
+ if (import.meta.env.DEV) {
172
+ const { schemas } = await import("./api.schemas");
173
+ const r = schemas["systemRolesGet"].data.safeParse(data);
174
+ if (!r.success)
175
+ throw new ContractApiError(-1, `[契约违例] systemRolesGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
176
+ }
177
+ return data;
178
+ }
179
+ catch (e) {
180
+ throw await toApiError(e);
181
+ }
182
+ }
183
+
184
+ export type SystemRolesPostBody = z.input<(typeof schemas)["systemRolesPost"]["body"]>;
185
+ export type SystemRolesPostData = z.infer<(typeof schemas)["systemRolesPost"]["data"]>;
186
+
187
+ export async function systemRolesPost(body: SystemRolesPostBody): Promise<SystemRolesPostData> {
188
+ const client = ensureReq();
189
+ try {
190
+ const env = await client.post(`system/roles`, { json: body }).json<OjEnvelope<SystemRolesPostData>>();
191
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
192
+ if (typeof env.code === "number" && env.code !== 0)
193
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
194
+ const data = env.data as SystemRolesPostData;
195
+ if (import.meta.env.DEV) {
196
+ const { schemas } = await import("./api.schemas");
197
+ const r = schemas["systemRolesPost"].data.safeParse(data);
198
+ if (!r.success)
199
+ throw new ContractApiError(-1, `[契约违例] systemRolesPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
200
+ }
201
+ return data;
202
+ }
203
+ catch (e) {
204
+ throw await toApiError(e);
205
+ }
206
+ }
207
+
208
+ export type SystemRolesDeleteQuery = z.input<(typeof schemas)["systemRolesDelete"]["query"]>;
209
+
210
+ export async function systemRolesDelete(query: SystemRolesDeleteQuery): Promise<unknown> {
211
+ const client = ensureReq();
212
+ try {
213
+ const env = await client.delete(`system/roles`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<unknown>>();
214
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
215
+ if (typeof env.code === "number" && env.code !== 0)
216
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
217
+ const data = env.data as unknown;
218
+ return data;
219
+ }
220
+ catch (e) {
221
+ throw await toApiError(e);
222
+ }
223
+ }
224
+
225
+ export type SystemRolesBindingsPutQuery = z.input<(typeof schemas)["systemRolesBindingsPut"]["query"]>;
226
+ export type SystemRolesBindingsPutBody = z.input<(typeof schemas)["systemRolesBindingsPut"]["body"]>;
227
+
228
+ export async function systemRolesBindingsPut(input: { query: SystemRolesBindingsPutQuery, body: SystemRolesBindingsPutBody }): Promise<unknown> {
229
+ const client = ensureReq();
230
+ try {
231
+ const env = await client.put(`system/roles/bindings`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<unknown>>();
232
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
233
+ if (typeof env.code === "number" && env.code !== 0)
234
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
235
+ const data = env.data as unknown;
236
+ return data;
237
+ }
238
+ catch (e) {
239
+ throw await toApiError(e);
240
+ }
241
+ }
242
+
243
+ export type SystemSettingsGetData = z.infer<(typeof schemas)["systemSettingsGet"]["data"]>;
244
+
245
+ export async function systemSettingsGet(): Promise<SystemSettingsGetData> {
246
+ const client = ensureReq();
247
+ try {
248
+ const env = await client.get(`system/settings`).json<OjEnvelope<SystemSettingsGetData>>();
249
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
250
+ if (typeof env.code === "number" && env.code !== 0)
251
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
252
+ const data = env.data as SystemSettingsGetData;
253
+ if (import.meta.env.DEV) {
254
+ const { schemas } = await import("./api.schemas");
255
+ const r = schemas["systemSettingsGet"].data.safeParse(data);
256
+ if (!r.success)
257
+ throw new ContractApiError(-1, `[契约违例] systemSettingsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
258
+ }
259
+ return data;
260
+ }
261
+ catch (e) {
262
+ throw await toApiError(e);
263
+ }
264
+ }
265
+
266
+ export type SystemSettingsPutBody = z.input<(typeof schemas)["systemSettingsPut"]["body"]>;
267
+
268
+ export async function systemSettingsPut(body: SystemSettingsPutBody): Promise<unknown> {
269
+ const client = ensureReq();
270
+ try {
271
+ const env = await client.put(`system/settings`, { json: body }).json<OjEnvelope<unknown>>();
272
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
273
+ if (typeof env.code === "number" && env.code !== 0)
274
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
275
+ const data = env.data as unknown;
276
+ return data;
277
+ }
278
+ catch (e) {
279
+ throw await toApiError(e);
280
+ }
281
+ }
282
+
283
+ export type SystemUsersGetData = z.infer<(typeof schemas)["systemUsersGet"]["data"]>;
284
+
285
+ export async function systemUsersGet(): Promise<SystemUsersGetData> {
286
+ const client = ensureReq();
287
+ try {
288
+ const env = await client.get(`system/users`).json<OjEnvelope<SystemUsersGetData>>();
289
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
290
+ if (typeof env.code === "number" && env.code !== 0)
291
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
292
+ const data = env.data as SystemUsersGetData;
293
+ if (import.meta.env.DEV) {
294
+ const { schemas } = await import("./api.schemas");
295
+ const r = schemas["systemUsersGet"].data.safeParse(data);
296
+ if (!r.success)
297
+ throw new ContractApiError(-1, `[契约违例] systemUsersGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
298
+ }
299
+ return data;
300
+ }
301
+ catch (e) {
302
+ throw await toApiError(e);
303
+ }
304
+ }
305
+
306
+ export type SystemUsersPostBody = z.input<(typeof schemas)["systemUsersPost"]["body"]>;
307
+ export type SystemUsersPostData = z.infer<(typeof schemas)["systemUsersPost"]["data"]>;
308
+
309
+ export async function systemUsersPost(body: SystemUsersPostBody): Promise<SystemUsersPostData> {
310
+ const client = ensureReq();
311
+ try {
312
+ const env = await client.post(`system/users`, { json: body }).json<OjEnvelope<SystemUsersPostData>>();
313
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
314
+ if (typeof env.code === "number" && env.code !== 0)
315
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
316
+ const data = env.data as SystemUsersPostData;
317
+ if (import.meta.env.DEV) {
318
+ const { schemas } = await import("./api.schemas");
319
+ const r = schemas["systemUsersPost"].data.safeParse(data);
320
+ if (!r.success)
321
+ throw new ContractApiError(-1, `[契约违例] systemUsersPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
322
+ }
323
+ return data;
324
+ }
325
+ catch (e) {
326
+ throw await toApiError(e);
327
+ }
328
+ }
329
+
330
+ export type SystemUsersForbiddenPutQuery = z.input<(typeof schemas)["systemUsersForbiddenPut"]["query"]>;
331
+ export type SystemUsersForbiddenPutBody = z.input<(typeof schemas)["systemUsersForbiddenPut"]["body"]>;
332
+
333
+ export async function systemUsersForbiddenPut(input: { query: SystemUsersForbiddenPutQuery, body: SystemUsersForbiddenPutBody }): Promise<unknown> {
334
+ const client = ensureReq();
335
+ try {
336
+ const env = await client.put(`system/users/forbidden`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<unknown>>();
337
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
338
+ if (typeof env.code === "number" && env.code !== 0)
339
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
340
+ const data = env.data as unknown;
341
+ return data;
342
+ }
343
+ catch (e) {
344
+ throw await toApiError(e);
345
+ }
346
+ }
347
+
348
+ export type SystemUsersPasswordPutQuery = z.input<(typeof schemas)["systemUsersPasswordPut"]["query"]>;
349
+ export type SystemUsersPasswordPutBody = z.input<(typeof schemas)["systemUsersPasswordPut"]["body"]>;
350
+
351
+ export async function systemUsersPasswordPut(input: { query: SystemUsersPasswordPutQuery, body: SystemUsersPasswordPutBody }): Promise<unknown> {
352
+ const client = ensureReq();
353
+ try {
354
+ const env = await client.put(`system/users/password`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<unknown>>();
355
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
356
+ if (typeof env.code === "number" && env.code !== 0)
357
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
358
+ const data = env.data as unknown;
359
+ return data;
360
+ }
361
+ catch (e) {
362
+ throw await toApiError(e);
363
+ }
364
+ }
365
+
366
+ export type SystemUsersRolesPutQuery = z.input<(typeof schemas)["systemUsersRolesPut"]["query"]>;
367
+ export type SystemUsersRolesPutBody = z.input<(typeof schemas)["systemUsersRolesPut"]["body"]>;
368
+
369
+ export async function systemUsersRolesPut(input: { query: SystemUsersRolesPutQuery, body: SystemUsersRolesPutBody }): Promise<unknown> {
370
+ const client = ensureReq();
371
+ try {
372
+ const env = await client.put(`system/users/roles`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<unknown>>();
373
+ // 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
374
+ if (typeof env.code === "number" && env.code !== 0)
375
+ throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
376
+ const data = env.data as unknown;
377
+ return data;
378
+ }
379
+ catch (e) {
380
+ throw await toApiError(e);
381
+ }
382
+ }
@@ -47,7 +47,7 @@ export default function OplogPage() {
47
47
  ];
48
48
 
49
49
  return (
50
- <Space direction="vertical" style={{ width: "100%" }}>
50
+ <Space direction="vertical" style={{ width: "100%", paddingTop: 16 }}>
51
51
  <Form
52
52
  layout="inline"
53
53
  onFinish={values => setFilters({
@@ -67,6 +67,7 @@ export default function RolesPage() {
67
67
 
68
68
  return (
69
69
  <Tabs
70
+ style={{ paddingTop: 16 }}
70
71
  items={[
71
72
  {
72
73
  key: "roles",
@@ -91,7 +91,7 @@ export default function SettingsPage() {
91
91
  .filter(g => g.items.length > 0);
92
92
 
93
93
  return (
94
- <Space direction="vertical" style={{ width: "100%" }}>
94
+ <Space direction="vertical" style={{ width: "100%", paddingTop: 16 }}>
95
95
  {groups.map(g => (
96
96
  <Card key={g.group} title={g.group}>
97
97
  <Space direction="vertical" style={{ width: "100%" }}>
@@ -115,7 +115,7 @@ export default function UsersPage() {
115
115
  ];
116
116
 
117
117
  return (
118
- <Space direction="vertical" style={{ width: "100%" }}>
118
+ <Space direction="vertical" style={{ width: "100%", paddingTop: 16 }}>
119
119
  <Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)}>
120
120
  {t("system:users.create")}
121
121
  </Button>
@@ -1,48 +1,40 @@
1
1
  /**
2
2
  * 模块工程配置:共享依赖一律不进 dependencies(宿主 importmap 提供),
3
3
  * 这里只登记模块清单(entry 相对本工程根)。
4
+ *
5
+ * 模块顺序即导航顺序:`home` 必须第一个(shell 的 "/" 重定向到它)。
4
6
  */
7
+ const allModules = [
8
+ // /home 必须是首个模块:shell 的 "/" → VITE_BASE_HOME_PATH(=/home)重定向
9
+ { name: "home", entry: "web/src/home/entry.ts" },
10
+ { name: "demo", entry: "web/src/demo/entry.ts" },
11
+ // /login 路由由模块提供:shell 宿主不挂 runtime 内置 baseRoutes
12
+ { name: "login", entry: "web/src/login/entry.ts" },
13
+ // 个人中心:runtime 用户菜单固定导航 /personal-center/my-profile,缺则点击落空
14
+ { name: "personal-center", entry: "web/src/personal-center/entry.ts" },
15
+ // 通知:onInit 注册 notificationsApi provider(四方法全必填),
16
+ // 通知铃的互动(单条已读/全部已读/清空)由此生效;未登记则永远回落内置只读兜底
17
+ { name: "notification", entry: "web/src/notification/entry.ts" },
18
+ // 系统管理:用户/成员资格/角色权限/操作日志/站点设置/登录方式(oj 后端 /api/system/*)
19
+ { name: "system", entry: "web/src/system/entry.ts" },
20
+ // #region demo-only
21
+ // 以下为模板内置的演示模块(about/access/exception/outside/route-nest),
22
+ // 用于把 templates 当可运行 demo 直接跑;其文件不在 `ojm init` 的
23
+ // init.include.yaml 白名单里,不拷入新工程,故本区间连同这些条目会被
24
+ // init 一并剥离,脚手架产出的配置不会残留指向缺失文件的死条目。
25
+ { name: "about", entry: "web/src/about/entry.ts" },
26
+ { name: "access", entry: "web/src/access/entry.ts" },
27
+ { name: "exception", entry: "web/src/exception/entry.ts" },
28
+ { name: "outside", entry: "web/src/outside/entry.ts" },
29
+ { name: "route-nest", entry: "web/src/route-nest/entry.ts" },
30
+ // 解决方案市场:第一方能力(消费 _platform 编排面 /api/_platform/market/*),
31
+ // 模板自带以便自演示;新工程默认不带,同上由 init 剥离。
32
+ { name: "oj-market", entry: "web/src/oj-market/entry.ts" },
33
+ // #endregion demo-only
34
+ ];
35
+
5
36
  export default {
6
37
  /** 产物 URL 前缀,留空表示同源相对路径 */
7
38
  baseUrl: "",
8
- modules: [
9
- {
10
- // /home 必须是首个模块:shell 的 "/" → VITE_BASE_HOME_PATH(=/home)重定向
11
- name: "home",
12
- entry: "web/src/home/entry.ts",
13
- enabled: true,
14
- },
15
- {
16
- name: "demo",
17
- entry: "web/src/demo/entry.ts",
18
- enabled: true,
19
- },
20
- {
21
- // /login 路由由模块提供:shell 宿主不挂 runtime 内置 baseRoutes
22
- name: "login",
23
- entry: "web/src/login/entry.ts",
24
- enabled: true,
25
- },
26
- {
27
- // 个人中心:runtime 用户菜单固定导航 /personal-center/my-profile,缺则点击落空
28
- name: "personal-center",
29
- entry: "web/src/personal-center/entry.ts",
30
- enabled: true,
31
- },
32
- {
33
- // 通知:onInit 注册 notificationsApi provider(四方法全必填),
34
- // 通知铃的互动(单条已读/全部已读/清空)由此生效;未登记则永远回落内置只读兜底
35
- name: "notification",
36
- entry: "web/src/notification/entry.ts",
37
- enabled: true,
38
- },
39
- {
40
- // 系统管理:用户/成员资格/角色权限/操作日志/站点设置/登录方式(oj 后端 /api/system/*)。
41
- // __client 不随模板分发:init 后跑一次 `oj openapi -o openapi.json && ojm api` 生成;
42
- // 生成前该模块加载失败(菜单缺失)属预期,README「系统管理模块」节有说明
43
- name: "system",
44
- entry: "web/src/system/entry.ts",
45
- enabled: true,
46
- },
47
- ],
39
+ modules: allModules,
48
40
  };
@@ -8,9 +8,9 @@
8
8
  "react-router": "7.18.2",
9
9
  "react-router/dom": "7.18.2",
10
10
  "@tanstack/react-query": "5.102.8",
11
- "@oj-module/runtime": "0.2.1",
12
- "@oj-module/runtime/contract": "0.2.1",
13
- "@oj-module/runtime/contract/errors": "0.2.1",
11
+ "@oj-module/runtime": "0.2.5",
12
+ "@oj-module/runtime/contract": "0.2.5",
13
+ "@oj-module/runtime/contract/errors": "0.2.5",
14
14
  "@plane/kit": "0.1.20",
15
15
  "@plane/editor": "0.1.20",
16
16
  "antd": "6.6.1",