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.
- package/README.md +14 -3
- package/dist/cli.js +191 -87
- package/package.json +1 -1
- package/template/.windy-template.json +2 -2
- package/template/README.md +8 -0
- package/template/apps/server/Dockerfile +2 -0
- package/template/apps/server/package.json +10 -8
- package/template/apps/server/src/access-guards.ts +1 -1
- package/template/apps/server/src/admin/routes.test.ts +10 -0
- package/template/apps/server/src/admin/routes.ts +4 -2
- package/template/apps/server/src/agent/routes.test.ts +1 -1
- package/template/apps/server/src/agent/routes.ts +2 -2
- package/template/apps/server/src/application-services.ts +3 -0
- package/template/apps/server/src/audit/drizzle-log-store.ts +2 -2
- package/template/apps/server/src/audit/policy.ts +1 -1
- package/template/apps/server/src/audit/recovery-queue.test.ts +1 -1
- package/template/apps/server/src/audit/recovery-queue.ts +1 -1
- package/template/apps/server/src/audit/redaction.ts +1 -1
- package/template/apps/server/src/audit/reliable-writer.test.ts +1 -1
- package/template/apps/server/src/audit/reliable-writer.ts +1 -1
- package/template/apps/server/src/audit/search-summary.ts +1 -1
- package/template/apps/server/src/auth/authentication-provider.test.ts +1 -1
- package/template/apps/server/src/auth/credential-service.ts +1 -1
- package/template/apps/server/src/auth/drizzle-repository.ts +2 -2
- package/template/apps/server/src/auth/drizzle-session-operations.ts +1 -1
- package/template/apps/server/src/auth/own-session-routes.test.ts +1 -1
- package/template/apps/server/src/auth/password.ts +2 -4
- package/template/apps/server/src/auth/repository.ts +1 -1
- package/template/apps/server/src/auth/routes.test.ts +1 -1
- package/template/apps/server/src/auth/service.ts +1 -1
- package/template/apps/server/src/bulk-data/artifact-store.ts +1 -1
- package/template/apps/server/src/bulk-data/dictionary-handler.ts +1 -1
- package/template/apps/server/src/bulk-data/drizzle-repository.ts +3 -3
- package/template/apps/server/src/bulk-data/repository.ts +1 -1
- package/template/apps/server/src/bulk-data/routes.test.ts +1 -1
- package/template/apps/server/src/bulk-data/routes.ts +1 -1
- package/template/apps/server/src/bulk-data/service.test.ts +1 -1
- package/template/apps/server/src/bulk-data/service.ts +1 -1
- package/template/apps/server/src/bulk-data/types.ts +1 -1
- package/template/apps/server/src/configuration/bootstrap.ts +2 -2
- package/template/apps/server/src/configuration/definition.ts +2 -2
- package/template/apps/server/src/configuration/drizzle-repository.ts +2 -2
- package/template/apps/server/src/configuration/repository.ts +1 -1
- package/template/apps/server/src/configuration/routes.ts +1 -1
- package/template/apps/server/src/configuration/service.ts +1 -1
- package/template/apps/server/src/data-access/context.ts +2 -2
- package/template/apps/server/src/data-access/query-specification.test.ts +1 -1
- package/template/apps/server/src/data-access/scoped-repository.integration.test.ts +1 -1
- package/template/apps/server/src/data-access/scoped-repository.ts +1 -1
- package/template/apps/server/src/data-access/scoped-resource.test.ts +1 -1
- package/template/apps/server/src/data-access/scoped-resource.ts +1 -1
- package/template/apps/server/src/data-governance/export/approval-port.ts +1 -1
- package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -1
- package/template/apps/server/src/data-governance/export/job-runtime.test.ts +2 -2
- package/template/apps/server/src/data-governance/export/job-runtime.ts +2 -3
- package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +2 -2
- package/template/apps/server/src/data-governance/export/postgres-api.integration.test.ts +1 -1
- package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +3 -3
- package/template/apps/server/src/data-governance/export/routes.ts +1 -1
- package/template/apps/server/src/data-governance/export/scope-snapshot.ts +1 -1
- package/template/apps/server/src/data-governance/export/service.ts +2 -2
- package/template/apps/server/src/data-governance/export/source.ts +1 -1
- package/template/apps/server/src/data-governance/export/types.ts +1 -1
- package/template/apps/server/src/data-governance/plaintext-access.test.ts +1 -1
- package/template/apps/server/src/data-governance/plaintext-access.ts +1 -1
- package/template/apps/server/src/data-governance/plaintext-postgres.integration.test.ts +1 -1
- package/template/apps/server/src/data-governance/user-plaintext-routes.ts +1 -1
- package/template/apps/server/src/data-governance/user-projection.ts +2 -2
- package/template/apps/server/src/example-modules.ts +25 -1
- package/template/apps/server/src/feature/manifest-feature-repository.test.ts +1 -1
- package/template/apps/server/src/feature/manifest-feature-repository.ts +1 -1
- package/template/apps/server/src/feature/routes.ts +3 -6
- package/template/apps/server/src/foundation-access.test.ts +1 -1
- package/template/apps/server/src/foundation-access.ts +1 -1
- package/template/apps/server/src/foundation.ts +21 -7
- package/template/apps/server/src/guards.test.ts +1 -1
- package/template/apps/server/src/guards.ts +3 -3
- package/template/apps/server/src/index.ts +27 -3
- package/template/{packages/modules → apps/server}/src/installed-business-modules.ts +2 -2
- package/template/apps/server/src/jobs/artifact-service.test.ts +1 -1
- package/template/apps/server/src/jobs/artifact-service.ts +2 -2
- package/template/apps/server/src/jobs/drizzle-artifact.ts +2 -2
- package/template/apps/server/src/jobs/drizzle-claim.ts +1 -1
- package/template/apps/server/src/jobs/drizzle-execution-repository.ts +2 -2
- package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +1 -1
- package/template/apps/server/src/jobs/drizzle-lease.ts +2 -2
- package/template/apps/server/src/jobs/drizzle-mappers.ts +3 -3
- package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +1 -1
- package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -1
- package/template/apps/server/src/jobs/drizzle-repository.ts +3 -3
- package/template/apps/server/src/jobs/execution-repository.ts +1 -1
- package/template/apps/server/src/jobs/execution.test.ts +2 -2
- package/template/apps/server/src/jobs/in-memory-claim.ts +1 -1
- package/template/apps/server/src/jobs/in-memory-execution.ts +1 -1
- package/template/apps/server/src/jobs/in-memory-lease.ts +1 -1
- package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +1 -1
- package/template/apps/server/src/jobs/legacy-adapter.test.ts +1 -1
- package/template/apps/server/src/jobs/legacy-adapter.ts +1 -1
- package/template/apps/server/src/jobs/legacy-service-runtime.ts +4 -2
- package/template/apps/server/src/jobs/repository.ts +2 -2
- package/template/apps/server/src/jobs/service.ts +2 -2
- package/template/apps/server/src/jobs/worker.ts +3 -2
- package/template/apps/server/src/license/legacy-license-resolver.ts +1 -1
- package/template/apps/server/src/license/license-resolver.test.ts +1 -1
- package/template/apps/server/src/license/license-resolver.ts +3 -3
- package/template/apps/server/src/license/routes-offline-code.test.ts +2 -2
- package/template/apps/server/src/license/routes.ts +1 -1
- package/template/apps/server/src/license/runtime-audit-reliability.test.ts +2 -2
- package/template/apps/server/src/license/runtime-reminder.test.ts +2 -2
- package/template/apps/server/src/license/runtime-service.test.ts +2 -2
- package/template/apps/server/src/license/runtime-service.ts +2 -2
- package/template/apps/server/src/module-composition.test.ts +1 -1
- package/template/apps/server/src/module-composition.ts +1 -1
- package/template/apps/server/src/module-host.test.ts +145 -0
- package/template/apps/server/src/module-host.ts +110 -0
- package/template/apps/server/src/notification/drizzle-repository.ts +2 -2
- package/template/apps/server/src/notification/repository.ts +1 -1
- package/template/apps/server/src/notification/routes.ts +1 -1
- package/template/apps/server/src/pagination.ts +1 -1
- package/template/apps/server/src/persistence.integration.test.ts +1 -1
- package/template/apps/server/src/persistence.ts +1 -1
- package/template/apps/server/src/profile/routes.ts +1 -1
- package/template/apps/server/src/route-guards.test.ts +1 -1
- package/template/apps/server/src/route-guards.ts +1 -1
- package/template/apps/server/src/runtime-feature.ts +125 -0
- package/template/apps/server/src/runtime-license.ts +1 -1
- package/template/apps/server/src/runtime.test.ts +48 -1
- package/template/apps/server/src/runtime.ts +17 -64
- package/template/apps/server/src/scheduler/audit.ts +1 -1
- package/template/apps/server/src/scheduler/definitions.test.ts +1 -1
- package/template/apps/server/src/scheduler/definitions.ts +2 -2
- package/template/apps/server/src/scheduler/drizzle-durable-links.ts +1 -1
- package/template/apps/server/src/scheduler/drizzle-mappers.ts +1 -1
- package/template/apps/server/src/scheduler/drizzle-repository.ts +1 -1
- package/template/apps/server/src/scheduler/execution-recorder.ts +1 -1
- package/template/apps/server/src/scheduler/history.ts +1 -1
- package/template/apps/server/src/scheduler/overview.ts +1 -1
- package/template/apps/server/src/scheduler/recovery-service.test.ts +1 -1
- package/template/apps/server/src/scheduler/recovery-service.ts +1 -1
- package/template/apps/server/src/scheduler/repository.ts +1 -1
- package/template/apps/server/src/scheduler/routes.ts +1 -1
- package/template/apps/server/src/scheduler/service-idle.test.ts +1 -1
- package/template/apps/server/src/scheduler/service.test.ts +1 -1
- package/template/apps/server/src/scheduler/service.ts +1 -1
- package/template/apps/server/src/scheduler/types.ts +1 -1
- package/template/apps/server/src/search/contracts.ts +2 -2
- package/template/apps/server/src/search/host.ts +1 -1
- package/template/apps/server/src/search/registry.ts +1 -1
- package/template/apps/server/src/search/routes.test.ts +1 -1
- package/template/apps/server/src/search/routes.ts +1 -1
- package/template/apps/server/src/search/service.ts +2 -2
- package/template/apps/server/src/search/test-support.ts +2 -2
- package/template/apps/server/src/session/routes.ts +1 -1
- package/template/apps/server/src/settings/drizzle-repository.ts +2 -2
- package/template/apps/server/src/settings/repository.ts +1 -1
- package/template/apps/server/src/settings/routes.test.ts +1 -1
- package/template/apps/server/src/settings/routes.ts +1 -1
- package/template/apps/server/src/settings/runtime.ts +1 -1
- package/template/apps/server/src/storage/blob-reference-registry.test.ts +1 -1
- package/template/apps/server/src/storage/blob-reference-registry.ts +1 -1
- package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +1 -1
- package/template/apps/server/src/storage/drizzle-upload-repository.ts +2 -2
- package/template/apps/server/src/storage/route-support.ts +1 -1
- package/template/apps/server/src/storage/routes.test.ts +1 -1
- package/template/apps/server/src/storage/routes.ts +2 -2
- package/template/apps/server/src/storage/runtime.ts +6 -4
- package/template/apps/server/src/system/audit-routes.ts +1 -1
- package/template/apps/server/src/system/department-routes.ts +1 -1
- package/template/apps/server/src/system/drizzle-repository.ts +1 -1
- package/template/apps/server/src/system/drizzle-scoped-repository.ts +1 -1
- package/template/apps/server/src/system/drizzle-system.ts +1 -1
- package/template/apps/server/src/system/entities.ts +1 -1
- package/template/apps/server/src/system/identity-route-config.ts +1 -1
- package/template/apps/server/src/system/interface-catalog.test.ts +3 -3
- package/template/apps/server/src/system/interface-catalog.ts +2 -2
- package/template/apps/server/src/system/menu-registry.ts +1 -1
- package/template/apps/server/src/system/menu-routes.ts +1 -1
- package/template/apps/server/src/system/operations.test.ts +1 -1
- package/template/apps/server/src/system/operations.ts +1 -1
- package/template/apps/server/src/system/redis-health.ts +1 -1
- package/template/apps/server/src/system/repository.ts +1 -1
- package/template/apps/server/src/system/resource-route-support.ts +1 -1
- package/template/apps/server/src/system/route-helpers.ts +1 -1
- package/template/apps/server/src/system/route-types.ts +1 -1
- package/template/apps/server/src/system/routes.test.ts +1 -1
- package/template/apps/server/src/system/routes.ts +1 -1
- package/template/apps/server/src/system/user-projection.ts +1 -1
- package/template/apps/server/src/work-order/data-scope.integration.test.ts +1 -1
- package/template/apps/server/src/work-order/drizzle-repository.integration.test.ts +1 -1
- package/template/apps/server/src/work-order/drizzle-repository.ts +2 -2
- package/template/apps/server/src/work-order/foundation-modules.test.ts +15 -5
- package/template/apps/server/src/work-order/repository.ts +1 -1
- package/template/apps/server/src/work-order/routes.test.ts +2 -2
- package/template/apps/server/src/work-order/routes.ts +2 -2
- package/template/apps/server/src/work-order/search-api.test.ts +3 -3
- package/template/apps/server/src/work-order/search-provider.test.ts +3 -3
- package/template/apps/server/src/work-order/service.ts +1 -1
- package/template/apps/server/src/work-order/task.test.ts +1 -1
- package/template/apps/server/src/work-order/task.ts +2 -2
- package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +2 -2
- package/template/apps/server/src/workflow/drizzle-repository.ts +3 -3
- package/template/apps/server/src/workflow/effects.test.ts +1 -1
- package/template/apps/server/src/workflow/effects.ts +1 -1
- package/template/apps/server/src/workflow/repository.ts +2 -2
- package/template/apps/server/src/workflow/routes.ts +3 -3
- package/template/apps/server/src/workflow/service.ts +1 -1
- package/template/apps/server/src/workflow/timeout-runtime.test.ts +1 -1
- package/template/apps/server/src/workflow/timeout-runtime.ts +2 -2
- package/template/apps/web/Dockerfile +2 -0
- package/template/apps/web/package.json +4 -4
- package/template/apps/web/runtime-server.ts +1 -1
- package/template/apps/web/src/app/layouts/AppLayout.vue +6 -0
- package/template/apps/web/src/components/auth/PasswordChangeForm.vue +52 -7
- package/template/apps/web/src/components/auth/PasswordChangeForm.webtest.ts +43 -0
- package/template/apps/web/src/components/common/DataPagination.vue +1 -1
- package/template/apps/web/src/components/license/LicenseActivationCodeForm.vue +1 -1
- package/template/apps/web/src/components/license/LicenseFlow.webtest.ts +2 -2
- package/template/apps/web/src/composables/useModuleConfigurations.ts +1 -1
- package/template/apps/web/src/composables/useWatermarkSettings.ts +1 -0
- package/template/apps/web/src/composables/watermark-settings.ts +6 -0
- package/template/apps/web/src/composables/watermark-settings.webtest.ts +27 -1
- package/template/apps/web/src/layout/AppSidebar.vue +12 -3
- package/template/apps/web/src/layout/AppSidebar.webtest.ts +11 -0
- package/template/apps/web/src/layout/GlobalWatermark.vue +25 -8
- package/template/apps/web/src/layout/GlobalWatermark.webtest.ts +109 -0
- package/template/apps/web/src/layout/NavigationSearchDialog.vue +1 -1
- package/template/apps/web/src/layout/NotificationMenu.vue +1 -1
- package/template/apps/web/src/layout/navigation.ts +5 -1
- package/template/apps/web/src/layout/navigation.webtest.ts +1 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigRollbackDialog.vue +1 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigVersionList.vue +1 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +1 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.webtest.ts +1 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +1 -1
- package/template/apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts +1 -1
- package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +21 -0
- package/template/apps/web/src/pages/system/SystemNotificationsPage.vue +2 -2
- package/template/apps/web/src/pages/system/components/AuditActionCell.vue +7 -2
- package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +7 -2
- package/template/apps/web/src/pages/system/components/NotificationPublishForm.vue +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.vue +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerRunTable.vue +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerRunTable.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.vue +1 -1
- package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +1 -1
- package/template/apps/web/src/pages/system/components/SystemResourceTable.vue +10 -3
- package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.vue +1 -1
- package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/components/role-policy/RolePolicyForm.vue +1 -1
- package/template/apps/web/src/pages/system/components/role-policy/permission-tree.ts +1 -1
- package/template/apps/web/src/pages/system/components/role-policy/permission-tree.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/composables/useSchedulerOperations.ts +2 -2
- package/template/apps/web/src/pages/system/composables/useSchedulerOperations.webtest.ts +1 -1
- package/template/apps/web/src/pages/system/composables/useSystemResource.ts +1 -1
- package/template/apps/web/src/router/manifest-routes.ts +1 -1
- package/template/apps/web/src/router/manifest-routes.webtest.ts +1 -1
- package/template/apps/web/src/services/access-api.ts +10 -1
- package/template/apps/web/src/services/configuration-api.ts +1 -1
- package/template/apps/web/src/services/license-api.ts +1 -1
- package/template/apps/web/src/services/notification-api.ts +2 -2
- package/template/apps/web/src/services/operations-api.ts +1 -1
- package/template/apps/web/src/services/platform-settings-api.ts +2 -2
- package/template/apps/web/src/services/profile-api.ts +2 -2
- package/template/docs/architecture/durable-jobs.md +5 -0
- package/template/docs/architecture/module-manifest-composition.md +14 -7
- package/template/docs/architecture/object-storage.md +1 -1
- package/template/docs/development/crud-generator.md +4 -1
- package/template/docs/platform/audit-reliability.md +1 -1
- package/template/package.json +2 -1
- package/template/packages/config/package.json +15 -4
- package/template/packages/config/src/platform.ts +1 -1
- package/template/packages/crud-generator/package.json +1 -1
- package/template/packages/crud-generator/src/generator.test.ts +16 -0
- package/template/packages/crud-generator/src/templates/domain.ts +1 -1
- package/template/packages/crud-generator/src/templates/manifest.ts +2 -2
- package/template/packages/crud-generator/src/templates/project.ts +3 -3
- package/template/packages/crud-generator/src/templates/repository.ts +1 -1
- package/template/packages/crud-generator/src/templates/routes.ts +2 -2
- package/template/packages/crud-generator/src/validation.ts +22 -1
- package/template/packages/database/package.json +15 -5
- package/template/packages/database/src/bundle-validation.ts +218 -0
- package/template/packages/database/src/dialects.ts +1 -1
- package/template/packages/database/src/runner.test.ts +160 -13
- package/template/packages/database/src/runner.ts +95 -77
- package/template/packages/database/src/schema/governed-exports.ts +1 -1
- package/template/packages/database/src/schema/identity.ts +1 -1
- package/template/packages/database/src/schema/license-v1.ts +1 -1
- package/template/packages/database/src/schema/notifications.ts +1 -1
- package/template/packages/database/src/schema/platform-settings.ts +1 -1
- package/template/packages/database/src/schema/workflow.ts +1 -1
- package/template/packages/database/src/sql-store.ts +1 -1
- package/template/packages/database/src/store.ts +1 -1
- package/template/packages/example-work-order/index.ts +1 -0
- package/template/packages/example-work-order/package.json +4 -3
- package/template/packages/example-work-order/src/contract.ts +1 -1
- package/template/packages/example-work-order/src/manifest.ts +8 -3
- package/template/packages/example-work-order/src/migration-bundle.test.ts +43 -0
- package/template/packages/example-work-order/src/migration-bundle.ts +64 -0
- package/template/packages/jobs/index.ts +2 -0
- package/template/packages/jobs/package.json +29 -0
- package/template/packages/jobs/src/handlers.test.ts +72 -0
- package/template/{apps/server/src/jobs/handler-registry.ts → packages/jobs/src/handlers.ts} +4 -4
- package/template/{apps/server/src/jobs → packages/jobs/src}/types.ts +7 -1
- package/template/packages/{license-sdk → jobs}/tsconfig.json +0 -1
- package/template/packages/modules/index.ts +1 -1
- package/template/packages/modules/package.json +15 -5
- package/template/packages/modules/src/catalog-validation.ts +123 -0
- package/template/packages/modules/src/composition.test.ts +75 -2
- package/template/packages/modules/src/composition.ts +4 -2
- package/template/packages/modules/src/manifest.ts +7 -12
- package/template/packages/modules/src/menu-composition.ts +1 -1
- package/template/packages/modules/src/system-api-binding.ts +1 -1
- package/template/packages/modules/src/system-api-data-governance.ts +1 -1
- package/template/packages/modules/src/system-api-permissions.ts +1 -1
- package/template/packages/modules/src/system-data-governance.ts +1 -1
- package/template/packages/modules/src/system-features.ts +1 -1
- package/template/packages/modules/src/system-governed-export-bindings.ts +1 -1
- package/template/packages/modules/src/system-module-catalog.ts +1 -1
- package/template/packages/server-sdk/index.ts +5 -0
- package/template/packages/server-sdk/package.json +25 -0
- package/template/packages/server-sdk/src/module-host.ts +29 -0
- package/template/packages/server-sdk/tsconfig.json +16 -0
- package/template/packages/shared/index.ts +3 -0
- package/template/packages/shared/package.json +14 -3
- package/template/packages/shared/src/audit.ts +22 -1
- package/template/packages/shared/src/license-catalog.test.ts +17 -0
- package/template/packages/shared/src/license-catalog.ts +33 -0
- package/template/packages/shared/src/migration.ts +39 -0
- package/template/packages/shared/src/password.ts +4 -0
- package/template/packages/storage/package.json +14 -3
- package/template/packages/license-sdk/index.ts +0 -13
- package/template/packages/license-sdk/package.json +0 -18
- package/template/packages/license-sdk/src/bounded-json-body.test.ts +0 -65
- package/template/packages/license-sdk/src/bounded-json-body.ts +0 -135
- package/template/packages/license-sdk/src/canonical-json.test.ts +0 -28
- package/template/packages/license-sdk/src/canonical-json.ts +0 -104
- package/template/packages/license-sdk/src/client.test.ts +0 -82
- package/template/packages/license-sdk/src/client.ts +0 -86
- package/template/packages/license-sdk/src/device.ts +0 -46
- package/template/packages/license-sdk/src/file-storage.test.ts +0 -80
- package/template/packages/license-sdk/src/file-storage.ts +0 -77
- package/template/packages/license-sdk/src/installation.test.ts +0 -241
- package/template/packages/license-sdk/src/installation.ts +0 -150
- package/template/packages/license-sdk/src/license-parser.ts +0 -56
- package/template/packages/license-sdk/src/offline-code-base32.ts +0 -57
- package/template/packages/license-sdk/src/offline-code-decompression.ts +0 -55
- package/template/packages/license-sdk/src/offline-code-limits.ts +0 -10
- package/template/packages/license-sdk/src/offline-code-wire.ts +0 -72
- package/template/packages/license-sdk/src/offline-code.test.ts +0 -172
- package/template/packages/license-sdk/src/offline-code.ts +0 -319
- package/template/packages/license-sdk/src/payload.test.ts +0 -72
- package/template/packages/license-sdk/src/payload.ts +0 -201
- package/template/packages/license-sdk/src/storage.ts +0 -64
- package/template/packages/license-sdk/src/test-fixtures.ts +0 -59
- package/template/packages/license-sdk/src/v1-test-vector.ts +0 -49
- package/template/packages/license-sdk/src/validation.test.ts +0 -62
- package/template/packages/license-sdk/src/validation.ts +0 -143
- package/template/packages/license-sdk/src/verification.test.ts +0 -97
- 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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
914
|
+
lstat as lstat4,
|
|
906
915
|
mkdir as mkdir3,
|
|
907
|
-
readFile as
|
|
908
|
-
readdir as
|
|
916
|
+
readFile as readFile9,
|
|
917
|
+
readdir as readdir4,
|
|
909
918
|
rm as rm3,
|
|
910
|
-
writeFile as
|
|
919
|
+
writeFile as writeFile8
|
|
911
920
|
} from "node:fs/promises";
|
|
912
|
-
import { basename as
|
|
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)
|
|
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
|
-
|
|
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/
|
|
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),
|
|
1854
|
+
await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join9(input.targetDirectory, relativePath2));
|
|
1756
1855
|
}
|
|
1757
1856
|
await materializeSelectedModules(input.targetDirectory, selectedModules);
|
|
1758
|
-
|
|
1759
|
-
const
|
|
1760
|
-
|
|
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
|
|
1763
|
-
await
|
|
1764
|
-
await
|
|
1765
|
-
await
|
|
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(
|
|
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 =
|
|
1875
|
+
const source = join9(sourceRoot, relativePath2);
|
|
1776
1876
|
try {
|
|
1777
|
-
await
|
|
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
|
|
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 =
|
|
1792
|
-
const extension =
|
|
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
|
|
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
|
|
1822
|
-
const name =
|
|
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
|
|
1828
|
-
await copyTree(
|
|
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(
|
|
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
|
|
1840
|
-
const path =
|
|
1939
|
+
for (const name of await readdir4(directory)) {
|
|
1940
|
+
const path = join9(directory, name);
|
|
1841
1941
|
await visit(path);
|
|
1842
|
-
if ((await
|
|
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
|
|
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
|
|
3690
|
-
import { join as
|
|
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
|
|
3824
|
+
readFile as readFile10,
|
|
3723
3825
|
rm as rm5,
|
|
3724
|
-
writeFile as
|
|
3826
|
+
writeFile as writeFile9
|
|
3725
3827
|
} from "node:fs/promises";
|
|
3726
|
-
import { dirname as dirname3, join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
3913
|
+
await rm5(join10(projectDirectory, updateStatePath), { force: true });
|
|
3812
3914
|
}
|
|
3813
3915
|
async function writeState(projectDirectory, state) {
|
|
3814
|
-
const path2 =
|
|
3916
|
+
const path2 = join10(projectDirectory, updateStatePath);
|
|
3815
3917
|
await mkdir5(dirname3(path2), { recursive: true });
|
|
3816
|
-
await
|
|
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
|
|
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
|
|
3926
|
-
import { dirname as dirname4, join as
|
|
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
|
|
4033
|
+
import { mkdir as mkdir6, mkdtemp, readFile as readFile12 } from "node:fs/promises";
|
|
3930
4034
|
import { tmpdir } from "node:os";
|
|
3931
|
-
import { basename as
|
|
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(
|
|
4038
|
+
const temporaryRoot = await mkdtemp(join12(tmpdir(), "windy-update-"));
|
|
3935
4039
|
const projectName = await readProjectName2(projectDirectory);
|
|
3936
|
-
const baseDirectory =
|
|
3937
|
-
const targetDirectory =
|
|
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 =
|
|
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 (
|
|
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
|
|
3983
|
-
return source.name ||
|
|
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
|
|
3988
|
-
import { join as
|
|
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
|
|
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
|
|
4097
|
+
import { join as join13 } from "node:path";
|
|
3994
4098
|
async function mergeTextFile(base, ours, theirs) {
|
|
3995
|
-
const root = await mkdtemp2(
|
|
4099
|
+
const root = await mkdtemp2(join13(tmpdir2(), "windy-merge-"));
|
|
3996
4100
|
try {
|
|
3997
|
-
const oursPath =
|
|
3998
|
-
const basePath =
|
|
3999
|
-
const theirsPath =
|
|
4101
|
+
const oursPath = join13(root, "ours");
|
|
4102
|
+
const basePath = join13(root, "base");
|
|
4103
|
+
const theirsPath = join13(root, "theirs");
|
|
4000
4104
|
await Promise.all([
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
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(
|
|
4122
|
-
readOptional(
|
|
4123
|
-
readOptional(
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
4376
|
+
await writeFile11(join15(root, ".windy/generation.json"), `${JSON.stringify(result.plan.targetProvenance, null, 2)}
|
|
4273
4377
|
`);
|
|
4274
|
-
await
|
|
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 =
|
|
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
|
|
4400
|
+
await writeFile11(path2, lines.join(`
|
|
4297
4401
|
`));
|
|
4298
4402
|
}
|
|
4299
4403
|
|