create-windy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (904) hide show
  1. package/README.md +114 -0
  2. package/assets/LICENSE-Apache-2.0.txt +201 -0
  3. package/dist/cli.js +1662 -0
  4. package/package.json +37 -0
  5. package/template/.dockerignore +11 -0
  6. package/template/.oxfmtrc.json +9 -0
  7. package/template/.oxlintrc.json +119 -0
  8. package/template/.windy-template.json +71 -0
  9. package/template/AGENTS.md +87 -0
  10. package/template/README.md +128 -0
  11. package/template/apps/server/Dockerfile +34 -0
  12. package/template/apps/server/package.json +30 -0
  13. package/template/apps/server/src/access-guards.ts +112 -0
  14. package/template/apps/server/src/admin/routes.test.ts +105 -0
  15. package/template/apps/server/src/admin/routes.ts +95 -0
  16. package/template/apps/server/src/agent/data-scope-routes.test.ts +143 -0
  17. package/template/apps/server/src/agent/routes.test.ts +244 -0
  18. package/template/apps/server/src/agent/routes.ts +257 -0
  19. package/template/apps/server/src/api-app.ts +32 -0
  20. package/template/apps/server/src/application-services.ts +154 -0
  21. package/template/apps/server/src/audit/contracts.ts +21 -0
  22. package/template/apps/server/src/audit/drizzle-log-store.ts +150 -0
  23. package/template/apps/server/src/audit/policy.ts +18 -0
  24. package/template/apps/server/src/audit/recovery-queue.test.ts +42 -0
  25. package/template/apps/server/src/audit/recovery-queue.ts +63 -0
  26. package/template/apps/server/src/audit/redaction.ts +55 -0
  27. package/template/apps/server/src/audit/reliable-writer.test.ts +200 -0
  28. package/template/apps/server/src/audit/reliable-writer.ts +201 -0
  29. package/template/apps/server/src/audit/search-summary.ts +32 -0
  30. package/template/apps/server/src/auth/actor-resolver.test.ts +138 -0
  31. package/template/apps/server/src/auth/actor-resolver.ts +109 -0
  32. package/template/apps/server/src/auth/authentication-provider.test.ts +180 -0
  33. package/template/apps/server/src/auth/authentication-provider.ts +117 -0
  34. package/template/apps/server/src/auth/authorization-snapshot.test.ts +117 -0
  35. package/template/apps/server/src/auth/authorization-snapshot.ts +98 -0
  36. package/template/apps/server/src/auth/bearer-token.ts +5 -0
  37. package/template/apps/server/src/auth/bootstrap-admin.ts +33 -0
  38. package/template/apps/server/src/auth/credential-restriction.ts +29 -0
  39. package/template/apps/server/src/auth/credential-routes.test.ts +190 -0
  40. package/template/apps/server/src/auth/credential-service.ts +165 -0
  41. package/template/apps/server/src/auth/development-bypass.ts +22 -0
  42. package/template/apps/server/src/auth/drizzle-repository.ts +315 -0
  43. package/template/apps/server/src/auth/drizzle-session-operations.ts +119 -0
  44. package/template/apps/server/src/auth/login-routes.ts +121 -0
  45. package/template/apps/server/src/auth/own-session-routes.test.ts +248 -0
  46. package/template/apps/server/src/auth/own-session-routes.ts +110 -0
  47. package/template/apps/server/src/auth/password.test.ts +30 -0
  48. package/template/apps/server/src/auth/password.ts +46 -0
  49. package/template/apps/server/src/auth/repository.test.ts +61 -0
  50. package/template/apps/server/src/auth/repository.ts +305 -0
  51. package/template/apps/server/src/auth/routes.test.ts +350 -0
  52. package/template/apps/server/src/auth/routes.ts +237 -0
  53. package/template/apps/server/src/auth/runtime.ts +20 -0
  54. package/template/apps/server/src/auth/service.ts +329 -0
  55. package/template/apps/server/src/auth/session-service.ts +123 -0
  56. package/template/apps/server/src/background/task-guard.test.ts +66 -0
  57. package/template/apps/server/src/background/task-guard.ts +49 -0
  58. package/template/apps/server/src/bulk-data/artifact-store.ts +82 -0
  59. package/template/apps/server/src/bulk-data/dictionary-handler.ts +122 -0
  60. package/template/apps/server/src/bulk-data/drizzle-repository.integration.test.ts +156 -0
  61. package/template/apps/server/src/bulk-data/drizzle-repository.ts +298 -0
  62. package/template/apps/server/src/bulk-data/helpers.ts +36 -0
  63. package/template/apps/server/src/bulk-data/input-validation.ts +99 -0
  64. package/template/apps/server/src/bulk-data/repository.ts +246 -0
  65. package/template/apps/server/src/bulk-data/resource-handler.ts +27 -0
  66. package/template/apps/server/src/bulk-data/routes.test.ts +169 -0
  67. package/template/apps/server/src/bulk-data/routes.ts +248 -0
  68. package/template/apps/server/src/bulk-data/scheduler-integration.test.ts +142 -0
  69. package/template/apps/server/src/bulk-data/service.test.ts +347 -0
  70. package/template/apps/server/src/bulk-data/service.ts +319 -0
  71. package/template/apps/server/src/bulk-data/types.ts +73 -0
  72. package/template/apps/server/src/configuration/bootstrap.ts +59 -0
  73. package/template/apps/server/src/configuration/definition.ts +89 -0
  74. package/template/apps/server/src/configuration/drizzle-repository.ts +166 -0
  75. package/template/apps/server/src/configuration/repository.ts +138 -0
  76. package/template/apps/server/src/configuration/routes.test.ts +178 -0
  77. package/template/apps/server/src/configuration/routes.ts +260 -0
  78. package/template/apps/server/src/configuration/service.test.ts +128 -0
  79. package/template/apps/server/src/configuration/service.ts +187 -0
  80. package/template/apps/server/src/data-access/context.ts +162 -0
  81. package/template/apps/server/src/data-access/department-tree.ts +27 -0
  82. package/template/apps/server/src/data-access/drizzle-predicate.test.ts +86 -0
  83. package/template/apps/server/src/data-access/drizzle-predicate.ts +50 -0
  84. package/template/apps/server/src/data-access/errors.ts +5 -0
  85. package/template/apps/server/src/data-access/platform-actor.ts +25 -0
  86. package/template/apps/server/src/data-access/query-specification.test.ts +82 -0
  87. package/template/apps/server/src/data-access/query-specification.ts +77 -0
  88. package/template/apps/server/src/data-access/scoped-repository.integration.test.ts +203 -0
  89. package/template/apps/server/src/data-access/scoped-repository.ts +268 -0
  90. package/template/apps/server/src/data-access/scoped-resource.test.ts +158 -0
  91. package/template/apps/server/src/data-access/scoped-resource.ts +141 -0
  92. package/template/apps/server/src/data-governance/export/approval-port.ts +84 -0
  93. package/template/apps/server/src/data-governance/export/authorization-port.test.ts +103 -0
  94. package/template/apps/server/src/data-governance/export/authorization-port.ts +69 -0
  95. package/template/apps/server/src/data-governance/export/drizzle-repository.integration.test.ts +88 -0
  96. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +97 -0
  97. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +339 -0
  98. package/template/apps/server/src/data-governance/export/job-runtime.ts +242 -0
  99. package/template/apps/server/src/data-governance/export/ndjson-stream.ts +62 -0
  100. package/template/apps/server/src/data-governance/export/postgres-api-actors.ts +140 -0
  101. package/template/apps/server/src/data-governance/export/postgres-api-assertions.ts +76 -0
  102. package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +265 -0
  103. package/template/apps/server/src/data-governance/export/postgres-api.integration.test.ts +298 -0
  104. package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +344 -0
  105. package/template/apps/server/src/data-governance/export/repository.test.ts +55 -0
  106. package/template/apps/server/src/data-governance/export/repository.ts +83 -0
  107. package/template/apps/server/src/data-governance/export/request-fingerprint.test.ts +51 -0
  108. package/template/apps/server/src/data-governance/export/request-fingerprint.ts +45 -0
  109. package/template/apps/server/src/data-governance/export/routes-integrity.test.ts +90 -0
  110. package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +239 -0
  111. package/template/apps/server/src/data-governance/export/routes.test.ts +182 -0
  112. package/template/apps/server/src/data-governance/export/routes.ts +215 -0
  113. package/template/apps/server/src/data-governance/export/scope-snapshot.test.ts +45 -0
  114. package/template/apps/server/src/data-governance/export/scope-snapshot.ts +27 -0
  115. package/template/apps/server/src/data-governance/export/service.ts +337 -0
  116. package/template/apps/server/src/data-governance/export/source.ts +69 -0
  117. package/template/apps/server/src/data-governance/export/types.ts +55 -0
  118. package/template/apps/server/src/data-governance/plaintext-access.test.ts +70 -0
  119. package/template/apps/server/src/data-governance/plaintext-access.ts +88 -0
  120. package/template/apps/server/src/data-governance/plaintext-postgres.integration.test.ts +223 -0
  121. package/template/apps/server/src/data-governance/user-plaintext-routes.test.ts +287 -0
  122. package/template/apps/server/src/data-governance/user-plaintext-routes.ts +181 -0
  123. package/template/apps/server/src/data-governance/user-projection.ts +54 -0
  124. package/template/apps/server/src/data-governance/user-sensitive-read-service.ts +54 -0
  125. package/template/apps/server/src/example-modules.ts +62 -0
  126. package/template/apps/server/src/example-permissions.ts +5 -0
  127. package/template/apps/server/src/feature/manifest-feature-repository.test.ts +187 -0
  128. package/template/apps/server/src/feature/manifest-feature-repository.ts +200 -0
  129. package/template/apps/server/src/feature/routes.authorization.test.ts +199 -0
  130. package/template/apps/server/src/feature/routes.ts +193 -0
  131. package/template/apps/server/src/foundation-access.test.ts +50 -0
  132. package/template/apps/server/src/foundation-access.ts +34 -0
  133. package/template/apps/server/src/foundation-route.ts +55 -0
  134. package/template/apps/server/src/foundation.ts +85 -0
  135. package/template/apps/server/src/guards.test.ts +74 -0
  136. package/template/apps/server/src/guards.ts +214 -0
  137. package/template/apps/server/src/http-app.test.ts +77 -0
  138. package/template/apps/server/src/http-app.ts +51 -0
  139. package/template/apps/server/src/index.ts +374 -0
  140. package/template/apps/server/src/jobs/artifact-service.test.ts +78 -0
  141. package/template/apps/server/src/jobs/artifact-service.ts +94 -0
  142. package/template/apps/server/src/jobs/drizzle-artifact.ts +63 -0
  143. package/template/apps/server/src/jobs/drizzle-claim.ts +111 -0
  144. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +299 -0
  145. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +232 -0
  146. package/template/apps/server/src/jobs/drizzle-lease.ts +21 -0
  147. package/template/apps/server/src/jobs/drizzle-mappers.ts +121 -0
  148. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +214 -0
  149. package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +135 -0
  150. package/template/apps/server/src/jobs/drizzle-repository.ts +268 -0
  151. package/template/apps/server/src/jobs/execution-repository.ts +72 -0
  152. package/template/apps/server/src/jobs/execution.test.ts +303 -0
  153. package/template/apps/server/src/jobs/handler-registry.ts +81 -0
  154. package/template/apps/server/src/jobs/in-memory-claim.ts +96 -0
  155. package/template/apps/server/src/jobs/in-memory-execution.ts +336 -0
  156. package/template/apps/server/src/jobs/in-memory-lease.ts +66 -0
  157. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +177 -0
  158. package/template/apps/server/src/jobs/legacy-adapter.test.ts +199 -0
  159. package/template/apps/server/src/jobs/legacy-adapter.ts +109 -0
  160. package/template/apps/server/src/jobs/legacy-service-runtime.ts +95 -0
  161. package/template/apps/server/src/jobs/repository.ts +141 -0
  162. package/template/apps/server/src/jobs/service.test.ts +64 -0
  163. package/template/apps/server/src/jobs/service.ts +44 -0
  164. package/template/apps/server/src/jobs/types.ts +180 -0
  165. package/template/apps/server/src/jobs/worker.ts +258 -0
  166. package/template/apps/server/src/license/legacy-license-resolver.ts +23 -0
  167. package/template/apps/server/src/license/license-resolver.test.ts +55 -0
  168. package/template/apps/server/src/license/license-resolver.ts +122 -0
  169. package/template/apps/server/src/license/reminder.test.ts +61 -0
  170. package/template/apps/server/src/license/reminder.ts +33 -0
  171. package/template/apps/server/src/license/restriction.test.ts +54 -0
  172. package/template/apps/server/src/license/restriction.ts +80 -0
  173. package/template/apps/server/src/license/routes-offline-code.test.ts +173 -0
  174. package/template/apps/server/src/license/routes.ts +99 -0
  175. package/template/apps/server/src/license/runtime-audit-reliability.test.ts +96 -0
  176. package/template/apps/server/src/license/runtime-reminder.test.ts +147 -0
  177. package/template/apps/server/src/license/runtime-service-test-http.ts +28 -0
  178. package/template/apps/server/src/license/runtime-service.test.ts +334 -0
  179. package/template/apps/server/src/license/runtime-service.ts +308 -0
  180. package/template/apps/server/src/module-composition.test.ts +70 -0
  181. package/template/apps/server/src/module-composition.ts +28 -0
  182. package/template/apps/server/src/notification/drizzle-repository.ts +233 -0
  183. package/template/apps/server/src/notification/repository.ts +160 -0
  184. package/template/apps/server/src/notification/routes.test.ts +151 -0
  185. package/template/apps/server/src/notification/routes.ts +185 -0
  186. package/template/apps/server/src/observability/bootstrap.ts +56 -0
  187. package/template/apps/server/src/observability/http-observability.test.ts +53 -0
  188. package/template/apps/server/src/observability/http-observability.ts +54 -0
  189. package/template/apps/server/src/observability/metrics.test.ts +36 -0
  190. package/template/apps/server/src/observability/metrics.ts +105 -0
  191. package/template/apps/server/src/observability/readiness.test.ts +36 -0
  192. package/template/apps/server/src/observability/readiness.ts +43 -0
  193. package/template/apps/server/src/observability/routes.test.ts +61 -0
  194. package/template/apps/server/src/observability/routes.ts +44 -0
  195. package/template/apps/server/src/pagination.ts +31 -0
  196. package/template/apps/server/src/persistence.integration.test.ts +54 -0
  197. package/template/apps/server/src/persistence.ts +118 -0
  198. package/template/apps/server/src/profile/routes.test.ts +190 -0
  199. package/template/apps/server/src/profile/routes.ts +173 -0
  200. package/template/apps/server/src/request-restriction.ts +29 -0
  201. package/template/apps/server/src/route-guards.test.ts +148 -0
  202. package/template/apps/server/src/route-guards.ts +63 -0
  203. package/template/apps/server/src/runtime-audit-list.test.ts +98 -0
  204. package/template/apps/server/src/runtime-config.ts +11 -0
  205. package/template/apps/server/src/runtime-development.ts +68 -0
  206. package/template/apps/server/src/runtime-license.ts +50 -0
  207. package/template/apps/server/src/runtime.test.ts +264 -0
  208. package/template/apps/server/src/runtime.ts +324 -0
  209. package/template/apps/server/src/scheduler/audit.ts +38 -0
  210. package/template/apps/server/src/scheduler/definitions.test.ts +35 -0
  211. package/template/apps/server/src/scheduler/definitions.ts +79 -0
  212. package/template/apps/server/src/scheduler/drizzle-durable-links.ts +52 -0
  213. package/template/apps/server/src/scheduler/drizzle-mappers.ts +36 -0
  214. package/template/apps/server/src/scheduler/drizzle-repository.integration.test.ts +174 -0
  215. package/template/apps/server/src/scheduler/drizzle-repository.ts +348 -0
  216. package/template/apps/server/src/scheduler/execution-context.ts +24 -0
  217. package/template/apps/server/src/scheduler/execution-recorder.ts +101 -0
  218. package/template/apps/server/src/scheduler/feature-preflight.ts +40 -0
  219. package/template/apps/server/src/scheduler/history.ts +22 -0
  220. package/template/apps/server/src/scheduler/overview.test.ts +89 -0
  221. package/template/apps/server/src/scheduler/overview.ts +125 -0
  222. package/template/apps/server/src/scheduler/recovery-conflict.ts +19 -0
  223. package/template/apps/server/src/scheduler/recovery-service.test.ts +238 -0
  224. package/template/apps/server/src/scheduler/recovery-service.ts +152 -0
  225. package/template/apps/server/src/scheduler/repository.ts +274 -0
  226. package/template/apps/server/src/scheduler/routes.test.ts +347 -0
  227. package/template/apps/server/src/scheduler/routes.ts +222 -0
  228. package/template/apps/server/src/scheduler/sensitive-text.ts +20 -0
  229. package/template/apps/server/src/scheduler/service-idle.test.ts +73 -0
  230. package/template/apps/server/src/scheduler/service.test.ts +330 -0
  231. package/template/apps/server/src/scheduler/service.ts +339 -0
  232. package/template/apps/server/src/scheduler/types.ts +103 -0
  233. package/template/apps/server/src/scheduler/worker.ts +38 -0
  234. package/template/apps/server/src/search/config.test.ts +43 -0
  235. package/template/apps/server/src/search/config.ts +62 -0
  236. package/template/apps/server/src/search/contracts.ts +127 -0
  237. package/template/apps/server/src/search/cursor.ts +39 -0
  238. package/template/apps/server/src/search/errors.ts +11 -0
  239. package/template/apps/server/src/search/host.ts +36 -0
  240. package/template/apps/server/src/search/masking.ts +6 -0
  241. package/template/apps/server/src/search/provider-execution.ts +195 -0
  242. package/template/apps/server/src/search/rate-limiter.ts +23 -0
  243. package/template/apps/server/src/search/registry.ts +105 -0
  244. package/template/apps/server/src/search/routes.test.ts +156 -0
  245. package/template/apps/server/src/search/routes.ts +95 -0
  246. package/template/apps/server/src/search/service.test.ts +314 -0
  247. package/template/apps/server/src/search/service.ts +257 -0
  248. package/template/apps/server/src/search/test-support.ts +122 -0
  249. package/template/apps/server/src/session/routes.test.ts +111 -0
  250. package/template/apps/server/src/session/routes.ts +56 -0
  251. package/template/apps/server/src/settings/drizzle-repository.ts +66 -0
  252. package/template/apps/server/src/settings/repository.ts +29 -0
  253. package/template/apps/server/src/settings/routes.test.ts +250 -0
  254. package/template/apps/server/src/settings/routes.ts +175 -0
  255. package/template/apps/server/src/settings/runtime.ts +13 -0
  256. package/template/apps/server/src/storage/blob-reference-registry.test.ts +25 -0
  257. package/template/apps/server/src/storage/blob-reference-registry.ts +15 -0
  258. package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +136 -0
  259. package/template/apps/server/src/storage/drizzle-upload-repository.ts +248 -0
  260. package/template/apps/server/src/storage/route-support.ts +84 -0
  261. package/template/apps/server/src/storage/routes.test.ts +288 -0
  262. package/template/apps/server/src/storage/routes.ts +297 -0
  263. package/template/apps/server/src/storage/runtime.ts +86 -0
  264. package/template/apps/server/src/system/audit-query.ts +17 -0
  265. package/template/apps/server/src/system/audit-routes.test.ts +139 -0
  266. package/template/apps/server/src/system/audit-routes.ts +113 -0
  267. package/template/apps/server/src/system/built-in-roles.ts +116 -0
  268. package/template/apps/server/src/system/department-routes.test.ts +80 -0
  269. package/template/apps/server/src/system/department-routes.ts +90 -0
  270. package/template/apps/server/src/system/drizzle-mapping.ts +53 -0
  271. package/template/apps/server/src/system/drizzle-repository.ts +298 -0
  272. package/template/apps/server/src/system/drizzle-scoped-repository.ts +235 -0
  273. package/template/apps/server/src/system/drizzle-system.ts +361 -0
  274. package/template/apps/server/src/system/entities.ts +78 -0
  275. package/template/apps/server/src/system/feature-routes.test.ts +55 -0
  276. package/template/apps/server/src/system/identity-route-config.ts +73 -0
  277. package/template/apps/server/src/system/interface-catalog.test.ts +103 -0
  278. package/template/apps/server/src/system/interface-catalog.ts +82 -0
  279. package/template/apps/server/src/system/menu-registry.test.ts +125 -0
  280. package/template/apps/server/src/system/menu-registry.ts +259 -0
  281. package/template/apps/server/src/system/menu-routes.test.ts +68 -0
  282. package/template/apps/server/src/system/menu-routes.ts +200 -0
  283. package/template/apps/server/src/system/mutation-runner.ts +33 -0
  284. package/template/apps/server/src/system/operation-monitoring.test.ts +78 -0
  285. package/template/apps/server/src/system/operation-monitoring.ts +233 -0
  286. package/template/apps/server/src/system/operations.test.ts +269 -0
  287. package/template/apps/server/src/system/operations.ts +155 -0
  288. package/template/apps/server/src/system/postgres-monitoring.ts +31 -0
  289. package/template/apps/server/src/system/redis-health.test.ts +116 -0
  290. package/template/apps/server/src/system/redis-health.ts +230 -0
  291. package/template/apps/server/src/system/repository.ts +234 -0
  292. package/template/apps/server/src/system/resource-access-response.ts +47 -0
  293. package/template/apps/server/src/system/resource-export-route.ts +64 -0
  294. package/template/apps/server/src/system/resource-route-support.ts +50 -0
  295. package/template/apps/server/src/system/response-projection.ts +24 -0
  296. package/template/apps/server/src/system/route-helpers.ts +104 -0
  297. package/template/apps/server/src/system/route-test-app.ts +27 -0
  298. package/template/apps/server/src/system/route-types.ts +52 -0
  299. package/template/apps/server/src/system/routes-validation.test.ts +61 -0
  300. package/template/apps/server/src/system/routes.test.ts +311 -0
  301. package/template/apps/server/src/system/routes.ts +354 -0
  302. package/template/apps/server/src/system/seed.test.ts +129 -0
  303. package/template/apps/server/src/system/seed.ts +237 -0
  304. package/template/apps/server/src/system/user-account-policy.test.ts +158 -0
  305. package/template/apps/server/src/system/user-account-policy.ts +103 -0
  306. package/template/apps/server/src/system/user-data-scope.ts +10 -0
  307. package/template/apps/server/src/system/user-department-validation.ts +17 -0
  308. package/template/apps/server/src/system/user-projection.test.ts +40 -0
  309. package/template/apps/server/src/system/user-projection.ts +35 -0
  310. package/template/apps/server/src/work-order/data-scope.integration.test.ts +171 -0
  311. package/template/apps/server/src/work-order/drizzle-repository.integration.test.ts +78 -0
  312. package/template/apps/server/src/work-order/drizzle-repository.ts +67 -0
  313. package/template/apps/server/src/work-order/foundation-modules.test.ts +85 -0
  314. package/template/apps/server/src/work-order/repository.ts +46 -0
  315. package/template/apps/server/src/work-order/routes.test.ts +209 -0
  316. package/template/apps/server/src/work-order/routes.ts +159 -0
  317. package/template/apps/server/src/work-order/search-api.test.ts +121 -0
  318. package/template/apps/server/src/work-order/search-provider.test.ts +201 -0
  319. package/template/apps/server/src/work-order/search-provider.ts +59 -0
  320. package/template/apps/server/src/work-order/service.ts +82 -0
  321. package/template/apps/server/src/work-order/task.test.ts +79 -0
  322. package/template/apps/server/src/work-order/task.ts +30 -0
  323. package/template/apps/server/src/workflow/assignee-directory.ts +23 -0
  324. package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +213 -0
  325. package/template/apps/server/src/workflow/drizzle-repository.ts +299 -0
  326. package/template/apps/server/src/workflow/effects.test.ts +64 -0
  327. package/template/apps/server/src/workflow/effects.ts +112 -0
  328. package/template/apps/server/src/workflow/repository.ts +160 -0
  329. package/template/apps/server/src/workflow/routes.test.ts +256 -0
  330. package/template/apps/server/src/workflow/routes.ts +249 -0
  331. package/template/apps/server/src/workflow/service.ts +196 -0
  332. package/template/apps/server/src/workflow/timeout-runtime.test.ts +96 -0
  333. package/template/apps/server/src/workflow/timeout-runtime.ts +66 -0
  334. package/template/apps/server/tsconfig.json +17 -0
  335. package/template/apps/web/Dockerfile +41 -0
  336. package/template/apps/web/components.json +24 -0
  337. package/template/apps/web/dev/dev-identity.ts +58 -0
  338. package/template/apps/web/dev/dev-port.test.ts +53 -0
  339. package/template/apps/web/dev/dev-port.ts +68 -0
  340. package/template/apps/web/dev/start.ts +37 -0
  341. package/template/apps/web/index.html +14 -0
  342. package/template/apps/web/package.json +44 -0
  343. package/template/apps/web/runtime-server.test.ts +86 -0
  344. package/template/apps/web/runtime-server.ts +143 -0
  345. package/template/apps/web/server.ts +21 -0
  346. package/template/apps/web/src/App.vue +22 -0
  347. package/template/apps/web/src/app/home/HomePage.vue +75 -0
  348. package/template/apps/web/src/app/home/HomeWelcome.vue +85 -0
  349. package/template/apps/web/src/app/home/HomeWelcome.webtest.ts +32 -0
  350. package/template/apps/web/src/app/layouts/AppLayout.vue +10 -0
  351. package/template/apps/web/src/components/auth/DevelopmentAuthWarning.vue +15 -0
  352. package/template/apps/web/src/components/auth/LoginForm.vue +80 -0
  353. package/template/apps/web/src/components/auth/LoginForm.webtest.ts +33 -0
  354. package/template/apps/web/src/components/auth/PasswordChangeForm.vue +90 -0
  355. package/template/apps/web/src/components/auth/UserSessionMenu.vue +60 -0
  356. package/template/apps/web/src/components/auth/UserSessionMenu.webtest.ts +45 -0
  357. package/template/apps/web/src/components/common/ConfirmDialog.vue +75 -0
  358. package/template/apps/web/src/components/common/DataPagination.vue +79 -0
  359. package/template/apps/web/src/components/common/DataPagination.webtest.ts +28 -0
  360. package/template/apps/web/src/components/common/EmptyState.vue +43 -0
  361. package/template/apps/web/src/components/common/FormDialog.vue +86 -0
  362. package/template/apps/web/src/components/common/ModalBody.vue +19 -0
  363. package/template/apps/web/src/components/common/ModalLayout.webtest.ts +54 -0
  364. package/template/apps/web/src/components/common/PageError.vue +46 -0
  365. package/template/apps/web/src/components/common/PageLoading.vue +41 -0
  366. package/template/apps/web/src/components/common/StatusSummary.vue +37 -0
  367. package/template/apps/web/src/components/common/UnsavedChangesDialog.vue +60 -0
  368. package/template/apps/web/src/components/common/UnsavedChangesDialog.webtest.ts +60 -0
  369. package/template/apps/web/src/components/license/LicenseActivationCodeForm.vue +80 -0
  370. package/template/apps/web/src/components/license/LicenseExpiryBanner.vue +54 -0
  371. package/template/apps/web/src/components/license/LicenseFlow.webtest.ts +170 -0
  372. package/template/apps/web/src/components/license/LicenseStatusCard.vue +95 -0
  373. package/template/apps/web/src/components/license/LicenseUploadForm.vue +79 -0
  374. package/template/apps/web/src/components/license/license-display.ts +12 -0
  375. package/template/apps/web/src/components/ui/alert/Alert.vue +21 -0
  376. package/template/apps/web/src/components/ui/alert/AlertAction.vue +17 -0
  377. package/template/apps/web/src/components/ui/alert/AlertDescription.vue +22 -0
  378. package/template/apps/web/src/components/ui/alert/AlertTitle.vue +22 -0
  379. package/template/apps/web/src/components/ui/alert/index.ts +25 -0
  380. package/template/apps/web/src/components/ui/badge/Badge.vue +29 -0
  381. package/template/apps/web/src/components/ui/badge/index.ts +28 -0
  382. package/template/apps/web/src/components/ui/breadcrumb/Breadcrumb.vue +18 -0
  383. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +26 -0
  384. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  385. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbLink.vue +24 -0
  386. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbList.vue +22 -0
  387. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  388. package/template/apps/web/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +23 -0
  389. package/template/apps/web/src/components/ui/breadcrumb/index.ts +7 -0
  390. package/template/apps/web/src/components/ui/button/Button.vue +31 -0
  391. package/template/apps/web/src/components/ui/button/index.ts +42 -0
  392. package/template/apps/web/src/components/ui/card/Card.vue +29 -0
  393. package/template/apps/web/src/components/ui/card/CardAction.vue +22 -0
  394. package/template/apps/web/src/components/ui/card/CardContent.vue +17 -0
  395. package/template/apps/web/src/components/ui/card/CardDescription.vue +17 -0
  396. package/template/apps/web/src/components/ui/card/CardFooter.vue +22 -0
  397. package/template/apps/web/src/components/ui/card/CardHeader.vue +22 -0
  398. package/template/apps/web/src/components/ui/card/CardTitle.vue +22 -0
  399. package/template/apps/web/src/components/ui/card/index.ts +7 -0
  400. package/template/apps/web/src/components/ui/checkbox/Checkbox.vue +41 -0
  401. package/template/apps/web/src/components/ui/checkbox/index.ts +1 -0
  402. package/template/apps/web/src/components/ui/dialog/Dialog.vue +15 -0
  403. package/template/apps/web/src/components/ui/dialog/DialogClose.vue +12 -0
  404. package/template/apps/web/src/components/ui/dialog/DialogContent.vue +62 -0
  405. package/template/apps/web/src/components/ui/dialog/DialogDescription.vue +30 -0
  406. package/template/apps/web/src/components/ui/dialog/DialogFooter.vue +33 -0
  407. package/template/apps/web/src/components/ui/dialog/DialogHeader.vue +17 -0
  408. package/template/apps/web/src/components/ui/dialog/DialogOverlay.vue +28 -0
  409. package/template/apps/web/src/components/ui/dialog/DialogScrollContent.vue +67 -0
  410. package/template/apps/web/src/components/ui/dialog/DialogTitle.vue +27 -0
  411. package/template/apps/web/src/components/ui/dialog/DialogTrigger.vue +12 -0
  412. package/template/apps/web/src/components/ui/dialog/index.ts +10 -0
  413. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
  414. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +50 -0
  415. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuContent.vue +48 -0
  416. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
  417. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuItem.vue +41 -0
  418. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +30 -0
  419. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  420. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +51 -0
  421. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  422. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +22 -0
  423. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  424. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +34 -0
  425. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +36 -0
  426. package/template/apps/web/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  427. package/template/apps/web/src/components/ui/dropdown-menu/index.ts +16 -0
  428. package/template/apps/web/src/components/ui/input/Input.vue +33 -0
  429. package/template/apps/web/src/components/ui/input/index.ts +1 -0
  430. package/template/apps/web/src/components/ui/select/Select.vue +15 -0
  431. package/template/apps/web/src/components/ui/select/SelectContent.vue +61 -0
  432. package/template/apps/web/src/components/ui/select/SelectGroup.vue +23 -0
  433. package/template/apps/web/src/components/ui/select/SelectItem.vue +49 -0
  434. package/template/apps/web/src/components/ui/select/SelectItemText.vue +12 -0
  435. package/template/apps/web/src/components/ui/select/SelectLabel.vue +19 -0
  436. package/template/apps/web/src/components/ui/select/SelectScrollDownButton.vue +34 -0
  437. package/template/apps/web/src/components/ui/select/SelectScrollUpButton.vue +34 -0
  438. package/template/apps/web/src/components/ui/select/SelectSeparator.vue +21 -0
  439. package/template/apps/web/src/components/ui/select/SelectTrigger.vue +43 -0
  440. package/template/apps/web/src/components/ui/select/SelectValue.vue +12 -0
  441. package/template/apps/web/src/components/ui/select/index.ts +11 -0
  442. package/template/apps/web/src/components/ui/separator/Separator.vue +30 -0
  443. package/template/apps/web/src/components/ui/separator/index.ts +1 -0
  444. package/template/apps/web/src/components/ui/sheet/Sheet.vue +15 -0
  445. package/template/apps/web/src/components/ui/sheet/SheetClose.vue +12 -0
  446. package/template/apps/web/src/components/ui/sheet/SheetContent.vue +62 -0
  447. package/template/apps/web/src/components/ui/sheet/SheetDescription.vue +23 -0
  448. package/template/apps/web/src/components/ui/sheet/SheetFooter.vue +15 -0
  449. package/template/apps/web/src/components/ui/sheet/SheetHeader.vue +15 -0
  450. package/template/apps/web/src/components/ui/sheet/SheetOverlay.vue +28 -0
  451. package/template/apps/web/src/components/ui/sheet/SheetTitle.vue +25 -0
  452. package/template/apps/web/src/components/ui/sheet/SheetTrigger.vue +12 -0
  453. package/template/apps/web/src/components/ui/sheet/index.ts +8 -0
  454. package/template/apps/web/src/components/ui/sidebar/Sidebar.vue +114 -0
  455. package/template/apps/web/src/components/ui/sidebar/SidebarContent.vue +23 -0
  456. package/template/apps/web/src/components/ui/sidebar/SidebarFooter.vue +18 -0
  457. package/template/apps/web/src/components/ui/sidebar/SidebarGroup.vue +18 -0
  458. package/template/apps/web/src/components/ui/sidebar/SidebarGroupAction.vue +29 -0
  459. package/template/apps/web/src/components/ui/sidebar/SidebarGroupContent.vue +18 -0
  460. package/template/apps/web/src/components/ui/sidebar/SidebarGroupLabel.vue +29 -0
  461. package/template/apps/web/src/components/ui/sidebar/SidebarHeader.vue +18 -0
  462. package/template/apps/web/src/components/ui/sidebar/SidebarInput.vue +19 -0
  463. package/template/apps/web/src/components/ui/sidebar/SidebarInset.vue +22 -0
  464. package/template/apps/web/src/components/ui/sidebar/SidebarMenu.vue +18 -0
  465. package/template/apps/web/src/components/ui/sidebar/SidebarMenuAction.vue +37 -0
  466. package/template/apps/web/src/components/ui/sidebar/SidebarMenuBadge.vue +23 -0
  467. package/template/apps/web/src/components/ui/sidebar/SidebarMenuButton.vue +60 -0
  468. package/template/apps/web/src/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
  469. package/template/apps/web/src/components/ui/sidebar/SidebarMenuItem.vue +18 -0
  470. package/template/apps/web/src/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
  471. package/template/apps/web/src/components/ui/sidebar/SidebarMenuSub.vue +23 -0
  472. package/template/apps/web/src/components/ui/sidebar/SidebarMenuSubButton.vue +39 -0
  473. package/template/apps/web/src/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
  474. package/template/apps/web/src/components/ui/sidebar/SidebarProvider.vue +128 -0
  475. package/template/apps/web/src/components/ui/sidebar/SidebarRail.vue +94 -0
  476. package/template/apps/web/src/components/ui/sidebar/SidebarSeparator.vue +19 -0
  477. package/template/apps/web/src/components/ui/sidebar/SidebarTrigger.vue +28 -0
  478. package/template/apps/web/src/components/ui/sidebar/index.ts +62 -0
  479. package/template/apps/web/src/components/ui/sidebar/sidebar-width.ts +29 -0
  480. package/template/apps/web/src/components/ui/sidebar/sidebar-width.webtest.ts +28 -0
  481. package/template/apps/web/src/components/ui/sidebar/utils.ts +26 -0
  482. package/template/apps/web/src/components/ui/skeleton/Skeleton.vue +17 -0
  483. package/template/apps/web/src/components/ui/skeleton/index.ts +1 -0
  484. package/template/apps/web/src/components/ui/sonner/Sonner.vue +70 -0
  485. package/template/apps/web/src/components/ui/sonner/index.ts +1 -0
  486. package/template/apps/web/src/components/ui/switch/Switch.vue +47 -0
  487. package/template/apps/web/src/components/ui/switch/Switch.webtest.ts +23 -0
  488. package/template/apps/web/src/components/ui/switch/index.ts +1 -0
  489. package/template/apps/web/src/components/ui/table/Table.vue +19 -0
  490. package/template/apps/web/src/components/ui/table/TableBody.vue +17 -0
  491. package/template/apps/web/src/components/ui/table/TableCaption.vue +17 -0
  492. package/template/apps/web/src/components/ui/table/TableCell.vue +22 -0
  493. package/template/apps/web/src/components/ui/table/TableEmpty.vue +37 -0
  494. package/template/apps/web/src/components/ui/table/TableFooter.vue +19 -0
  495. package/template/apps/web/src/components/ui/table/TableHead.vue +22 -0
  496. package/template/apps/web/src/components/ui/table/TableHeader.vue +14 -0
  497. package/template/apps/web/src/components/ui/table/TableRow.vue +22 -0
  498. package/template/apps/web/src/components/ui/table/index.ts +9 -0
  499. package/template/apps/web/src/components/ui/table/utils.ts +10 -0
  500. package/template/apps/web/src/components/ui/tabs/Tabs.vue +27 -0
  501. package/template/apps/web/src/components/ui/tabs/TabsContent.vue +23 -0
  502. package/template/apps/web/src/components/ui/tabs/TabsList.vue +34 -0
  503. package/template/apps/web/src/components/ui/tabs/TabsTrigger.vue +33 -0
  504. package/template/apps/web/src/components/ui/tabs/index.ts +24 -0
  505. package/template/apps/web/src/components/ui/tooltip/Tooltip.vue +15 -0
  506. package/template/apps/web/src/components/ui/tooltip/TooltipContent.vue +49 -0
  507. package/template/apps/web/src/components/ui/tooltip/TooltipProvider.vue +14 -0
  508. package/template/apps/web/src/components/ui/tooltip/TooltipTrigger.vue +12 -0
  509. package/template/apps/web/src/components/ui/tooltip/index.ts +4 -0
  510. package/template/apps/web/src/composables/useAccessSnapshot.ts +55 -0
  511. package/template/apps/web/src/composables/useAccessSnapshot.webtest.ts +39 -0
  512. package/template/apps/web/src/composables/useAppToast.ts +30 -0
  513. package/template/apps/web/src/composables/useAuthSession.ts +127 -0
  514. package/template/apps/web/src/composables/useAuthSession.webtest.ts +48 -0
  515. package/template/apps/web/src/composables/useLicenseReminderRefresh.ts +27 -0
  516. package/template/apps/web/src/composables/useLicenseReminderRefresh.webtest.ts +30 -0
  517. package/template/apps/web/src/composables/useLicenseRuntime.ts +90 -0
  518. package/template/apps/web/src/composables/useLoginFlow.ts +39 -0
  519. package/template/apps/web/src/composables/useModuleConfigurations.ts +116 -0
  520. package/template/apps/web/src/composables/usePasswordChange.ts +31 -0
  521. package/template/apps/web/src/composables/usePlatformSettings.ts +90 -0
  522. package/template/apps/web/src/composables/useSessionContext.ts +56 -0
  523. package/template/apps/web/src/composables/useTheme.ts +123 -0
  524. package/template/apps/web/src/composables/useUnsavedChangesConfirmation.ts +55 -0
  525. package/template/apps/web/src/composables/useWatermarkSettings.ts +56 -0
  526. package/template/apps/web/src/composables/watermark-settings.ts +45 -0
  527. package/template/apps/web/src/composables/watermark-settings.webtest.ts +38 -0
  528. package/template/apps/web/src/env.d.ts +17 -0
  529. package/template/apps/web/src/layout/AppHeader.vue +107 -0
  530. package/template/apps/web/src/layout/AppShell.vue +55 -0
  531. package/template/apps/web/src/layout/AppShell.webtest.ts +75 -0
  532. package/template/apps/web/src/layout/AppSidebar.vue +262 -0
  533. package/template/apps/web/src/layout/AppSidebar.webtest.ts +167 -0
  534. package/template/apps/web/src/layout/GlobalWatermark.vue +38 -0
  535. package/template/apps/web/src/layout/NavigationSearchDialog.vue +166 -0
  536. package/template/apps/web/src/layout/NavigationSearchDialog.webtest.ts +84 -0
  537. package/template/apps/web/src/layout/NotificationMenu.vue +174 -0
  538. package/template/apps/web/src/layout/NotificationMenu.webtest.ts +102 -0
  539. package/template/apps/web/src/layout/ThemeToggle.vue +44 -0
  540. package/template/apps/web/src/layout/navigation.ts +103 -0
  541. package/template/apps/web/src/layout/navigation.webtest.ts +99 -0
  542. package/template/apps/web/src/lib/date-time.ts +21 -0
  543. package/template/apps/web/src/lib/date-time.webtest.ts +14 -0
  544. package/template/apps/web/src/lib/utils.ts +7 -0
  545. package/template/apps/web/src/main.ts +11 -0
  546. package/template/apps/web/src/pages/AccessDeniedPage.vue +61 -0
  547. package/template/apps/web/src/pages/auth/ChangePasswordPage.vue +46 -0
  548. package/template/apps/web/src/pages/auth/LoginPage.vue +63 -0
  549. package/template/apps/web/src/pages/configuration/ModuleConfigurationPage.vue +15 -0
  550. package/template/apps/web/src/pages/configuration/components/ModuleConfigRollbackDialog.vue +51 -0
  551. package/template/apps/web/src/pages/configuration/components/ModuleConfigVersionList.vue +116 -0
  552. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +126 -0
  553. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.webtest.ts +73 -0
  554. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +236 -0
  555. package/template/apps/web/src/pages/dashboard/DashboardPage.vue +39 -0
  556. package/template/apps/web/src/pages/dashboard/DashboardPage.webtest.ts +37 -0
  557. package/template/apps/web/src/pages/dashboard/components/DashboardAttention.vue +36 -0
  558. package/template/apps/web/src/pages/dashboard/components/DashboardMetricCards.vue +28 -0
  559. package/template/apps/web/src/pages/dashboard/dashboard-presenter.ts +115 -0
  560. package/template/apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts +92 -0
  561. package/template/apps/web/src/pages/license/LicensePage.vue +65 -0
  562. package/template/apps/web/src/pages/profile/PersonalSettingsPage.vue +177 -0
  563. package/template/apps/web/src/pages/profile/PersonalSettingsPage.webtest.ts +78 -0
  564. package/template/apps/web/src/pages/settings/BrandingSettingsSection.vue +198 -0
  565. package/template/apps/web/src/pages/settings/GlobalSettingsPage.vue +195 -0
  566. package/template/apps/web/src/pages/settings/GlobalSettingsPage.webtest.ts +314 -0
  567. package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +115 -0
  568. package/template/apps/web/src/pages/settings/logo-file.ts +23 -0
  569. package/template/apps/web/src/pages/settings/logo-file.webtest.ts +14 -0
  570. package/template/apps/web/src/pages/system/SystemNotificationsPage.vue +262 -0
  571. package/template/apps/web/src/pages/system/SystemNotificationsPage.webtest.ts +88 -0
  572. package/template/apps/web/src/pages/system/SystemOperationsPage.vue +151 -0
  573. package/template/apps/web/src/pages/system/SystemOperationsPage.webtest.ts +146 -0
  574. package/template/apps/web/src/pages/system/SystemResourceRoutePage.vue +80 -0
  575. package/template/apps/web/src/pages/system/SystemResourceRoutePage.webtest.ts +100 -0
  576. package/template/apps/web/src/pages/system/components/AuditActionCell.vue +87 -0
  577. package/template/apps/web/src/pages/system/components/AuditActionCell.webtest.ts +66 -0
  578. package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +119 -0
  579. package/template/apps/web/src/pages/system/components/AuditLogFilters.webtest.ts +59 -0
  580. package/template/apps/web/src/pages/system/components/DiskUsageChart.vue +62 -0
  581. package/template/apps/web/src/pages/system/components/FeatureLicensePolicyDialog.vue +136 -0
  582. package/template/apps/web/src/pages/system/components/FeatureLicensePolicyDialog.webtest.ts +67 -0
  583. package/template/apps/web/src/pages/system/components/NotificationPublishForm.vue +57 -0
  584. package/template/apps/web/src/pages/system/components/OperationCacheMonitor.vue +73 -0
  585. package/template/apps/web/src/pages/system/components/OperationOnlineUsers.vue +60 -0
  586. package/template/apps/web/src/pages/system/components/OperationOnlineUsers.webtest.ts +35 -0
  587. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.vue +118 -0
  588. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts +64 -0
  589. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.vue +297 -0
  590. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts +145 -0
  591. package/template/apps/web/src/pages/system/components/SchedulerRunTable.vue +127 -0
  592. package/template/apps/web/src/pages/system/components/SchedulerRunTable.webtest.ts +75 -0
  593. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.vue +125 -0
  594. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.webtest.ts +84 -0
  595. package/template/apps/web/src/pages/system/components/SystemResourceFilters.vue +64 -0
  596. package/template/apps/web/src/pages/system/components/SystemResourceForm.vue +102 -0
  597. package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +360 -0
  598. package/template/apps/web/src/pages/system/components/SystemResourcePage.webtest.ts +263 -0
  599. package/template/apps/web/src/pages/system/components/SystemResourceTable.vue +242 -0
  600. package/template/apps/web/src/pages/system/components/SystemResourceTable.webtest.ts +196 -0
  601. package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkActions.vue +142 -0
  602. package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkJobDetail.vue +109 -0
  603. package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkJobList.vue +127 -0
  604. package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkPanel.vue +72 -0
  605. package/template/apps/web/src/pages/system/components/dictionary-bulk/DictionaryBulkPanel.webtest.ts +255 -0
  606. package/template/apps/web/src/pages/system/components/feature-license-policy.ts +12 -0
  607. package/template/apps/web/src/pages/system/components/menu-management/MenuManagementPage.vue +131 -0
  608. package/template/apps/web/src/pages/system/components/menu-management/MenuManagementPage.webtest.ts +228 -0
  609. package/template/apps/web/src/pages/system/components/menu-management/MenuStructureTable.vue +230 -0
  610. package/template/apps/web/src/pages/system/components/menu-management/menu-model.ts +161 -0
  611. package/template/apps/web/src/pages/system/components/menu-management/menu-model.webtest.ts +133 -0
  612. package/template/apps/web/src/pages/system/components/menu-management/useMenuManagement.ts +117 -0
  613. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.vue +144 -0
  614. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.webtest.ts +55 -0
  615. package/template/apps/web/src/pages/system/components/role-policy/RolePolicyForm.vue +134 -0
  616. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.ts +58 -0
  617. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.webtest.ts +80 -0
  618. package/template/apps/web/src/pages/system/components/user-account/UserAccountForm.vue +307 -0
  619. package/template/apps/web/src/pages/system/components/user-account/UserRoleSelector.vue +111 -0
  620. package/template/apps/web/src/pages/system/components/user-account/UserRoleSelector.webtest.ts +45 -0
  621. package/template/apps/web/src/pages/system/components/user-account/save-user-account.ts +47 -0
  622. package/template/apps/web/src/pages/system/composables/useDictionaryBulkJobs.ts +152 -0
  623. package/template/apps/web/src/pages/system/composables/useFeatureLicenseEditor.ts +38 -0
  624. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.ts +141 -0
  625. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.webtest.ts +224 -0
  626. package/template/apps/web/src/pages/system/composables/useSystemResource.ts +269 -0
  627. package/template/apps/web/src/pages/system/composables/useSystemResource.webtest.ts +51 -0
  628. package/template/apps/web/src/pages/system/dictionary-bulk-presenter.ts +126 -0
  629. package/template/apps/web/src/pages/system/resource-config.ts +233 -0
  630. package/template/apps/web/src/router/auth-navigation.ts +76 -0
  631. package/template/apps/web/src/router/index.ts +246 -0
  632. package/template/apps/web/src/router/index.webtest.ts +396 -0
  633. package/template/apps/web/src/router/manifest-routes.ts +59 -0
  634. package/template/apps/web/src/services/access-api.ts +26 -0
  635. package/template/apps/web/src/services/auth-api.ts +72 -0
  636. package/template/apps/web/src/services/bulk-data-api.ts +105 -0
  637. package/template/apps/web/src/services/configuration-api.ts +43 -0
  638. package/template/apps/web/src/services/http.ts +145 -0
  639. package/template/apps/web/src/services/http.webtest.ts +73 -0
  640. package/template/apps/web/src/services/license-api.ts +53 -0
  641. package/template/apps/web/src/services/notification-api.ts +51 -0
  642. package/template/apps/web/src/services/operations-api.ts +128 -0
  643. package/template/apps/web/src/services/platform-settings-api.ts +21 -0
  644. package/template/apps/web/src/services/profile-api.ts +17 -0
  645. package/template/apps/web/src/services/session-context-api.ts +20 -0
  646. package/template/apps/web/src/services/system-api.ts +156 -0
  647. package/template/apps/web/src/style.css +142 -0
  648. package/template/apps/web/src/style.webtest.ts +18 -0
  649. package/template/apps/web/tsconfig.json +23 -0
  650. package/template/apps/web/vite.config.ts +26 -0
  651. package/template/apps/web/vitest.config.ts +14 -0
  652. package/template/bunfig.toml +2 -0
  653. package/template/docker-compose.yml +74 -0
  654. package/template/docs/adapters/ruoyi-vue-compatibility.md +93 -0
  655. package/template/docs/architecture/admin-surface-boundary.md +24 -0
  656. package/template/docs/architecture/data-scope-query-enforcement.md +26 -0
  657. package/template/docs/architecture/durable-jobs.md +101 -0
  658. package/template/docs/architecture/minimal-approval-workflow.md +60 -0
  659. package/template/docs/architecture/module-manifest-composition.md +47 -0
  660. package/template/docs/architecture/object-storage.md +65 -0
  661. package/template/docs/architecture/search-provider-protocol.md +59 -0
  662. package/template/docs/development/crud-generator.md +57 -0
  663. package/template/docs/license/license-offline-activation-code.md +67 -0
  664. package/template/docs/operations/observability.md +50 -0
  665. package/template/docs/platform/agent-tools.md +37 -0
  666. package/template/docs/platform/audit-reliability.md +95 -0
  667. package/template/docs/platform/bulk-data-jobs.md +156 -0
  668. package/template/docs/platform/data-access-control.md +62 -0
  669. package/template/docs/platform/module-configuration.md +98 -0
  670. package/template/docs/platform/navigation-registry.md +36 -0
  671. package/template/docs/platform/notifications.md +33 -0
  672. package/template/docs/platform/operations-overview.md +35 -0
  673. package/template/docs/platform/organization-membership.md +31 -0
  674. package/template/docs/platform/platform-authentication.md +127 -0
  675. package/template/docs/platform/platform-shell-settings.md +88 -0
  676. package/template/docs/platform/scheduled-task-executor.md +89 -0
  677. package/template/docs/platform/system-crud-api.md +100 -0
  678. package/template/docs/platform/web-system-crud.md +96 -0
  679. package/template/docs/product/built-in-roles.md +26 -0
  680. package/template/drizzle.config.ts +16 -0
  681. package/template/examples/inventory-item.crud.json +55 -0
  682. package/template/package.json +55 -0
  683. package/template/packages/config/index.test.ts +114 -0
  684. package/template/packages/config/index.ts +4 -0
  685. package/template/packages/config/package.json +13 -0
  686. package/template/packages/config/src/definition.ts +109 -0
  687. package/template/packages/config/src/environment-loader.ts +240 -0
  688. package/template/packages/config/src/platform.ts +185 -0
  689. package/template/packages/config/src/secrets.ts +69 -0
  690. package/template/packages/crud-generator/index.ts +3 -0
  691. package/template/packages/crud-generator/package.json +12 -0
  692. package/template/packages/crud-generator/src/cli.ts +31 -0
  693. package/template/packages/crud-generator/src/definition.ts +48 -0
  694. package/template/packages/crud-generator/src/generator.test.ts +180 -0
  695. package/template/packages/crud-generator/src/generator.ts +99 -0
  696. package/template/packages/crud-generator/src/template-helpers.ts +72 -0
  697. package/template/packages/crud-generator/src/templates/domain.ts +27 -0
  698. package/template/packages/crud-generator/src/templates/drizzle-repository.ts +126 -0
  699. package/template/packages/crud-generator/src/templates/dto.ts +19 -0
  700. package/template/packages/crud-generator/src/templates/index.ts +8 -0
  701. package/template/packages/crud-generator/src/templates/manifest.ts +69 -0
  702. package/template/packages/crud-generator/src/templates/project.ts +161 -0
  703. package/template/packages/crud-generator/src/templates/repository.ts +23 -0
  704. package/template/packages/crud-generator/src/templates/routes.ts +158 -0
  705. package/template/packages/crud-generator/src/templates/schema.ts +45 -0
  706. package/template/packages/crud-generator/src/templates/service.ts +32 -0
  707. package/template/packages/crud-generator/src/validation.ts +205 -0
  708. package/template/packages/crud-generator/tsconfig.json +15 -0
  709. package/template/packages/database/drizzle/0000_organic_madame_web.sql +136 -0
  710. package/template/packages/database/drizzle/0001_flawless_senator_kelly.sql +80 -0
  711. package/template/packages/database/drizzle/0002_woozy_squadron_supreme.sql +53 -0
  712. package/template/packages/database/drizzle/0003_far_carnage.sql +17 -0
  713. package/template/packages/database/drizzle/0004_flat_bastion.sql +2 -0
  714. package/template/packages/database/drizzle/0005_fixed_enchantress.sql +6 -0
  715. package/template/packages/database/drizzle/0006_groovy_overlord.sql +146 -0
  716. package/template/packages/database/drizzle/0007_chubby_may_parker.sql +9 -0
  717. package/template/packages/database/drizzle/0008_secret_toxin.sql +21 -0
  718. package/template/packages/database/drizzle/0009_ambiguous_adam_warlock.sql +46 -0
  719. package/template/packages/database/drizzle/0010_complex_orphan.sql +42 -0
  720. package/template/packages/database/drizzle/0011_lowly_maria_hill.sql +42 -0
  721. package/template/packages/database/drizzle/0012_serious_marvex.sql +11 -0
  722. package/template/packages/database/drizzle/0013_mysterious_miek.sql +48 -0
  723. package/template/packages/database/drizzle/0014_graceful_husk.sql +1 -0
  724. package/template/packages/database/drizzle/0015_illegal_jazinda.sql +29 -0
  725. package/template/packages/database/drizzle/0016_seed_platform_roles.sql +21 -0
  726. package/template/packages/database/drizzle/0017_silly_thunderbolt.sql +35 -0
  727. package/template/packages/database/drizzle/0018_cheerful_alex_power.sql +22 -0
  728. package/template/packages/database/drizzle/0019_omniscient_luckman.sql +3 -0
  729. package/template/packages/database/drizzle/0020_handy_vertigo.sql +18 -0
  730. package/template/packages/database/drizzle/0021_plain_paladin.sql +51 -0
  731. package/template/packages/database/drizzle/0022_icy_rhodey.sql +2 -0
  732. package/template/packages/database/drizzle/0023_fresh_thunderbolt_ross.sql +138 -0
  733. package/template/packages/database/drizzle/0024_misty_lizard.sql +13 -0
  734. package/template/packages/database/drizzle/0025_premium_songbird.sql +6 -0
  735. package/template/packages/database/drizzle/0026_aberrant_doctor_octopus.sql +42 -0
  736. package/template/packages/database/drizzle/0027_tiny_diamondback.sql +5 -0
  737. package/template/packages/database/drizzle/0028_condemned_ulik.sql +27 -0
  738. package/template/packages/database/drizzle/0029_clean_nightshade.sql +5 -0
  739. package/template/packages/database/drizzle/0030_governed_export_constraints.sql +84 -0
  740. package/template/packages/database/drizzle/meta/0000_snapshot.json +973 -0
  741. package/template/packages/database/drizzle/meta/0001_snapshot.json +1559 -0
  742. package/template/packages/database/drizzle/meta/0002_snapshot.json +1911 -0
  743. package/template/packages/database/drizzle/meta/0003_snapshot.json +2047 -0
  744. package/template/packages/database/drizzle/meta/0004_snapshot.json +2059 -0
  745. package/template/packages/database/drizzle/meta/0005_snapshot.json +2084 -0
  746. package/template/packages/database/drizzle/meta/0006_snapshot.json +3192 -0
  747. package/template/packages/database/drizzle/meta/0007_snapshot.json +3208 -0
  748. package/template/packages/database/drizzle/meta/0008_snapshot.json +3367 -0
  749. package/template/packages/database/drizzle/meta/0009_snapshot.json +3629 -0
  750. package/template/packages/database/drizzle/meta/0010_snapshot.json +3955 -0
  751. package/template/packages/database/drizzle/meta/0011_snapshot.json +4299 -0
  752. package/template/packages/database/drizzle/meta/0012_snapshot.json +4368 -0
  753. package/template/packages/database/drizzle/meta/0013_snapshot.json +4483 -0
  754. package/template/packages/database/drizzle/meta/0014_snapshot.json +4489 -0
  755. package/template/packages/database/drizzle/meta/0015_snapshot.json +4771 -0
  756. package/template/packages/database/drizzle/meta/0016_snapshot.json +4694 -0
  757. package/template/packages/database/drizzle/meta/0017_snapshot.json +4731 -0
  758. package/template/packages/database/drizzle/meta/0018_snapshot.json +4978 -0
  759. package/template/packages/database/drizzle/meta/0019_snapshot.json +4996 -0
  760. package/template/packages/database/drizzle/meta/0020_snapshot.json +5140 -0
  761. package/template/packages/database/drizzle/meta/0021_snapshot.json +5535 -0
  762. package/template/packages/database/drizzle/meta/0022_snapshot.json +5541 -0
  763. package/template/packages/database/drizzle/meta/0023_snapshot.json +6667 -0
  764. package/template/packages/database/drizzle/meta/0024_snapshot.json +6780 -0
  765. package/template/packages/database/drizzle/meta/0025_snapshot.json +6849 -0
  766. package/template/packages/database/drizzle/meta/0026_snapshot.json +7185 -0
  767. package/template/packages/database/drizzle/meta/0027_snapshot.json +7225 -0
  768. package/template/packages/database/drizzle/meta/0028_snapshot.json +7454 -0
  769. package/template/packages/database/drizzle/meta/0029_snapshot.json +7460 -0
  770. package/template/packages/database/drizzle/meta/0030_snapshot.json +7473 -0
  771. package/template/packages/database/drizzle/meta/_journal.json +223 -0
  772. package/template/packages/database/index.ts +5 -0
  773. package/template/packages/database/package.json +17 -0
  774. package/template/packages/database/src/dialects.test.ts +33 -0
  775. package/template/packages/database/src/dialects.ts +139 -0
  776. package/template/packages/database/src/runner.test.ts +96 -0
  777. package/template/packages/database/src/runner.ts +175 -0
  778. package/template/packages/database/src/schema/bulk-data.ts +87 -0
  779. package/template/packages/database/src/schema/common.ts +33 -0
  780. package/template/packages/database/src/schema/durable-jobs.ts +266 -0
  781. package/template/packages/database/src/schema/file-storage.ts +94 -0
  782. package/template/packages/database/src/schema/governance.ts +195 -0
  783. package/template/packages/database/src/schema/governed-exports.ts +90 -0
  784. package/template/packages/database/src/schema/identity.ts +169 -0
  785. package/template/packages/database/src/schema/index.ts +33 -0
  786. package/template/packages/database/src/schema/license-legacy.ts +93 -0
  787. package/template/packages/database/src/schema/license-v1.ts +246 -0
  788. package/template/packages/database/src/schema/migration-history.ts +30 -0
  789. package/template/packages/database/src/schema/notifications.ts +60 -0
  790. package/template/packages/database/src/schema/platform-settings.ts +55 -0
  791. package/template/packages/database/src/schema/scheduler.ts +89 -0
  792. package/template/packages/database/src/schema/work-orders.ts +23 -0
  793. package/template/packages/database/src/schema/workflow.ts +86 -0
  794. package/template/packages/database/src/schema-durable-links.test.ts +27 -0
  795. package/template/packages/database/src/schema-governed-exports.test.ts +49 -0
  796. package/template/packages/database/src/schema-workflow-notification.test.ts +63 -0
  797. package/template/packages/database/src/schema.test.ts +343 -0
  798. package/template/packages/database/src/sql-store.test.ts +92 -0
  799. package/template/packages/database/src/sql-store.ts +101 -0
  800. package/template/packages/database/src/store.ts +32 -0
  801. package/template/packages/database/tsconfig.json +17 -0
  802. package/template/packages/example-work-order/index.ts +3 -0
  803. package/template/packages/example-work-order/package.json +13 -0
  804. package/template/packages/example-work-order/src/contract.ts +50 -0
  805. package/template/packages/example-work-order/src/manifest.test.ts +54 -0
  806. package/template/packages/example-work-order/src/manifest.ts +120 -0
  807. package/template/packages/example-work-order/src/schema.ts +27 -0
  808. package/template/packages/license-sdk/index.ts +13 -0
  809. package/template/packages/license-sdk/package.json +18 -0
  810. package/template/packages/license-sdk/src/bounded-json-body.test.ts +65 -0
  811. package/template/packages/license-sdk/src/bounded-json-body.ts +135 -0
  812. package/template/packages/license-sdk/src/canonical-json.test.ts +28 -0
  813. package/template/packages/license-sdk/src/canonical-json.ts +104 -0
  814. package/template/packages/license-sdk/src/client.test.ts +82 -0
  815. package/template/packages/license-sdk/src/client.ts +86 -0
  816. package/template/packages/license-sdk/src/device.ts +46 -0
  817. package/template/packages/license-sdk/src/file-storage.test.ts +80 -0
  818. package/template/packages/license-sdk/src/file-storage.ts +77 -0
  819. package/template/packages/license-sdk/src/installation.test.ts +241 -0
  820. package/template/packages/license-sdk/src/installation.ts +150 -0
  821. package/template/packages/license-sdk/src/license-parser.ts +56 -0
  822. package/template/packages/license-sdk/src/offline-code-base32.ts +57 -0
  823. package/template/packages/license-sdk/src/offline-code-decompression.ts +55 -0
  824. package/template/packages/license-sdk/src/offline-code-limits.ts +10 -0
  825. package/template/packages/license-sdk/src/offline-code-wire.ts +72 -0
  826. package/template/packages/license-sdk/src/offline-code.test.ts +172 -0
  827. package/template/packages/license-sdk/src/offline-code.ts +319 -0
  828. package/template/packages/license-sdk/src/payload.test.ts +72 -0
  829. package/template/packages/license-sdk/src/payload.ts +201 -0
  830. package/template/packages/license-sdk/src/storage.ts +64 -0
  831. package/template/packages/license-sdk/src/test-fixtures.ts +59 -0
  832. package/template/packages/license-sdk/src/v1-test-vector.ts +49 -0
  833. package/template/packages/license-sdk/src/validation.test.ts +62 -0
  834. package/template/packages/license-sdk/src/validation.ts +143 -0
  835. package/template/packages/license-sdk/src/verification.test.ts +97 -0
  836. package/template/packages/license-sdk/src/verification.ts +199 -0
  837. package/template/packages/license-sdk/tsconfig.json +17 -0
  838. package/template/packages/modules/index.ts +8 -0
  839. package/template/packages/modules/package.json +13 -0
  840. package/template/packages/modules/src/composition.test.ts +267 -0
  841. package/template/packages/modules/src/composition.ts +342 -0
  842. package/template/packages/modules/src/installed-business-modules.ts +10 -0
  843. package/template/packages/modules/src/manifest.ts +97 -0
  844. package/template/packages/modules/src/menu-composition.test.ts +64 -0
  845. package/template/packages/modules/src/menu-composition.ts +54 -0
  846. package/template/packages/modules/src/registry.ts +53 -0
  847. package/template/packages/modules/src/system-admin-routes.ts +134 -0
  848. package/template/packages/modules/src/system-agent-tools.ts +28 -0
  849. package/template/packages/modules/src/system-api-binding.ts +37 -0
  850. package/template/packages/modules/src/system-api-data-governance.ts +21 -0
  851. package/template/packages/modules/src/system-api-permissions.ts +344 -0
  852. package/template/packages/modules/src/system-audit-actions.ts +70 -0
  853. package/template/packages/modules/src/system-data-governance.ts +30 -0
  854. package/template/packages/modules/src/system-features.ts +143 -0
  855. package/template/packages/modules/src/system-governed-export-bindings.ts +31 -0
  856. package/template/packages/modules/src/system-module-catalog.test.ts +145 -0
  857. package/template/packages/modules/src/system-module-catalog.ts +250 -0
  858. package/template/packages/modules/src/system-modules.test.ts +344 -0
  859. package/template/packages/modules/src/system-modules.ts +335 -0
  860. package/template/packages/modules/src/system-permissions.ts +142 -0
  861. package/template/packages/modules/user/module.ts +72 -0
  862. package/template/packages/shared/index.ts +16 -0
  863. package/template/packages/shared/package.json +9 -0
  864. package/template/packages/shared/src/audit.test.ts +17 -0
  865. package/template/packages/shared/src/audit.ts +237 -0
  866. package/template/packages/shared/src/correlation.test.ts +10 -0
  867. package/template/packages/shared/src/correlation.ts +11 -0
  868. package/template/packages/shared/src/data-governance.test.ts +44 -0
  869. package/template/packages/shared/src/data-governance.ts +89 -0
  870. package/template/packages/shared/src/database.ts +67 -0
  871. package/template/packages/shared/src/feature.test.ts +54 -0
  872. package/template/packages/shared/src/feature.ts +104 -0
  873. package/template/packages/shared/src/license-legacy.ts +153 -0
  874. package/template/packages/shared/src/license.test.ts +63 -0
  875. package/template/packages/shared/src/license.ts +267 -0
  876. package/template/packages/shared/src/module-configuration.ts +50 -0
  877. package/template/packages/shared/src/notification.ts +46 -0
  878. package/template/packages/shared/src/platform-settings.ts +5 -0
  879. package/template/packages/shared/src/primitives.ts +47 -0
  880. package/template/packages/shared/src/profile.ts +13 -0
  881. package/template/packages/shared/src/rbac.ts +117 -0
  882. package/template/packages/shared/src/ruoyi.ts +98 -0
  883. package/template/packages/shared/src/scheduler.ts +108 -0
  884. package/template/packages/shared/src/search-provider.ts +24 -0
  885. package/template/packages/shared/src/workflow.test.ts +225 -0
  886. package/template/packages/shared/src/workflow.ts +307 -0
  887. package/template/packages/storage/index.ts +11 -0
  888. package/template/packages/storage/package.json +12 -0
  889. package/template/packages/storage/src/blob-store.ts +64 -0
  890. package/template/packages/storage/src/content-hash.ts +24 -0
  891. package/template/packages/storage/src/file-service.test.ts +100 -0
  892. package/template/packages/storage/src/file-service.ts +59 -0
  893. package/template/packages/storage/src/in-memory-upload-repository.ts +154 -0
  894. package/template/packages/storage/src/local-file-blob-store.test.ts +175 -0
  895. package/template/packages/storage/src/local-file-blob-store.ts +344 -0
  896. package/template/packages/storage/src/local-file-maintenance.ts +133 -0
  897. package/template/packages/storage/src/memory-blob-store.test.ts +16 -0
  898. package/template/packages/storage/src/memory-blob-store.ts +100 -0
  899. package/template/packages/storage/src/upload-repository.ts +43 -0
  900. package/template/packages/storage/src/upload-service.test.ts +246 -0
  901. package/template/packages/storage/src/upload-service.ts +334 -0
  902. package/template/packages/storage/src/upload-streams.ts +123 -0
  903. package/template/packages/storage/src/upload-types.ts +110 -0
  904. package/template/packages/storage/tsconfig.json +16 -0
package/dist/cli.js ADDED
@@ -0,0 +1,1662 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/arguments.ts
4
+ import { resolve } from "node:path";
5
+
6
+ // src/profile.ts
7
+ var starterProfile = {
8
+ key: "private-enterprise",
9
+ label: "私有部署企业版",
10
+ isolation: "single-organization-single-tenant",
11
+ database: "postgresql",
12
+ includesLicenseAuthority: false
13
+ };
14
+ var projectLicenseKeys = ["UNLICENSED", "MIT", "Apache-2.0"];
15
+
16
+ // src/optional-module-distribution.ts
17
+ var optionalModuleManifests = [
18
+ {
19
+ ...module("system.storage", "文件存储", "上传、下载和对象生命周期。", [
20
+ "system",
21
+ "system.settings"
22
+ ]),
23
+ packages: ["packages/storage"],
24
+ fileRoots: ["apps/server/src/storage"],
25
+ documentation: ["docs/architecture/object-storage.md"],
26
+ schemaFiles: ["packages/database/src/schema/file-storage.ts"],
27
+ databaseTables: [
28
+ "file_upload_sessions",
29
+ "file_upload_parts",
30
+ "file_metadata"
31
+ ]
32
+ },
33
+ {
34
+ ...module("system.agent", "Agent Tool", "受控 Agent 工具宿主。", [
35
+ "system",
36
+ "system.audit"
37
+ ]),
38
+ fileRoots: [
39
+ "apps/server/src/agent",
40
+ "packages/modules/src/system-agent-tools.ts"
41
+ ],
42
+ documentation: ["docs/platform/agent-tools.md"]
43
+ },
44
+ {
45
+ ...module("system.scheduler", "任务调度", "任务、重试、历史和恢复。", [
46
+ "system",
47
+ "system.audit"
48
+ ]),
49
+ fileRoots: [
50
+ "apps/server/src/scheduler",
51
+ "apps/server/src/jobs",
52
+ "apps/server/src/application-services.ts",
53
+ "apps/web/src/pages/system/components/SchedulerOperationsPanel.vue",
54
+ "apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts",
55
+ "apps/web/src/pages/system/components/SchedulerRunTable.vue",
56
+ "apps/web/src/pages/system/components/SchedulerRunTable.webtest.ts",
57
+ "apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.vue",
58
+ "apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.webtest.ts",
59
+ "apps/web/src/pages/system/composables/useSchedulerOperations.ts",
60
+ "apps/web/src/pages/system/composables/useSchedulerOperations.webtest.ts"
61
+ ],
62
+ documentation: [
63
+ "docs/architecture/durable-jobs.md",
64
+ "docs/platform/scheduled-task-executor.md"
65
+ ],
66
+ schemaFiles: [
67
+ "packages/database/src/schema/durable-jobs.ts",
68
+ "packages/database/src/schema/scheduler.ts"
69
+ ],
70
+ databaseTables: [
71
+ "durable_jobs",
72
+ "durable_job_stages",
73
+ "durable_job_attempts",
74
+ "durable_job_leases",
75
+ "durable_job_progress",
76
+ "durable_job_artifacts",
77
+ "durable_job_failures",
78
+ "durable_job_recoveries",
79
+ "scheduled_tasks",
80
+ "scheduled_task_runs"
81
+ ]
82
+ },
83
+ {
84
+ ...module("system.notification", "站内通知", "通知发布、阅读和归档。", [
85
+ "system",
86
+ "system.identity"
87
+ ]),
88
+ fileRoots: [
89
+ "apps/server/src/notification",
90
+ "apps/web/src/layout/NotificationMenu.vue",
91
+ "apps/web/src/layout/NotificationMenu.webtest.ts",
92
+ "apps/web/src/pages/system/SystemNotificationsPage.vue",
93
+ "apps/web/src/pages/system/SystemNotificationsPage.webtest.ts",
94
+ "apps/web/src/pages/system/components/NotificationPublishForm.vue"
95
+ ],
96
+ documentation: ["docs/platform/notifications.md"],
97
+ schemaFiles: ["packages/database/src/schema/notifications.ts"],
98
+ databaseTables: ["platform_notifications", "notification_reads"]
99
+ },
100
+ {
101
+ ...module("system.workflow", "审批工作流", "审批、转交、超时和补偿。", [
102
+ "system",
103
+ "system.identity",
104
+ "system.notification",
105
+ "system.scheduler"
106
+ ]),
107
+ fileRoots: [
108
+ "apps/server/src/workflow",
109
+ "packages/database/src/schema-workflow-notification.test.ts"
110
+ ],
111
+ documentation: ["docs/architecture/minimal-approval-workflow.md"],
112
+ schemaFiles: ["packages/database/src/schema/workflow.ts"],
113
+ databaseTables: ["workflow_work_items", "workflow_transitions"]
114
+ },
115
+ {
116
+ ...module("system.bulk-data", "批量数据", "批量导入导出与结果留存。", [
117
+ "system",
118
+ "system.storage",
119
+ "system.scheduler"
120
+ ]),
121
+ fileRoots: [
122
+ "apps/server/src/bulk-data",
123
+ "apps/web/src/pages/system/components/dictionary-bulk",
124
+ "apps/web/src/pages/system/composables/useDictionaryBulkJobs.ts",
125
+ "apps/web/src/pages/system/dictionary-bulk-presenter.ts",
126
+ "apps/web/src/services/bulk-data-api.ts",
127
+ "packages/database/src/schema-durable-links.test.ts"
128
+ ],
129
+ documentation: ["docs/platform/bulk-data-jobs.md"],
130
+ schemaFiles: ["packages/database/src/schema/bulk-data.ts"],
131
+ databaseTables: ["bulk_data_jobs", "bulk_data_artifacts"]
132
+ },
133
+ {
134
+ ...module("system.search", "平台搜索", "权限感知搜索与 Provider 聚合。", [
135
+ "system"
136
+ ]),
137
+ fileRoots: [
138
+ "apps/server/src/search",
139
+ "apps/web/src/layout/NavigationSearchDialog.vue",
140
+ "apps/web/src/layout/NavigationSearchDialog.webtest.ts"
141
+ ],
142
+ documentation: ["docs/architecture/search-provider-protocol.md"]
143
+ },
144
+ {
145
+ ...module("system.data-governance", "数据治理", "敏感字段、明文访问和治理导出。", [
146
+ "system",
147
+ "system.identity",
148
+ "system.audit",
149
+ "system.storage",
150
+ "system.workflow",
151
+ "system.scheduler"
152
+ ]),
153
+ fileRoots: [
154
+ "apps/server/src/data-governance",
155
+ "packages/modules/src/system-api-data-governance.ts",
156
+ "packages/modules/src/system-data-governance.ts",
157
+ "packages/modules/src/system-governed-export-bindings.ts",
158
+ "packages/database/src/schema-governed-exports.test.ts"
159
+ ],
160
+ documentation: ["docs/architecture/sensitive-data-governance.md"],
161
+ schemaFiles: ["packages/database/src/schema/governed-exports.ts"],
162
+ databaseTables: ["governed_export_requests"]
163
+ },
164
+ {
165
+ ...module("work-order", "示例工单", "可替换的业务模块接入示例。", [
166
+ "system",
167
+ "system.identity",
168
+ "system.search",
169
+ "system.scheduler"
170
+ ]),
171
+ packages: ["packages/example-work-order"],
172
+ fileRoots: [
173
+ "apps/server/src/work-order",
174
+ "apps/server/src/example-modules.ts",
175
+ "apps/server/src/example-permissions.ts"
176
+ ],
177
+ documentation: ["docs/development/example-work-order.md"],
178
+ schemaFiles: ["packages/database/src/schema/work-orders.ts"],
179
+ databaseTables: ["work_orders"]
180
+ }
181
+ ];
182
+ function module(name, label, description, dependencies) {
183
+ const selection = "optional";
184
+ return {
185
+ name,
186
+ version: "0.1.0",
187
+ label,
188
+ description,
189
+ selection,
190
+ dependencies,
191
+ conflicts: [],
192
+ packages: [],
193
+ fileRoots: [],
194
+ documentation: [],
195
+ schemaFiles: [],
196
+ databaseTables: [],
197
+ transientDatabaseTables: [],
198
+ databaseStatementTokens: [],
199
+ uninstallPolicy: "retain-data"
200
+ };
201
+ }
202
+
203
+ // src/module-distribution.ts
204
+ var requiredModuleNames = ["system", "system.identity"];
205
+ var recommendedModuleNames = [
206
+ "system.settings",
207
+ "system.configuration",
208
+ "system.audit",
209
+ "system.operations"
210
+ ];
211
+ var platformModules = [
212
+ module2("system", "系统核心", "Admin 准入、Feature 与数据库基线。", "required"),
213
+ module2("system.identity", "身份与权限", "认证、用户、角色、组织和数据范围。", "required", ["system"]),
214
+ {
215
+ ...module2("system.settings", "平台设置", "品牌、Logo 与水印。", "recommended", ["system"]),
216
+ fileRoots: [
217
+ "apps/server/src/settings",
218
+ "apps/web/src/pages/settings",
219
+ "apps/web/src/layout/GlobalWatermark.vue",
220
+ "apps/web/src/services/platform-settings-api.ts",
221
+ "apps/web/src/composables/useWatermarkSettings.ts",
222
+ "apps/web/src/composables/watermark-settings.ts",
223
+ "apps/web/src/composables/watermark-settings.webtest.ts"
224
+ ],
225
+ documentation: ["docs/platform/platform-shell-settings.md"],
226
+ databaseTables: ["platform_branding_settings"]
227
+ },
228
+ {
229
+ ...module2("system.configuration", "配置版本", "类型化配置、应用和回滚。", "recommended", ["system"]),
230
+ fileRoots: [
231
+ "apps/server/src/configuration",
232
+ "apps/web/src/pages/configuration",
233
+ "apps/web/src/services/configuration-api.ts",
234
+ "apps/web/src/composables/useModuleConfigurations.ts"
235
+ ],
236
+ documentation: ["docs/platform/module-configuration.md"],
237
+ databaseTables: ["module_config_versions"],
238
+ databaseStatementTokens: [
239
+ "idx_module_config_versions_",
240
+ "uk_module_config_versions_"
241
+ ]
242
+ },
243
+ {
244
+ ...module2("system.license", "离线 License", "离线验签、安装和限制态。", "optional", ["system"]),
245
+ packages: ["packages/license-sdk"],
246
+ fileRoots: [
247
+ "apps/server/src/license",
248
+ "apps/web/src/components/license",
249
+ "apps/web/src/pages/license",
250
+ "apps/web/src/composables/useLicenseReminderRefresh.ts",
251
+ "apps/web/src/composables/useLicenseReminderRefresh.webtest.ts",
252
+ "apps/web/src/composables/useLicenseRuntime.ts",
253
+ "apps/web/src/services/license-api.ts",
254
+ "apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts",
255
+ "apps/web/src/router/index.webtest.ts"
256
+ ],
257
+ documentation: ["docs/license/license-offline-activation-code.md"],
258
+ schemaFiles: [
259
+ "packages/database/src/schema/license-legacy.ts",
260
+ "packages/database/src/schema/license-v1.ts"
261
+ ],
262
+ databaseTables: [
263
+ "license_operators",
264
+ "license_operator_sessions",
265
+ "license_keys",
266
+ "license_key_compatibilities",
267
+ "license_governance_events",
268
+ "license_customers",
269
+ "license_projects",
270
+ "license_versions",
271
+ "license_contract_versions",
272
+ "license_nodes",
273
+ "licenses",
274
+ "license_replacements",
275
+ "license_events",
276
+ "legacy_license_projects",
277
+ "legacy_license_issue_records",
278
+ "legacy_licenses"
279
+ ],
280
+ transientDatabaseTables: ["license_issue_records"],
281
+ databaseStatementTokens: [
282
+ "reject_license_immutable_mutation",
283
+ "idx_licenses_",
284
+ "idx_license_",
285
+ "uk_license_",
286
+ "legacy_license_"
287
+ ]
288
+ },
289
+ {
290
+ ...module2("system.audit", "审计日志", "审计查询、可靠写入和恢复。", "recommended", ["system"]),
291
+ fileRoots: [
292
+ "apps/server/src/audit/drizzle-log-store.ts",
293
+ "apps/server/src/audit/recovery-queue.ts",
294
+ "apps/server/src/audit/recovery-queue.test.ts",
295
+ "apps/server/src/audit/reliable-writer.ts",
296
+ "apps/server/src/audit/reliable-writer.test.ts",
297
+ "apps/server/src/persistence.integration.test.ts",
298
+ "apps/server/src/system/audit-routes.ts",
299
+ "apps/server/src/system/audit-routes.test.ts",
300
+ "apps/web/src/pages/system/components/AuditActionCell.vue",
301
+ "apps/web/src/pages/system/components/AuditActionCell.webtest.ts",
302
+ "apps/web/src/pages/system/components/AuditLogFilters.vue",
303
+ "apps/web/src/pages/system/components/AuditLogFilters.webtest.ts"
304
+ ],
305
+ documentation: ["docs/platform/audit-reliability.md"],
306
+ databaseTables: ["audit_logs"],
307
+ databaseStatementTokens: ["idx_audit_logs_"]
308
+ },
309
+ {
310
+ ...module2("system.operations", "运维监控", "服务、数据库、缓存、磁盘和会话监控。", "recommended", ["system", "system.configuration"]),
311
+ fileRoots: [
312
+ "apps/server/src/system/operation-monitoring.ts",
313
+ "apps/server/src/system/operation-monitoring.test.ts",
314
+ "apps/server/src/system/operations.ts",
315
+ "apps/server/src/system/operations.test.ts",
316
+ "apps/server/src/system/postgres-monitoring.ts",
317
+ "apps/web/src/pages/system/SystemOperationsPage.vue",
318
+ "apps/web/src/pages/system/SystemOperationsPage.webtest.ts",
319
+ "apps/web/src/pages/system/components/OperationCacheMonitor.vue",
320
+ "apps/web/src/pages/system/components/DiskUsageChart.vue",
321
+ "apps/web/src/pages/system/components/OperationOnlineUsers.vue",
322
+ "apps/web/src/pages/system/components/OperationOnlineUsers.webtest.ts",
323
+ "apps/web/src/pages/system/components/OperationServiceMonitor.vue",
324
+ "apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts",
325
+ "apps/web/src/services/operations-api.ts"
326
+ ],
327
+ documentation: ["docs/platform/operations-overview.md"]
328
+ },
329
+ ...optionalModuleManifests
330
+ ];
331
+ var moduleDistributionCatalog = validateCatalog(platformModules);
332
+ function resolveModuleSelection(input = {}) {
333
+ const known = new Map(moduleDistributionCatalog.map((item) => [item.name, item]));
334
+ const selected = new Set(requiredModuleNames);
335
+ if (input.includeAll) {
336
+ for (const item of moduleDistributionCatalog)
337
+ selected.add(item.name);
338
+ } else if (input.includeRecommended !== false) {
339
+ for (const name of recommendedModuleNames)
340
+ selected.add(name);
341
+ }
342
+ for (const name of input.requested || []) {
343
+ if (!known.has(name))
344
+ throw new Error(`未知模块:${name}`);
345
+ selected.add(name);
346
+ }
347
+ let changed = true;
348
+ while (changed) {
349
+ changed = false;
350
+ for (const name of selected) {
351
+ const manifest = known.get(name);
352
+ if (!manifest)
353
+ throw new Error(`未知模块:${name}`);
354
+ for (const dependency of manifest.dependencies) {
355
+ if (selected.has(dependency))
356
+ continue;
357
+ selected.add(dependency);
358
+ changed = true;
359
+ }
360
+ }
361
+ }
362
+ for (const name of selected) {
363
+ const manifest = known.get(name);
364
+ for (const conflict of manifest?.conflicts || []) {
365
+ if (selected.has(conflict))
366
+ throw new Error(`模块冲突:${name} 与 ${conflict}`);
367
+ }
368
+ }
369
+ return moduleDistributionCatalog.filter(({ name }) => selected.has(name)).map(({ name }) => name);
370
+ }
371
+ function selectedModuleManifests(names) {
372
+ const selected = new Set(names);
373
+ const resolved = resolveModuleSelection({
374
+ requested: names,
375
+ includeRecommended: false
376
+ });
377
+ if (resolved.some((name) => !selected.has(name))) {
378
+ throw new Error("模块选择缺少依赖,请先通过 resolveModuleSelection 解析");
379
+ }
380
+ return moduleDistributionCatalog.filter(({ name }) => selected.has(name));
381
+ }
382
+ function module2(name, label, description, selection, dependencies = []) {
383
+ return {
384
+ name,
385
+ version: "0.1.0",
386
+ label,
387
+ description,
388
+ selection,
389
+ dependencies,
390
+ conflicts: [],
391
+ packages: [],
392
+ fileRoots: [],
393
+ documentation: [],
394
+ schemaFiles: [],
395
+ databaseTables: [],
396
+ transientDatabaseTables: [],
397
+ databaseStatementTokens: [],
398
+ uninstallPolicy: "retain-data"
399
+ };
400
+ }
401
+ function validateCatalog(manifests) {
402
+ const names = new Set;
403
+ for (const manifest of manifests) {
404
+ if (names.has(manifest.name))
405
+ throw new Error(`分发模块重复:${manifest.name}`);
406
+ names.add(manifest.name);
407
+ }
408
+ for (const manifest of manifests) {
409
+ for (const dependency of manifest.dependencies) {
410
+ if (!names.has(dependency))
411
+ throw new Error(`${manifest.name} 依赖未知模块:${dependency}`);
412
+ if (dependency === manifest.name)
413
+ throw new Error(`${manifest.name} 不能依赖自身`);
414
+ }
415
+ for (const conflict of manifest.conflicts) {
416
+ if (!names.has(conflict))
417
+ throw new Error(`${manifest.name} 冲突模块未知:${conflict}`);
418
+ }
419
+ }
420
+ return manifests;
421
+ }
422
+
423
+ // src/arguments.ts
424
+ function parseArguments(args) {
425
+ if (args.includes("--help") || args.includes("-h"))
426
+ return "help";
427
+ const projectName = readProjectName(args);
428
+ if (!projectName)
429
+ throw new Error("请提供项目名,例如:npx create-windy my-app");
430
+ const profile = readValue(args, "--profile") || starterProfile.key;
431
+ if (profile !== starterProfile.key) {
432
+ throw new Error(`当前只支持 ${starterProfile.key} profile`);
433
+ }
434
+ const requestedModules = readValues(args, "--module");
435
+ const includeAll = args.includes("--all-modules");
436
+ const noOptionalModules = args.includes("--no-optional-modules");
437
+ if (includeAll && noOptionalModules) {
438
+ throw new Error("--all-modules 不能与 --no-optional-modules 同时使用");
439
+ }
440
+ const projectLicense = readProjectLicense(args);
441
+ const selectedModules = resolveModuleSelection({
442
+ requested: requestedModules,
443
+ includeRecommended: !noOptionalModules,
444
+ includeAll
445
+ });
446
+ const explicitSelection = requestedModules.length > 0 || includeAll || noOptionalModules;
447
+ return {
448
+ projectName,
449
+ targetDirectory: resolve(process.cwd(), projectName),
450
+ profile,
451
+ install: !args.includes("--skip-install"),
452
+ verify: args.includes("--verify"),
453
+ keepOnError: args.includes("--keep-on-error"),
454
+ selectedModules,
455
+ includeExample: selectedModules.includes("work-order"),
456
+ includeOxc: !args.includes("--no-oxc"),
457
+ projectLicense,
458
+ licenseHolder: readValue(args, "--license-holder"),
459
+ interactive: !args.includes("--yes") && !explicitSelection,
460
+ initializeGit: !args.includes("--no-git")
461
+ };
462
+ }
463
+ function readProjectName(args) {
464
+ const flagsWithValues = new Set([
465
+ "--profile",
466
+ "--module",
467
+ "--license",
468
+ "--license-holder"
469
+ ]);
470
+ for (let index = 0;index < args.length; index += 1) {
471
+ const value = args[index];
472
+ if (!value)
473
+ continue;
474
+ if (flagsWithValues.has(value)) {
475
+ index += 1;
476
+ continue;
477
+ }
478
+ if (!value.startsWith("-"))
479
+ return value;
480
+ }
481
+ }
482
+ function readValue(args, flag) {
483
+ const index = args.indexOf(flag);
484
+ return index >= 0 ? args[index + 1] : undefined;
485
+ }
486
+ function readValues(args, flag) {
487
+ return args.flatMap((value, index) => value === flag && args[index + 1] ? [args[index + 1]] : []);
488
+ }
489
+ function readProjectLicense(args) {
490
+ const value = readValue(args, "--license") || "UNLICENSED";
491
+ if (!projectLicenseKeys.includes(value)) {
492
+ throw new Error(`不支持的项目许可证:${value}`);
493
+ }
494
+ return value;
495
+ }
496
+ var helpText = `create-windy <项目名> [选项]
497
+
498
+ 选项:
499
+ --profile private-enterprise 单组织、单租户、私有部署 profile
500
+ --skip-install 只生成文件,不执行 bun install
501
+ --verify 安装后执行 typecheck、test 和 build
502
+ --keep-on-error 失败时保留新生成目录用于诊断
503
+ --module <key> 增加模块,可重复使用
504
+ --all-modules 选择目录中的全部模块
505
+ --no-optional-modules 只生成 system 与 system.identity
506
+ --no-oxc 不引入 Oxlint、Oxfmt 及其配置和脚本
507
+ --license <SPDX> UNLICENSED、MIT 或 Apache-2.0
508
+ --license-holder <名称> MIT 许可证的权利人名称
509
+ --yes 接受默认选择,不进入交互问答
510
+ --no-git 不初始化 Git 仓库和创建首次提交
511
+ -h, --help 显示帮助
512
+ `;
513
+
514
+ // src/create-project.ts
515
+ import { mkdir as mkdir4, readdir as readdir4, rm as rm4 } from "node:fs/promises";
516
+
517
+ // src/commands.ts
518
+ import { spawn } from "node:child_process";
519
+
520
+ class CommandExecutionError extends Error {
521
+ constructor(command, args, exitCode, signal) {
522
+ const outcome = signal ? `信号 ${signal}` : `退出码 ${exitCode ?? "未知"}`;
523
+ super(`${command} ${args.join(" ")} 执行失败(${outcome})`);
524
+ this.name = "CommandExecutionError";
525
+ }
526
+ }
527
+ async function runCommand(command, args, cwd) {
528
+ await new Promise((resolve2, reject) => {
529
+ const child = spawn(command, args, { cwd, stdio: "inherit" });
530
+ child.once("error", reject);
531
+ child.once("exit", (code, signal) => {
532
+ if (code === 0)
533
+ resolve2();
534
+ else
535
+ reject(new CommandExecutionError(command, args, code, signal));
536
+ });
537
+ });
538
+ }
539
+ async function installAndVerify(targetDirectory, install, verify, execute = runCommand) {
540
+ if (install || verify)
541
+ await execute("bun", ["install"], targetDirectory);
542
+ if (!verify)
543
+ return;
544
+ await execute("bun", ["run", "typecheck"], targetDirectory);
545
+ await execute("bun", ["run", "test"], targetDirectory);
546
+ await execute("bun", ["run", "build"], targetDirectory);
547
+ }
548
+
549
+ // src/bun-runtime.ts
550
+ import { spawn as spawn2 } from "node:child_process";
551
+ var minimumBunVersion = "1.3.14";
552
+ async function assertSupportedBun(readVersion = readBunVersion) {
553
+ let version;
554
+ try {
555
+ version = (await readVersion()).trim();
556
+ } catch (error) {
557
+ if (isMissingCommand(error)) {
558
+ throw new Error(`未检测到 Bun。请先安装 Bun ${minimumBunVersion} 或更高版本,再重新运行 create-windy。`, { cause: error });
559
+ }
560
+ throw error;
561
+ }
562
+ const parsed = parseVersion(version);
563
+ if (!parsed || compareVersions(parsed, parseVersion(minimumBunVersion)) < 0) {
564
+ throw new Error(`当前 Bun 版本为 ${version || "未知"},create-windy 要求 Bun ${minimumBunVersion} 或更高版本。`);
565
+ }
566
+ return version;
567
+ }
568
+ async function readBunVersion() {
569
+ return await new Promise((resolve2, reject) => {
570
+ const child = spawn2("bun", ["--version"], {
571
+ stdio: ["ignore", "pipe", "pipe"]
572
+ });
573
+ let stdout = "";
574
+ let stderr = "";
575
+ child.stdout.setEncoding("utf8");
576
+ child.stderr.setEncoding("utf8");
577
+ child.stdout.on("data", (chunk) => stdout += chunk);
578
+ child.stderr.on("data", (chunk) => stderr += chunk);
579
+ child.once("error", reject);
580
+ child.once("close", (code, signal) => {
581
+ if (code === 0)
582
+ resolve2(stdout);
583
+ else {
584
+ const outcome = signal ? `信号 ${signal}` : `退出码 ${code ?? "未知"}`;
585
+ reject(new Error(`bun --version 执行失败(${outcome}):${stderr.trim()}`));
586
+ }
587
+ });
588
+ });
589
+ }
590
+ function parseVersion(version) {
591
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version);
592
+ if (!match)
593
+ return;
594
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
595
+ }
596
+ function compareVersions(left, right) {
597
+ for (let index = 0;index < left.length; index += 1) {
598
+ const difference = left[index] - right[index];
599
+ if (difference !== 0)
600
+ return difference;
601
+ }
602
+ return 0;
603
+ }
604
+ function isMissingCommand(error) {
605
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
606
+ }
607
+
608
+ // src/git.ts
609
+ async function initializeGitRepository(targetDirectory, execute = runCommand) {
610
+ try {
611
+ await execute("git", ["init", "-b", "main"], targetDirectory);
612
+ } catch (error) {
613
+ return {
614
+ status: "skipped",
615
+ warning: `未能初始化 Git 仓库,项目文件已保留。${recoveryHint(error)}`
616
+ };
617
+ }
618
+ try {
619
+ await execute("git", ["add", "--all"], targetDirectory);
620
+ } catch (error) {
621
+ return {
622
+ status: "skipped",
623
+ warning: `Git 仓库已初始化,但文件暂未加入暂存区。${recoveryHint(error)}`
624
+ };
625
+ }
626
+ try {
627
+ await execute("git", ["commit", "-m", "chore: initialize project"], targetDirectory);
628
+ } catch (error) {
629
+ return {
630
+ status: "skipped",
631
+ warning: "Git 仓库已初始化且文件已暂存,但首次提交未完成。请配置 Git 用户身份后运行 git commit。" + compactReason(error)
632
+ };
633
+ }
634
+ return { status: "committed" };
635
+ }
636
+ function recoveryHint(error) {
637
+ return `请确认已安装 Git 后手动运行 git init。${compactReason(error)}`;
638
+ }
639
+ function compactReason(error) {
640
+ const message = error instanceof Error ? error.message : String(error);
641
+ return message ? `(原因:${message})` : "";
642
+ }
643
+
644
+ // src/generator.ts
645
+ import {
646
+ copyFile,
647
+ lstat as lstat3,
648
+ mkdir as mkdir3,
649
+ readFile as readFile7,
650
+ readdir as readdir3,
651
+ rm as rm3,
652
+ writeFile as writeFile7
653
+ } from "node:fs/promises";
654
+ import { basename as basename2, extname as extname2, join as join7 } from "node:path";
655
+
656
+ // src/customer-docker.ts
657
+ import { readFile, writeFile } from "node:fs/promises";
658
+ import { join } from "node:path";
659
+ var supplierWorkspaceCopies = [
660
+ "COPY apps/license/package.json apps/license/package.json",
661
+ "COPY apps/signing-service/package.json apps/signing-service/package.json",
662
+ "COPY packages/create-windy/package.json packages/create-windy/package.json"
663
+ ];
664
+ async function prepareCustomerDockerfiles(root) {
665
+ await Promise.all(["apps/server/Dockerfile", "apps/web/Dockerfile"].map(async (path) => {
666
+ const absolutePath = join(root, path);
667
+ const source = await readFile(absolutePath, "utf8");
668
+ await writeFile(absolutePath, rewriteCustomerDockerfile(source));
669
+ }));
670
+ }
671
+ function rewriteCustomerDockerfile(source) {
672
+ const lines = source.split(`
673
+ `).filter((line) => {
674
+ return !supplierWorkspaceCopies.includes(line) && !line.includes("deploy/production/server-entrypoint.sh");
675
+ });
676
+ return lines.join(`
677
+ `).replace("COPY package.json bun.lock ./", "COPY package.json ./").replace("RUN bun install --frozen-lockfile", "RUN bun install");
678
+ }
679
+
680
+ // src/code-quality.ts
681
+ import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
682
+ import { join as join2 } from "node:path";
683
+ var oxcStarterPolicy = [
684
+ "- 代码检查与格式化统一使用 Oxc:Oxlint 和 Oxfmt,不使用 ESLint 或 Prettier。",
685
+ "- Oxc 是 Starter 默认提供的代码质量方案;项目生成后由项目所有者决定是否保留、替换或并行使用其它工具。"
686
+ ].join(`
687
+ `);
688
+ var noCodeQualityPolicy = "- 本项目生成时未引入 lint 或 format 工具;项目所有者可按团队需要自行选择。";
689
+ async function reflectCodeQualityChoice(targetDirectory, includeOxc) {
690
+ const path = join2(targetDirectory, "AGENTS.md");
691
+ const source = await readFile2(path, "utf8");
692
+ if (includeOxc)
693
+ return;
694
+ if (!source.includes(oxcStarterPolicy)) {
695
+ throw new Error("无法同步 --no-oxc 的项目开发约束");
696
+ }
697
+ await writeFile2(path, source.replace(oxcStarterPolicy, noCodeQualityPolicy));
698
+ }
699
+
700
+ // src/license-files.ts
701
+ import { mkdir, readFile as readFile3, rm, writeFile as writeFile3 } from "node:fs/promises";
702
+ import { dirname, join as join3, resolve as resolve2 } from "node:path";
703
+ import { fileURLToPath } from "node:url";
704
+ var packageRoot = resolve2(dirname(fileURLToPath(import.meta.url)), "..");
705
+ var apacheLicensePath = resolve2(packageRoot, "assets/LICENSE-Apache-2.0.txt");
706
+ async function applyProjectLicense(targetDirectory, license, holder, year = new Date().getFullYear()) {
707
+ const target = join3(targetDirectory, "LICENSE");
708
+ if (license === "UNLICENSED") {
709
+ await rm(target, { force: true });
710
+ return;
711
+ }
712
+ if (license === "MIT") {
713
+ const owner = holder?.trim();
714
+ if (!owner)
715
+ throw new Error("选择 MIT 时必须填写许可证权利人名称");
716
+ await mkdir(targetDirectory, { recursive: true });
717
+ await writeFile3(target, mitLicense(year, owner));
718
+ return;
719
+ }
720
+ await mkdir(targetDirectory, { recursive: true });
721
+ await writeFile3(target, await readFile3(apacheLicensePath));
722
+ }
723
+ function mitLicense(year, holder) {
724
+ return `MIT License
725
+
726
+ Copyright (c) ${year} ${holder}
727
+
728
+ Permission is hereby granted, free of charge, to any person obtaining a copy
729
+ of this software and associated documentation files (the "Software"), to deal
730
+ in the Software without restriction, including without limitation the rights
731
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
732
+ copies of the Software, and to permit persons to whom the Software is
733
+ furnished to do so, subject to the following conditions:
734
+
735
+ The above copyright notice and this permission notice shall be included in all
736
+ copies or substantial portions of the Software.
737
+
738
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
739
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
740
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
741
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
742
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
743
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
744
+ SOFTWARE.
745
+ `;
746
+ }
747
+
748
+ // src/managed-files.ts
749
+ import { createHash } from "node:crypto";
750
+ import { lstat, readdir, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
751
+ import { join as join4, relative, sep } from "node:path";
752
+ var managedFilesManifestPath = ".windy/files.json";
753
+ var ignoredDirectoryNames = new Set([".git", "node_modules", "dist"]);
754
+ var ignoredFiles = new Set(["bun.lock", managedFilesManifestPath]);
755
+ var projectOwnedRoots = [
756
+ "apps/web/src/app",
757
+ "apps/server/src/work-order",
758
+ "packages/example-work-order"
759
+ ];
760
+ var sharedScaffoldRoots = [
761
+ "README.md",
762
+ "AGENTS.md",
763
+ ".env.example",
764
+ "docker-compose.yml",
765
+ "apps/web/src/layout",
766
+ "apps/web/src/router"
767
+ ];
768
+ async function writeManagedFilesManifest(targetDirectory, generatorVersion) {
769
+ const paths = await collectFiles(targetDirectory);
770
+ const files = await Promise.all(paths.map(async (path) => {
771
+ const content = await readFile4(join4(targetDirectory, path));
772
+ return {
773
+ path,
774
+ ownership: classifyOwnership(path),
775
+ hash: createHash("sha256").update(content).digest("hex")
776
+ };
777
+ }));
778
+ const manifest = {
779
+ schemaVersion: 1,
780
+ generatorVersion,
781
+ algorithm: "sha256",
782
+ files
783
+ };
784
+ await writeFile4(join4(targetDirectory, managedFilesManifestPath), `${JSON.stringify(manifest, null, 2)}
785
+ `);
786
+ }
787
+ function classifyOwnership(path) {
788
+ if (matchesRoot(path, projectOwnedRoots))
789
+ return "project-owned";
790
+ if (matchesRoot(path, sharedScaffoldRoots))
791
+ return "shared-scaffold";
792
+ return "windy-managed";
793
+ }
794
+ async function collectFiles(root) {
795
+ const files = [];
796
+ await visit(root, files);
797
+ return files.sort();
798
+ async function visit(directory, output) {
799
+ for (const name of (await readdir(directory)).sort()) {
800
+ if (ignoredDirectoryNames.has(name))
801
+ continue;
802
+ const path = join4(directory, name);
803
+ const metadata = await lstat(path);
804
+ if (metadata.isSymbolicLink())
805
+ continue;
806
+ if (metadata.isDirectory()) {
807
+ await visit(path, output);
808
+ continue;
809
+ }
810
+ const relativePath = relative(root, path).split(sep).join("/");
811
+ if (!ignoredFiles.has(relativePath))
812
+ output.push(relativePath);
813
+ }
814
+ }
815
+ }
816
+ function matchesRoot(path, roots) {
817
+ return roots.some((root) => path === root || path.startsWith(`${root}/`));
818
+ }
819
+
820
+ // src/module-materializer.ts
821
+ import { lstat as lstat2, readFile as readFile5, readdir as readdir2, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
822
+ import { basename, extname, join as join5, relative as relative2, sep as sep2 } from "node:path";
823
+ var textExtensions = new Set([
824
+ ".css",
825
+ ".html",
826
+ ".json",
827
+ ".md",
828
+ ".mjs",
829
+ ".sql",
830
+ ".ts",
831
+ ".vue",
832
+ ".yaml",
833
+ ".yml"
834
+ ]);
835
+ async function materializeSelectedModules(targetDirectory, selectedNames) {
836
+ selectedModuleManifests(selectedNames);
837
+ const selected = new Set(selectedNames);
838
+ const removed = moduleDistributionCatalog.filter(({ name }) => !selected.has(name));
839
+ const removedPackageNames = await readRemovedPackageNames(targetDirectory, removed.flatMap(({ packages }) => packages));
840
+ await stripModuleBlocks(targetDirectory, selected);
841
+ await pruneDatabaseArtifacts(targetDirectory, removed.flatMap(({ databaseTables, transientDatabaseTables }) => [
842
+ ...databaseTables,
843
+ ...transientDatabaseTables
844
+ ]), removed.flatMap(({ databaseStatementTokens }) => databaseStatementTokens));
845
+ const removedRoots = removed.flatMap((manifest) => [
846
+ ...manifest.packages,
847
+ ...manifest.fileRoots,
848
+ ...manifest.documentation,
849
+ ...manifest.schemaFiles
850
+ ]);
851
+ await Promise.all([...new Set(removedRoots)].map((path) => rm2(join5(targetDirectory, path), { recursive: true, force: true })));
852
+ await pruneWorkspaceReferences(targetDirectory, removedPackageNames, removedRoots);
853
+ }
854
+ async function stripModuleBlocks(root, selected) {
855
+ for (const path of await collectFiles2(root)) {
856
+ if (!textExtensions.has(extname(path)))
857
+ continue;
858
+ const source = await readFile5(path, "utf8");
859
+ if (!source.includes("@windy-module"))
860
+ continue;
861
+ const output = stripTaggedSource(source, selected, relativePath(root, path));
862
+ await writeFile5(path, output);
863
+ }
864
+ }
865
+ function stripTaggedSource(source, selected, path = "source") {
866
+ const stack = [];
867
+ const output = [];
868
+ for (const line of source.split(`
869
+ `)) {
870
+ const marker = line.match(/@windy-module\s+([a-z0-9.-]+)\s+(begin|end)/);
871
+ if (marker?.[2] === "begin") {
872
+ const name = marker[1];
873
+ stack.push({ name, keep: selected.has(name) });
874
+ continue;
875
+ }
876
+ if (marker?.[2] === "end") {
877
+ const current = stack.pop();
878
+ if (!current || current.name !== marker[1]) {
879
+ throw new Error(`${path} 的模块组合标记不成对`);
880
+ }
881
+ continue;
882
+ }
883
+ if (stack.every(({ keep }) => keep))
884
+ output.push(line);
885
+ }
886
+ if (stack.length)
887
+ throw new Error(`${path} 的模块组合标记未闭合`);
888
+ return output.join(`
889
+ `);
890
+ }
891
+ async function readRemovedPackageNames(root, roots) {
892
+ const names = new Set;
893
+ for (const packageRoot2 of roots) {
894
+ try {
895
+ const value = JSON.parse(await readFile5(join5(root, packageRoot2, "package.json"), "utf8"));
896
+ if (value.name)
897
+ names.add(value.name);
898
+ } catch (error) {
899
+ if (!isMissing(error))
900
+ throw error;
901
+ }
902
+ }
903
+ return names;
904
+ }
905
+ async function pruneWorkspaceReferences(root, removedPackages, removedRoots) {
906
+ for (const path of await collectFiles2(root)) {
907
+ if (basename(path) === "package.json") {
908
+ const value = JSON.parse(await readFile5(path, "utf8"));
909
+ let changed = false;
910
+ for (const section of ["dependencies", "devDependencies"]) {
911
+ const dependencies = value[section];
912
+ for (const name of removedPackages) {
913
+ if (!dependencies?.[name])
914
+ continue;
915
+ delete dependencies[name];
916
+ changed = true;
917
+ }
918
+ }
919
+ if (changed)
920
+ await writeFile5(path, `${JSON.stringify(value, null, 2)}
921
+ `);
922
+ continue;
923
+ }
924
+ if (basename(path) !== "Dockerfile")
925
+ continue;
926
+ const source = await readFile5(path, "utf8");
927
+ const output = source.split(`
928
+ `).filter((line) => !removedRoots.some((root2) => line.includes(root2))).join(`
929
+ `);
930
+ if (output !== source)
931
+ await writeFile5(path, output);
932
+ }
933
+ }
934
+ async function pruneDatabaseArtifacts(root, tableNames, statementTokens) {
935
+ if (!tableNames.length && !statementTokens.length)
936
+ return;
937
+ const tablePatterns = tableNames.map((name) => new RegExp(`(?:"${escapeRegExp(name)}"|\\b${escapeRegExp(name)}\\b)`));
938
+ const drizzleRoot = join5(root, "packages/database/drizzle");
939
+ try {
940
+ for (const path of await collectFiles2(drizzleRoot)) {
941
+ if (path.endsWith(".sql")) {
942
+ const source = await readFile5(path, "utf8");
943
+ const statements = source.split("--> statement-breakpoint").map((statement) => statement.trim()).filter(Boolean).filter((statement) => !tablePatterns.some((pattern) => pattern.test(statement)) && !statementTokens.some((token) => statement.includes(token)));
944
+ await writeFile5(path, statements.length ? `${statements.join(`
945
+ --> statement-breakpoint
946
+ `)}
947
+ ` : `-- 此 migration 的模块未被当前项目选择。
948
+ `);
949
+ } else if (path.endsWith("_snapshot.json")) {
950
+ const snapshot = JSON.parse(await readFile5(path, "utf8"));
951
+ for (const name of tableNames)
952
+ delete snapshot.tables?.[`public.${name}`];
953
+ await writeFile5(path, `${JSON.stringify(snapshot, null, 2)}
954
+ `);
955
+ }
956
+ }
957
+ } catch (error) {
958
+ if (!isMissing(error))
959
+ throw error;
960
+ }
961
+ }
962
+ async function collectFiles2(root) {
963
+ const files = [];
964
+ await visit(root);
965
+ return files.sort();
966
+ async function visit(directory) {
967
+ for (const name of (await readdir2(directory)).sort()) {
968
+ if ([".git", "node_modules", "dist"].includes(name))
969
+ continue;
970
+ const path = join5(directory, name);
971
+ const metadata = await lstat2(path);
972
+ if (metadata.isSymbolicLink())
973
+ continue;
974
+ if (metadata.isDirectory())
975
+ await visit(path);
976
+ else
977
+ files.push(path);
978
+ }
979
+ }
980
+ }
981
+ function relativePath(root, path) {
982
+ return relative2(root, path).split(sep2).join("/");
983
+ }
984
+ function escapeRegExp(value) {
985
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
986
+ }
987
+ function isMissing(error) {
988
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
989
+ }
990
+
991
+ // src/project-files.ts
992
+ var starterCompose = `services:
993
+ postgres:
994
+ image: postgres:17-alpine
995
+ environment:
996
+ POSTGRES_DB: windy
997
+ POSTGRES_USER: windy
998
+ POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:?请在 .env 中设置 POSTGRES_PASSWORD}
999
+ ports:
1000
+ - "5432:5432"
1001
+ volumes:
1002
+ - postgres-data:/var/lib/postgresql/data
1003
+ healthcheck:
1004
+ test: ["CMD-SHELL", "pg_isready -U windy -d windy"]
1005
+ interval: 10s
1006
+ timeout: 5s
1007
+ retries: 5
1008
+
1009
+ migrate:
1010
+ build:
1011
+ context: .
1012
+ dockerfile: apps/server/Dockerfile
1013
+ command: ["bun", "run", "db:migrate"]
1014
+ environment:
1015
+ DATABASE_URL: postgresql://windy:\${POSTGRES_PASSWORD}@postgres:5432/windy
1016
+ volumes:
1017
+ - ./packages:/app/packages
1018
+ depends_on:
1019
+ postgres:
1020
+ condition: service_healthy
1021
+
1022
+ server:
1023
+ build:
1024
+ context: .
1025
+ dockerfile: apps/server/Dockerfile
1026
+ command: ["bun", "run", "--cwd", "apps/server", "dev"]
1027
+ environment:
1028
+ NODE_ENV: development
1029
+ PORT: 3000
1030
+ DATABASE_URL: postgresql://windy:\${POSTGRES_PASSWORD}@postgres:5432/windy
1031
+ WINDY_BOOTSTRAP_ADMIN_PASSWORD: \${WINDY_BOOTSTRAP_ADMIN_PASSWORD:?请在 .env 中设置管理员初始密码}
1032
+ WINDY_AUDIT_QUEUE_FILE: /app/data/audit/recovery-queue.json
1033
+ WINDY_CONTAINERIZED: "1"
1034
+ WINDY_SYSTEM_USAGE_PATHS: /app/data/audit
1035
+ ports:
1036
+ - "3000:3000"
1037
+ volumes:
1038
+ - ./apps/server:/app/apps/server
1039
+ - ./packages:/app/packages
1040
+ - server-audit-data:/app/data/audit
1041
+ depends_on:
1042
+ migrate:
1043
+ condition: service_completed_successfully
1044
+
1045
+ web:
1046
+ build:
1047
+ context: .
1048
+ dockerfile: apps/web/Dockerfile
1049
+ command: ["bun", "run", "--cwd", "apps/web", "dev"]
1050
+ environment:
1051
+ NODE_ENV: development
1052
+ WINDY_DEV_PORT: 9746
1053
+ API_UPSTREAM: http://server:3000
1054
+ VITE_DEV_HOST: 0.0.0.0
1055
+ ports:
1056
+ - "9746:9746"
1057
+ volumes:
1058
+ - ./apps/web:/app/apps/web
1059
+ - ./packages:/app/packages
1060
+ depends_on:
1061
+ - server
1062
+
1063
+ volumes:
1064
+ postgres-data:
1065
+ server-audit-data:
1066
+ `;
1067
+ function environmentExample(includeExample) {
1068
+ return `# 复制为 .env 后填写。不要提交真实密码。
1069
+ POSTGRES_PASSWORD=
1070
+ WINDY_BOOTSTRAP_ADMIN_PASSWORD=
1071
+
1072
+ # 可选搜索配置;不配置时启用 Manifest 中默认开启的 Provider。${includeExample ? `
1073
+ # SEARCH_PROVIDER_KEYS=work-order.ticket.search` : `
1074
+ # 当前 core profile 没有业务 SearchProvider;接入业务模块后再配置 Key。`}
1075
+ # SEARCH_PROVIDER_TIMEOUT_MS=800
1076
+ # SEARCH_HEALTH_TIMEOUT_MS=500
1077
+ # SEARCH_MAX_REQUESTS_PER_MINUTE=30
1078
+ `;
1079
+ }
1080
+ function starterDocsReadme(includeOfflineLicense = true) {
1081
+ return `# Windy Starter 文档
1082
+
1083
+ 本目录只包含客户运行项目需要的平台架构、开发接入和运维可观测性文档。
1084
+ License 签发中心、独立签名服务、Vault、发布治理、内部任务记录和模板产品
1085
+ 规划属于软件供应方控制面,不进入客户 Starter。
1086
+
1087
+ - 架构:从 [Module Manifest 组合](./architecture/module-manifest-composition.md) 开始。
1088
+ - 平台开发:从 [系统 CRUD API](./platform/system-crud-api.md) 和 [CRUD 生成器](./development/crud-generator.md) 开始。
1089
+ ${includeOfflineLicense ? "- License 消费端:[离线激活与安装协议](./license/license-offline-activation-code.md);运行时 SDK 位于 `packages/license-sdk`。" : ""}
1090
+ - 运维:[可观测性](./operations/observability.md) 与 [运维总览](./platform/operations-overview.md)。
1091
+ - 兼容:[RuoYi-Vue Adapter](./adapters/ruoyi-vue-compatibility.md)。
1092
+ `;
1093
+ }
1094
+ function starterReadme(projectName, includeExample = true, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = []) {
1095
+ const selected = new Set(selectedModules);
1096
+ const moduleRows = moduleDistributionCatalog.map(({ name, description, selection }) => `| \`${name}\` | ${selected.has(name) ? "已包含" : "未包含"} | ${selection === "required" ? "H0" : "H2"} | ${description} |`).join(`
1097
+ `);
1098
+ return `# ${projectName}
1099
+
1100
+ ${projectName} 是由 create-windy 生成的单组织、单租户企业应用项目。用户功能层位于
1101
+ \`/\`,平台管理控制面位于 \`/admin/**\`;业务功能可以按自己的产品习惯开发,不需要
1102
+ 复用 Admin 页面结构。
1103
+
1104
+ 本项目固定使用 Bun 1.3.14 或更高版本,当前法律许可为 \`${projectLicense}\`。项目不包含
1105
+ 软件供应方的 License Authority、内部签名服务、发布密钥或私有源仓库信息。
1106
+ ${includeExample ? "创建时包含了 `work-order` 示例模块,用于演示 Module Manifest 接入;它不是生产工单产品,可以在正式开发前替换。" : "创建时未选择 `work-order` 示例模块,当前项目只包含平台模块。"}
1107
+
1108
+ ## 环境要求
1109
+
1110
+ - Bun 1.3.14+
1111
+ - Docker 与 Docker Compose(推荐的本地完整运行方式)
1112
+ - Git(创建器默认已经初始化;使用 \`--no-git\` 时除外)
1113
+
1114
+ 不要使用 npm、Yarn 或 pnpm 安装本项目依赖,也不要提交它们产生的 lockfile;唯一的
1115
+ 依赖锁文件是 \`bun.lock\`。
1116
+
1117
+ ## 第一次运行
1118
+
1119
+ \`\`\`bash
1120
+ bun install
1121
+ cp .env.example .env
1122
+ # 为 POSTGRES_PASSWORD 和 WINDY_BOOTSTRAP_ADMIN_PASSWORD 设置本地值
1123
+ docker compose up --build
1124
+ \`\`\`
1125
+
1126
+ | 服务 | 地址 |
1127
+ | ---- | ---- |
1128
+ | Web | http://localhost:9746 |
1129
+ | Server 健康检查 | http://localhost:3000/api/health |
1130
+ | PostgreSQL | localhost:5432 |
1131
+
1132
+ Docker Web 固定使用 \`9746\`。只在宿主机运行 Web 时使用:
1133
+
1134
+ \`\`\`bash
1135
+ bun run dev:web
1136
+ \`\`\`
1137
+
1138
+ 本地 Web 从 \`8746\` 开始探测。同一项目已经运行时会直接输出已有地址;其它服务占用
1139
+ 时会自动使用后续端口,最多检查 100 个。实际地址始终以终端输出为准。
1140
+
1141
+ ## 页面与登录
1142
+
1143
+ | 路径 | 访问要求 | 说明 |
1144
+ | ---- | -------- | ---- |
1145
+ | \`/login\` | 公开 | 登录成功后回到安全的站内目标,默认进入 \`/\` |
1146
+ | \`/\` | 已登录 | 最小用户首页,也是业务功能开发入口 |
1147
+ | \`/admin\` | Admin 准入能力 | 平台管理首页 |
1148
+ | \`/admin/**\` | 对应 Feature 与 RBAC | 平台配置、身份、审计和运维页面 |
1149
+
1150
+ 普通用户登录后不会加载 Admin Bootstrap。只有服务端确认 \`system.admin\` 可用且当前
1151
+ 账号拥有 \`system.admin.access\` 时,首页才显示“进入管理后台”;直接访问 Admin 仍会
1152
+ 独立校验权限。
1153
+
1154
+ ## 当前生成选择
1155
+
1156
+ | 选项 | 当前项目 |
1157
+ | ---- | -------- |
1158
+ | Profile | \`private-enterprise\` |
1159
+ | Runtime / Package Manager | Bun |
1160
+ | 代码质量 | ${includeOxc ? "Oxlint + Oxfmt" : "未预装 lint/format 工具"} |
1161
+ | 示例工单 | ${includeExample ? "已包含" : "未包含"} |
1162
+ | 法律许可 | \`${projectLicense}\` |
1163
+
1164
+ 平台当前注册的全部模块如下。H0 表示 profile 锁定核心;H2 表示创建时可以物理包含或
1165
+ 排除,并已有生成、类型检查、测试和构建证据。H2 不代表项目部署后已经支持无损安装、
1166
+ 升级或卸载;那需要 H3 的生命周期命令与数据处置证据。
1167
+
1168
+ | Module Key | 当前项目 | 热插拔可靠度 | 说明 |
1169
+ | ---------- | -------- | ------------ | ---- |
1170
+ ${moduleRows}
1171
+
1172
+ 精确生成来源和选择记录在 \`.windy/generation.json\`。当前版本尚未提供通用
1173
+ \`module add/remove\` 或 \`windy update\`,不要把 Feature Flag 关闭当成模块已经卸载。
1174
+
1175
+ ## 常用命令
1176
+
1177
+ \`\`\`bash
1178
+ bun run dev:web
1179
+ bun run dev:server
1180
+ bun run typecheck
1181
+ bun run test
1182
+ bun run build
1183
+ ${includeOxc ? `bun run lint
1184
+ bun run format` : "# 本项目未预装 lint/format 工具,可按团队需要自行选择。"}
1185
+ \`\`\`
1186
+
1187
+ ## 开发约束
1188
+
1189
+ - 新增路由默认需要登录;只有显式 public 的页面允许匿名访问。
1190
+ - 新功能必须在 Module Manifest 中使用同一稳定基础 key 注册 Feature、RBAC、API、
1191
+ 菜单或入口及审计动作。
1192
+ - 业务模块默认不进入 Admin;只有明确声明并通过 Guard 的管理能力才注册到
1193
+ \`/admin/**\`。
1194
+ - 模块之间通过公开 service、Interface 或注册机制协作,不跨模块直连 Repository。
1195
+ - 数据访问通过 Repository + Drizzle,不在业务代码中依赖 PostgreSQL 方言。
1196
+
1197
+ 平台能力、二次开发约束和运维说明从 [docs/README.md](docs/README.md) 开始。
1198
+
1199
+ ## Git 与后续升级
1200
+
1201
+ create-windy 默认建立 \`main\` 分支并创建 \`chore: initialize project\` 首次提交。若当时
1202
+ 没有配置 Git 用户身份,文件会保留在暂存区;配置身份后手动提交即可。
1203
+
1204
+ 未来的 Windy 更新器会根据 project lock 和文件所有权执行三方合并,不会要求连接
1205
+ 私有源仓库,也不会静默覆盖项目代码。该更新引擎当前尚未交付。
1206
+
1207
+ ## License
1208
+
1209
+ 本项目当前法律许可证为 \`${projectLicense}\`。${projectLicense === "UNLICENSED" ? "项目没有附带开源许可证。" : "完整许可证正文位于根目录 `LICENSE`。"}法律许可证与 \`system.license\` 离线运行时授权模块是两个不同概念;更换其中一个
1210
+ 不会自动更换另一个。
1211
+ `;
1212
+ }
1213
+
1214
+ // src/project-package.ts
1215
+ function createStarterPackage(source, projectName, includeOxc = true, projectLicense = "UNLICENSED", selectedModules = []) {
1216
+ const devDependencies = { ...source.devDependencies };
1217
+ if (!includeOxc) {
1218
+ delete devDependencies.oxfmt;
1219
+ delete devDependencies.oxlint;
1220
+ }
1221
+ return {
1222
+ ...source,
1223
+ name: projectName,
1224
+ private: true,
1225
+ license: projectLicense,
1226
+ packageManager: "bun@1.3.14",
1227
+ engines: { ...source.engines, bun: ">=1.3.14" },
1228
+ scripts: {
1229
+ dev: "bun run --cwd apps/web dev",
1230
+ "dev:web": "bun run --cwd apps/web dev",
1231
+ "dev:server": "bun run --cwd apps/server dev",
1232
+ build: "bun run --cwd apps/web build",
1233
+ "db:generate": "drizzle-kit generate --config drizzle.config.ts",
1234
+ "db:migrate": "drizzle-kit migrate --config drizzle.config.ts",
1235
+ "generate:crud": "bun run packages/crud-generator/src/cli.ts",
1236
+ typecheck: [
1237
+ "bun run --cwd apps/web typecheck",
1238
+ "bun run --cwd apps/server typecheck",
1239
+ ...selectedModules.includes("system.license") ? ["bun run --cwd packages/license-sdk typecheck"] : [],
1240
+ ...selectedModules.includes("system.storage") ? ["bun run --cwd packages/storage typecheck"] : [],
1241
+ "bun run --cwd packages/database typecheck",
1242
+ "bun run --cwd packages/crud-generator typecheck"
1243
+ ].join(" && "),
1244
+ ...includeOxc ? { lint: "oxlint .", format: "oxfmt" } : {},
1245
+ test: "bun test && bun run --cwd apps/web test"
1246
+ },
1247
+ devDependencies
1248
+ };
1249
+ }
1250
+
1251
+ // src/template-manifest.ts
1252
+ var templateRootFiles = [
1253
+ ".dockerignore",
1254
+ ".gitignore",
1255
+ ".oxfmtrc.json",
1256
+ ".oxlintrc.json",
1257
+ "AGENTS.md",
1258
+ "README.md",
1259
+ "bunfig.toml",
1260
+ "docker-compose.yml",
1261
+ "drizzle.config.ts",
1262
+ "package.json"
1263
+ ];
1264
+ var templateDirectories = [
1265
+ "apps/server",
1266
+ "apps/web",
1267
+ "examples",
1268
+ "packages/config",
1269
+ "packages/crud-generator",
1270
+ "packages/database",
1271
+ "packages/example-work-order",
1272
+ "packages/license-sdk",
1273
+ "packages/modules",
1274
+ "packages/shared",
1275
+ "packages/storage"
1276
+ ];
1277
+ var templateDocumentationFiles = [
1278
+ "docs/adapters/ruoyi-vue-compatibility.md",
1279
+ "docs/architecture/admin-surface-boundary.md",
1280
+ "docs/architecture/data-scope-query-enforcement.md",
1281
+ "docs/architecture/durable-jobs.md",
1282
+ "docs/architecture/minimal-approval-workflow.md",
1283
+ "docs/architecture/module-manifest-composition.md",
1284
+ "docs/architecture/object-storage.md",
1285
+ "docs/architecture/search-provider-protocol.md",
1286
+ "docs/development/crud-generator.md",
1287
+ "docs/license/license-offline-activation-code.md",
1288
+ "docs/operations/observability.md",
1289
+ "docs/platform/agent-tools.md",
1290
+ "docs/platform/audit-reliability.md",
1291
+ "docs/platform/bulk-data-jobs.md",
1292
+ "docs/platform/data-access-control.md",
1293
+ "docs/platform/module-configuration.md",
1294
+ "docs/platform/navigation-registry.md",
1295
+ "docs/platform/notifications.md",
1296
+ "docs/platform/operations-overview.md",
1297
+ "docs/platform/organization-membership.md",
1298
+ "docs/platform/platform-authentication.md",
1299
+ "docs/platform/platform-shell-settings.md",
1300
+ "docs/platform/scheduled-task-executor.md",
1301
+ "docs/platform/system-crud-api.md",
1302
+ "docs/platform/web-system-crud.md",
1303
+ "docs/product/built-in-roles.md"
1304
+ ];
1305
+ var templatePaths = [
1306
+ ...templateRootFiles,
1307
+ ...templateDirectories,
1308
+ ...templateDocumentationFiles
1309
+ ];
1310
+ function generationTemplatePaths(includeExample, includeOxc = true) {
1311
+ return templatePaths.filter((path) => (includeExample || path !== "packages/example-work-order") && (includeOxc || path !== ".oxfmtrc.json" && path !== ".oxlintrc.json"));
1312
+ }
1313
+ var excludedNames = new Set([
1314
+ ".DS_Store",
1315
+ ".env",
1316
+ ".git",
1317
+ ".tmp",
1318
+ "dist",
1319
+ "node_modules"
1320
+ ]);
1321
+ var excludedRuntimeFiles = new Set([
1322
+ "credentials.json",
1323
+ "license-state.json",
1324
+ "recovery-queue.json"
1325
+ ]);
1326
+
1327
+ // src/provenance.ts
1328
+ import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile6 } from "node:fs/promises";
1329
+ import { join as join6 } from "node:path";
1330
+ var templateMetadataFile = ".windy-template.json";
1331
+ var generationMetadataFile = ".windy/generation.json";
1332
+ async function readTemplateMetadata(sourceRoot) {
1333
+ const path = join6(sourceRoot, templateMetadataFile);
1334
+ const parsed = JSON.parse(await readFile6(path, "utf8"));
1335
+ if (!isTemplateMetadata(parsed)) {
1336
+ throw new Error("create-windy 模板来源元数据无效");
1337
+ }
1338
+ return parsed;
1339
+ }
1340
+ async function writeGenerationProvenance(targetDirectory, metadata, profile, selectedModules, includeOxc, legalLicense) {
1341
+ const requested = selectedModuleManifests(selectedModules);
1342
+ const versions = new Map(metadata.modules.map((item) => [item.name, item]));
1343
+ const modules = requested.map(({ name }) => {
1344
+ const version = versions.get(name);
1345
+ if (!version)
1346
+ throw new Error(`模板来源缺少模块版本:${name}`);
1347
+ return version;
1348
+ });
1349
+ const provenance = {
1350
+ ...metadata,
1351
+ windyVersion: metadata.generatorVersion,
1352
+ profile,
1353
+ modules,
1354
+ toolchain: {
1355
+ runtime: "bun",
1356
+ codeQuality: includeOxc ? "oxc" : "none"
1357
+ },
1358
+ legalLicense,
1359
+ appliedRecipes: [],
1360
+ managedFilesManifest: ".windy/files.json",
1361
+ choices: {
1362
+ includeExample: selectedModules.includes("work-order"),
1363
+ includeOxc
1364
+ }
1365
+ };
1366
+ const path = join6(targetDirectory, generationMetadataFile);
1367
+ await mkdir2(join6(path, ".."), { recursive: true });
1368
+ await writeFile6(path, `${JSON.stringify(provenance, null, 2)}
1369
+ `);
1370
+ }
1371
+ function isTemplateMetadata(value) {
1372
+ if (!value || typeof value !== "object")
1373
+ return false;
1374
+ const metadata = value;
1375
+ return metadata.schemaVersion === 1 && typeof metadata.templateCommit === "string" && /^[0-9a-f]{40}$/.test(metadata.templateCommit) && typeof metadata.generatorVersion === "string" && metadata.generatorVersion.length > 0 && Array.isArray(metadata.modules) && metadata.modules.every(isModuleVersion);
1376
+ }
1377
+ function isModuleVersion(value) {
1378
+ if (!value || typeof value !== "object")
1379
+ return false;
1380
+ const module3 = value;
1381
+ return typeof module3.name === "string" && module3.name.length > 0 && typeof module3.version === "string" && module3.version.length > 0;
1382
+ }
1383
+
1384
+ // src/generator.ts
1385
+ async function generateProject(input) {
1386
+ validateProjectName(input.projectName);
1387
+ await assertTargetAvailable(input.targetDirectory);
1388
+ await mkdir3(input.targetDirectory, { recursive: true });
1389
+ const includeExample = input.includeExample ?? true;
1390
+ const includeOxc = input.includeOxc ?? true;
1391
+ const projectLicense = input.projectLicense ?? "UNLICENSED";
1392
+ const templateMetadata = await readTemplateMetadata(input.sourceRoot);
1393
+ const selectedModules = input.selectedModules ?? templateMetadata.modules.filter(({ name }) => includeExample || name !== "work-order").map(({ name }) => name);
1394
+ for (const relativePath2 of generationTemplatePaths(true, includeOxc)) {
1395
+ await copyTree(join7(input.sourceRoot, relativePath2), join7(input.targetDirectory, relativePath2));
1396
+ }
1397
+ await materializeSelectedModules(input.targetDirectory, selectedModules);
1398
+ const packagePath = join7(input.targetDirectory, "package.json");
1399
+ const packageJson = JSON.parse(await readFile7(packagePath, "utf8"));
1400
+ await writeFile7(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules), null, 2)}
1401
+ `);
1402
+ await writeFile7(join7(input.targetDirectory, "docker-compose.yml"), starterCompose);
1403
+ await writeFile7(join7(input.targetDirectory, ".env.example"), environmentExample(includeExample));
1404
+ await writeFile7(join7(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
1405
+ await writeFile7(join7(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license")));
1406
+ await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
1407
+ await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
1408
+ await prepareCustomerDockerfiles(input.targetDirectory);
1409
+ await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense);
1410
+ await rm3(join7(input.targetDirectory, "bun.lock"), { force: true });
1411
+ await writeManagedFilesManifest(input.targetDirectory, templateMetadata.generatorVersion);
1412
+ }
1413
+ async function assertGeneratedProjectIsClean(targetDirectory) {
1414
+ const violations = [];
1415
+ await walk(targetDirectory, async (path) => {
1416
+ const name = basename2(path);
1417
+ const extension = extname2(name).toLowerCase();
1418
+ if (excludedNames.has(name) || excludedRuntimeFiles.has(name) || [".key", ".pem", ".p12", ".pfx"].includes(extension)) {
1419
+ violations.push(path.slice(targetDirectory.length + 1));
1420
+ }
1421
+ });
1422
+ if (violations.length) {
1423
+ throw new Error(`生成物包含禁止文件:${violations.sort().join("、")}`);
1424
+ }
1425
+ }
1426
+ function validateProjectName(projectName) {
1427
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(projectName)) {
1428
+ throw new Error("项目名只能包含小写字母、数字、点、短横线和下划线");
1429
+ }
1430
+ if (projectName === "." || projectName === "..") {
1431
+ throw new Error("项目名不能是当前目录或上级目录");
1432
+ }
1433
+ }
1434
+ async function assertTargetAvailable(targetDirectory) {
1435
+ try {
1436
+ const entries = await readdir3(targetDirectory);
1437
+ if (entries.length)
1438
+ throw new Error("目标目录不是空目录");
1439
+ } catch (error) {
1440
+ if (isMissing2(error))
1441
+ return;
1442
+ throw error;
1443
+ }
1444
+ }
1445
+ async function copyTree(source, target) {
1446
+ const metadata = await lstat3(source);
1447
+ const name = basename2(source);
1448
+ if (shouldExclude(name) || metadata.isSymbolicLink())
1449
+ return;
1450
+ if (metadata.isDirectory()) {
1451
+ await mkdir3(target, { recursive: true });
1452
+ for (const child of await readdir3(source)) {
1453
+ await copyTree(join7(source, child), join7(target, child));
1454
+ }
1455
+ return;
1456
+ }
1457
+ await mkdir3(join7(target, ".."), { recursive: true });
1458
+ await copyFile(source, target);
1459
+ }
1460
+ function shouldExclude(name) {
1461
+ return excludedNames.has(name) || excludedRuntimeFiles.has(name);
1462
+ }
1463
+ async function walk(directory, visit) {
1464
+ for (const name of await readdir3(directory)) {
1465
+ const path = join7(directory, name);
1466
+ await visit(path);
1467
+ if ((await lstat3(path)).isDirectory())
1468
+ await walk(path, visit);
1469
+ }
1470
+ }
1471
+ function isMissing2(error) {
1472
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1473
+ }
1474
+
1475
+ // src/template-root.ts
1476
+ import { access } from "node:fs/promises";
1477
+ import { dirname as dirname2, resolve as resolve3 } from "node:path";
1478
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
1479
+ async function resolveTemplateRoot() {
1480
+ const currentDirectory = dirname2(fileURLToPath2(import.meta.url));
1481
+ const templateRoot = resolve3(currentDirectory, "../template");
1482
+ try {
1483
+ await access(resolve3(templateRoot, "package.json"));
1484
+ return templateRoot;
1485
+ } catch {
1486
+ throw new Error("create-windy 模板快照缺失。开发仓库请先执行 template:sync;发布包应自带模板。");
1487
+ }
1488
+ }
1489
+
1490
+ // src/create-project.ts
1491
+ async function createProject(options, dependencies = {}) {
1492
+ const bunVersion = await (dependencies.checkBun ?? assertSupportedBun)();
1493
+ const targetState = await inspectTarget(options.targetDirectory);
1494
+ const generate = dependencies.generate ?? generateProject;
1495
+ const inspect = dependencies.inspect ?? assertGeneratedProjectIsClean;
1496
+ const resolveTemplate = dependencies.resolveTemplate ?? resolveTemplateRoot;
1497
+ let stage = "生成文件";
1498
+ try {
1499
+ await generate({
1500
+ sourceRoot: await resolveTemplate(),
1501
+ targetDirectory: options.targetDirectory,
1502
+ projectName: options.projectName,
1503
+ includeExample: options.includeExample,
1504
+ includeOxc: options.includeOxc,
1505
+ selectedModules: options.selectedModules,
1506
+ projectLicense: options.projectLicense,
1507
+ licenseHolder: options.licenseHolder,
1508
+ profile: options.profile
1509
+ });
1510
+ stage = "检查生成物";
1511
+ await inspect(options.targetDirectory);
1512
+ stage = "安装与验证";
1513
+ await installAndVerify(options.targetDirectory, options.install, options.verify, dependencies.commandExecutor);
1514
+ } catch (error) {
1515
+ await rollbackFailedTarget(options, targetState);
1516
+ throw stageError(stage, error);
1517
+ }
1518
+ const log = dependencies.log ?? console.log;
1519
+ let gitInitialized = false;
1520
+ if (options.initializeGit) {
1521
+ const result = await (dependencies.initializeGit ?? initializeGitRepository)(options.targetDirectory, dependencies.commandExecutor);
1522
+ gitInitialized = result.status === "committed";
1523
+ if (result.status === "skipped")
1524
+ log(`
1525
+ 警告:${result.warning}`);
1526
+ }
1527
+ log(`
1528
+ 已创建 ${options.projectName}`);
1529
+ log(`运行时:Bun ${bunVersion}`);
1530
+ log(options.initializeGit ? gitInitialized ? "Git:已创建 main 分支和首次提交" : "Git:项目已保留,请按上述提示完成初始化" : "Git:已按 --no-git 跳过");
1531
+ log(`下一步:cd ${options.projectName} && bun run dev`);
1532
+ }
1533
+ async function inspectTarget(path) {
1534
+ try {
1535
+ return (await readdir4(path)).length === 0 ? "empty" : "non-empty";
1536
+ } catch (error) {
1537
+ if (isMissing3(error))
1538
+ return "missing";
1539
+ throw error;
1540
+ }
1541
+ }
1542
+ async function rollbackFailedTarget(options, initialState) {
1543
+ if (options.keepOnError || initialState === "non-empty")
1544
+ return;
1545
+ await rm4(options.targetDirectory, { recursive: true, force: true });
1546
+ if (initialState === "empty") {
1547
+ await mkdir4(options.targetDirectory, { recursive: true });
1548
+ }
1549
+ }
1550
+ function stageError(stage, error) {
1551
+ const reason = sanitizeReason(error instanceof Error ? error.message : String(error));
1552
+ return new Error(`create-windy ${stage}阶段失败:${reason}`, {
1553
+ cause: error
1554
+ });
1555
+ }
1556
+ function sanitizeReason(reason) {
1557
+ return reason.replace(/\b([A-Z][A-Z0-9_]*(?:PASSWORD|SECRET|TOKEN|DATABASE_URL)[A-Z0-9_]*)=\S+/g, "$1=[已隐藏]").replace(/:\/\/([^\s:/]+):([^\s@]+)@/g, "://$1:[已隐藏]@");
1558
+ }
1559
+ function isMissing3(error) {
1560
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1561
+ }
1562
+
1563
+ // src/interactive-selection.ts
1564
+ import { createInterface } from "node:readline/promises";
1565
+ import { stdin, stdout } from "node:process";
1566
+ async function applyInteractiveSelection(options, prompter = terminalPrompter()) {
1567
+ if (!options.interactive)
1568
+ return options;
1569
+ const optional = moduleDistributionCatalog.filter(({ name }) => !requiredModuleNames.includes(name));
1570
+ const requested = await prompter.selectModules({
1571
+ choices: optional.map(({ name, label, selection }) => ({
1572
+ value: name,
1573
+ label: `${label} (${name})`,
1574
+ hint: selection === "recommended" ? "推荐,默认选中" : "可选"
1575
+ })),
1576
+ defaults: [...recommendedModuleNames]
1577
+ });
1578
+ const includeOxc = await prompter.confirm("是否引入 Oxlint + Oxfmt?", true);
1579
+ const projectLicense = await prompter.selectLicense();
1580
+ const licenseHolder = projectLicense === "MIT" ? (await prompter.text("MIT 许可证权利人名称:")).trim() : undefined;
1581
+ if (projectLicense === "MIT" && !licenseHolder) {
1582
+ throw new Error("选择 MIT 时必须填写许可证权利人名称");
1583
+ }
1584
+ const selectedModules = resolveModuleSelection({
1585
+ includeRecommended: false,
1586
+ requested
1587
+ });
1588
+ return {
1589
+ ...options,
1590
+ selectedModules,
1591
+ includeExample: selectedModules.includes("work-order"),
1592
+ includeOxc,
1593
+ projectLicense,
1594
+ licenseHolder,
1595
+ interactive: false
1596
+ };
1597
+ }
1598
+ function terminalPrompter() {
1599
+ const question = async (message) => {
1600
+ const readline = createInterface({ input: stdin, output: stdout });
1601
+ try {
1602
+ return await readline.question(message);
1603
+ } finally {
1604
+ readline.close();
1605
+ }
1606
+ };
1607
+ return {
1608
+ async selectModules({ choices, defaults }) {
1609
+ stdout.write(`
1610
+ 请选择要生成的平台模块(逗号分隔编号,直接回车采用推荐项):
1611
+ `);
1612
+ choices.forEach((choice, index) => {
1613
+ const checked = defaults.includes(choice.value) ? "x" : " ";
1614
+ stdout.write(` ${index + 1}. [${checked}] ${choice.label} — ${choice.hint}
1615
+ `);
1616
+ });
1617
+ const answer = (await question("> ")).trim();
1618
+ if (!answer)
1619
+ return defaults;
1620
+ const indexes = answer.split(",").map((part) => Number(part.trim()) - 1);
1621
+ if (indexes.some((index) => !Number.isSafeInteger(index) || !choices[index])) {
1622
+ throw new Error("模块选择包含无效编号");
1623
+ }
1624
+ return [...new Set(indexes.map((index) => choices[index].value))];
1625
+ },
1626
+ async confirm(message, defaultValue) {
1627
+ const hint = defaultValue ? "Y/n" : "y/N";
1628
+ const answer = (await question(`${message} (${hint}) `)).trim().toLowerCase();
1629
+ if (!answer)
1630
+ return defaultValue;
1631
+ return answer === "y" || answer === "yes";
1632
+ },
1633
+ async selectLicense() {
1634
+ const answer = (await question(`项目法律许可证:1. UNLICENSED(默认) 2. MIT 3. Apache-2.0
1635
+ > `)).trim();
1636
+ if (!answer || answer === "1")
1637
+ return "UNLICENSED";
1638
+ if (answer === "2")
1639
+ return "MIT";
1640
+ if (answer === "3")
1641
+ return "Apache-2.0";
1642
+ throw new Error("许可证选择包含无效编号");
1643
+ },
1644
+ text(message) {
1645
+ return question(message);
1646
+ }
1647
+ };
1648
+ }
1649
+
1650
+ // src/cli.ts
1651
+ async function main() {
1652
+ const options = parseArguments(process.argv.slice(2));
1653
+ if (options === "help") {
1654
+ console.log(helpText);
1655
+ return;
1656
+ }
1657
+ await createProject(await applyInteractiveSelection(options));
1658
+ }
1659
+ main().catch((error) => {
1660
+ console.error(error instanceof Error ? error.message : String(error));
1661
+ process.exitCode = 1;
1662
+ });