create-windy 0.2.6 → 0.2.8

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 (361) hide show
  1. package/README.md +14 -3
  2. package/dist/cli.js +191 -87
  3. package/package.json +1 -1
  4. package/template/.windy-template.json +2 -2
  5. package/template/README.md +8 -0
  6. package/template/apps/server/Dockerfile +2 -0
  7. package/template/apps/server/package.json +10 -8
  8. package/template/apps/server/src/access-guards.ts +1 -1
  9. package/template/apps/server/src/admin/routes.test.ts +10 -0
  10. package/template/apps/server/src/admin/routes.ts +4 -2
  11. package/template/apps/server/src/agent/routes.test.ts +1 -1
  12. package/template/apps/server/src/agent/routes.ts +2 -2
  13. package/template/apps/server/src/application-services.ts +3 -0
  14. package/template/apps/server/src/audit/drizzle-log-store.ts +2 -2
  15. package/template/apps/server/src/audit/policy.ts +1 -1
  16. package/template/apps/server/src/audit/recovery-queue.test.ts +1 -1
  17. package/template/apps/server/src/audit/recovery-queue.ts +1 -1
  18. package/template/apps/server/src/audit/redaction.ts +1 -1
  19. package/template/apps/server/src/audit/reliable-writer.test.ts +1 -1
  20. package/template/apps/server/src/audit/reliable-writer.ts +1 -1
  21. package/template/apps/server/src/audit/search-summary.ts +1 -1
  22. package/template/apps/server/src/auth/authentication-provider.test.ts +1 -1
  23. package/template/apps/server/src/auth/credential-service.ts +1 -1
  24. package/template/apps/server/src/auth/drizzle-repository.ts +2 -2
  25. package/template/apps/server/src/auth/drizzle-session-operations.ts +1 -1
  26. package/template/apps/server/src/auth/own-session-routes.test.ts +1 -1
  27. package/template/apps/server/src/auth/password.ts +2 -4
  28. package/template/apps/server/src/auth/repository.ts +1 -1
  29. package/template/apps/server/src/auth/routes.test.ts +1 -1
  30. package/template/apps/server/src/auth/service.ts +1 -1
  31. package/template/apps/server/src/bulk-data/artifact-store.ts +1 -1
  32. package/template/apps/server/src/bulk-data/dictionary-handler.ts +1 -1
  33. package/template/apps/server/src/bulk-data/drizzle-repository.ts +3 -3
  34. package/template/apps/server/src/bulk-data/repository.ts +1 -1
  35. package/template/apps/server/src/bulk-data/routes.test.ts +1 -1
  36. package/template/apps/server/src/bulk-data/routes.ts +1 -1
  37. package/template/apps/server/src/bulk-data/service.test.ts +1 -1
  38. package/template/apps/server/src/bulk-data/service.ts +1 -1
  39. package/template/apps/server/src/bulk-data/types.ts +1 -1
  40. package/template/apps/server/src/configuration/bootstrap.ts +2 -2
  41. package/template/apps/server/src/configuration/definition.ts +2 -2
  42. package/template/apps/server/src/configuration/drizzle-repository.ts +2 -2
  43. package/template/apps/server/src/configuration/repository.ts +1 -1
  44. package/template/apps/server/src/configuration/routes.ts +1 -1
  45. package/template/apps/server/src/configuration/service.ts +1 -1
  46. package/template/apps/server/src/data-access/context.ts +2 -2
  47. package/template/apps/server/src/data-access/query-specification.test.ts +1 -1
  48. package/template/apps/server/src/data-access/scoped-repository.integration.test.ts +1 -1
  49. package/template/apps/server/src/data-access/scoped-repository.ts +1 -1
  50. package/template/apps/server/src/data-access/scoped-resource.test.ts +1 -1
  51. package/template/apps/server/src/data-access/scoped-resource.ts +1 -1
  52. package/template/apps/server/src/data-governance/export/approval-port.ts +1 -1
  53. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -1
  54. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +2 -2
  55. package/template/apps/server/src/data-governance/export/job-runtime.ts +2 -3
  56. package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +2 -2
  57. package/template/apps/server/src/data-governance/export/postgres-api.integration.test.ts +1 -1
  58. package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +3 -3
  59. package/template/apps/server/src/data-governance/export/routes.ts +1 -1
  60. package/template/apps/server/src/data-governance/export/scope-snapshot.ts +1 -1
  61. package/template/apps/server/src/data-governance/export/service.ts +2 -2
  62. package/template/apps/server/src/data-governance/export/source.ts +1 -1
  63. package/template/apps/server/src/data-governance/export/types.ts +1 -1
  64. package/template/apps/server/src/data-governance/plaintext-access.test.ts +1 -1
  65. package/template/apps/server/src/data-governance/plaintext-access.ts +1 -1
  66. package/template/apps/server/src/data-governance/plaintext-postgres.integration.test.ts +1 -1
  67. package/template/apps/server/src/data-governance/user-plaintext-routes.ts +1 -1
  68. package/template/apps/server/src/data-governance/user-projection.ts +2 -2
  69. package/template/apps/server/src/example-modules.ts +25 -1
  70. package/template/apps/server/src/feature/manifest-feature-repository.test.ts +1 -1
  71. package/template/apps/server/src/feature/manifest-feature-repository.ts +1 -1
  72. package/template/apps/server/src/feature/routes.ts +3 -6
  73. package/template/apps/server/src/foundation-access.test.ts +1 -1
  74. package/template/apps/server/src/foundation-access.ts +1 -1
  75. package/template/apps/server/src/foundation.ts +21 -7
  76. package/template/apps/server/src/guards.test.ts +1 -1
  77. package/template/apps/server/src/guards.ts +3 -3
  78. package/template/apps/server/src/index.ts +27 -3
  79. package/template/{packages/modules → apps/server}/src/installed-business-modules.ts +2 -2
  80. package/template/apps/server/src/jobs/artifact-service.test.ts +1 -1
  81. package/template/apps/server/src/jobs/artifact-service.ts +2 -2
  82. package/template/apps/server/src/jobs/drizzle-artifact.ts +2 -2
  83. package/template/apps/server/src/jobs/drizzle-claim.ts +1 -1
  84. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +2 -2
  85. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +1 -1
  86. package/template/apps/server/src/jobs/drizzle-lease.ts +2 -2
  87. package/template/apps/server/src/jobs/drizzle-mappers.ts +3 -3
  88. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +1 -1
  89. package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -1
  90. package/template/apps/server/src/jobs/drizzle-repository.ts +3 -3
  91. package/template/apps/server/src/jobs/execution-repository.ts +1 -1
  92. package/template/apps/server/src/jobs/execution.test.ts +2 -2
  93. package/template/apps/server/src/jobs/in-memory-claim.ts +1 -1
  94. package/template/apps/server/src/jobs/in-memory-execution.ts +1 -1
  95. package/template/apps/server/src/jobs/in-memory-lease.ts +1 -1
  96. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +1 -1
  97. package/template/apps/server/src/jobs/legacy-adapter.test.ts +1 -1
  98. package/template/apps/server/src/jobs/legacy-adapter.ts +1 -1
  99. package/template/apps/server/src/jobs/legacy-service-runtime.ts +4 -2
  100. package/template/apps/server/src/jobs/repository.ts +2 -2
  101. package/template/apps/server/src/jobs/service.ts +2 -2
  102. package/template/apps/server/src/jobs/worker.ts +3 -2
  103. package/template/apps/server/src/license/legacy-license-resolver.ts +1 -1
  104. package/template/apps/server/src/license/license-resolver.test.ts +1 -1
  105. package/template/apps/server/src/license/license-resolver.ts +3 -3
  106. package/template/apps/server/src/license/routes-offline-code.test.ts +2 -2
  107. package/template/apps/server/src/license/routes.ts +1 -1
  108. package/template/apps/server/src/license/runtime-audit-reliability.test.ts +2 -2
  109. package/template/apps/server/src/license/runtime-reminder.test.ts +2 -2
  110. package/template/apps/server/src/license/runtime-service.test.ts +2 -2
  111. package/template/apps/server/src/license/runtime-service.ts +2 -2
  112. package/template/apps/server/src/module-composition.test.ts +1 -1
  113. package/template/apps/server/src/module-composition.ts +1 -1
  114. package/template/apps/server/src/module-host.test.ts +145 -0
  115. package/template/apps/server/src/module-host.ts +110 -0
  116. package/template/apps/server/src/notification/drizzle-repository.ts +2 -2
  117. package/template/apps/server/src/notification/repository.ts +1 -1
  118. package/template/apps/server/src/notification/routes.ts +1 -1
  119. package/template/apps/server/src/pagination.ts +1 -1
  120. package/template/apps/server/src/persistence.integration.test.ts +1 -1
  121. package/template/apps/server/src/persistence.ts +1 -1
  122. package/template/apps/server/src/profile/routes.ts +1 -1
  123. package/template/apps/server/src/route-guards.test.ts +1 -1
  124. package/template/apps/server/src/route-guards.ts +1 -1
  125. package/template/apps/server/src/runtime-feature.ts +125 -0
  126. package/template/apps/server/src/runtime-license.ts +1 -1
  127. package/template/apps/server/src/runtime.test.ts +48 -1
  128. package/template/apps/server/src/runtime.ts +17 -64
  129. package/template/apps/server/src/scheduler/audit.ts +1 -1
  130. package/template/apps/server/src/scheduler/definitions.test.ts +1 -1
  131. package/template/apps/server/src/scheduler/definitions.ts +2 -2
  132. package/template/apps/server/src/scheduler/drizzle-durable-links.ts +1 -1
  133. package/template/apps/server/src/scheduler/drizzle-mappers.ts +1 -1
  134. package/template/apps/server/src/scheduler/drizzle-repository.ts +1 -1
  135. package/template/apps/server/src/scheduler/execution-recorder.ts +1 -1
  136. package/template/apps/server/src/scheduler/history.ts +1 -1
  137. package/template/apps/server/src/scheduler/overview.ts +1 -1
  138. package/template/apps/server/src/scheduler/recovery-service.test.ts +1 -1
  139. package/template/apps/server/src/scheduler/recovery-service.ts +1 -1
  140. package/template/apps/server/src/scheduler/repository.ts +1 -1
  141. package/template/apps/server/src/scheduler/routes.ts +1 -1
  142. package/template/apps/server/src/scheduler/service-idle.test.ts +1 -1
  143. package/template/apps/server/src/scheduler/service.test.ts +1 -1
  144. package/template/apps/server/src/scheduler/service.ts +1 -1
  145. package/template/apps/server/src/scheduler/types.ts +1 -1
  146. package/template/apps/server/src/search/contracts.ts +2 -2
  147. package/template/apps/server/src/search/host.ts +1 -1
  148. package/template/apps/server/src/search/registry.ts +1 -1
  149. package/template/apps/server/src/search/routes.test.ts +1 -1
  150. package/template/apps/server/src/search/routes.ts +1 -1
  151. package/template/apps/server/src/search/service.ts +2 -2
  152. package/template/apps/server/src/search/test-support.ts +2 -2
  153. package/template/apps/server/src/session/routes.ts +1 -1
  154. package/template/apps/server/src/settings/drizzle-repository.ts +2 -2
  155. package/template/apps/server/src/settings/repository.ts +1 -1
  156. package/template/apps/server/src/settings/routes.test.ts +1 -1
  157. package/template/apps/server/src/settings/routes.ts +1 -1
  158. package/template/apps/server/src/settings/runtime.ts +1 -1
  159. package/template/apps/server/src/storage/blob-reference-registry.test.ts +1 -1
  160. package/template/apps/server/src/storage/blob-reference-registry.ts +1 -1
  161. package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +1 -1
  162. package/template/apps/server/src/storage/drizzle-upload-repository.ts +2 -2
  163. package/template/apps/server/src/storage/route-support.ts +1 -1
  164. package/template/apps/server/src/storage/routes.test.ts +1 -1
  165. package/template/apps/server/src/storage/routes.ts +2 -2
  166. package/template/apps/server/src/storage/runtime.ts +6 -4
  167. package/template/apps/server/src/system/audit-routes.ts +1 -1
  168. package/template/apps/server/src/system/department-routes.ts +1 -1
  169. package/template/apps/server/src/system/drizzle-repository.ts +1 -1
  170. package/template/apps/server/src/system/drizzle-scoped-repository.ts +1 -1
  171. package/template/apps/server/src/system/drizzle-system.ts +1 -1
  172. package/template/apps/server/src/system/entities.ts +1 -1
  173. package/template/apps/server/src/system/identity-route-config.ts +1 -1
  174. package/template/apps/server/src/system/interface-catalog.test.ts +3 -3
  175. package/template/apps/server/src/system/interface-catalog.ts +2 -2
  176. package/template/apps/server/src/system/menu-registry.ts +1 -1
  177. package/template/apps/server/src/system/menu-routes.ts +1 -1
  178. package/template/apps/server/src/system/operations.test.ts +1 -1
  179. package/template/apps/server/src/system/operations.ts +1 -1
  180. package/template/apps/server/src/system/redis-health.ts +1 -1
  181. package/template/apps/server/src/system/repository.ts +1 -1
  182. package/template/apps/server/src/system/resource-route-support.ts +1 -1
  183. package/template/apps/server/src/system/route-helpers.ts +1 -1
  184. package/template/apps/server/src/system/route-types.ts +1 -1
  185. package/template/apps/server/src/system/routes.test.ts +1 -1
  186. package/template/apps/server/src/system/routes.ts +1 -1
  187. package/template/apps/server/src/system/user-projection.ts +1 -1
  188. package/template/apps/server/src/work-order/data-scope.integration.test.ts +1 -1
  189. package/template/apps/server/src/work-order/drizzle-repository.integration.test.ts +1 -1
  190. package/template/apps/server/src/work-order/drizzle-repository.ts +2 -2
  191. package/template/apps/server/src/work-order/foundation-modules.test.ts +15 -5
  192. package/template/apps/server/src/work-order/repository.ts +1 -1
  193. package/template/apps/server/src/work-order/routes.test.ts +2 -2
  194. package/template/apps/server/src/work-order/routes.ts +2 -2
  195. package/template/apps/server/src/work-order/search-api.test.ts +3 -3
  196. package/template/apps/server/src/work-order/search-provider.test.ts +3 -3
  197. package/template/apps/server/src/work-order/service.ts +1 -1
  198. package/template/apps/server/src/work-order/task.test.ts +1 -1
  199. package/template/apps/server/src/work-order/task.ts +2 -2
  200. package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +2 -2
  201. package/template/apps/server/src/workflow/drizzle-repository.ts +3 -3
  202. package/template/apps/server/src/workflow/effects.test.ts +1 -1
  203. package/template/apps/server/src/workflow/effects.ts +1 -1
  204. package/template/apps/server/src/workflow/repository.ts +2 -2
  205. package/template/apps/server/src/workflow/routes.ts +3 -3
  206. package/template/apps/server/src/workflow/service.ts +1 -1
  207. package/template/apps/server/src/workflow/timeout-runtime.test.ts +1 -1
  208. package/template/apps/server/src/workflow/timeout-runtime.ts +2 -2
  209. package/template/apps/web/Dockerfile +2 -0
  210. package/template/apps/web/package.json +4 -4
  211. package/template/apps/web/runtime-server.ts +1 -1
  212. package/template/apps/web/src/app/layouts/AppLayout.vue +6 -0
  213. package/template/apps/web/src/components/auth/PasswordChangeForm.vue +52 -7
  214. package/template/apps/web/src/components/auth/PasswordChangeForm.webtest.ts +43 -0
  215. package/template/apps/web/src/components/common/DataPagination.vue +1 -1
  216. package/template/apps/web/src/components/license/LicenseActivationCodeForm.vue +1 -1
  217. package/template/apps/web/src/components/license/LicenseFlow.webtest.ts +2 -2
  218. package/template/apps/web/src/composables/useModuleConfigurations.ts +1 -1
  219. package/template/apps/web/src/composables/useWatermarkSettings.ts +1 -0
  220. package/template/apps/web/src/composables/watermark-settings.ts +6 -0
  221. package/template/apps/web/src/composables/watermark-settings.webtest.ts +27 -1
  222. package/template/apps/web/src/layout/AppSidebar.vue +12 -3
  223. package/template/apps/web/src/layout/AppSidebar.webtest.ts +11 -0
  224. package/template/apps/web/src/layout/GlobalWatermark.vue +25 -8
  225. package/template/apps/web/src/layout/GlobalWatermark.webtest.ts +109 -0
  226. package/template/apps/web/src/layout/NavigationSearchDialog.vue +1 -1
  227. package/template/apps/web/src/layout/NotificationMenu.vue +1 -1
  228. package/template/apps/web/src/layout/navigation.ts +5 -1
  229. package/template/apps/web/src/layout/navigation.webtest.ts +1 -1
  230. package/template/apps/web/src/pages/configuration/components/ModuleConfigRollbackDialog.vue +1 -1
  231. package/template/apps/web/src/pages/configuration/components/ModuleConfigVersionList.vue +1 -1
  232. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +1 -1
  233. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.webtest.ts +1 -1
  234. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +1 -1
  235. package/template/apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts +1 -1
  236. package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +21 -0
  237. package/template/apps/web/src/pages/system/SystemNotificationsPage.vue +2 -2
  238. package/template/apps/web/src/pages/system/components/AuditActionCell.vue +7 -2
  239. package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +7 -2
  240. package/template/apps/web/src/pages/system/components/NotificationPublishForm.vue +1 -1
  241. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.vue +1 -1
  242. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts +1 -1
  243. package/template/apps/web/src/pages/system/components/SchedulerRunTable.vue +1 -1
  244. package/template/apps/web/src/pages/system/components/SchedulerRunTable.webtest.ts +1 -1
  245. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.vue +1 -1
  246. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.webtest.ts +1 -1
  247. package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +1 -1
  248. package/template/apps/web/src/pages/system/components/SystemResourceTable.vue +10 -3
  249. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.vue +1 -1
  250. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.webtest.ts +1 -1
  251. package/template/apps/web/src/pages/system/components/role-policy/RolePolicyForm.vue +1 -1
  252. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.ts +1 -1
  253. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.webtest.ts +1 -1
  254. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.ts +2 -2
  255. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.webtest.ts +1 -1
  256. package/template/apps/web/src/pages/system/composables/useSystemResource.ts +1 -1
  257. package/template/apps/web/src/router/manifest-routes.ts +1 -1
  258. package/template/apps/web/src/router/manifest-routes.webtest.ts +1 -1
  259. package/template/apps/web/src/services/access-api.ts +10 -1
  260. package/template/apps/web/src/services/configuration-api.ts +1 -1
  261. package/template/apps/web/src/services/license-api.ts +1 -1
  262. package/template/apps/web/src/services/notification-api.ts +2 -2
  263. package/template/apps/web/src/services/operations-api.ts +1 -1
  264. package/template/apps/web/src/services/platform-settings-api.ts +2 -2
  265. package/template/apps/web/src/services/profile-api.ts +2 -2
  266. package/template/docs/architecture/durable-jobs.md +5 -0
  267. package/template/docs/architecture/module-manifest-composition.md +14 -7
  268. package/template/docs/architecture/object-storage.md +1 -1
  269. package/template/docs/development/crud-generator.md +4 -1
  270. package/template/docs/platform/audit-reliability.md +1 -1
  271. package/template/package.json +2 -1
  272. package/template/packages/config/package.json +15 -4
  273. package/template/packages/config/src/platform.ts +1 -1
  274. package/template/packages/crud-generator/package.json +1 -1
  275. package/template/packages/crud-generator/src/generator.test.ts +16 -0
  276. package/template/packages/crud-generator/src/templates/domain.ts +1 -1
  277. package/template/packages/crud-generator/src/templates/manifest.ts +2 -2
  278. package/template/packages/crud-generator/src/templates/project.ts +3 -3
  279. package/template/packages/crud-generator/src/templates/repository.ts +1 -1
  280. package/template/packages/crud-generator/src/templates/routes.ts +2 -2
  281. package/template/packages/crud-generator/src/validation.ts +22 -1
  282. package/template/packages/database/package.json +15 -5
  283. package/template/packages/database/src/bundle-validation.ts +218 -0
  284. package/template/packages/database/src/dialects.ts +1 -1
  285. package/template/packages/database/src/runner.test.ts +160 -13
  286. package/template/packages/database/src/runner.ts +95 -77
  287. package/template/packages/database/src/schema/governed-exports.ts +1 -1
  288. package/template/packages/database/src/schema/identity.ts +1 -1
  289. package/template/packages/database/src/schema/license-v1.ts +1 -1
  290. package/template/packages/database/src/schema/notifications.ts +1 -1
  291. package/template/packages/database/src/schema/platform-settings.ts +1 -1
  292. package/template/packages/database/src/schema/workflow.ts +1 -1
  293. package/template/packages/database/src/sql-store.ts +1 -1
  294. package/template/packages/database/src/store.ts +1 -1
  295. package/template/packages/example-work-order/index.ts +1 -0
  296. package/template/packages/example-work-order/package.json +4 -3
  297. package/template/packages/example-work-order/src/contract.ts +1 -1
  298. package/template/packages/example-work-order/src/manifest.ts +8 -3
  299. package/template/packages/example-work-order/src/migration-bundle.test.ts +43 -0
  300. package/template/packages/example-work-order/src/migration-bundle.ts +64 -0
  301. package/template/packages/jobs/index.ts +2 -0
  302. package/template/packages/jobs/package.json +29 -0
  303. package/template/packages/jobs/src/handlers.test.ts +72 -0
  304. package/template/{apps/server/src/jobs/handler-registry.ts → packages/jobs/src/handlers.ts} +4 -4
  305. package/template/{apps/server/src/jobs → packages/jobs/src}/types.ts +7 -1
  306. package/template/packages/{license-sdk → jobs}/tsconfig.json +0 -1
  307. package/template/packages/modules/index.ts +1 -1
  308. package/template/packages/modules/package.json +15 -5
  309. package/template/packages/modules/src/catalog-validation.ts +123 -0
  310. package/template/packages/modules/src/composition.test.ts +75 -2
  311. package/template/packages/modules/src/composition.ts +4 -2
  312. package/template/packages/modules/src/manifest.ts +7 -12
  313. package/template/packages/modules/src/menu-composition.ts +1 -1
  314. package/template/packages/modules/src/system-api-binding.ts +1 -1
  315. package/template/packages/modules/src/system-api-data-governance.ts +1 -1
  316. package/template/packages/modules/src/system-api-permissions.ts +1 -1
  317. package/template/packages/modules/src/system-data-governance.ts +1 -1
  318. package/template/packages/modules/src/system-features.ts +1 -1
  319. package/template/packages/modules/src/system-governed-export-bindings.ts +1 -1
  320. package/template/packages/modules/src/system-module-catalog.ts +1 -1
  321. package/template/packages/server-sdk/index.ts +5 -0
  322. package/template/packages/server-sdk/package.json +25 -0
  323. package/template/packages/server-sdk/src/module-host.ts +29 -0
  324. package/template/packages/server-sdk/tsconfig.json +16 -0
  325. package/template/packages/shared/index.ts +3 -0
  326. package/template/packages/shared/package.json +14 -3
  327. package/template/packages/shared/src/audit.ts +22 -1
  328. package/template/packages/shared/src/license-catalog.test.ts +17 -0
  329. package/template/packages/shared/src/license-catalog.ts +33 -0
  330. package/template/packages/shared/src/migration.ts +39 -0
  331. package/template/packages/shared/src/password.ts +4 -0
  332. package/template/packages/storage/package.json +14 -3
  333. package/template/packages/license-sdk/index.ts +0 -13
  334. package/template/packages/license-sdk/package.json +0 -18
  335. package/template/packages/license-sdk/src/bounded-json-body.test.ts +0 -65
  336. package/template/packages/license-sdk/src/bounded-json-body.ts +0 -135
  337. package/template/packages/license-sdk/src/canonical-json.test.ts +0 -28
  338. package/template/packages/license-sdk/src/canonical-json.ts +0 -104
  339. package/template/packages/license-sdk/src/client.test.ts +0 -82
  340. package/template/packages/license-sdk/src/client.ts +0 -86
  341. package/template/packages/license-sdk/src/device.ts +0 -46
  342. package/template/packages/license-sdk/src/file-storage.test.ts +0 -80
  343. package/template/packages/license-sdk/src/file-storage.ts +0 -77
  344. package/template/packages/license-sdk/src/installation.test.ts +0 -241
  345. package/template/packages/license-sdk/src/installation.ts +0 -150
  346. package/template/packages/license-sdk/src/license-parser.ts +0 -56
  347. package/template/packages/license-sdk/src/offline-code-base32.ts +0 -57
  348. package/template/packages/license-sdk/src/offline-code-decompression.ts +0 -55
  349. package/template/packages/license-sdk/src/offline-code-limits.ts +0 -10
  350. package/template/packages/license-sdk/src/offline-code-wire.ts +0 -72
  351. package/template/packages/license-sdk/src/offline-code.test.ts +0 -172
  352. package/template/packages/license-sdk/src/offline-code.ts +0 -319
  353. package/template/packages/license-sdk/src/payload.test.ts +0 -72
  354. package/template/packages/license-sdk/src/payload.ts +0 -201
  355. package/template/packages/license-sdk/src/storage.ts +0 -64
  356. package/template/packages/license-sdk/src/test-fixtures.ts +0 -59
  357. package/template/packages/license-sdk/src/v1-test-vector.ts +0 -49
  358. package/template/packages/license-sdk/src/validation.test.ts +0 -62
  359. package/template/packages/license-sdk/src/validation.ts +0 -143
  360. package/template/packages/license-sdk/src/verification.test.ts +0 -97
  361. package/template/packages/license-sdk/src/verification.ts +0 -199
package/README.md CHANGED
@@ -66,6 +66,12 @@ npx create-windy@latest my-dashboard \
66
66
  法律许可证与离线 `system.license` 是两项独立选择:前者决定项目代码授权,后者
67
67
  为离线部署提供运行时验签与限制态。
68
68
 
69
+ 选择 `system.license` 时,Server 与 Web 通过 npm 依赖
70
+ `@southwind-ai/license@^0.1.1` 使用运行时能力;生成项目及 `create-windy` 模板快照都不包含
71
+ `packages/license-sdk` 源码。公网 npm 已发布兼容的 `@southwind-ai/license@0.1.1`;
72
+ 发布包含该模块的新版创建器前,必须先确认目标 registry 中存在兼容版本,并完成真实
73
+ 安装回归。
74
+
69
75
  未选择的模块会从 package、源码、依赖、Composition、Manifest、schema、migration
70
76
  和模块文档中物理排除,而不是只隐藏菜单或关闭 Feature。模块依赖会自动补齐;未知
71
77
  模块和不闭合组合会在写入前拒绝。
@@ -99,9 +105,14 @@ bun run dev
99
105
  ```
100
106
 
101
107
  create-windy 会生成仅供本机使用、被 Git 忽略且权限为 `0600` 的 `.env`,其中数据库
102
- 与管理员开发密码均为随机值。`bun run dev` 会通过 Docker Compose 等待 PostgreSQL、
103
- 执行 migration,再启动 Server 与 Web;首次运行前需安装并启动 Docker 与 Docker
104
- Compose。
108
+ 与管理员开发密码均为随机值。全新数据库的初始平台账号固定为 `admin`,初始密码查看
109
+ `.env` 中的 `WINDY_BOOTSTRAP_ADMIN_PASSWORD`;创建器只提示密码位置,不会把随机密码
110
+ 直接打印在终端。首次登录必须修改密码,新密码需要 12-128 个字符,且不能与当前密码
111
+ 相同。
112
+
113
+ `bun run dev` 会通过 Docker Compose 等待 PostgreSQL、执行 migration,再启动 Server
114
+ 与 Web;首次运行前需安装并启动 Docker 与 Docker Compose。环境变量只负责初始化全新
115
+ 数据库,数据库已有管理员后,重启服务不会重新覆盖其密码。
105
116
 
106
117
  只调试单个应用时可分别使用 `bun run dev:web` 和 `bun run dev:server`。`dev:web` 不会
107
118
  隐式启动后端;`dev:server` 也不会自动启动 PostgreSQL 或执行 migration。
package/dist/cli.js CHANGED
@@ -359,7 +359,8 @@ var optionalModuleManifests = [
359
359
  "system",
360
360
  "system.identity",
361
361
  "system.search",
362
- "system.scheduler"
362
+ "system.scheduler",
363
+ "system.storage"
363
364
  ]),
364
365
  packages: ["packages/example-work-order"],
365
366
  fileRoots: [
@@ -383,6 +384,7 @@ function module(name, label, description, dependencies) {
383
384
  dependencies,
384
385
  conflicts: [],
385
386
  packages: [],
387
+ registryDependencies: [],
386
388
  fileRoots: [],
387
389
  documentation: [],
388
390
  schemaFiles: [],
@@ -435,7 +437,13 @@ var platformModules = [
435
437
  },
436
438
  {
437
439
  ...module2("system.license", "离线 License", "离线验签、安装和限制态。", "optional", ["system"]),
438
- packages: ["packages/license-sdk"],
440
+ registryDependencies: [
441
+ {
442
+ sourceName: "@southwind-ai/license",
443
+ name: "@southwind-ai/license",
444
+ version: "^0.1.1"
445
+ }
446
+ ],
439
447
  fileRoots: [
440
448
  "apps/server/src/license",
441
449
  "apps/web/src/components/license",
@@ -582,6 +590,7 @@ function module2(name, label, description, selection, dependencies = []) {
582
590
  dependencies,
583
591
  conflicts: [],
584
592
  packages: [],
593
+ registryDependencies: [],
585
594
  fileRoots: [],
586
595
  documentation: [],
587
596
  schemaFiles: [],
@@ -711,7 +720,7 @@ var helpText = `create-windy <项目名> [选项]
711
720
  `;
712
721
 
713
722
  // src/create-project.ts
714
- import { mkdir as mkdir4, readdir as readdir4, rm as rm4 } from "node:fs/promises";
723
+ import { mkdir as mkdir4, readdir as readdir5, rm as rm4 } from "node:fs/promises";
715
724
 
716
725
  // src/commands.ts
717
726
  import { spawn } from "node:child_process";
@@ -902,14 +911,14 @@ function isAlreadyExists(error) {
902
911
  // src/generator.ts
903
912
  import {
904
913
  copyFile,
905
- lstat as lstat3,
914
+ lstat as lstat4,
906
915
  mkdir as mkdir3,
907
- readFile as readFile8,
908
- readdir as readdir3,
916
+ readFile as readFile9,
917
+ readdir as readdir4,
909
918
  rm as rm3,
910
- writeFile as writeFile7
919
+ writeFile as writeFile8
911
920
  } from "node:fs/promises";
912
- import { basename as basename2, extname as extname2, join as join8 } from "node:path";
921
+ import { basename as basename3, extname as extname3, join as join9 } from "node:path";
913
922
 
914
923
  // src/customer-docker.ts
915
924
  import { readFile as readFile2, writeFile } from "node:fs/promises";
@@ -919,6 +928,7 @@ var supplierWorkspaceCopies = [
919
928
  "COPY apps/signing-service/package.json apps/signing-service/package.json",
920
929
  "COPY packages/create-windy/package.json packages/create-windy/package.json"
921
930
  ];
931
+ var supplierWorkspacePaths = ["packages/license-sdk"];
922
932
  async function prepareCustomerDockerfiles(root) {
923
933
  await Promise.all(["apps/server/Dockerfile", "apps/web/Dockerfile"].map(async (path) => {
924
934
  const absolutePath = join2(root, path);
@@ -929,7 +939,7 @@ async function prepareCustomerDockerfiles(root) {
929
939
  function rewriteCustomerDockerfile(source) {
930
940
  const lines = source.split(`
931
941
  `).filter((line) => {
932
- return !supplierWorkspaceCopies.includes(line) && !line.includes("deploy/production/server-entrypoint.sh");
942
+ return !supplierWorkspaceCopies.includes(line) && !supplierWorkspacePaths.some((path) => line.includes(path)) && !line.includes("deploy/production/server-entrypoint.sh");
933
943
  });
934
944
  return lines.join(`
935
945
  `).replace("COPY package.json bun.lock ./", "COPY package.json ./").replace("RUN bun install --frozen-lockfile", "RUN bun install");
@@ -1131,6 +1141,10 @@ async function materializeSelectedModules(targetDirectory, selectedNames) {
1131
1141
  const selected = new Set(selectedNames);
1132
1142
  const removed = moduleDistributionCatalog.filter(({ name }) => !selected.has(name));
1133
1143
  const removedPackageNames = await readRemovedPackageNames(targetDirectory, removed.flatMap(({ packages }) => packages));
1144
+ for (const dependency of removed.flatMap(({ registryDependencies }) => registryDependencies)) {
1145
+ removedPackageNames.add(dependency.sourceName);
1146
+ removedPackageNames.add(dependency.name);
1147
+ }
1134
1148
  await stripModuleBlocks(targetDirectory, selected);
1135
1149
  await pruneDatabaseArtifacts(targetDirectory, removed.flatMap(({ databaseTables, transientDatabaseTables }) => [
1136
1150
  ...databaseTables,
@@ -1380,7 +1394,7 @@ License 签发中心、独立签名服务、Vault、发布治理、内部任务
1380
1394
 
1381
1395
  - 架构:从 [Module Manifest 组合](./architecture/module-manifest-composition.md) 开始。
1382
1396
  - 平台开发:从 [系统 CRUD API](./platform/system-crud-api.md) 和 [CRUD 生成器](./development/crud-generator.md) 开始。
1383
- ${includeOfflineLicense ? "- License 消费端:[离线激活与安装协议](./license/license-offline-activation-code.md);运行时 SDK 位于 `packages/license-sdk`。" : ""}
1397
+ ${includeOfflineLicense ? "- License 消费端:[离线激活与安装协议](./license/license-offline-activation-code.md);运行时能力由 npm 依赖 `@southwind-ai/license` 提供。" : ""}
1384
1398
  - 运维:[可观测性](./operations/observability.md) 与 [运维总览](./platform/operations-overview.md)。
1385
1399
  - 兼容:[RuoYi-Vue Adapter](./adapters/ruoyi-vue-compatibility.md)。
1386
1400
  `;
@@ -1443,6 +1457,14 @@ bun run dev:server
1443
1457
 
1444
1458
  ## 页面与登录
1445
1459
 
1460
+ 全新数据库的初始平台账号为 \`admin\`。初始密码不是所有项目共用的固定值,而是
1461
+ create-windy 在本机 \`.env\` 中随机生成的 \`WINDY_BOOTSTRAP_ADMIN_PASSWORD\`;该文件已
1462
+ 被 Git 忽略,请在本机直接查看,不要把密码提交到仓库或复制到文档。首次登录会要求
1463
+ 立即修改密码,新密码必须为 12-128 个字符,且不能与当前密码相同。
1464
+
1465
+ \`.env\` 只负责全新数据库的首次初始化。账号密码写入数据库后,重启不会用环境变量
1466
+ 覆盖已有密码;如果已经完成首次改密,应使用修改后的密码登录。
1467
+
1446
1468
  | 路径 | 访问要求 | 说明 |
1447
1469
  | ---- | -------- | ---- |
1448
1470
  | \`/login\` | 公开 | 登录成功后回到安全的站内目标,默认进入 \`/\` |
@@ -1563,7 +1585,8 @@ function createStarterPackage(source, projectName, includeOxc = true, projectLic
1563
1585
  typecheck: [
1564
1586
  "bun run --cwd apps/web typecheck",
1565
1587
  "bun run --cwd apps/server typecheck",
1566
- ...selectedModules.includes("system.license") ? ["bun run --cwd packages/license-sdk typecheck"] : [],
1588
+ "bun run --cwd packages/jobs typecheck",
1589
+ "bun run --cwd packages/server-sdk typecheck",
1567
1590
  ...selectedModules.includes("system.storage") ? ["bun run --cwd packages/storage typecheck"] : [],
1568
1591
  "bun run --cwd packages/database typecheck",
1569
1592
  "bun run --cwd packages/crud-generator typecheck"
@@ -1604,8 +1627,9 @@ var templateDirectories = [
1604
1627
  "packages/crud-generator",
1605
1628
  "packages/database",
1606
1629
  "packages/example-work-order",
1607
- "packages/license-sdk",
1630
+ "packages/jobs",
1608
1631
  "packages/modules",
1632
+ "packages/server-sdk",
1609
1633
  "packages/shared",
1610
1634
  "packages/storage"
1611
1635
  ];
@@ -1741,6 +1765,81 @@ function isModuleVersion(value) {
1741
1765
  return typeof module3.name === "string" && module3.name.length > 0 && typeof module3.version === "string" && module3.version.length > 0;
1742
1766
  }
1743
1767
 
1768
+ // src/registry-dependencies.ts
1769
+ import { lstat as lstat3, readFile as readFile8, readdir as readdir3, writeFile as writeFile7 } from "node:fs/promises";
1770
+ import { basename as basename2, extname as extname2, join as join8 } from "node:path";
1771
+ var dependencySections = [
1772
+ "dependencies",
1773
+ "devDependencies",
1774
+ "optionalDependencies",
1775
+ "peerDependencies"
1776
+ ];
1777
+ var replaceableExtensions = new Set([
1778
+ ".css",
1779
+ ".html",
1780
+ ".js",
1781
+ ".json",
1782
+ ".md",
1783
+ ".mjs",
1784
+ ".ts",
1785
+ ".tsx",
1786
+ ".vue"
1787
+ ]);
1788
+ async function materializeRegistryDependencies(root, dependencies) {
1789
+ if (!dependencies.length)
1790
+ return;
1791
+ for (const path of await collectFiles3(root)) {
1792
+ if (!replaceableExtensions.has(extname2(path)))
1793
+ continue;
1794
+ if (basename2(path) === "package.json") {
1795
+ await rewritePackageJson(path, dependencies);
1796
+ continue;
1797
+ }
1798
+ const source = await readFile8(path, "utf8");
1799
+ const output = dependencies.reduce((value, dependency) => value.replaceAll(dependency.sourceName, dependency.name), source);
1800
+ if (output !== source)
1801
+ await writeFile7(path, output);
1802
+ }
1803
+ }
1804
+ async function rewritePackageJson(path, registryDependencies) {
1805
+ const value = JSON.parse(await readFile8(path, "utf8"));
1806
+ let changed = false;
1807
+ for (const section of dependencySections) {
1808
+ const dependencies = value[section];
1809
+ if (!dependencies)
1810
+ continue;
1811
+ for (const dependency of registryDependencies) {
1812
+ if (!(dependency.sourceName in dependencies))
1813
+ continue;
1814
+ delete dependencies[dependency.sourceName];
1815
+ dependencies[dependency.name] = dependency.version;
1816
+ changed = true;
1817
+ }
1818
+ }
1819
+ if (changed)
1820
+ await writeFile7(path, `${JSON.stringify(value, null, 2)}
1821
+ `);
1822
+ }
1823
+ async function collectFiles3(root) {
1824
+ const files = [];
1825
+ await visit(root);
1826
+ return files.sort();
1827
+ async function visit(directory) {
1828
+ for (const name of (await readdir3(directory)).sort()) {
1829
+ if ([".git", "node_modules", "dist"].includes(name))
1830
+ continue;
1831
+ const path = join8(directory, name);
1832
+ const metadata = await lstat3(path);
1833
+ if (metadata.isSymbolicLink())
1834
+ continue;
1835
+ if (metadata.isDirectory())
1836
+ await visit(path);
1837
+ else
1838
+ files.push(path);
1839
+ }
1840
+ }
1841
+ }
1842
+
1744
1843
  // src/generator.ts
1745
1844
  async function generateProject(input) {
1746
1845
  validateProjectName(input.projectName);
@@ -1752,29 +1851,30 @@ async function generateProject(input) {
1752
1851
  const templateMetadata = await readTemplateMetadata(input.sourceRoot);
1753
1852
  const selectedModules = input.selectedModules ?? templateMetadata.modules.filter(({ name }) => includeExample || name !== "work-order").map(({ name }) => name);
1754
1853
  for (const relativePath2 of generationTemplatePaths(true, includeOxc)) {
1755
- await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join8(input.targetDirectory, relativePath2));
1854
+ await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join9(input.targetDirectory, relativePath2));
1756
1855
  }
1757
1856
  await materializeSelectedModules(input.targetDirectory, selectedModules);
1758
- const packagePath = join8(input.targetDirectory, "package.json");
1759
- const packageJson = JSON.parse(await readFile8(packagePath, "utf8"));
1760
- await writeFile7(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion), null, 2)}
1857
+ await materializeRegistryDependencies(input.targetDirectory, selectedModuleManifests(selectedModules).flatMap(({ registryDependencies }) => registryDependencies));
1858
+ const packagePath = join9(input.targetDirectory, "package.json");
1859
+ const packageJson = JSON.parse(await readFile9(packagePath, "utf8"));
1860
+ await writeFile8(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion), null, 2)}
1761
1861
  `);
1762
- await writeFile7(join8(input.targetDirectory, "docker-compose.yml"), starterCompose);
1763
- await writeFile7(join8(input.targetDirectory, ".env.example"), environmentExample(includeExample));
1764
- await writeFile7(join8(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
1765
- await writeFile7(join8(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license")));
1862
+ await writeFile8(join9(input.targetDirectory, "docker-compose.yml"), starterCompose);
1863
+ await writeFile8(join9(input.targetDirectory, ".env.example"), environmentExample(includeExample));
1864
+ await writeFile8(join9(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
1865
+ await writeFile8(join9(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license")));
1766
1866
  await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
1767
1867
  await applyWindyBaseLicense(input.targetDirectory);
1768
1868
  await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
1769
1869
  await prepareCustomerDockerfiles(input.targetDirectory);
1770
1870
  await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense);
1771
- await rm3(join8(input.targetDirectory, "bun.lock"), { force: true });
1871
+ await rm3(join9(input.targetDirectory, "bun.lock"), { force: true });
1772
1872
  await writeManagedFilesManifest(input.targetDirectory, templateMetadata.generatorVersion);
1773
1873
  }
1774
1874
  async function resolveTemplateSource(sourceRoot, relativePath2) {
1775
- const source = join8(sourceRoot, relativePath2);
1875
+ const source = join9(sourceRoot, relativePath2);
1776
1876
  try {
1777
- await lstat3(source);
1877
+ await lstat4(source);
1778
1878
  return source;
1779
1879
  } catch (error) {
1780
1880
  if (!isMissing2(error))
@@ -1783,13 +1883,13 @@ async function resolveTemplateSource(sourceRoot, relativePath2) {
1783
1883
  const alias = npmTemplateAliases[relativePath2];
1784
1884
  if (!alias)
1785
1885
  return source;
1786
- return join8(sourceRoot, alias);
1886
+ return join9(sourceRoot, alias);
1787
1887
  }
1788
1888
  async function assertGeneratedProjectIsClean(targetDirectory) {
1789
1889
  const violations = [];
1790
1890
  await walk(targetDirectory, async (path) => {
1791
- const name = basename2(path);
1792
- const extension = extname2(name).toLowerCase();
1891
+ const name = basename3(path);
1892
+ const extension = extname3(name).toLowerCase();
1793
1893
  if (excludedNames.has(name) || excludedRuntimeFiles.has(name) || [".key", ".pem", ".p12", ".pfx"].includes(extension)) {
1794
1894
  violations.push(path.slice(targetDirectory.length + 1));
1795
1895
  }
@@ -1808,7 +1908,7 @@ function validateProjectName(projectName) {
1808
1908
  }
1809
1909
  async function assertTargetAvailable(targetDirectory) {
1810
1910
  try {
1811
- const entries = await readdir3(targetDirectory);
1911
+ const entries = await readdir4(targetDirectory);
1812
1912
  if (entries.length)
1813
1913
  throw new Error("目标目录不是空目录");
1814
1914
  } catch (error) {
@@ -1818,28 +1918,28 @@ async function assertTargetAvailable(targetDirectory) {
1818
1918
  }
1819
1919
  }
1820
1920
  async function copyTree(source, target) {
1821
- const metadata = await lstat3(source);
1822
- const name = basename2(source);
1921
+ const metadata = await lstat4(source);
1922
+ const name = basename3(source);
1823
1923
  if (shouldExclude(name) || metadata.isSymbolicLink())
1824
1924
  return;
1825
1925
  if (metadata.isDirectory()) {
1826
1926
  await mkdir3(target, { recursive: true });
1827
- for (const child of await readdir3(source)) {
1828
- await copyTree(join8(source, child), join8(target, child));
1927
+ for (const child of await readdir4(source)) {
1928
+ await copyTree(join9(source, child), join9(target, child));
1829
1929
  }
1830
1930
  return;
1831
1931
  }
1832
- await mkdir3(join8(target, ".."), { recursive: true });
1932
+ await mkdir3(join9(target, ".."), { recursive: true });
1833
1933
  await copyFile(source, target);
1834
1934
  }
1835
1935
  function shouldExclude(name) {
1836
1936
  return excludedNames.has(name) || excludedRuntimeFiles.has(name);
1837
1937
  }
1838
1938
  async function walk(directory, visit) {
1839
- for (const name of await readdir3(directory)) {
1840
- const path = join8(directory, name);
1939
+ for (const name of await readdir4(directory)) {
1940
+ const path = join9(directory, name);
1841
1941
  await visit(path);
1842
- if ((await lstat3(path)).isDirectory())
1942
+ if ((await lstat4(path)).isDirectory())
1843
1943
  await walk(path, visit);
1844
1944
  }
1845
1945
  }
@@ -1907,6 +2007,8 @@ async function createProject(options, dependencies = {}) {
1907
2007
  log(`运行时:Bun ${bunVersion}`);
1908
2008
  log(options.initializeGit ? gitInitialized ? "Git:已创建 main 分支和首次提交" : "Git:项目已保留,请按上述提示完成初始化" : "Git:已按 --no-git 跳过");
1909
2009
  log(localEnvironment === "created" ? "本地 .env:已生成随机开发密码(权限 0600)" : "本地 .env:已存在,未覆盖");
2010
+ log("初始平台账号:admin");
2011
+ log("初始平台密码:查看 .env 中的 WINDY_BOOTSTRAP_ADMIN_PASSWORD(首次登录后必须修改)");
1910
2012
  log("下一步(启动数据库、迁移、后端与前端):");
1911
2013
  log(` cd ${options.projectName}`);
1912
2014
  log(" bun run dev");
@@ -1914,7 +2016,7 @@ async function createProject(options, dependencies = {}) {
1914
2016
  }
1915
2017
  async function inspectTarget(path) {
1916
2018
  try {
1917
- return (await readdir4(path)).length === 0 ? "empty" : "non-empty";
2019
+ return (await readdir5(path)).length === 0 ? "empty" : "non-empty";
1918
2020
  } catch (error) {
1919
2021
  if (isMissing3(error))
1920
2022
  return "missing";
@@ -3686,8 +3788,8 @@ import { rm as rm8 } from "node:fs/promises";
3686
3788
  import { resolve as resolve4 } from "node:path";
3687
3789
 
3688
3790
  // src/update/doctor.ts
3689
- import { readFile as readFile10 } from "node:fs/promises";
3690
- import { join as join10 } from "node:path";
3791
+ import { readFile as readFile11 } from "node:fs/promises";
3792
+ import { join as join11 } from "node:path";
3691
3793
 
3692
3794
  // src/update/process.ts
3693
3795
  import { spawn as spawn3 } from "node:child_process";
@@ -3719,11 +3821,11 @@ import {
3719
3821
  access as access2,
3720
3822
  copyFile as copyFile2,
3721
3823
  mkdir as mkdir5,
3722
- readFile as readFile9,
3824
+ readFile as readFile10,
3723
3825
  rm as rm5,
3724
- writeFile as writeFile8
3826
+ writeFile as writeFile9
3725
3827
  } from "node:fs/promises";
3726
- import { dirname as dirname3, join as join9 } from "node:path";
3828
+ import { dirname as dirname3, join as join10 } from "node:path";
3727
3829
  var updateStatePath = ".windy/update-state.json";
3728
3830
  async function applyTransaction(plan) {
3729
3831
  if (plan.conflicts.length) {
@@ -3732,7 +3834,7 @@ async function applyTransaction(plan) {
3732
3834
  const changed = plan.files.filter(({ action }) => action === "create" || action === "update" || action === "delete");
3733
3835
  for (const file of changed)
3734
3836
  assertSafePath(file.path);
3735
- const backupDirectory = join9(plan.projectDirectory, ".windy/backups", plan.id);
3837
+ const backupDirectory = join10(plan.projectDirectory, ".windy/backups", plan.id);
3736
3838
  const protectedPaths = new Set([
3737
3839
  ...changed.map(({ path: path2 }) => path2),
3738
3840
  ".windy/generation.json",
@@ -3741,12 +3843,12 @@ async function applyTransaction(plan) {
3741
3843
  ]);
3742
3844
  const backupEntries = [];
3743
3845
  for (const path2 of protectedPaths) {
3744
- const source = join9(plan.projectDirectory, path2);
3846
+ const source = join10(plan.projectDirectory, path2);
3745
3847
  const existed = await exists(source);
3746
3848
  backupEntries.push({ path: path2, existed });
3747
3849
  if (!existed)
3748
3850
  continue;
3749
- const target = join9(backupDirectory, "files", path2);
3851
+ const target = join10(backupDirectory, "files", path2);
3750
3852
  await mkdir5(dirname3(target), { recursive: true });
3751
3853
  await copyFile2(source, target);
3752
3854
  }
@@ -3759,7 +3861,7 @@ async function applyTransaction(plan) {
3759
3861
  await writeState(plan.projectDirectory, state);
3760
3862
  try {
3761
3863
  for (const file of changed) {
3762
- const target = join9(plan.projectDirectory, file.path);
3864
+ const target = join10(plan.projectDirectory, file.path);
3763
3865
  if (file.action === "delete") {
3764
3866
  await rm5(target, { force: true });
3765
3867
  continue;
@@ -3767,7 +3869,7 @@ async function applyTransaction(plan) {
3767
3869
  if (!file.content)
3768
3870
  throw new Error(`更新计划缺少文件内容:${file.path}`);
3769
3871
  await mkdir5(dirname3(target), { recursive: true });
3770
- await writeFile8(target, file.content);
3872
+ await writeFile9(target, file.content);
3771
3873
  }
3772
3874
  } catch (error) {
3773
3875
  await restoreUpdateState(plan.projectDirectory, state);
@@ -3782,7 +3884,7 @@ async function applyTransaction(plan) {
3782
3884
  }
3783
3885
  async function readUpdateState(projectDirectory) {
3784
3886
  try {
3785
- const parsed = JSON.parse(await readFile9(join9(projectDirectory, updateStatePath), "utf8"));
3887
+ const parsed = JSON.parse(await readFile10(join10(projectDirectory, updateStatePath), "utf8"));
3786
3888
  if (!isUpdateState(parsed))
3787
3889
  throw new Error("更新恢复状态无效,请人工检查 .windy 目录");
3788
3890
  return parsed;
@@ -3795,25 +3897,25 @@ async function readUpdateState(projectDirectory) {
3795
3897
  async function restoreUpdateState(projectDirectory, state) {
3796
3898
  for (const entry of state.entries) {
3797
3899
  assertSafePath(entry.path);
3798
- const target = join9(projectDirectory, entry.path);
3900
+ const target = join10(projectDirectory, entry.path);
3799
3901
  if (!entry.existed) {
3800
3902
  await rm5(target, { force: true });
3801
3903
  continue;
3802
3904
  }
3803
- const backup = join9(state.backupDirectory, "files", entry.path);
3905
+ const backup = join10(state.backupDirectory, "files", entry.path);
3804
3906
  await mkdir5(dirname3(target), { recursive: true });
3805
3907
  await copyFile2(backup, target);
3806
3908
  }
3807
- await rm5(join9(projectDirectory, updateStatePath), { force: true });
3909
+ await rm5(join10(projectDirectory, updateStatePath), { force: true });
3808
3910
  await rm5(state.backupDirectory, { recursive: true, force: true });
3809
3911
  }
3810
3912
  async function clearUpdateState(projectDirectory) {
3811
- await rm5(join9(projectDirectory, updateStatePath), { force: true });
3913
+ await rm5(join10(projectDirectory, updateStatePath), { force: true });
3812
3914
  }
3813
3915
  async function writeState(projectDirectory, state) {
3814
- const path2 = join9(projectDirectory, updateStatePath);
3916
+ const path2 = join10(projectDirectory, updateStatePath);
3815
3917
  await mkdir5(dirname3(path2), { recursive: true });
3816
- await writeFile8(path2, `${JSON.stringify(state, null, 2)}
3918
+ await writeFile9(path2, `${JSON.stringify(state, null, 2)}
3817
3919
  `);
3818
3920
  }
3819
3921
  async function exists(path2) {
@@ -3861,7 +3963,7 @@ async function diagnoseProject(projectDirectory, repair = false) {
3861
3963
  if (file.ownership === "project-owned")
3862
3964
  continue;
3863
3965
  try {
3864
- const changed = hashContent(await readFile10(join10(projectDirectory, file.path))) !== file.hash;
3966
+ const changed = hashContent(await readFile11(join11(projectDirectory, file.path))) !== file.hash;
3865
3967
  if (!changed)
3866
3968
  continue;
3867
3969
  modifiedManagedFiles.push(file.path);
@@ -3897,7 +3999,9 @@ var recipes = [
3897
3999
  { id: "starter-0.2.2-to-0.2.3", from: "0.2.2", to: "0.2.3" },
3898
4000
  { id: "starter-0.2.3-to-0.2.4", from: "0.2.3", to: "0.2.4" },
3899
4001
  { id: "starter-0.2.4-to-0.2.5", from: "0.2.4", to: "0.2.5" },
3900
- { id: "starter-0.2.5-to-0.2.6", from: "0.2.5", to: "0.2.6" }
4002
+ { id: "starter-0.2.5-to-0.2.6", from: "0.2.5", to: "0.2.6" },
4003
+ { id: "starter-0.2.6-to-0.2.7", from: "0.2.6", to: "0.2.7" },
4004
+ { id: "starter-0.2.7-to-0.2.8", from: "0.2.7", to: "0.2.8" }
3901
4005
  ];
3902
4006
  function resolveRecipeChain(sourceVersion, targetVersion) {
3903
4007
  if (sourceVersion === targetVersion)
@@ -3922,19 +4026,19 @@ function resolveRecipeChain(sourceVersion, targetVersion) {
3922
4026
  }
3923
4027
 
3924
4028
  // src/update/updater.ts
3925
- import { mkdir as mkdir7, readFile as readFile13, rm as rm7, writeFile as writeFile10 } from "node:fs/promises";
3926
- import { dirname as dirname4, join as join14 } from "node:path";
4029
+ import { mkdir as mkdir7, readFile as readFile14, rm as rm7, writeFile as writeFile11 } from "node:fs/promises";
4030
+ import { dirname as dirname4, join as join15 } from "node:path";
3927
4031
 
3928
4032
  // src/update/artifacts.ts
3929
- import { mkdir as mkdir6, mkdtemp, readFile as readFile11 } from "node:fs/promises";
4033
+ import { mkdir as mkdir6, mkdtemp, readFile as readFile12 } from "node:fs/promises";
3930
4034
  import { tmpdir } from "node:os";
3931
- import { basename as basename3, join as join11 } from "node:path";
4035
+ import { basename as basename4, join as join12 } from "node:path";
3932
4036
  class PublishedArtifactProvider {
3933
4037
  async prepare(projectDirectory, provenance) {
3934
- const temporaryRoot = await mkdtemp(join11(tmpdir(), "windy-update-"));
4038
+ const temporaryRoot = await mkdtemp(join12(tmpdir(), "windy-update-"));
3935
4039
  const projectName = await readProjectName2(projectDirectory);
3936
- const baseDirectory = join11(temporaryRoot, "base", projectName);
3937
- const targetDirectory = join11(temporaryRoot, "target", projectName);
4040
+ const baseDirectory = join12(temporaryRoot, "base", projectName);
4041
+ const targetDirectory = join12(temporaryRoot, "target", projectName);
3938
4042
  await generatePublishedBase(temporaryRoot, projectName, provenance, baseDirectory);
3939
4043
  await generateProject({
3940
4044
  sourceRoot: await resolveTemplateRoot(),
@@ -3950,7 +4054,7 @@ class PublishedArtifactProvider {
3950
4054
  }
3951
4055
  }
3952
4056
  async function generatePublishedBase(temporaryRoot, projectName, provenance, expectedDirectory) {
3953
- const parent = join11(temporaryRoot, "base");
4057
+ const parent = join12(temporaryRoot, "base");
3954
4058
  await mkdir6(parent, { recursive: true });
3955
4059
  const args = [
3956
4060
  "--bun",
@@ -3974,33 +4078,33 @@ async function generatePublishedBase(temporaryRoot, projectName, provenance, exp
3974
4078
  }
3975
4079
  }
3976
4080
  await assertProcess("bunx", args, parent);
3977
- if (join11(parent, projectName) !== expectedDirectory) {
4081
+ if (join12(parent, projectName) !== expectedDirectory) {
3978
4082
  throw new Error("历史 artifact 生成目录异常");
3979
4083
  }
3980
4084
  }
3981
4085
  async function readProjectName2(projectDirectory) {
3982
- const source = JSON.parse(await readFile11(join11(projectDirectory, "package.json"), "utf8"));
3983
- return source.name || basename3(projectDirectory);
4086
+ const source = JSON.parse(await readFile12(join12(projectDirectory, "package.json"), "utf8"));
4087
+ return source.name || basename4(projectDirectory);
3984
4088
  }
3985
4089
 
3986
4090
  // src/update/planner.ts
3987
- import { access as access3, readFile as readFile12 } from "node:fs/promises";
3988
- import { join as join13 } from "node:path";
4091
+ import { access as access3, readFile as readFile13 } from "node:fs/promises";
4092
+ import { join as join14 } from "node:path";
3989
4093
 
3990
4094
  // src/update/merge.ts
3991
- import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile9 } from "node:fs/promises";
4095
+ import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile10 } from "node:fs/promises";
3992
4096
  import { tmpdir as tmpdir2 } from "node:os";
3993
- import { join as join12 } from "node:path";
4097
+ import { join as join13 } from "node:path";
3994
4098
  async function mergeTextFile(base, ours, theirs) {
3995
- const root = await mkdtemp2(join12(tmpdir2(), "windy-merge-"));
4099
+ const root = await mkdtemp2(join13(tmpdir2(), "windy-merge-"));
3996
4100
  try {
3997
- const oursPath = join12(root, "ours");
3998
- const basePath = join12(root, "base");
3999
- const theirsPath = join12(root, "theirs");
4101
+ const oursPath = join13(root, "ours");
4102
+ const basePath = join13(root, "base");
4103
+ const theirsPath = join13(root, "theirs");
4000
4104
  await Promise.all([
4001
- writeFile9(oursPath, ours),
4002
- writeFile9(basePath, base),
4003
- writeFile9(theirsPath, theirs)
4105
+ writeFile10(oursPath, ours),
4106
+ writeFile10(basePath, base),
4107
+ writeFile10(theirsPath, theirs)
4004
4108
  ]);
4005
4109
  const result = await captureProcess("git", ["merge-file", "-p", "--diff3", oursPath, basePath, theirsPath], root);
4006
4110
  if (result.code === 0) {
@@ -4118,9 +4222,9 @@ async function createUpdatePlan(request, artifacts) {
4118
4222
  }
4119
4223
  async function planFile(path2, project, baseRoot, targetRoot, source, target) {
4120
4224
  const [ours, base, theirs] = await Promise.all([
4121
- readOptional(join13(project, path2)),
4122
- readOptional(join13(baseRoot, path2)),
4123
- readOptional(join13(targetRoot, path2))
4225
+ readOptional(join14(project, path2)),
4226
+ readOptional(join14(baseRoot, path2)),
4227
+ readOptional(join14(targetRoot, path2))
4124
4228
  ]);
4125
4229
  const ownership = target?.ownership || source?.ownership || classifyOwnership(path2);
4126
4230
  if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
@@ -4188,7 +4292,7 @@ function conflict(path2, ownership, reason) {
4188
4292
  }
4189
4293
  async function readOptional(path2) {
4190
4294
  try {
4191
- return await readFile12(path2);
4295
+ return await readFile13(path2);
4192
4296
  } catch (error) {
4193
4297
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
4194
4298
  return;
@@ -4204,7 +4308,7 @@ async function assertGitClean(projectDirectory) {
4204
4308
  }
4205
4309
  async function assertNoPendingUpdate(projectDirectory) {
4206
4310
  try {
4207
- await access3(join13(projectDirectory, ".windy/update-state.json"));
4311
+ await access3(join14(projectDirectory, ".windy/update-state.json"));
4208
4312
  throw new Error("检测到未完成更新,请先运行 bun run windy doctor --repair");
4209
4313
  } catch (error) {
4210
4314
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -4240,7 +4344,7 @@ class DefaultStarterUpdater {
4240
4344
  try {
4241
4345
  await this.#execute("bun", ["install", "--force"], result.plan.projectDirectory);
4242
4346
  steps.push({ name: "bun install --force", status: "passed" });
4243
- const packageJson = JSON.parse(await readFile13(join14(result.plan.projectDirectory, "package.json"), "utf8"));
4347
+ const packageJson = JSON.parse(await readFile14(join15(result.plan.projectDirectory, "package.json"), "utf8"));
4244
4348
  for (const name of ["lint", "typecheck", "test", "build"]) {
4245
4349
  if (!packageJson.scripts?.[name]) {
4246
4350
  steps.push({ name: `bun run ${name}`, status: "skipped" });
@@ -4269,13 +4373,13 @@ class DefaultStarterUpdater {
4269
4373
  }
4270
4374
  async function finalize(result) {
4271
4375
  const root = result.plan.projectDirectory;
4272
- await writeFile10(join14(root, ".windy/generation.json"), `${JSON.stringify(result.plan.targetProvenance, null, 2)}
4376
+ await writeFile11(join15(root, ".windy/generation.json"), `${JSON.stringify(result.plan.targetProvenance, null, 2)}
4273
4377
  `);
4274
- await writeFile10(join14(root, ".windy/files.json"), `${JSON.stringify(result.plan.targetManifest, null, 2)}
4378
+ await writeFile11(join15(root, ".windy/files.json"), `${JSON.stringify(result.plan.targetManifest, null, 2)}
4275
4379
  `);
4276
4380
  }
4277
4381
  async function writeReport(result, steps, relativePath2) {
4278
- const path2 = join14(result.plan.projectDirectory, relativePath2);
4382
+ const path2 = join15(result.plan.projectDirectory, relativePath2);
4279
4383
  await mkdir7(dirname4(path2), { recursive: true });
4280
4384
  const lines = [
4281
4385
  `# Windy 更新报告 ${result.plan.id}`,
@@ -4293,7 +4397,7 @@ async function writeReport(result, steps, relativePath2) {
4293
4397
  `备份保留在 \`.windy/backups/${result.plan.id}\`,确认稳定后可人工删除。`,
4294
4398
  ""
4295
4399
  ];
4296
- await writeFile10(path2, lines.join(`
4400
+ await writeFile11(path2, lines.join(`
4297
4401
  `));
4298
4402
  }
4299
4403
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {