create-windy 0.3.18 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -13
- package/dist/cli.js +788 -280
- package/package.json +1 -1
- package/template/.agents/skills/windy-business-module/SKILL.md +34 -10
- package/template/.windy-template.json +2 -2
- package/template/AGENTS.md +18 -8
- package/template/README.md +32 -22
- package/template/apps/agent-server/src/southwind_agent_server/adk_debug.py +38 -5
- package/template/apps/agent-server/tests/test_adk_debug_result_polling.py +139 -0
- package/template/apps/server/Dockerfile +1 -0
- package/template/apps/server/package.json +1 -0
- package/template/apps/server/scripts/validate-module-composition-once.ts +4 -0
- package/template/apps/server/scripts/validate-module-composition.ts +28 -0
- package/template/apps/server/src/agent/data-scope-routes.test.ts +20 -5
- package/template/apps/server/src/agent/routes.test.ts +20 -7
- package/template/apps/server/src/agent/routes.ts +14 -0
- package/template/apps/server/src/agent/runtime-bootstrap.ts +22 -6
- package/template/apps/server/src/agent/sandbox-worker.ts +2 -2
- package/template/apps/server/src/agent/unavailable-routes.ts +33 -0
- package/template/apps/server/src/app/server-composition.ts +56 -0
- package/template/apps/server/src/application-services.ts +2 -0
- package/template/apps/server/src/bulk-data/service.ts +14 -0
- package/template/apps/server/src/data-governance/export/authorization-port.ts +1 -1
- package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +18 -2
- package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +10 -9
- package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +6 -8
- package/template/apps/server/src/data-governance/user-plaintext-routes.test.ts +4 -2
- package/template/apps/server/src/feature/routes.authorization.test.ts +26 -1
- package/template/apps/server/src/feature/routes.ts +33 -15
- package/template/apps/server/src/foundation-activation.test.ts +60 -0
- package/template/apps/server/src/foundation.ts +64 -5
- package/template/apps/server/src/guards.test.ts +23 -0
- package/template/apps/server/src/guards.ts +12 -0
- package/template/apps/server/src/index.ts +28 -34
- package/template/apps/server/src/installed-business-modules.ts +13 -24
- package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +1 -0
- package/template/apps/server/src/jobs/legacy-adapter.test.ts +106 -0
- package/template/apps/server/src/jobs/legacy-service-runtime.ts +40 -0
- package/template/apps/server/src/license/activation.test.ts +30 -0
- package/template/apps/server/src/license/activation.ts +26 -0
- package/template/apps/server/src/license/restriction.test.ts +16 -0
- package/template/apps/server/src/license/routes-offline-code.test.ts +6 -2
- package/template/apps/server/src/license/routes.ts +20 -4
- package/template/apps/server/src/license/runtime-service.test.ts +10 -2
- package/template/apps/server/src/module-bootstrap.ts +14 -23
- package/template/apps/server/src/module-composition.test.ts +43 -2
- package/template/apps/server/src/module-composition.ts +29 -0
- package/template/apps/server/src/module-host/durable-context-guard.test.ts +172 -0
- package/template/apps/server/src/module-host/durable-context-unavailable.test.ts +50 -1
- package/template/apps/server/src/module-host/durable-context.test.ts +42 -25
- package/template/apps/server/src/module-host/durable-context.ts +42 -2
- package/template/apps/server/src/module-host/durable-handler-registration.ts +96 -5
- package/template/apps/server/src/module-host/implementation-completeness.test.ts +185 -0
- package/template/apps/server/src/module-host/implementation-completeness.ts +132 -0
- package/template/apps/server/src/module-host/initialize-contracts.ts +14 -0
- package/template/apps/server/src/module-host/initialize.test.ts +78 -2
- package/template/apps/server/src/module-host/initialize.ts +15 -4
- package/template/apps/server/src/module-host/project-attachments.test.ts +92 -0
- package/template/apps/server/src/module-host/project-attachments.ts +58 -0
- package/template/apps/server/src/module-host/project-composition-package.test.ts +186 -0
- package/template/apps/server/src/module-host/project-composition.test.ts +260 -0
- package/template/apps/server/src/module-host/project-composition.ts +311 -0
- package/template/apps/server/src/module-host/request-context.ts +3 -0
- package/template/apps/server/src/module-host/route-declaration.ts +15 -6
- package/template/apps/server/src/module-host/route-installer.test.ts +15 -2
- package/template/apps/server/src/module-host/route-installer.ts +12 -2
- package/template/apps/server/src/module-host/route-registration.test.ts +13 -4
- package/template/apps/server/src/module-host/runtime-composition-compatibility.test.ts +63 -0
- package/template/apps/server/src/module-host/runtime-composition-compatibility.ts +46 -0
- package/template/apps/server/src/module-host/runtime-composition.ts +34 -0
- package/template/apps/server/src/module-host/search-provider-registration.test.ts +64 -0
- package/template/apps/server/src/module-host/search-provider-registration.ts +35 -0
- package/template/apps/server/src/module-host/static-route-authorization.test.ts +99 -0
- package/template/apps/server/src/module-host/static-route-authorization.ts +90 -0
- package/template/apps/server/src/module-host/task-definitions.ts +1 -0
- package/template/apps/server/src/module-host/user-directory-composition.test.ts +4 -1
- package/template/apps/server/src/module-host.test.ts +2 -0
- package/template/apps/server/src/module-preflight.test.ts +289 -0
- package/template/apps/server/src/module-preflight.ts +96 -0
- package/template/apps/server/src/module-runtime-validation.ts +1 -0
- package/template/apps/server/src/platform-app-bootstrap.ts +50 -0
- package/template/apps/server/src/platform-http-runtime.ts +32 -7
- package/template/apps/server/src/route-guards.test.ts +22 -0
- package/template/apps/server/src/route-guards.ts +10 -3
- package/template/apps/server/src/runtime-audit-query.ts +50 -0
- package/template/apps/server/src/runtime-feature.test.ts +46 -0
- package/template/apps/server/src/runtime-feature.ts +5 -0
- package/template/apps/server/src/runtime.ts +10 -49
- package/template/apps/server/src/scheduler/audit-action.test.ts +49 -0
- package/template/apps/server/src/scheduler/audit.ts +1 -1
- package/template/apps/server/src/scheduler/execution-recorder.ts +10 -5
- package/template/apps/server/src/scheduler/recovery-service.test.ts +4 -3
- package/template/apps/server/src/scheduler/service-idle.test.ts +4 -3
- package/template/apps/server/src/scheduler/service.test.ts +1 -0
- package/template/apps/server/src/scheduler/service.ts +18 -21
- package/template/apps/server/src/scheduler/types.ts +5 -1
- package/template/apps/server/src/startup-composition-validation.test.ts +35 -0
- package/template/apps/server/src/startup-composition-validation.ts +54 -0
- package/template/apps/server/src/startup-preflight.test.ts +36 -0
- package/template/apps/server/src/startup-preflight.ts +37 -0
- package/template/apps/server/src/system/audit-routes.test.ts +9 -3
- package/template/apps/server/src/system/department-routes.test.ts +5 -3
- package/template/apps/server/src/system/feature-routes.test.ts +4 -3
- package/template/apps/server/src/system/interface-catalog.test.ts +5 -3
- package/template/apps/server/src/system/interface-catalog.ts +3 -0
- package/template/apps/server/src/system/menu-routes.test.ts +5 -3
- package/template/apps/server/src/system/route-test-runtime.ts +24 -0
- package/template/apps/server/src/system/routes-validation.test.ts +7 -3
- package/template/apps/server/src/system/routes.test.ts +21 -11
- package/template/apps/server/src/system/routes.ts +11 -2
- package/template/apps/server/src/work-order/foundation-modules.test.ts +6 -4
- package/template/apps/server/src/work-order/routes.test.ts +8 -0
- package/template/apps/server/src/work-order/task.test.ts +6 -1
- package/template/apps/web/Dockerfile +5 -0
- package/template/apps/web/package.json +1 -0
- package/template/apps/web/scripts/validate-admin-ui-composition.ts +106 -0
- package/template/apps/web/src/app/web-composition.ts +24 -0
- package/template/apps/web/src/app/web-composition.webtest.ts +15 -0
- package/template/apps/web/src/layout/AppSidebar.vue +8 -1
- package/template/apps/web/src/layout/NavigationSearchDialog.vue +8 -1
- package/template/apps/web/src/layout/navigation.ts +29 -4
- package/template/apps/web/src/layout/navigation.webtest.ts +51 -0
- package/template/apps/web/src/pages/dashboard/dashboard-presenter.ts +6 -1
- package/template/apps/web/src/pages/work-orders/WorkOrderListPage.vue +202 -0
- package/template/apps/web/src/pages/work-orders/WorkOrderListPage.webtest.ts +51 -0
- package/template/apps/web/src/router/admin-extension-loader.ts +44 -0
- package/template/apps/web/src/router/admin-extension-loader.webtest.ts +49 -0
- package/template/apps/web/src/router/admin-ui-composition-plugin.ts +33 -0
- package/template/apps/web/src/router/admin-ui-composition-plugin.webtest.ts +20 -0
- package/template/apps/web/src/router/admin-ui-composition.ts +313 -0
- package/template/apps/web/src/router/admin-ui-composition.webtest.ts +225 -0
- package/template/apps/web/src/router/admin-ui-module-registry-plugin.ts +55 -0
- package/template/apps/web/src/router/admin-ui-module-registry-plugin.webtest.ts +46 -0
- package/template/apps/web/src/router/business-routes.ts +32 -45
- package/template/apps/web/src/router/business-routes.webtest.ts +40 -44
- package/template/apps/web/src/router/index.ts +64 -54
- package/template/apps/web/src/router/manifest-routes.ts +27 -7
- package/template/apps/web/src/router/manifest-routes.webtest.ts +10 -2
- package/template/apps/web/src/router/platform-admin-route-bindings.ts +58 -0
- package/template/apps/web/src/router/reserved-route-paths.ts +14 -0
- package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +10 -4
- package/template/apps/web/src/router/web-composition-host.ts +20 -0
- package/template/apps/web/src/services/work-order-api.ts +16 -0
- package/template/apps/web/src/services/work-order-api.webtest.ts +21 -0
- package/template/apps/web/src/virtual-admin-ui-modules.d.ts +5 -0
- package/template/apps/web/vite.config.ts +22 -1
- package/template/docs/architecture/migration-bundle.md +10 -7
- package/template/docs/architecture/module-manifest-composition.md +85 -3
- package/template/docs/architecture/search-provider-protocol.md +6 -1
- package/template/docs/architecture/server-module-interface.md +70 -7
- package/template/docs/development/business-web-routes.md +53 -50
- package/template/docs/development/module-lifecycle.md +48 -54
- package/template/docs/platform/agent-runtime.md +2 -0
- package/template/docs/platform/navigation-registry.md +5 -4
- package/template/package.json +1 -1
- package/template/packages/config/package.json +1 -1
- package/template/packages/database/package.json +1 -1
- package/template/packages/example-work-order/package.json +6 -0
- package/template/packages/example-work-order/src/admin-page.ts +78 -0
- package/template/packages/example-work-order/src/admin.ts +35 -0
- package/template/packages/example-work-order/src/manifest.test.ts +62 -5
- package/template/packages/example-work-order/src/manifest.ts +54 -7
- package/template/packages/example-work-order/src/migration-bundle.ts +8 -0
- package/template/packages/example-work-order/src/server-module.ts +2 -2
- package/template/packages/jobs/package.json +1 -1
- package/template/packages/modules/index.ts +4 -0
- package/template/packages/modules/package.json +3 -2
- package/template/packages/modules/src/admin-ui-entry.ts +8 -0
- package/template/packages/modules/src/admin-ui-manifest.test.ts +52 -0
- package/template/packages/modules/src/admin-ui-manifest.ts +53 -0
- package/template/packages/modules/src/capability-audit-validation.test.ts +127 -0
- package/template/packages/modules/src/capability-audit-validation.ts +38 -0
- package/template/packages/modules/src/capability-guard-validation.ts +148 -0
- package/template/packages/modules/src/capability-key-validation.test.ts +150 -0
- package/template/packages/modules/src/composition-fixtures.test-support.ts +7 -5
- package/template/packages/modules/src/composition.test.ts +74 -9
- package/template/packages/modules/src/composition.ts +8 -0
- package/template/packages/modules/src/manifest.ts +1 -0
- package/template/packages/modules/src/migration-bundle-validation.test.ts +23 -0
- package/template/packages/modules/src/module-host-range.test.ts +57 -0
- package/template/packages/modules/src/module-host-range.ts +125 -0
- package/template/packages/modules/src/project-module-assembly.test.ts +133 -0
- package/template/packages/modules/src/project-module-assembly.ts +126 -0
- package/template/packages/modules/src/system-admin-routes.ts +6 -5
- package/template/packages/modules/src/system-admin-ui-catalog.ts +72 -0
- package/template/packages/modules/src/system-agent-tools.ts +2 -2
- package/template/packages/modules/src/system-api-binding.ts +43 -9
- package/template/packages/modules/src/system-api-control-plane.ts +202 -0
- package/template/packages/modules/src/system-api-data-governance.ts +4 -2
- package/template/packages/modules/src/system-api-operational.ts +57 -8
- package/template/packages/modules/src/system-api-permissions.ts +115 -21
- package/template/packages/modules/src/system-api-watermark.ts +3 -0
- package/template/packages/modules/src/system-audit-actions.ts +7 -0
- package/template/packages/modules/src/system-data-governance.ts +5 -2
- package/template/packages/modules/src/system-features.ts +31 -0
- package/template/packages/modules/src/system-governed-export-bindings.ts +8 -4
- package/template/packages/modules/src/system-module-catalog.test.ts +39 -4
- package/template/packages/modules/src/system-module-catalog.ts +68 -7
- package/template/packages/modules/src/system-module-tasks.ts +8 -1
- package/template/packages/modules/src/system-modules-access.test.ts +4 -0
- package/template/packages/modules/src/system-modules.test.ts +10 -2
- package/template/packages/modules/src/system-modules.ts +6 -5
- package/template/packages/modules/src/system-permissions.ts +4 -0
- package/template/packages/modules/user/module.ts +19 -2
- package/template/packages/server-sdk/index.ts +8 -0
- package/template/packages/server-sdk/package.json +2 -1
- package/template/packages/server-sdk/src/durable-handler.ts +16 -1
- package/template/packages/server-sdk/src/module-adapter.test.ts +44 -0
- package/template/packages/server-sdk/src/module-adapter.ts +59 -0
- package/template/packages/server-sdk/src/route-definition.ts +3 -2
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/audit.test.ts +7 -0
- package/template/packages/shared/src/audit.ts +16 -0
- package/template/packages/shared/src/migration-bundle-validation.ts +9 -11
- package/template/packages/shared/src/rbac.ts +2 -0
- package/template/apps/web/src/app/business-routes.ts +0 -22
package/dist/cli.js
CHANGED
|
@@ -206,6 +206,39 @@ var starterProfile = {
|
|
|
206
206
|
};
|
|
207
207
|
var projectLicenseKeys = ["UNLICENSED", "MIT", "Apache-2.0"];
|
|
208
208
|
|
|
209
|
+
// src/module-distribution-validation.ts
|
|
210
|
+
function validateModuleDistributionCatalog(manifests) {
|
|
211
|
+
const names = new Set;
|
|
212
|
+
for (const manifest of manifests) {
|
|
213
|
+
if (names.has(manifest.name)) {
|
|
214
|
+
throw new Error(`\u5206\u53D1\u6A21\u5757\u91CD\u590D\uFF1A${manifest.name}`);
|
|
215
|
+
}
|
|
216
|
+
names.add(manifest.name);
|
|
217
|
+
}
|
|
218
|
+
for (const manifest of manifests) {
|
|
219
|
+
for (const dependency of manifest.dependencies) {
|
|
220
|
+
if (!names.has(dependency)) {
|
|
221
|
+
throw new Error(`${manifest.name} \u4F9D\u8D56\u672A\u77E5\u6A21\u5757\uFF1A${dependency}`);
|
|
222
|
+
}
|
|
223
|
+
if (dependency === manifest.name) {
|
|
224
|
+
throw new Error(`${manifest.name} \u4E0D\u80FD\u4F9D\u8D56\u81EA\u8EAB`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
for (const conflict of manifest.conflicts) {
|
|
228
|
+
if (!names.has(conflict)) {
|
|
229
|
+
throw new Error(`${manifest.name} \u51B2\u7A81\u6A21\u5757\u672A\u77E5\uFF1A${conflict}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (!manifest.installRecipe) {
|
|
233
|
+
throw new Error(`${manifest.name} \u7F3A\u5C11\u5B89\u88C5 recipe`);
|
|
234
|
+
}
|
|
235
|
+
if (!manifest.uninstallRecipe) {
|
|
236
|
+
throw new Error(`${manifest.name} \u7F3A\u5C11\u5378\u8F7D recipe`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return manifests;
|
|
240
|
+
}
|
|
241
|
+
|
|
209
242
|
// src/optional-module-distribution.ts
|
|
210
243
|
var optionalModuleManifests = [
|
|
211
244
|
{
|
|
@@ -213,6 +246,7 @@ var optionalModuleManifests = [
|
|
|
213
246
|
"system",
|
|
214
247
|
"system.settings"
|
|
215
248
|
]),
|
|
249
|
+
runtimeActivation: "physical-only",
|
|
216
250
|
fileRoots: [
|
|
217
251
|
"apps/server/src/storage",
|
|
218
252
|
"apps/server/src/module-host/route-installer.test.ts",
|
|
@@ -300,6 +334,7 @@ var optionalModuleManifests = [
|
|
|
300
334
|
"apps/server/src/application-services.ts",
|
|
301
335
|
"apps/server/src/module-host/durable-context.ts",
|
|
302
336
|
"apps/server/src/module-host/durable-context.test.ts",
|
|
337
|
+
"apps/server/src/module-host/durable-context-guard.test.ts",
|
|
303
338
|
"apps/server/src/module-host/durable-context-unavailable.test.ts",
|
|
304
339
|
"apps/server/src/module-host/job-port.test.ts",
|
|
305
340
|
"apps/server/src/module-host/task-definitions.ts",
|
|
@@ -436,6 +471,7 @@ var optionalModuleManifests = [
|
|
|
436
471
|
"system.workflow",
|
|
437
472
|
"system.scheduler"
|
|
438
473
|
]),
|
|
474
|
+
runtimeActivation: "physical-only",
|
|
439
475
|
fileRoots: [
|
|
440
476
|
"apps/server/src/data-governance",
|
|
441
477
|
"apps/server/src/module-host/governed-resource-routes.ts",
|
|
@@ -460,11 +496,17 @@ var optionalModuleManifests = [
|
|
|
460
496
|
"system.scheduler",
|
|
461
497
|
"system.storage"
|
|
462
498
|
]),
|
|
499
|
+
deploymentInstall: "project-composition-required",
|
|
500
|
+
runtimePackage: "@southwind-ai/example-work-order",
|
|
463
501
|
packages: ["packages/example-work-order"],
|
|
464
502
|
fileRoots: [
|
|
465
503
|
"apps/server/src/work-order",
|
|
466
504
|
"apps/server/src/example-modules.ts",
|
|
467
|
-
"apps/server/src/example-permissions.ts"
|
|
505
|
+
"apps/server/src/example-permissions.ts",
|
|
506
|
+
"apps/web/src/pages/work-orders",
|
|
507
|
+
"apps/web/src/app/web-composition.webtest.ts",
|
|
508
|
+
"apps/web/src/services/work-order-api.ts",
|
|
509
|
+
"apps/web/src/services/work-order-api.webtest.ts"
|
|
468
510
|
],
|
|
469
511
|
documentation: ["docs/development/example-work-order.md"],
|
|
470
512
|
schemaFiles: ["packages/example-work-order/src/drizzle-schema.ts"],
|
|
@@ -478,12 +520,15 @@ function module(name, label, description, dependencies) {
|
|
|
478
520
|
return {
|
|
479
521
|
name,
|
|
480
522
|
version: "0.1.0",
|
|
481
|
-
windyRange: "^0.
|
|
523
|
+
windyRange: "^0.4.0",
|
|
482
524
|
label,
|
|
483
525
|
description,
|
|
484
526
|
selection,
|
|
527
|
+
runtimeActivation: "toggle",
|
|
528
|
+
deploymentInstall: "project-composition-required",
|
|
485
529
|
dependencies,
|
|
486
530
|
conflicts: [],
|
|
531
|
+
runtimePackage: null,
|
|
487
532
|
packages: [],
|
|
488
533
|
registryDependencies: [],
|
|
489
534
|
fileRoots: [],
|
|
@@ -514,6 +559,7 @@ var platformModules = [
|
|
|
514
559
|
module2("system.identity", "\u8EAB\u4EFD\u4E0E\u6743\u9650", "\u8BA4\u8BC1\u3001\u7528\u6237\u3001\u89D2\u8272\u3001\u7EC4\u7EC7\u548C\u6570\u636E\u8303\u56F4\u3002", "required", ["system"]),
|
|
515
560
|
{
|
|
516
561
|
...module2("system.settings", "\u5E73\u53F0\u8BBE\u7F6E", "\u54C1\u724C\u3001Logo \u4E0E\u6C34\u5370\u3002", "recommended", ["system"]),
|
|
562
|
+
runtimeActivation: "physical-only",
|
|
517
563
|
fileRoots: [
|
|
518
564
|
"apps/server/src/settings",
|
|
519
565
|
"apps/web/src/pages/settings",
|
|
@@ -647,7 +693,7 @@ var platformModules = [
|
|
|
647
693
|
},
|
|
648
694
|
...optionalModuleManifests
|
|
649
695
|
];
|
|
650
|
-
var moduleDistributionCatalog =
|
|
696
|
+
var moduleDistributionCatalog = validateModuleDistributionCatalog(platformModules);
|
|
651
697
|
function resolveModuleSelection(input = {}) {
|
|
652
698
|
const known = new Map(moduleDistributionCatalog.map((item) => [item.name, item]));
|
|
653
699
|
const selected = new Set(requiredModuleNames);
|
|
@@ -702,12 +748,15 @@ function module2(name, label, description, selection, dependencies = []) {
|
|
|
702
748
|
return {
|
|
703
749
|
name,
|
|
704
750
|
version: "0.1.0",
|
|
705
|
-
windyRange: "^0.
|
|
751
|
+
windyRange: "^0.4.0",
|
|
706
752
|
label,
|
|
707
753
|
description,
|
|
708
754
|
selection,
|
|
755
|
+
runtimeActivation: "toggle",
|
|
756
|
+
deploymentInstall: "project-composition-required",
|
|
709
757
|
dependencies,
|
|
710
758
|
conflicts: [],
|
|
759
|
+
runtimePackage: null,
|
|
711
760
|
packages: [],
|
|
712
761
|
registryDependencies: [],
|
|
713
762
|
fileRoots: [],
|
|
@@ -724,33 +773,6 @@ function module2(name, label, description, selection, dependencies = []) {
|
|
|
724
773
|
uninstallRecipe: `module-${name}-uninstall`
|
|
725
774
|
};
|
|
726
775
|
}
|
|
727
|
-
function validateCatalog(manifests) {
|
|
728
|
-
const names = new Set;
|
|
729
|
-
for (const manifest of manifests) {
|
|
730
|
-
if (names.has(manifest.name))
|
|
731
|
-
throw new Error(`\u5206\u53D1\u6A21\u5757\u91CD\u590D\uFF1A${manifest.name}`);
|
|
732
|
-
names.add(manifest.name);
|
|
733
|
-
}
|
|
734
|
-
for (const manifest of manifests) {
|
|
735
|
-
for (const dependency of manifest.dependencies) {
|
|
736
|
-
if (!names.has(dependency))
|
|
737
|
-
throw new Error(`${manifest.name} \u4F9D\u8D56\u672A\u77E5\u6A21\u5757\uFF1A${dependency}`);
|
|
738
|
-
if (dependency === manifest.name)
|
|
739
|
-
throw new Error(`${manifest.name} \u4E0D\u80FD\u4F9D\u8D56\u81EA\u8EAB`);
|
|
740
|
-
}
|
|
741
|
-
for (const conflict of manifest.conflicts) {
|
|
742
|
-
if (!names.has(conflict))
|
|
743
|
-
throw new Error(`${manifest.name} \u51B2\u7A81\u6A21\u5757\u672A\u77E5\uFF1A${conflict}`);
|
|
744
|
-
}
|
|
745
|
-
if (!manifest.installRecipe) {
|
|
746
|
-
throw new Error(`${manifest.name} \u7F3A\u5C11\u5B89\u88C5 recipe`);
|
|
747
|
-
}
|
|
748
|
-
if (!manifest.uninstallRecipe) {
|
|
749
|
-
throw new Error(`${manifest.name} \u7F3A\u5C11\u5378\u8F7D recipe`);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
return manifests;
|
|
753
|
-
}
|
|
754
776
|
|
|
755
777
|
// src/arguments.ts
|
|
756
778
|
function parseArguments(args) {
|
|
@@ -833,9 +855,12 @@ var helpText = `create-windy <\u9879\u76EE\u540D> [\u9009\u9879]
|
|
|
833
855
|
create-windy update --dry-run [--to <\u7248\u672C>] [--cwd <\u76EE\u5F55>]
|
|
834
856
|
create-windy update [--to <\u7248\u672C>] [--cwd <\u76EE\u5F55>]
|
|
835
857
|
create-windy module list [--cwd <\u76EE\u5F55>]
|
|
836
|
-
create-windy module add <key...> [--dry-run] [--
|
|
837
|
-
create-windy module
|
|
838
|
-
create-windy module
|
|
858
|
+
create-windy module add <key...> [--dry-run] [--skip-install] [--yes]
|
|
859
|
+
create-windy module enable <key...> [--dry-run] [--yes] [--cwd <\u76EE\u5F55>]
|
|
860
|
+
create-windy module disable <key...> [--dry-run] [--yes] [--cwd <\u76EE\u5F55>]
|
|
861
|
+
create-windy module update [key...] [--dry-run] [--skip-install] [--yes]
|
|
862
|
+
create-windy module remove <key...> [--dry-run] [--skip-install] [--yes]
|
|
863
|
+
[--data-disposition <\u7B56\u7565>]
|
|
839
864
|
[--data-plan <\u6587\u4EF6>] [--confirm-data-disposition] [--cwd <\u76EE\u5F55>]
|
|
840
865
|
create-windy schema handoff [--config <JSON>] [--cwd <\u76EE\u5F55>]
|
|
841
866
|
|
|
@@ -1214,12 +1239,12 @@ import {
|
|
|
1214
1239
|
copyFile,
|
|
1215
1240
|
lstat as lstat5,
|
|
1216
1241
|
mkdir as mkdir3,
|
|
1217
|
-
readFile as
|
|
1242
|
+
readFile as readFile10,
|
|
1218
1243
|
readdir as readdir5,
|
|
1219
1244
|
rm as rm4,
|
|
1220
|
-
writeFile as
|
|
1245
|
+
writeFile as writeFile9
|
|
1221
1246
|
} from "fs/promises";
|
|
1222
|
-
import { basename as basename5, extname as extname3, join as
|
|
1247
|
+
import { basename as basename5, extname as extname3, join as join11 } from "path";
|
|
1223
1248
|
|
|
1224
1249
|
// src/customer-docker.ts
|
|
1225
1250
|
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
@@ -1304,9 +1329,11 @@ var ignoredFiles = new Set([
|
|
|
1304
1329
|
".windy/update-state.json"
|
|
1305
1330
|
]);
|
|
1306
1331
|
var projectOwnedRoots = [
|
|
1332
|
+
"windy.modules.json",
|
|
1307
1333
|
"module-schema.lineages.json",
|
|
1308
1334
|
"module-schema",
|
|
1309
|
-
"apps/web/src
|
|
1335
|
+
"apps/web/src",
|
|
1336
|
+
"apps/server/src/app",
|
|
1310
1337
|
"apps/agent-server/project",
|
|
1311
1338
|
"apps/server/src/installed-business-modules.ts",
|
|
1312
1339
|
"apps/server/src/domain-schema",
|
|
@@ -1323,8 +1350,6 @@ var sharedScaffoldRoots = [
|
|
|
1323
1350
|
"apps/server/Dockerfile",
|
|
1324
1351
|
"apps/server/src/index.ts",
|
|
1325
1352
|
"apps/web/Dockerfile",
|
|
1326
|
-
"apps/web/src/layout",
|
|
1327
|
-
"apps/web/src/router",
|
|
1328
1353
|
"packages/database/src/schema/index.ts"
|
|
1329
1354
|
];
|
|
1330
1355
|
async function writeManagedFilesManifest(targetDirectory, generatorVersion) {
|
|
@@ -2688,9 +2713,10 @@ MCP \u6BCF\u6B21\u8C03\u7528\u90FD\u4F1A\u91CD\u65B0\u6267\u884C Feature\u3001RB
|
|
|
2688
2713
|
\u548C \`dev:agent\` \u662F\u53E6\u4E00\u6761\u53EF\u9009\u94FE\u8DEF\u3002\u5B8C\u6574\u8FB9\u754C\u89C1
|
|
2689
2714
|
[MCP \u4E1A\u52A1\u80FD\u529B](./docs/architecture/mcp-business-capabilities.md) \u4E0E
|
|
2690
2715
|
[Agent Tool](./docs/platform/agent-tools.md)\u3002` : `\u5F53\u524D\u7EC4\u5408\u672A\u5305\u542B \`system.agent\`\uFF0CMCP Server\u3001Agent Tool Host \u548C\u76F8\u5173\u6587\u6863\u5DF2\u88AB
|
|
2691
|
-
\u7269\u7406\u88C1\u526A\u3002\u521B\u5EFA\u65F6\u53EF\u589E\u52A0 \`--module system.agent\` \u6216\u4F7F\u7528 \`--all-modules\`\
|
|
2692
|
-
\u9879\u76EE\
|
|
2693
|
-
\
|
|
2716
|
+
\u7269\u7406\u88C1\u526A\u3002\u521B\u5EFA\u65F6\u53EF\u589E\u52A0 \`--module system.agent\` \u6216\u4F7F\u7528 \`--all-modules\`\u3002\u5F53\u524D\u6CA1\u6709
|
|
2717
|
+
self-contained H3 \u6A21\u5757\uFF0C\u5DF2\u90E8\u7F72\u9879\u76EE\u5F53\u524D\u4E0D\u80FD\u901A\u8FC7\u6A21\u5757\u547D\u4EE4\u8865\u88C5 \`system.agent\`\uFF1B
|
|
2718
|
+
\`module add\` \u4F1A\u5728\u5199\u5165\u524D fail closed\u3002\u4E0D\u8981\u624B\u5DE5\u590D\u5236 MCP Adapter \u6216\u53E6\u5EFA\u6388\u6743\u94FE\u3002\u4ED3\u5E93
|
|
2719
|
+
Skill \u4ECD\u53EF\u7528\u4E8E\u666E\u901A\u4E1A\u52A1\u6A21\u5757\u5F00\u53D1\u3002`}
|
|
2694
2720
|
`;
|
|
2695
2721
|
}
|
|
2696
2722
|
|
|
@@ -3076,7 +3102,14 @@ function starterReadme(projectName, includeExample = true, includeOxc = true, pr
|
|
|
3076
3102
|
const selected = new Set(selectedModules);
|
|
3077
3103
|
const includeAgent = selected.has("system.agent");
|
|
3078
3104
|
const includeSearch = selected.has("system.search");
|
|
3079
|
-
const
|
|
3105
|
+
const toggleableModule = moduleDistributionCatalog.find(({ name, selection, runtimeActivation }) => selected.has(name) && selection !== "required" && runtimeActivation === "toggle" && !moduleDistributionCatalog.some((candidate) => selected.has(candidate.name) && candidate.dependencies.includes(name)))?.name;
|
|
3106
|
+
const moduleActivationCommands = toggleableModule ? [
|
|
3107
|
+
`bun run windy module disable ${toggleableModule} --dry-run`,
|
|
3108
|
+
`bun run windy module disable ${toggleableModule}`,
|
|
3109
|
+
`bun run windy module enable ${toggleableModule}`
|
|
3110
|
+
].join(`
|
|
3111
|
+
`) : "# \u5F53\u524D\u7EC4\u5408\u6CA1\u6709\u53EF\u5B89\u5168 runtime disable \u7684\u5DF2\u5B89\u88C5\u53EF\u9009\u6A21\u5757";
|
|
3112
|
+
const moduleRows = moduleDistributionCatalog.map(({ name, description, selection }) => `| \`${name}\` | ${selected.has(name) ? "\u5DF2\u5305\u542B" : "\u672A\u5305\u542B"} | ${selection === "required" ? "H0" : "H2"} | ${description} |`).join(`
|
|
3080
3113
|
`);
|
|
3081
3114
|
return `# ${projectName}
|
|
3082
3115
|
|
|
@@ -3242,22 +3275,29 @@ create-windy \u5728\u672C\u673A \`.env\` \u4E2D\u968F\u673A\u751F\u6210\u7684 \`
|
|
|
3242
3275
|
| \u6CD5\u5F8B\u8BB8\u53EF | \`${projectLicense}\` |
|
|
3243
3276
|
|
|
3244
3277
|
\u5E73\u53F0\u5F53\u524D\u6CE8\u518C\u7684\u5168\u90E8\u6A21\u5757\u5982\u4E0B\u3002H0 \u8868\u793A profile \u9501\u5B9A\u6838\u5FC3\uFF1BH2 \u8868\u793A\u521B\u5EFA\u65F6\u53EF\u4EE5\u7269\u7406\u5305\u542B\u6216
|
|
3245
|
-
\u6392\u9664\uFF1BH3 \u8FD8\u5177\u5907\u90E8\u7F72\u671F\u5B89\u88C5\u3001\u66F4\u65B0\u3001\u6570\u636E\u4FDD\u7559\u5378\u8F7D\u548C\u91CD\u88C5\u8BC1\u636E\u3002\
|
|
3246
|
-
\
|
|
3278
|
+
\u6392\u9664\uFF1BH3 \u8FD8\u5177\u5907\u90E8\u7F72\u671F\u5B89\u88C5\u3001\u66F4\u65B0\u3001\u6570\u636E\u4FDD\u7559\u5378\u8F7D\u548C\u91CD\u88C5\u8BC1\u636E\u3002\u5F53\u524D\u6CA1\u6709 H3 \u6A21\u5757\uFF0C\u4E5F\u4E0D
|
|
3279
|
+
\u652F\u6301\u4EFB\u610F npm package \u540D\u79F0\u5B89\u88C5\u3002
|
|
3247
3280
|
|
|
3248
3281
|
| Module Key | \u5F53\u524D\u9879\u76EE | \u70ED\u63D2\u62D4\u53EF\u9760\u5EA6 | \u8BF4\u660E |
|
|
3249
3282
|
| ---------- | -------- | ------------ | ---- |
|
|
3250
3283
|
${moduleRows}
|
|
3251
3284
|
|
|
3252
|
-
\u9879\u76EE\
|
|
3253
|
-
\
|
|
3254
|
-
\`
|
|
3255
|
-
\
|
|
3256
|
-
\
|
|
3257
|
-
|
|
3258
|
-
\
|
|
3259
|
-
|
|
3260
|
-
\
|
|
3285
|
+
\u9879\u76EE\u88C5\u914D\u9009\u62E9\u8BB0\u5F55\u5728 project-owned \u7684 \`windy.modules.json\`\uFF0C\u53EF\u63D0\u4EA4 Git \u5E76\u7ED3\u6784\u5316\u7F16\u8F91\uFF1B
|
|
3286
|
+
\u5B83\u53EA\u4FDD\u5B58\u65E0\u7248\u672C package \u5165\u53E3\u3001\u542F\u7528\u72B6\u6001\u3001\u987A\u5E8F\u3001Admin \u53EF\u89C1\u6027\u4E0E\u6A21\u5757\u914D\u7F6E\u3002\u4F9D\u8D56\u7248\u672C\u4E8B\u5B9E
|
|
3287
|
+
\u4ECD\u53EA\u6765\u81EA \`package.json\` \u4E0E \`bun.lock\`\u3002Server \u9ED8\u8BA4\u4ECE
|
|
3288
|
+
\`apps/server/src/app/server-composition.ts\` \u88C5\u914D Adapter\uFF1BWeb \u901A\u8FC7 package \u7684
|
|
3289
|
+
browser-safe \`./admin\` \u4E0E project-owned \u7684
|
|
3290
|
+
\`apps/web/src/app/web-composition.ts\` \u88C5\u914D\u9875\u9762\uFF0C\u4E0D\u590D\u5236\u7B2C\u4E8C\u4EFD Feature\u3001Permission
|
|
3291
|
+
\u6216\u8DEF\u7531\u6E05\u5355\u3002\u6574\u4E2A \`apps/web/src\` \u4E0E\u6574\u4E2A \`apps/server/src/app\` \u90FD\u662F
|
|
3292
|
+
project-owned\uFF0C\u5BA2\u6237\u53EF\u4EE5\u4FEE\u6539 Router\u3001layout\u3001\u9875\u9762\u3001Host \u548C Server \u7EC4\u5408\uFF1B\u666E\u901A
|
|
3293
|
+
\`windy update\` \u4E0D\u4F1A\u8986\u76D6\u6216\u4E09\u65B9\u5408\u5E76\u8FD9\u4E9B\u6587\u4EF6\u3002
|
|
3294
|
+
|
|
3295
|
+
\u7CBE\u786E\u751F\u6210\u6765\u6E90\u4FDD\u7559\u5728 \`.windy/generation.json\`\u3002\u5F53\u524D\u7248\u672C\u5DF2\u63D0\u4F9B\u53EF\u56DE\u6EDA\u7684
|
|
3296
|
+
\`windy update\` \u4E0E \`windy module list/enable/disable\`\u3002\u5F53\u524D\u5185\u7F6E\u6A21\u5757\u4ECD\u4F9D\u8D56
|
|
3297
|
+
source/template \u6216 project-owned Composition\uFF1B\u5F53\u524D\u5185\u7F6E\u6A21\u5757\u7684 add/update/remove
|
|
3298
|
+
\u5B9E\u9645\u96C6\u5408\u53D8\u5316\u4F1A\u5728\u5199\u5165\u524D fail closed\u3002Feature Flag \u5173\u95ED\u3001module disable \u4E0E\u7269\u7406\u5378\u8F7D\u662F
|
|
3299
|
+
\u4E09\u4E2A\u4E0D\u540C\u52A8\u4F5C\uFF1B\`system.settings\`\u3001\`system.storage\` \u548C
|
|
3300
|
+
\`system.data-governance\` \u53EA\u80FD\u5728\u521B\u5EFA\u671F\u7269\u7406\u6392\u9664\uFF0C\u90E8\u7F72\u540E\u4E0D\u80FD\u53EA\u6539 registry \u5B89\u5168\u505C\u7528\u3002
|
|
3261
3301
|
|
|
3262
3302
|
## \u5E38\u7528\u547D\u4EE4
|
|
3263
3303
|
|
|
@@ -3274,8 +3314,7 @@ bun run windy doctor
|
|
|
3274
3314
|
bun run windy update --check
|
|
3275
3315
|
bun run windy update --dry-run
|
|
3276
3316
|
bun run windy module list
|
|
3277
|
-
|
|
3278
|
-
bun run windy module remove work-order --dry-run
|
|
3317
|
+
${moduleActivationCommands}
|
|
3279
3318
|
${includeOxc ? `bun run lint
|
|
3280
3319
|
bun run format` : "# \u672C\u9879\u76EE\u672A\u9884\u88C5 lint/format \u5DE5\u5177\uFF0C\u53EF\u6309\u56E2\u961F\u9700\u8981\u81EA\u884C\u9009\u62E9\u3002"}
|
|
3281
3320
|
\`\`\`
|
|
@@ -3284,7 +3323,9 @@ ${includeOxc ? "\u63D0\u4EA4\u65F6 Husky \u4F1A\u901A\u8FC7 lint-staged \u4E0E O
|
|
|
3284
3323
|
|
|
3285
3324
|
\u66F4\u65B0\u524D\u65E0\u9700\u63D0\u4EA4\u3001\u6682\u5B58\u6216\u6E05\u7406\u4E1A\u52A1\u6539\u52A8\u3002\`--dry-run\` \u53EA\u751F\u6210\u8BA1\u5212\uFF0C\u4E0D\u5199\u9879\u76EE\uFF1B\u65E0\u5173 WIP
|
|
3286
3325
|
\u4FDD\u6301\u539F\u6837\uFF0C\u547D\u4E2D\u540C\u4E00\u8DEF\u5F84\u65F6\u6309\u51BB\u7ED3\u5FEB\u7167\u4E0E\u4E09\u65B9\u5408\u5E76 fail closed\u3002\u6B63\u5F0F\u66F4\u65B0\u5148\u5907\u4EFD\uFF0C\u518D\u505A
|
|
3287
|
-
package \u5B57\u6BB5\u7EA7\u5408\u5E76\u3001\u5171\u4EAB\u811A\u624B\u67B6\u4E09\u65B9\u5408\u5E76\u4E0E\u5B8C\u6574\u9A8C\u8BC1\u3002\
|
|
3326
|
+
package \u5B57\u6BB5\u7EA7\u5408\u5E76\u3001\u5171\u4EAB\u811A\u624B\u67B6\u4E09\u65B9\u5408\u5E76\u4E0E\u5B8C\u6574\u9A8C\u8BC1\u3002\u6574\u4E2A \`apps/web/src\` \u548C
|
|
3327
|
+
\`apps/server/src/app\` \u4FDD\u6301\u9879\u76EE\u7248\u672C\u3002\u4EFB\u4F55\u51B2\u7A81\u90FD\u4F1A\u5728\u5199\u5165\u524D\u4E2D\u6B62\uFF0C\u6A21\u5757\u542F\u505C\u5728\u4EA4\u4E92
|
|
3328
|
+
\u7EC8\u7AEF\u786E\u8BA4\uFF1BCI\u3001Agent \u6216\u5176\u5B83\u975E TTY \u73AF\u5883\u5FC5\u987B\u663E\u5F0F\u4F20\u5165 \`--yes\`\u3002
|
|
3288
3329
|
\u65E0\u5E76\u53D1\u53D8\u5316\u7684\u9A8C\u8BC1\u5931\u8D25\u4F1A\u81EA\u52A8\u56DE\u6EDA\uFF1B\u4E2D\u65AD\u6062\u590D\u4F7F\u7528
|
|
3289
3330
|
\`bun run windy doctor --repair\`\u3002\u8BE5\u547D\u4EE4\u5728\u63D0\u4EA4\u70B9\u524D\u4FDD\u7559\u5E76\u53D1\u7F16\u8F91\u5E76\u56DE\u6EDA\u5176\u4F59\u8DEF\u5F84\uFF0C
|
|
3290
3331
|
\u5728 committed \u63D0\u4EA4\u70B9\u540E\u53EA\u5B8C\u6210\u4E8B\u52A1\u72B6\u6001\u4E0E\u5907\u4EFD\u6E05\u7406\uFF0C\u4E0D\u56DE\u6EDA\u9879\u76EE\u6587\u4EF6\u3002
|
|
@@ -3307,9 +3348,10 @@ create-windy \u9ED8\u8BA4\u5EFA\u7ACB \`main\` \u5206\u652F\u5E76\u521B\u5EFA \`
|
|
|
3307
3348
|
\u6CA1\u6709\u914D\u7F6E Git \u7528\u6237\u8EAB\u4EFD\uFF0C\u6587\u4EF6\u4F1A\u4FDD\u7559\u5728\u6682\u5B58\u533A\uFF1B\u914D\u7F6E\u8EAB\u4EFD\u540E\u624B\u52A8\u63D0\u4EA4\u5373\u53EF\u3002
|
|
3308
3349
|
|
|
3309
3350
|
\u5F53\u524D\u5DF2\u4EA4\u4ED8\u7684 Windy \u66F4\u65B0\u5668\u4F1A\u6839\u636E Project Lock \u548C\u6587\u4EF6\u6240\u6709\u6743\uFF0C\u4ECE Project Lock \u6307\u5411\u7684
|
|
3310
|
-
\u7CBE\u786E npm artifact \u91CD\u5EFA Base \u5E76\u6267\u884C\u4E09\u65B9\u5408\u5E76\uFF1B\u5B83\u4E0D\u8FDE\u63A5\u79C1\u6709\u6E90\u4ED3\u5E93\
|
|
3311
|
-
\
|
|
3312
|
-
\
|
|
3351
|
+
\u7CBE\u786E npm artifact \u91CD\u5EFA Base \u5E76\u6267\u884C\u4E09\u65B9\u5408\u5E76\uFF1B\u5B83\u4E0D\u8FDE\u63A5\u79C1\u6709\u6E90\u4ED3\u5E93\u3002
|
|
3352
|
+
\u66F4\u65B0\u5668\u4E0D\u4F1A\u9759\u9ED8\u8986\u76D6\u9879\u76EE\u4EE3\u7801\u3002\`module enable/disable\` \u53EA\u4EE5 CAS \u4E8B\u52A1\u66F4\u65B0
|
|
3353
|
+
\`windy.modules.json\`\uFF1B\u5F53\u524D\u5185\u7F6E\u6A21\u5757\u7684 add/update/remove \u5B9E\u9645\u96C6\u5408\u53D8\u5316\u5728\u751F\u6210\u66F4\u65B0
|
|
3354
|
+
\u8BA1\u5212\u524D\u5373\u88AB\u62D2\u7EDD\u3002
|
|
3313
3355
|
|
|
3314
3356
|
## License
|
|
3315
3357
|
|
|
@@ -3666,6 +3708,109 @@ async function collectFiles3(root) {
|
|
|
3666
3708
|
}
|
|
3667
3709
|
}
|
|
3668
3710
|
|
|
3711
|
+
// src/project-module-registry.ts
|
|
3712
|
+
import { createHash as createHash3 } from "crypto";
|
|
3713
|
+
import { readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
|
|
3714
|
+
import { join as join10 } from "path";
|
|
3715
|
+
var projectModuleRegistryPath = "windy.modules.json";
|
|
3716
|
+
async function readProjectModuleRegistrySnapshot(projectDirectory, installedNames) {
|
|
3717
|
+
const path = join10(projectDirectory, projectModuleRegistryPath);
|
|
3718
|
+
let content;
|
|
3719
|
+
try {
|
|
3720
|
+
content = await readFile9(path);
|
|
3721
|
+
} catch (error) {
|
|
3722
|
+
if (isMissing4(error)) {
|
|
3723
|
+
throw new Error(`\u9879\u76EE\u7F3A\u5C11 ${projectModuleRegistryPath}\uFF1B\u8BF7\u5148\u8FD0\u884C bun run windy update`, { cause: error });
|
|
3724
|
+
}
|
|
3725
|
+
throw error;
|
|
3726
|
+
}
|
|
3727
|
+
const registry = parseProjectModuleRegistry(content);
|
|
3728
|
+
assertRegistryMatchesInstalled(registry, installedNames);
|
|
3729
|
+
return {
|
|
3730
|
+
content,
|
|
3731
|
+
hash: createHash3("sha256").update(content).digest("hex"),
|
|
3732
|
+
registry
|
|
3733
|
+
};
|
|
3734
|
+
}
|
|
3735
|
+
function parseProjectModuleRegistry(content) {
|
|
3736
|
+
const parsed = JSON.parse(typeof content === "string" ? content : new TextDecoder().decode(content));
|
|
3737
|
+
if (!parsed || typeof parsed !== "object")
|
|
3738
|
+
invalidRegistry();
|
|
3739
|
+
const value = parsed;
|
|
3740
|
+
if (value.schemaVersion !== 1 || !Array.isArray(value.modules)) {
|
|
3741
|
+
invalidRegistry();
|
|
3742
|
+
}
|
|
3743
|
+
const names = new Set;
|
|
3744
|
+
const orders = new Set;
|
|
3745
|
+
for (const item of value.modules) {
|
|
3746
|
+
if (!isRegistration(item))
|
|
3747
|
+
invalidRegistry();
|
|
3748
|
+
if (names.has(item.name)) {
|
|
3749
|
+
throw new Error(`\u6A21\u5757\u88C5\u914D\u6E05\u5355\u5B58\u5728\u91CD\u590D name\uFF1A${item.name}`);
|
|
3750
|
+
}
|
|
3751
|
+
if (orders.has(item.order)) {
|
|
3752
|
+
throw new Error(`\u6A21\u5757\u88C5\u914D\u6E05\u5355\u5B58\u5728\u91CD\u590D order\uFF1A${item.order}`);
|
|
3753
|
+
}
|
|
3754
|
+
names.add(item.name);
|
|
3755
|
+
orders.add(item.order);
|
|
3756
|
+
}
|
|
3757
|
+
return value;
|
|
3758
|
+
}
|
|
3759
|
+
async function writeInitialProjectModuleRegistry(targetDirectory, selectedNames) {
|
|
3760
|
+
const manifests = selectedModuleManifests(selectedNames);
|
|
3761
|
+
const modules = await Promise.all(manifests.map(async (manifest, index) => ({
|
|
3762
|
+
name: manifest.name,
|
|
3763
|
+
package: manifest.runtimePackage,
|
|
3764
|
+
enabled: true,
|
|
3765
|
+
order: (index + 1) * 100,
|
|
3766
|
+
admin: { visible: true },
|
|
3767
|
+
config: {}
|
|
3768
|
+
})));
|
|
3769
|
+
const registry = { schemaVersion: 1, modules };
|
|
3770
|
+
await writeFile8(join10(targetDirectory, projectModuleRegistryPath), `${JSON.stringify(registry, null, 2)}
|
|
3771
|
+
`);
|
|
3772
|
+
}
|
|
3773
|
+
function assertRegistryMatchesInstalled(registry, installedNames) {
|
|
3774
|
+
const installed = new Set(installedNames);
|
|
3775
|
+
const registered = new Set(registry.modules.map(({ name }) => name));
|
|
3776
|
+
const extra = registry.modules.map(({ name }) => name).filter((name) => !installed.has(name));
|
|
3777
|
+
if (extra.length) {
|
|
3778
|
+
throw new Error(`\u6A21\u5757\u88C5\u914D\u6E05\u5355\u5305\u542B\u672A\u5B89\u88C5\u6A21\u5757\uFF1A${extra.join("\u3001")}`);
|
|
3779
|
+
}
|
|
3780
|
+
const missing = installedNames.filter((name) => !registered.has(name));
|
|
3781
|
+
if (missing.length) {
|
|
3782
|
+
throw new Error(`\u5DF2\u5B89\u88C5\u6A21\u5757\u7F3A\u5C11\u88C5\u914D\u58F0\u660E\uFF1A${missing.join("\u3001")}`);
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
function isRegistration(value) {
|
|
3786
|
+
if (!value || typeof value !== "object")
|
|
3787
|
+
return false;
|
|
3788
|
+
const item = value;
|
|
3789
|
+
const admin = item.admin;
|
|
3790
|
+
return typeof item.name === "string" && item.name.length > 0 && (item.package === null || typeof item.package === "string" && isPackageName(item.package)) && typeof item.enabled === "boolean" && Number.isSafeInteger(item.order) && Number(item.order) >= 0 && admin !== undefined && typeof admin === "object" && typeof admin.visible === "boolean" && typeof item.config === "object" && item.config !== null && !Array.isArray(item.config);
|
|
3791
|
+
}
|
|
3792
|
+
function isPackageName(value) {
|
|
3793
|
+
if (!value || value.length > 214 || value !== value.toLowerCase()) {
|
|
3794
|
+
return false;
|
|
3795
|
+
}
|
|
3796
|
+
const parts = value.startsWith("@") ? value.slice(1).split("/") : [value];
|
|
3797
|
+
if (parts.length !== (value.startsWith("@") ? 2 : 1))
|
|
3798
|
+
return false;
|
|
3799
|
+
return parts.every(isPackageNamePart);
|
|
3800
|
+
}
|
|
3801
|
+
function isPackageNamePart(value) {
|
|
3802
|
+
if (!value || value === "node_modules" || value === "favicon.ico" || value.startsWith(".") || value.startsWith("_")) {
|
|
3803
|
+
return false;
|
|
3804
|
+
}
|
|
3805
|
+
return /^[a-z0-9!~*'()._-]+$/.test(value);
|
|
3806
|
+
}
|
|
3807
|
+
function invalidRegistry() {
|
|
3808
|
+
throw new Error("\u9879\u76EE\u6A21\u5757\u88C5\u914D\u6E05\u5355\u65E0\u6548");
|
|
3809
|
+
}
|
|
3810
|
+
function isMissing4(error) {
|
|
3811
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3669
3814
|
// src/generator.ts
|
|
3670
3815
|
async function generateProject(input) {
|
|
3671
3816
|
validateProjectName(input.projectName);
|
|
@@ -3678,39 +3823,40 @@ async function generateProject(input) {
|
|
|
3678
3823
|
const selectedModules = input.selectedModules ?? templateMetadata.modules.filter(({ name }) => requestedIncludeExample || name !== "work-order").map(({ name }) => name);
|
|
3679
3824
|
const includeExample = selectedModules.includes("work-order");
|
|
3680
3825
|
for (const relativePath2 of generationTemplatePaths(true, includeOxc)) {
|
|
3681
|
-
await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2),
|
|
3826
|
+
await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join11(input.targetDirectory, relativePath2));
|
|
3682
3827
|
}
|
|
3683
3828
|
await materializeSelectedModules(input.targetDirectory, selectedModules);
|
|
3684
3829
|
await materializeRegistryDependencies(input.targetDirectory, selectedModuleManifests(selectedModules).flatMap(({ registryDependencies }) => registryDependencies));
|
|
3685
|
-
const packagePath =
|
|
3686
|
-
const packageJson = JSON.parse(await
|
|
3687
|
-
await
|
|
3830
|
+
const packagePath = join11(input.targetDirectory, "package.json");
|
|
3831
|
+
const packageJson = JSON.parse(await readFile10(packagePath, "utf8"));
|
|
3832
|
+
await writeFile9(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion), null, 2)}
|
|
3688
3833
|
`);
|
|
3689
|
-
await
|
|
3690
|
-
await
|
|
3691
|
-
await
|
|
3692
|
-
await
|
|
3834
|
+
await writeFile9(join11(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search")));
|
|
3835
|
+
await writeFile9(join11(input.targetDirectory, ".env.example"), environmentExample(includeExample, selectedModules.includes("system.agent"), selectedModules.includes("system.search")));
|
|
3836
|
+
await writeFile9(join11(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
|
|
3837
|
+
await writeFile9(join11(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), selectedModules.includes("system.agent"), selectedModules.includes("system.operations")));
|
|
3693
3838
|
await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
|
|
3694
3839
|
await applyWindyBaseLicense(input.targetDirectory);
|
|
3695
3840
|
await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
|
|
3696
3841
|
await prepareCustomerDockerfiles(input.targetDirectory);
|
|
3697
3842
|
await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense);
|
|
3698
|
-
await
|
|
3843
|
+
await writeInitialProjectModuleRegistry(input.targetDirectory, selectedModules);
|
|
3844
|
+
await rm4(join11(input.targetDirectory, "bun.lock"), { force: true });
|
|
3699
3845
|
await writeManagedFilesManifest(input.targetDirectory, templateMetadata.generatorVersion);
|
|
3700
3846
|
}
|
|
3701
3847
|
async function resolveTemplateSource(sourceRoot, relativePath2) {
|
|
3702
|
-
const source =
|
|
3848
|
+
const source = join11(sourceRoot, relativePath2);
|
|
3703
3849
|
try {
|
|
3704
3850
|
await lstat5(source);
|
|
3705
3851
|
return source;
|
|
3706
3852
|
} catch (error) {
|
|
3707
|
-
if (!
|
|
3853
|
+
if (!isMissing5(error))
|
|
3708
3854
|
throw error;
|
|
3709
3855
|
}
|
|
3710
3856
|
const alias = npmTemplateAliases[relativePath2];
|
|
3711
3857
|
if (!alias)
|
|
3712
3858
|
return source;
|
|
3713
|
-
return
|
|
3859
|
+
return join11(sourceRoot, alias);
|
|
3714
3860
|
}
|
|
3715
3861
|
async function assertGeneratedProjectIsClean(targetDirectory) {
|
|
3716
3862
|
const violations = [];
|
|
@@ -3739,7 +3885,7 @@ async function assertTargetAvailable(targetDirectory) {
|
|
|
3739
3885
|
if (entries.length)
|
|
3740
3886
|
throw new Error("\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u7A7A\u76EE\u5F55");
|
|
3741
3887
|
} catch (error) {
|
|
3742
|
-
if (
|
|
3888
|
+
if (isMissing5(error))
|
|
3743
3889
|
return;
|
|
3744
3890
|
throw error;
|
|
3745
3891
|
}
|
|
@@ -3752,11 +3898,11 @@ async function copyTree(source, target) {
|
|
|
3752
3898
|
if (metadata.isDirectory()) {
|
|
3753
3899
|
await mkdir3(target, { recursive: true });
|
|
3754
3900
|
for (const child of await readdir5(source)) {
|
|
3755
|
-
await copyTree(
|
|
3901
|
+
await copyTree(join11(source, child), join11(target, child));
|
|
3756
3902
|
}
|
|
3757
3903
|
return;
|
|
3758
3904
|
}
|
|
3759
|
-
await mkdir3(
|
|
3905
|
+
await mkdir3(join11(target, ".."), { recursive: true });
|
|
3760
3906
|
await copyFile(source, target);
|
|
3761
3907
|
}
|
|
3762
3908
|
function shouldExclude(name) {
|
|
@@ -3764,13 +3910,13 @@ function shouldExclude(name) {
|
|
|
3764
3910
|
}
|
|
3765
3911
|
async function walk(directory, visit) {
|
|
3766
3912
|
for (const name of await readdir5(directory)) {
|
|
3767
|
-
const path =
|
|
3913
|
+
const path = join11(directory, name);
|
|
3768
3914
|
await visit(path);
|
|
3769
3915
|
if ((await lstat5(path)).isDirectory())
|
|
3770
3916
|
await walk(path, visit);
|
|
3771
3917
|
}
|
|
3772
3918
|
}
|
|
3773
|
-
function
|
|
3919
|
+
function isMissing5(error) {
|
|
3774
3920
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
3775
3921
|
}
|
|
3776
3922
|
|
|
@@ -3850,7 +3996,7 @@ async function inspectTarget(path) {
|
|
|
3850
3996
|
try {
|
|
3851
3997
|
return (await readdir6(path)).length === 0 ? "empty" : "non-empty";
|
|
3852
3998
|
} catch (error) {
|
|
3853
|
-
if (
|
|
3999
|
+
if (isMissing6(error))
|
|
3854
4000
|
return "missing";
|
|
3855
4001
|
throw error;
|
|
3856
4002
|
}
|
|
@@ -3872,7 +4018,7 @@ function stageError(stage, error) {
|
|
|
3872
4018
|
function sanitizeReason(reason) {
|
|
3873
4019
|
return reason.replace(/\b([A-Z][A-Z0-9_]*(?:PASSWORD|SECRET|TOKEN|DATABASE_URL)[A-Z0-9_]*)=\S+/g, "$1=[\u5DF2\u9690\u85CF]").replace(/:\/\/([^\s:/]+):([^\s@]+)@/g, "://$1:[\u5DF2\u9690\u85CF]@");
|
|
3874
4020
|
}
|
|
3875
|
-
function
|
|
4021
|
+
function isMissing6(error) {
|
|
3876
4022
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
3877
4023
|
}
|
|
3878
4024
|
|
|
@@ -5620,8 +5766,8 @@ import { rm as rm10 } from "fs/promises";
|
|
|
5620
5766
|
import { resolve as resolve8 } from "path";
|
|
5621
5767
|
|
|
5622
5768
|
// src/update/doctor.ts
|
|
5623
|
-
import { readFile as
|
|
5624
|
-
import { join as
|
|
5769
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
5770
|
+
import { join as join15 } from "path";
|
|
5625
5771
|
|
|
5626
5772
|
// src/update/process.ts
|
|
5627
5773
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -6163,12 +6309,12 @@ function casError(path2, artifactPath, cause) {
|
|
|
6163
6309
|
|
|
6164
6310
|
// src/update/transaction-runtime.ts
|
|
6165
6311
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
6166
|
-
import { join as
|
|
6312
|
+
import { join as join13 } from "path";
|
|
6167
6313
|
|
|
6168
6314
|
// src/update/transaction-state-temporaries.ts
|
|
6169
6315
|
import { randomUUID } from "crypto";
|
|
6170
6316
|
import { readdir as readdir7 } from "fs/promises";
|
|
6171
|
-
import { join as
|
|
6317
|
+
import { join as join12 } from "path";
|
|
6172
6318
|
function serializeTransactionState(state) {
|
|
6173
6319
|
return `${JSON.stringify(state, null, 2)}
|
|
6174
6320
|
`;
|
|
@@ -6284,7 +6430,7 @@ function stateTemporaryName(identity, cleanup) {
|
|
|
6284
6430
|
return `${prefix}.${identity.kind}.${identity.ownerToken}.${identity.nonce}.tmp`;
|
|
6285
6431
|
}
|
|
6286
6432
|
async function listWindyDirectory(root) {
|
|
6287
|
-
return readdir7(
|
|
6433
|
+
return readdir7(join12(root, ".windy")).catch((error) => {
|
|
6288
6434
|
if (hasFsCode3(error, "ENOENT"))
|
|
6289
6435
|
return [];
|
|
6290
6436
|
throw error;
|
|
@@ -6318,7 +6464,7 @@ function createTransactionState(root, updateId, entries, manifestHash) {
|
|
|
6318
6464
|
return {
|
|
6319
6465
|
schemaVersion: 1,
|
|
6320
6466
|
updateId,
|
|
6321
|
-
backupDirectory:
|
|
6467
|
+
backupDirectory: join13(root, backupRelativePath(updateId)),
|
|
6322
6468
|
entries,
|
|
6323
6469
|
ownerToken: randomUUID2(),
|
|
6324
6470
|
phase: "claiming",
|
|
@@ -6377,7 +6523,7 @@ async function backupEntriesToDisk(root, backupPath, entries, afterEntry) {
|
|
|
6377
6523
|
if (entry.mode !== undefined && await safeFileMode(root, entry.path) !== entry.mode) {
|
|
6378
6524
|
throw new TransactionCasError(`\u5F85\u5907\u4EFD\u6587\u4EF6 mode \u5DF2\u53D8\u5316\uFF1A${entry.path}`, entry.path);
|
|
6379
6525
|
}
|
|
6380
|
-
await writeExclusive(root,
|
|
6526
|
+
await writeExclusive(root, join13(backupPath, "files", entry.path), content, undefined, entry.mode);
|
|
6381
6527
|
await afterEntry?.();
|
|
6382
6528
|
}
|
|
6383
6529
|
}
|
|
@@ -6685,7 +6831,7 @@ async function removeOwnedResidue(root, evidence, hash, mode) {
|
|
|
6685
6831
|
}
|
|
6686
6832
|
|
|
6687
6833
|
// src/update/transaction-recovery-files.ts
|
|
6688
|
-
import { join as
|
|
6834
|
+
import { join as join14 } from "path";
|
|
6689
6835
|
function matchesExpected(actualHash, actualMode, expected, expectedMode) {
|
|
6690
6836
|
return expected.kind === "missing" ? actualHash === undefined : actualHash === expected.value && (expectedMode === undefined || actualMode === expectedMode);
|
|
6691
6837
|
}
|
|
@@ -6697,7 +6843,7 @@ async function readRecoveryBackups(root, backupPath, state, preserved) {
|
|
|
6697
6843
|
await inspectSafePath(root, entry.path);
|
|
6698
6844
|
if (!entry.existed)
|
|
6699
6845
|
continue;
|
|
6700
|
-
const backupFile =
|
|
6846
|
+
const backupFile = join14(backupPath, "files", entry.path);
|
|
6701
6847
|
const content = await readSafeOptional(root, backupFile);
|
|
6702
6848
|
if (!content)
|
|
6703
6849
|
throw new Error(`\u4E8B\u52A1\u5907\u4EFD\u7F3A\u5931\uFF1A${entry.path}`);
|
|
@@ -7328,7 +7474,7 @@ async function diagnoseProject(projectDirectory, repair = false) {
|
|
|
7328
7474
|
if (file.ownership === "project-owned")
|
|
7329
7475
|
continue;
|
|
7330
7476
|
try {
|
|
7331
|
-
const changed = hashContent(await
|
|
7477
|
+
const changed = hashContent(await readFile11(join15(projectDirectory, file.path))) !== file.hash;
|
|
7332
7478
|
if (!changed)
|
|
7333
7479
|
continue;
|
|
7334
7480
|
modifiedManagedFiles.push(file.path);
|
|
@@ -7368,6 +7514,16 @@ var recipes = [
|
|
|
7368
7514
|
id: "starter-0.3.17-to-0.3.18",
|
|
7369
7515
|
from: "0.3.17",
|
|
7370
7516
|
to: "0.3.18"
|
|
7517
|
+
},
|
|
7518
|
+
{
|
|
7519
|
+
id: "starter-0.3.18-to-0.3.19",
|
|
7520
|
+
from: "0.3.18",
|
|
7521
|
+
to: "0.3.19"
|
|
7522
|
+
},
|
|
7523
|
+
{
|
|
7524
|
+
id: "starter-0.3.19-to-0.4.0",
|
|
7525
|
+
from: "0.3.19",
|
|
7526
|
+
to: "0.4.0"
|
|
7371
7527
|
}
|
|
7372
7528
|
];
|
|
7373
7529
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
@@ -7413,18 +7569,18 @@ function parseVersion2(version) {
|
|
|
7413
7569
|
}
|
|
7414
7570
|
|
|
7415
7571
|
// src/update/updater.ts
|
|
7416
|
-
import { readFile as
|
|
7417
|
-
import { join as
|
|
7572
|
+
import { readFile as readFile21, rm as rm8 } from "fs/promises";
|
|
7573
|
+
import { join as join26 } from "path";
|
|
7418
7574
|
|
|
7419
7575
|
// src/update/artifacts.ts
|
|
7420
|
-
import { mkdtemp, readFile as
|
|
7576
|
+
import { mkdtemp, readFile as readFile14 } from "fs/promises";
|
|
7421
7577
|
import { tmpdir } from "os";
|
|
7422
|
-
import { basename as basename8, join as
|
|
7578
|
+
import { basename as basename8, join as join18 } from "path";
|
|
7423
7579
|
|
|
7424
7580
|
// src/update/published-artifacts.ts
|
|
7425
|
-
import { createHash as
|
|
7426
|
-
import { mkdir as mkdir6, readFile as
|
|
7427
|
-
import { basename as basename7, join as
|
|
7581
|
+
import { createHash as createHash4 } from "crypto";
|
|
7582
|
+
import { mkdir as mkdir6, readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
|
|
7583
|
+
import { basename as basename7, join as join16 } from "path";
|
|
7428
7584
|
|
|
7429
7585
|
// src/update/safe-archive.ts
|
|
7430
7586
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
@@ -7476,17 +7632,17 @@ async function downloadPublicArtifact(temporaryRoot, label, version, expectedInt
|
|
|
7476
7632
|
}
|
|
7477
7633
|
const archive = await readBoundedResponse(response, `create-windy@${version} artifact `);
|
|
7478
7634
|
verifyArchive(metadata, archive);
|
|
7479
|
-
const destination =
|
|
7480
|
-
const archivePath =
|
|
7481
|
-
await
|
|
7635
|
+
const destination = join16(temporaryRoot, `${label}-artifact`);
|
|
7636
|
+
const archivePath = join16(temporaryRoot, `${label}.tgz`);
|
|
7637
|
+
await writeFile10(archivePath, archive);
|
|
7482
7638
|
await extractSafeTarArchive({
|
|
7483
7639
|
archivePath,
|
|
7484
7640
|
destination,
|
|
7485
7641
|
cwd: temporaryRoot
|
|
7486
7642
|
});
|
|
7487
|
-
const packageRoot2 =
|
|
7488
|
-
const packageJson = JSON.parse(await
|
|
7489
|
-
const template = await readTemplateMetadata(
|
|
7643
|
+
const packageRoot2 = join16(destination, "package");
|
|
7644
|
+
const packageJson = JSON.parse(await readFile12(join16(packageRoot2, "package.json"), "utf8"));
|
|
7645
|
+
const template = await readTemplateMetadata(join16(packageRoot2, "template"));
|
|
7490
7646
|
if (packageJson.name !== "create-windy" || packageJson.version !== version || template.generatorVersion !== version) {
|
|
7491
7647
|
throw new Error(`create-windy@${version} \u5305\u8EAB\u4EFD\u6216\u6A21\u677F\u5143\u6570\u636E\u4E0D\u4E00\u81F4`);
|
|
7492
7648
|
}
|
|
@@ -7611,17 +7767,17 @@ function boundedSizeError(label) {
|
|
|
7611
7767
|
return new Error(`${label}\u8D85\u8FC7\u5B89\u5168\u4E0A\u9650`);
|
|
7612
7768
|
}
|
|
7613
7769
|
function verifyArchive(metadata, archive) {
|
|
7614
|
-
const integrity = `sha512-${
|
|
7615
|
-
const shasum =
|
|
7770
|
+
const integrity = `sha512-${createHash4("sha512").update(archive).digest("base64")}`;
|
|
7771
|
+
const shasum = createHash4("sha1").update(archive).digest("hex");
|
|
7616
7772
|
if (integrity !== metadata.dist.integrity || shasum !== metadata.dist.shasum) {
|
|
7617
7773
|
throw new Error(`create-windy@${metadata.version} artifact \u5B8C\u6574\u6027\u6821\u9A8C\u5931\u8D25`);
|
|
7618
7774
|
}
|
|
7619
7775
|
}
|
|
7620
7776
|
async function generatePublicArtifactProject(temporaryRoot, label, projectName, packageRoot2, provenance) {
|
|
7621
|
-
const parent =
|
|
7777
|
+
const parent = join16(temporaryRoot, label);
|
|
7622
7778
|
await mkdir6(parent, { recursive: true });
|
|
7623
7779
|
const args = [
|
|
7624
|
-
|
|
7780
|
+
join16(packageRoot2, "dist/cli.js"),
|
|
7625
7781
|
projectName,
|
|
7626
7782
|
"--yes",
|
|
7627
7783
|
"--skip-install",
|
|
@@ -7641,7 +7797,7 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
|
|
|
7641
7797
|
}
|
|
7642
7798
|
}
|
|
7643
7799
|
await assertProcess("bun", args, parent);
|
|
7644
|
-
return
|
|
7800
|
+
return join16(parent, projectName);
|
|
7645
7801
|
}
|
|
7646
7802
|
|
|
7647
7803
|
// src/module-history.ts
|
|
@@ -7649,18 +7805,18 @@ import {
|
|
|
7649
7805
|
lstat as lstat6,
|
|
7650
7806
|
mkdir as mkdir7,
|
|
7651
7807
|
readdir as readdir8,
|
|
7652
|
-
readFile as
|
|
7653
|
-
writeFile as
|
|
7808
|
+
readFile as readFile13,
|
|
7809
|
+
writeFile as writeFile11
|
|
7654
7810
|
} from "fs/promises";
|
|
7655
|
-
import { dirname as dirname6, join as
|
|
7811
|
+
import { dirname as dirname6, join as join17, relative as relative4, sep as sep4 } from "path";
|
|
7656
7812
|
async function archiveRemovedModuleMigrations(input) {
|
|
7657
7813
|
await assertExistingHistoryIntegrity(input.projectDirectory);
|
|
7658
|
-
let changed = await copyMigrationTree(input.projectDirectory, ".windy/module-history",
|
|
7814
|
+
let changed = await copyMigrationTree(input.projectDirectory, ".windy/module-history", join17(input.targetDirectory, ".windy/module-history"));
|
|
7659
7815
|
const target = new Set(input.targetModules);
|
|
7660
7816
|
const removed = moduleDistributionCatalog.filter(({ name }) => input.sourceModules.includes(name) && !target.has(name));
|
|
7661
7817
|
for (const manifest of removed) {
|
|
7662
7818
|
for (const root of manifest.migrationRoots) {
|
|
7663
|
-
changed = await copyMigrationTree(input.projectDirectory, root,
|
|
7819
|
+
changed = await copyMigrationTree(input.projectDirectory, root, join17(input.targetDirectory, ".windy/module-history", manifest.name, root)) || changed;
|
|
7664
7820
|
}
|
|
7665
7821
|
}
|
|
7666
7822
|
if (changed) {
|
|
@@ -7668,7 +7824,7 @@ async function archiveRemovedModuleMigrations(input) {
|
|
|
7668
7824
|
}
|
|
7669
7825
|
}
|
|
7670
7826
|
async function assertExistingHistoryIntegrity(projectDirectory) {
|
|
7671
|
-
const historyRoot =
|
|
7827
|
+
const historyRoot = join17(projectDirectory, ".windy/module-history");
|
|
7672
7828
|
const metadata = await readOptionalMetadata(historyRoot);
|
|
7673
7829
|
if (!metadata)
|
|
7674
7830
|
return;
|
|
@@ -7683,13 +7839,13 @@ async function assertExistingHistoryIntegrity(projectDirectory) {
|
|
|
7683
7839
|
if (!entry || isMissingManagedFile(entry)) {
|
|
7684
7840
|
throw new Error(`\u6A21\u5757 migration \u5386\u53F2\u672A\u767B\u8BB0\u5230\u53D7\u7BA1\u6E05\u5355\uFF1A${relativePath2}`);
|
|
7685
7841
|
}
|
|
7686
|
-
if (hashContent(await
|
|
7842
|
+
if (hashContent(await readFile13(path2)) !== entry.hash) {
|
|
7687
7843
|
throw new Error(`\u6A21\u5757 migration \u5386\u53F2\u5DF2\u88AB\u4FEE\u6539\uFF1A${relativePath2}`);
|
|
7688
7844
|
}
|
|
7689
7845
|
}
|
|
7690
7846
|
}
|
|
7691
7847
|
async function copyMigrationTree(projectRoot, relativeRoot, targetRoot) {
|
|
7692
|
-
const sourceRoot =
|
|
7848
|
+
const sourceRoot = join17(projectRoot, relativeRoot);
|
|
7693
7849
|
const rootMetadata = await readOptionalMetadata(sourceRoot);
|
|
7694
7850
|
if (!rootMetadata)
|
|
7695
7851
|
return false;
|
|
@@ -7697,9 +7853,9 @@ async function copyMigrationTree(projectRoot, relativeRoot, targetRoot) {
|
|
|
7697
7853
|
throw new Error(`\u6A21\u5757 migration \u6839\u76EE\u5F55\u65E0\u6548\uFF1A${relativeRoot}`);
|
|
7698
7854
|
}
|
|
7699
7855
|
for (const source of await collectRegularFiles(sourceRoot)) {
|
|
7700
|
-
const target =
|
|
7856
|
+
const target = join17(targetRoot, relative4(sourceRoot, source).split(sep4).join("/"));
|
|
7701
7857
|
await mkdir7(dirname6(target), { recursive: true });
|
|
7702
|
-
await
|
|
7858
|
+
await writeFile11(target, await readFile13(source));
|
|
7703
7859
|
}
|
|
7704
7860
|
return true;
|
|
7705
7861
|
}
|
|
@@ -7709,7 +7865,7 @@ async function collectRegularFiles(root) {
|
|
|
7709
7865
|
return files.sort();
|
|
7710
7866
|
async function visit(directory) {
|
|
7711
7867
|
for (const name of (await readdir8(directory)).sort()) {
|
|
7712
|
-
const path2 =
|
|
7868
|
+
const path2 = join17(directory, name);
|
|
7713
7869
|
const metadata = await lstat6(path2);
|
|
7714
7870
|
if (metadata.isSymbolicLink()) {
|
|
7715
7871
|
throw new Error(`\u6A21\u5757 migration \u4E0D\u5141\u8BB8\u7B26\u53F7\u94FE\u63A5\uFF1A${path2}`);
|
|
@@ -7739,10 +7895,10 @@ class PublishedArtifactProvider {
|
|
|
7739
7895
|
this.#fetch = fetcher;
|
|
7740
7896
|
}
|
|
7741
7897
|
async prepare(projectDirectory, provenance, targetModules) {
|
|
7742
|
-
const temporaryRoot = await mkdtemp(
|
|
7898
|
+
const temporaryRoot = await mkdtemp(join18(tmpdir(), "windy-update-"));
|
|
7743
7899
|
const projectName = await readProjectName2(projectDirectory);
|
|
7744
|
-
const baseDirectory =
|
|
7745
|
-
const targetDirectory =
|
|
7900
|
+
const baseDirectory = join18(temporaryRoot, "base", projectName);
|
|
7901
|
+
const targetDirectory = join18(temporaryRoot, "target", projectName);
|
|
7746
7902
|
const baseArtifact = await downloadPublicArtifact(temporaryRoot, "base", provenance.generatorVersion, undefined, this.#fetch);
|
|
7747
7903
|
if (baseArtifact.identity.templateCommit !== provenance.templateCommit) {
|
|
7748
7904
|
throw new Error("Project Lock \u4E0E\u6765\u6E90 registry artifact \u7684 template commit \u4E0D\u4E00\u81F4");
|
|
@@ -7770,13 +7926,13 @@ class PublishedArtifactProvider {
|
|
|
7770
7926
|
}
|
|
7771
7927
|
}
|
|
7772
7928
|
async function readProjectName2(projectDirectory) {
|
|
7773
|
-
const source = JSON.parse(await
|
|
7929
|
+
const source = JSON.parse(await readFile14(join18(projectDirectory, "package.json"), "utf8"));
|
|
7774
7930
|
return source.name || basename8(projectDirectory);
|
|
7775
7931
|
}
|
|
7776
7932
|
|
|
7777
7933
|
// src/update/planner.ts
|
|
7778
|
-
import { readFile as
|
|
7779
|
-
import { dirname as dirname7, join as
|
|
7934
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
7935
|
+
import { dirname as dirname7, join as join24 } from "path";
|
|
7780
7936
|
|
|
7781
7937
|
// src/update/docker-copy-update-plan.ts
|
|
7782
7938
|
async function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
|
|
@@ -7864,12 +8020,12 @@ function matchesWorkspace(pattern, directory) {
|
|
|
7864
8020
|
}
|
|
7865
8021
|
|
|
7866
8022
|
// src/update/migration-reconciler.ts
|
|
7867
|
-
import { readFile as
|
|
7868
|
-
import { join as
|
|
8023
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
8024
|
+
import { join as join20 } from "path";
|
|
7869
8025
|
|
|
7870
8026
|
// src/update/migration-project-file.ts
|
|
7871
|
-
import { readFile as
|
|
7872
|
-
import { join as
|
|
8027
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
8028
|
+
import { join as join19 } from "path";
|
|
7873
8029
|
async function readProjectJson(input, path2) {
|
|
7874
8030
|
const content = await readProjectFile(input, path2);
|
|
7875
8031
|
if (!content) {
|
|
@@ -7885,7 +8041,7 @@ async function readProjectFile(input, path2) {
|
|
|
7885
8041
|
}
|
|
7886
8042
|
let content;
|
|
7887
8043
|
try {
|
|
7888
|
-
content = await
|
|
8044
|
+
content = await readFile15(join19(input.projectDirectory, path2));
|
|
7889
8045
|
} catch (error) {
|
|
7890
8046
|
if (!isMissingFileError(error))
|
|
7891
8047
|
throw error;
|
|
@@ -8004,7 +8160,7 @@ async function reconcileDrizzleMigrations(input) {
|
|
|
8004
8160
|
const tag = `${prefix}_${name}`;
|
|
8005
8161
|
const sqlPath = `${drizzleRoot}/${tag}.sql`;
|
|
8006
8162
|
const snapshotPath = `${drizzleRoot}/meta/${prefix}_snapshot.json`;
|
|
8007
|
-
const sql = await
|
|
8163
|
+
const sql = await readFile16(join20(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
|
|
8008
8164
|
merged.id = targetAfter.id;
|
|
8009
8165
|
merged.prevId = currentSnapshot.id;
|
|
8010
8166
|
const snapshot = encodeJson(merged);
|
|
@@ -8051,9 +8207,9 @@ function unchanged(targetManifest) {
|
|
|
8051
8207
|
async function readJournals(input) {
|
|
8052
8208
|
try {
|
|
8053
8209
|
const [base, project, target] = await Promise.all([
|
|
8054
|
-
readJson(
|
|
8210
|
+
readJson(join20(input.baseDirectory, journalPath)),
|
|
8055
8211
|
readProjectJson(input, journalPath),
|
|
8056
|
-
readJson(
|
|
8212
|
+
readJson(join20(input.targetDirectory, journalPath))
|
|
8057
8213
|
]);
|
|
8058
8214
|
return { base, project, target };
|
|
8059
8215
|
} catch (error) {
|
|
@@ -8091,7 +8247,7 @@ async function readSnapshot(root, tag) {
|
|
|
8091
8247
|
const match = migrationPattern.exec(tag);
|
|
8092
8248
|
if (!match)
|
|
8093
8249
|
throw new Error(`${journalPath}\uFF1Amigration tag \u683C\u5F0F\u65E0\u6548\uFF1A${tag}`);
|
|
8094
|
-
return await readJson(
|
|
8250
|
+
return await readJson(join20(root, `${drizzleRoot}/meta/${match[1]}_snapshot.json`));
|
|
8095
8251
|
}
|
|
8096
8252
|
function validateUniqueNames(journal, label, conflicts) {
|
|
8097
8253
|
const seen = new Set;
|
|
@@ -8132,27 +8288,27 @@ function encodeJson(value) {
|
|
|
8132
8288
|
`);
|
|
8133
8289
|
}
|
|
8134
8290
|
async function readJson(path2) {
|
|
8135
|
-
return JSON.parse(await
|
|
8291
|
+
return JSON.parse(await readFile16(path2, "utf8"));
|
|
8136
8292
|
}
|
|
8137
8293
|
|
|
8138
8294
|
// src/update/planner-file.ts
|
|
8139
|
-
import { readFile as
|
|
8140
|
-
import { join as
|
|
8295
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
8296
|
+
import { join as join22 } from "path";
|
|
8141
8297
|
|
|
8142
8298
|
// src/update/merge.ts
|
|
8143
|
-
import { mkdtemp as mkdtemp2, rm as rm6, writeFile as
|
|
8299
|
+
import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile12 } from "fs/promises";
|
|
8144
8300
|
import { tmpdir as tmpdir2 } from "os";
|
|
8145
|
-
import { join as
|
|
8301
|
+
import { join as join21 } from "path";
|
|
8146
8302
|
async function mergeTextFile(base, ours, theirs) {
|
|
8147
|
-
const root = await mkdtemp2(
|
|
8303
|
+
const root = await mkdtemp2(join21(tmpdir2(), "windy-merge-"));
|
|
8148
8304
|
try {
|
|
8149
|
-
const oursPath =
|
|
8150
|
-
const basePath =
|
|
8151
|
-
const theirsPath =
|
|
8305
|
+
const oursPath = join21(root, "ours");
|
|
8306
|
+
const basePath = join21(root, "base");
|
|
8307
|
+
const theirsPath = join21(root, "theirs");
|
|
8152
8308
|
await Promise.all([
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8309
|
+
writeFile12(oursPath, ours),
|
|
8310
|
+
writeFile12(basePath, base),
|
|
8311
|
+
writeFile12(theirsPath, theirs)
|
|
8156
8312
|
]);
|
|
8157
8313
|
const result2 = await captureProcess("git", ["merge-file", "-p", "--diff3", oursPath, basePath, theirsPath], root);
|
|
8158
8314
|
if (result2.code === 0) {
|
|
@@ -8406,10 +8562,10 @@ function conflict(path2, reason, expectedProjectContent) {
|
|
|
8406
8562
|
// src/update/planner-file.ts
|
|
8407
8563
|
async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false, forcePlatformBaseline = false) {
|
|
8408
8564
|
const [base, theirs] = await Promise.all([
|
|
8409
|
-
readOptional(
|
|
8410
|
-
targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional(
|
|
8565
|
+
readOptional(join22(baseRoot, path2)),
|
|
8566
|
+
targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional(join22(targetRoot, path2))
|
|
8411
8567
|
]);
|
|
8412
|
-
const ownership = source?.ownership
|
|
8568
|
+
const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
|
|
8413
8569
|
const expected = expectationForSnapshot(ours);
|
|
8414
8570
|
if (ownership === "project-owned") {
|
|
8415
8571
|
if (manageGeneratedProjectOwned) {
|
|
@@ -8514,7 +8670,7 @@ function conflict2(path2, ownership, reason, expectedProjectContent) {
|
|
|
8514
8670
|
}
|
|
8515
8671
|
async function readOptional(path2) {
|
|
8516
8672
|
try {
|
|
8517
|
-
return await
|
|
8673
|
+
return await readFile17(path2);
|
|
8518
8674
|
} catch (error) {
|
|
8519
8675
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
8520
8676
|
return;
|
|
@@ -8523,28 +8679,43 @@ async function readOptional(path2) {
|
|
|
8523
8679
|
}
|
|
8524
8680
|
}
|
|
8525
8681
|
|
|
8682
|
+
// src/update/planner-modules.ts
|
|
8683
|
+
function resolveModuleRecipeIds(request) {
|
|
8684
|
+
const lifecycle = request.lifecycle;
|
|
8685
|
+
if (!lifecycle)
|
|
8686
|
+
return [];
|
|
8687
|
+
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
8688
|
+
if (lifecycle.action === "add") {
|
|
8689
|
+
return lifecycle.addedModules.map((name) => catalog.get(name).installRecipe);
|
|
8690
|
+
}
|
|
8691
|
+
if (lifecycle.action === "remove") {
|
|
8692
|
+
return lifecycle.removedModules.map((name) => catalog.get(name).uninstallRecipe);
|
|
8693
|
+
}
|
|
8694
|
+
return lifecycle.updatedModules.flatMap((name) => catalog.get(name).updateRecipes);
|
|
8695
|
+
}
|
|
8696
|
+
|
|
8526
8697
|
// src/update/planner-snapshots.ts
|
|
8527
|
-
import { readFile as
|
|
8528
|
-
import { join as
|
|
8698
|
+
import { readFile as readFile18, stat as stat2 } from "fs/promises";
|
|
8699
|
+
import { join as join23 } from "path";
|
|
8529
8700
|
async function snapshotProjectFiles(project, paths, seed) {
|
|
8530
8701
|
const snapshots = new Map(seed);
|
|
8531
8702
|
await Promise.all([...paths].filter((path2) => !snapshots.has(path2)).map(async (path2) => {
|
|
8532
|
-
snapshots.set(path2, await readOptional2(
|
|
8703
|
+
snapshots.set(path2, await readOptional2(join23(project, path2)));
|
|
8533
8704
|
}));
|
|
8534
8705
|
return snapshots;
|
|
8535
8706
|
}
|
|
8536
8707
|
async function snapshotProjectModes(project, paths) {
|
|
8537
|
-
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(
|
|
8708
|
+
return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(join23(project, path2))])));
|
|
8538
8709
|
}
|
|
8539
8710
|
async function assertPlanSnapshots(project, expectations) {
|
|
8540
8711
|
const changed = [];
|
|
8541
8712
|
for (const expectation2 of expectations) {
|
|
8542
|
-
const actual = expectationForSnapshot(await readOptional2(
|
|
8713
|
+
const actual = expectationForSnapshot(await readOptional2(join23(project, expectation2.path)));
|
|
8543
8714
|
if (JSON.stringify(actual) !== JSON.stringify(expectation2.expected)) {
|
|
8544
8715
|
changed.push(expectation2.path);
|
|
8545
8716
|
continue;
|
|
8546
8717
|
}
|
|
8547
|
-
if ("mode" in expectation2 && await readModeOptional(
|
|
8718
|
+
if ("mode" in expectation2 && await readModeOptional(join23(project, expectation2.path)) !== expectation2.mode) {
|
|
8548
8719
|
changed.push(expectation2.path);
|
|
8549
8720
|
}
|
|
8550
8721
|
}
|
|
@@ -8556,7 +8727,7 @@ async function readModeOptional(path2) {
|
|
|
8556
8727
|
try {
|
|
8557
8728
|
return (await stat2(path2)).mode & 511;
|
|
8558
8729
|
} catch (error) {
|
|
8559
|
-
if (
|
|
8730
|
+
if (isMissing7(error))
|
|
8560
8731
|
return;
|
|
8561
8732
|
throw error;
|
|
8562
8733
|
}
|
|
@@ -8569,21 +8740,21 @@ async function readSourceParentMode(path2) {
|
|
|
8569
8740
|
}
|
|
8570
8741
|
return info.mode & 493 | 493;
|
|
8571
8742
|
} catch (error) {
|
|
8572
|
-
if (
|
|
8743
|
+
if (isMissing7(error))
|
|
8573
8744
|
return 493;
|
|
8574
8745
|
throw error;
|
|
8575
8746
|
}
|
|
8576
8747
|
}
|
|
8577
8748
|
async function readOptional2(path2) {
|
|
8578
8749
|
try {
|
|
8579
|
-
return await
|
|
8750
|
+
return await readFile18(path2);
|
|
8580
8751
|
} catch (error) {
|
|
8581
|
-
if (
|
|
8752
|
+
if (isMissing7(error))
|
|
8582
8753
|
return;
|
|
8583
8754
|
throw error;
|
|
8584
8755
|
}
|
|
8585
8756
|
}
|
|
8586
|
-
function
|
|
8757
|
+
function isMissing7(error) {
|
|
8587
8758
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
8588
8759
|
}
|
|
8589
8760
|
|
|
@@ -8620,8 +8791,8 @@ var oxcManagedPaths = new Set([
|
|
|
8620
8791
|
]);
|
|
8621
8792
|
async function createUpdatePlan(request, artifacts) {
|
|
8622
8793
|
await assertProjectReadyForUpdate(request.projectDirectory);
|
|
8623
|
-
const manifestPath =
|
|
8624
|
-
const expectedManifestHash = hashContent(await
|
|
8794
|
+
const manifestPath = join24(request.projectDirectory, ".windy/files.json");
|
|
8795
|
+
const expectedManifestHash = hashContent(await readFile19(manifestPath));
|
|
8625
8796
|
const generationSnapshot = await readGenerationProvenanceSnapshot(request.projectDirectory);
|
|
8626
8797
|
const provenance = generationSnapshot.provenance;
|
|
8627
8798
|
const targetModules = resolveUpdateTargetModules(provenance.modules.map(({ name }) => name), request.targetModules);
|
|
@@ -8667,8 +8838,8 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8667
8838
|
const paths = new Set([...sourceEntries.keys(), ...targetEntries.keys()]);
|
|
8668
8839
|
for (const path2 of paths) {
|
|
8669
8840
|
if (!projectSnapshots.has(path2)) {
|
|
8670
|
-
projectSnapshots.set(path2, await readOptional2(
|
|
8671
|
-
projectModes.set(path2, await readModeOptional(
|
|
8841
|
+
projectSnapshots.set(path2, await readOptional2(join24(request.projectDirectory, path2)));
|
|
8842
|
+
projectModes.set(path2, await readModeOptional(join24(request.projectDirectory, path2)));
|
|
8672
8843
|
}
|
|
8673
8844
|
}
|
|
8674
8845
|
const files = await planFiles({
|
|
@@ -8690,10 +8861,10 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8690
8861
|
for (const file of files) {
|
|
8691
8862
|
file.expectedProjectMode = projectModes.get(file.path);
|
|
8692
8863
|
if (file.action === "create" || file.action === "update") {
|
|
8693
|
-
file.mode = file.expectedProjectMode ?? await readModeOptional(
|
|
8864
|
+
file.mode = file.expectedProjectMode ?? await readModeOptional(join24(artifactSet.targetDirectory, file.path));
|
|
8694
8865
|
}
|
|
8695
8866
|
if (file.action === "create") {
|
|
8696
|
-
file.parentMode = await readSourceParentMode(
|
|
8867
|
+
file.parentMode = await readSourceParentMode(join24(artifactSet.targetDirectory, dirname7(file.path)));
|
|
8697
8868
|
}
|
|
8698
8869
|
}
|
|
8699
8870
|
const plannedPaths = new Set(files.map(({ path: path2 }) => path2));
|
|
@@ -8713,7 +8884,7 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8713
8884
|
...migrations.conflicts,
|
|
8714
8885
|
...files.flatMap((file) => file.conflict ? [`${file.path}\uFF1A${file.conflict}`] : [])
|
|
8715
8886
|
];
|
|
8716
|
-
if (hashContent(await
|
|
8887
|
+
if (hashContent(await readFile19(manifestPath)) !== expectedManifestHash) {
|
|
8717
8888
|
throw new Error("\u751F\u6210\u66F4\u65B0\u8BA1\u5212\u671F\u95F4\u53D7\u7BA1\u6E05\u5355\u53D1\u751F\u53D8\u5316");
|
|
8718
8889
|
}
|
|
8719
8890
|
await assertPlanSnapshots(request.projectDirectory, [
|
|
@@ -8745,19 +8916,6 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
8745
8916
|
lifecycle: request.lifecycle
|
|
8746
8917
|
};
|
|
8747
8918
|
}
|
|
8748
|
-
function resolveModuleRecipeIds(request) {
|
|
8749
|
-
const lifecycle = request.lifecycle;
|
|
8750
|
-
if (!lifecycle)
|
|
8751
|
-
return [];
|
|
8752
|
-
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
8753
|
-
if (lifecycle.action === "add") {
|
|
8754
|
-
return lifecycle.addedModules.map((name) => catalog.get(name).installRecipe);
|
|
8755
|
-
}
|
|
8756
|
-
if (lifecycle.action === "remove") {
|
|
8757
|
-
return lifecycle.removedModules.map((name) => catalog.get(name).uninstallRecipe);
|
|
8758
|
-
}
|
|
8759
|
-
return lifecycle.updatedModules.flatMap((name) => catalog.get(name).updateRecipes);
|
|
8760
|
-
}
|
|
8761
8919
|
async function planFiles(input) {
|
|
8762
8920
|
const files = [];
|
|
8763
8921
|
for (const path2 of [...input.paths].sort()) {
|
|
@@ -8851,9 +9009,9 @@ function frozenManifestHash(file, finalizedHashes) {
|
|
|
8851
9009
|
}
|
|
8852
9010
|
|
|
8853
9011
|
// src/update/format-stabilizer.ts
|
|
8854
|
-
import { mkdir as mkdir8, mkdtemp as mkdtemp3, readFile as
|
|
9012
|
+
import { mkdir as mkdir8, mkdtemp as mkdtemp3, readFile as readFile20, rm as rm7, writeFile as writeFile13 } from "fs/promises";
|
|
8855
9013
|
import { tmpdir as tmpdir3 } from "os";
|
|
8856
|
-
import { dirname as dirname8, extname as extname4, join as
|
|
9014
|
+
import { dirname as dirname8, extname as extname4, join as join25, resolve as resolve6, sep as sep5 } from "path";
|
|
8857
9015
|
var formattedExtensions = new Set([
|
|
8858
9016
|
".cjs",
|
|
8859
9017
|
".css",
|
|
@@ -8892,7 +9050,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
8892
9050
|
}
|
|
8893
9051
|
}
|
|
8894
9052
|
inputs.set(".windy/generation.json", new TextEncoder().encode(generationContent));
|
|
8895
|
-
const temporaryRoot = await mkdtemp3(
|
|
9053
|
+
const temporaryRoot = await mkdtemp3(join25(tmpdir3(), "windy-update-format-"));
|
|
8896
9054
|
try {
|
|
8897
9055
|
const stagedPaths = await stageInputs(temporaryRoot, inputs);
|
|
8898
9056
|
for (let offset = 0;offset < stagedPaths.length; offset += 80) {
|
|
@@ -8900,14 +9058,14 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
|
|
|
8900
9058
|
"x",
|
|
8901
9059
|
"oxfmt",
|
|
8902
9060
|
"--write",
|
|
8903
|
-
`--config=${
|
|
9061
|
+
`--config=${join25(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
|
|
8904
9062
|
...stagedPaths.slice(offset, offset + 80)
|
|
8905
9063
|
], result2.plan.projectDirectory);
|
|
8906
9064
|
}
|
|
8907
9065
|
const hashes = plannedContentHashes(result2);
|
|
8908
9066
|
let formattedGeneration = generationContent;
|
|
8909
9067
|
for (const [path2, original] of inputs) {
|
|
8910
|
-
const formatted = await
|
|
9068
|
+
const formatted = await readFile20(safeTemporaryPath(temporaryRoot, path2));
|
|
8911
9069
|
if (path2 === ".windy/generation.json") {
|
|
8912
9070
|
formattedGeneration = formatted.toString();
|
|
8913
9071
|
continue;
|
|
@@ -8934,7 +9092,7 @@ async function stageInputs(temporaryRoot, inputs) {
|
|
|
8934
9092
|
for (const [path2, content] of inputs) {
|
|
8935
9093
|
const target = safeTemporaryPath(temporaryRoot, path2);
|
|
8936
9094
|
await mkdir8(dirname8(target), { recursive: true });
|
|
8937
|
-
await
|
|
9095
|
+
await writeFile13(target, content);
|
|
8938
9096
|
paths.push(target);
|
|
8939
9097
|
}
|
|
8940
9098
|
return paths;
|
|
@@ -9061,7 +9219,7 @@ class DefaultStarterUpdater {
|
|
|
9061
9219
|
const plannedPaths = new Set(result2.plan.files.map(({ path: path2 }) => path2));
|
|
9062
9220
|
replaceExpectations(result2, verificationSnapshot.filter(({ path: path2 }) => !metadataPaths2.has(path2) && !plannedPaths.has(path2)));
|
|
9063
9221
|
verificationExpectationsFrozen = true;
|
|
9064
|
-
const packageJson = JSON.parse(await
|
|
9222
|
+
const packageJson = JSON.parse(await readFile21(join26(result2.plan.projectDirectory, "package.json"), "utf8"));
|
|
9065
9223
|
for (const name of ["lint", "typecheck", "test", "build"]) {
|
|
9066
9224
|
if (!packageJson.scripts?.[name]) {
|
|
9067
9225
|
steps.push({ name: `bun run ${name}`, status: "skipped" });
|
|
@@ -9145,8 +9303,10 @@ function expectedForPath(result2, path2) {
|
|
|
9145
9303
|
}
|
|
9146
9304
|
|
|
9147
9305
|
// src/module-lifecycle.ts
|
|
9148
|
-
import {
|
|
9149
|
-
|
|
9306
|
+
import { rm as rm9 } from "fs/promises";
|
|
9307
|
+
|
|
9308
|
+
// src/project-module-activation.ts
|
|
9309
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
9150
9310
|
|
|
9151
9311
|
// src/module-version-range.ts
|
|
9152
9312
|
function isVersionInCaretRange(version, range) {
|
|
@@ -9172,67 +9332,199 @@ function compareVersion(left, right) {
|
|
|
9172
9332
|
return 0;
|
|
9173
9333
|
}
|
|
9174
9334
|
|
|
9175
|
-
// src/module-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
throw new Error("module \u53EA\u652F\u6301 list\u3001add\u3001update\u3001remove");
|
|
9180
|
-
}
|
|
9181
|
-
const log = dependencies.log ?? console.log;
|
|
9182
|
-
const provenance = await readGenerationProvenance(projectDirectory);
|
|
9183
|
-
const installed = provenance.modules.map(({ name }) => name);
|
|
9184
|
-
if (action === "list") {
|
|
9185
|
-
printModuleList(provenance.modules, log);
|
|
9186
|
-
return;
|
|
9335
|
+
// src/project-module-activation.ts
|
|
9336
|
+
function planProjectModuleActivation(input) {
|
|
9337
|
+
if (input.requestedModules.length === 0) {
|
|
9338
|
+
throw new Error(`module ${input.action} \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u6A21\u5757 key`);
|
|
9187
9339
|
}
|
|
9188
|
-
const
|
|
9189
|
-
|
|
9190
|
-
|
|
9340
|
+
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
9341
|
+
const installed = new Set(input.registry.modules.map(({ name }) => name));
|
|
9342
|
+
for (const name of input.requestedModules) {
|
|
9343
|
+
const manifest = catalog.get(name);
|
|
9344
|
+
if (!manifest)
|
|
9345
|
+
throw new Error(`\u672A\u77E5\u6A21\u5757\uFF1A${name}`);
|
|
9346
|
+
if (!installed.has(name))
|
|
9347
|
+
throw new Error(`\u672A\u5B89\u88C5\u6A21\u5757\u4E0D\u80FD\u542F\u505C\uFF1A${name}`);
|
|
9348
|
+
assertCompatible(input.windyVersion, manifest.windyRange, name);
|
|
9349
|
+
}
|
|
9350
|
+
const target = new Map(input.registry.modules.map(({ name, enabled }) => [name, enabled]));
|
|
9351
|
+
if (input.action === "enable") {
|
|
9352
|
+
for (const name of input.requestedModules) {
|
|
9353
|
+
enableWithDependencies(name, target, installed, catalog, new Set);
|
|
9354
|
+
}
|
|
9355
|
+
} else {
|
|
9356
|
+
assertOptionalModules(input.requestedModules);
|
|
9357
|
+
assertRuntimeToggleSupported(input.requestedModules, catalog);
|
|
9358
|
+
for (const name of input.requestedModules)
|
|
9359
|
+
target.set(name, false);
|
|
9360
|
+
assertNoEnabledDependents(target, catalog);
|
|
9361
|
+
}
|
|
9362
|
+
assertEnabledCompatibility(target, input.windyVersion, catalog);
|
|
9363
|
+
assertEnabledConflicts(target, catalog);
|
|
9364
|
+
const modules = input.registry.modules.map((registration) => ({
|
|
9365
|
+
...registration,
|
|
9366
|
+
enabled: target.get(registration.name)
|
|
9367
|
+
}));
|
|
9368
|
+
const changedModules = modules.filter((registration, index) => registration.enabled !== input.registry.modules[index]?.enabled).map(({ name }) => name);
|
|
9369
|
+
const registry = {
|
|
9370
|
+
schemaVersion: 1,
|
|
9371
|
+
modules
|
|
9372
|
+
};
|
|
9373
|
+
return {
|
|
9374
|
+
action: input.action,
|
|
9375
|
+
requestedModules: input.requestedModules,
|
|
9376
|
+
changedModules,
|
|
9377
|
+
expectedRegistryHash: input.expectedRegistryHash,
|
|
9378
|
+
registry,
|
|
9379
|
+
content: `${JSON.stringify(registry, null, 2)}
|
|
9380
|
+
`
|
|
9381
|
+
};
|
|
9382
|
+
}
|
|
9383
|
+
function assertRuntimeToggleSupported(names, catalog) {
|
|
9384
|
+
const unsupported = names.filter((name) => catalog.get(name)?.runtimeActivation === "physical-only");
|
|
9385
|
+
if (unsupported.length) {
|
|
9386
|
+
throw new Error(`${unsupported.join("\u3001")} \u4E0D\u652F\u6301\u5B89\u5168 runtime disable\uFF1B\u5DF2\u90E8\u7F72\u9879\u76EE\u9700\u7531\u4EBA\u5DE5\u8FC1\u79FB\u5B8C\u6210\u7269\u7406\u5378\u8F7D`);
|
|
9191
9387
|
}
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9388
|
+
}
|
|
9389
|
+
async function applyProjectModuleActivation(projectDirectory, plan) {
|
|
9390
|
+
const state = await applyMetadataTransaction({
|
|
9391
|
+
id: `module-${plan.action}-${randomUUID4()}`,
|
|
9392
|
+
projectDirectory,
|
|
9393
|
+
guards: [
|
|
9394
|
+
{
|
|
9395
|
+
path: projectModuleRegistryPath,
|
|
9396
|
+
hash: plan.expectedRegistryHash
|
|
9397
|
+
}
|
|
9398
|
+
],
|
|
9399
|
+
writes: [{ path: projectModuleRegistryPath, content: plan.content }]
|
|
9200
9400
|
});
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
log("\u6A21\u5757\u96C6\u5408\u5DF2\u6EE1\u8DB3\u8BF7\u6C42\uFF0C\u65E0\u9700\u4FEE\u6539");
|
|
9204
|
-
return;
|
|
9401
|
+
if (!state.ownerToken) {
|
|
9402
|
+
throw new Error("\u6A21\u5757\u88C5\u914D\u4E8B\u52A1\u7F3A\u5C11\u6240\u6709\u6743\u4EE4\u724C");
|
|
9205
9403
|
}
|
|
9206
|
-
|
|
9207
|
-
const updater = dependencies.updater ?? new DefaultStarterUpdater;
|
|
9208
|
-
const plan = await updater.plan({
|
|
9404
|
+
await finalizeOwnedTransaction({
|
|
9209
9405
|
projectDirectory,
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9406
|
+
ownerToken: state.ownerToken,
|
|
9407
|
+
expectations: [
|
|
9408
|
+
expectationForContent(projectModuleRegistryPath, plan.content)
|
|
9409
|
+
]
|
|
9213
9410
|
});
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9411
|
+
}
|
|
9412
|
+
function enableWithDependencies(name, target, installed, catalog, visiting) {
|
|
9413
|
+
if (visiting.has(name))
|
|
9414
|
+
throw new Error(`\u6A21\u5757\u4F9D\u8D56\u5B58\u5728\u5FAA\u73AF\uFF1A${name}`);
|
|
9415
|
+
visiting.add(name);
|
|
9416
|
+
const manifest = catalog.get(name);
|
|
9417
|
+
for (const dependency of manifest.dependencies) {
|
|
9418
|
+
if (!installed.has(dependency)) {
|
|
9419
|
+
throw new Error(`${name} \u7F3A\u5C11\u5DF2\u5B89\u88C5\u4F9D\u8D56\uFF1A${dependency}`);
|
|
9420
|
+
}
|
|
9421
|
+
enableWithDependencies(dependency, target, installed, catalog, visiting);
|
|
9220
9422
|
}
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9423
|
+
visiting.delete(name);
|
|
9424
|
+
target.set(name, true);
|
|
9425
|
+
}
|
|
9426
|
+
function assertOptionalModules(names) {
|
|
9427
|
+
const required = names.filter((name) => requiredModuleNames.includes(name));
|
|
9428
|
+
if (required.length) {
|
|
9429
|
+
throw new Error(`\u6838\u5FC3\u6A21\u5757\u4E0D\u53EF\u505C\u7528\uFF1A${required.join("\u3001")}`);
|
|
9224
9430
|
}
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9431
|
+
}
|
|
9432
|
+
function assertNoEnabledDependents(target, catalog) {
|
|
9433
|
+
const blockers = [...target].filter(([, enabled]) => enabled).flatMap(([name]) => {
|
|
9434
|
+
const disabled = catalog.get(name).dependencies.filter((dependency) => !target.get(dependency));
|
|
9435
|
+
return disabled.map((dependency) => `${name}\u2192${dependency}`);
|
|
9436
|
+
});
|
|
9437
|
+
if (blockers.length) {
|
|
9438
|
+
throw new Error(`\u542F\u7528\u6A21\u5757\u4ECD\u4F9D\u8D56\u5F85\u505C\u7528\u6A21\u5757\uFF1A${blockers.join("\u3001")}`);
|
|
9228
9439
|
}
|
|
9229
|
-
const result2 = await updater.apply(plan);
|
|
9230
|
-
const report = await updater.verify(result2);
|
|
9231
|
-
log(`
|
|
9232
|
-
\u6A21\u5757${actionLabel(action)}\u5B8C\u6210\uFF1A${requested.join("\u3001")}`);
|
|
9233
|
-
log(`\u62A5\u544A\uFF1A${report.reportPath}`);
|
|
9234
9440
|
}
|
|
9235
|
-
|
|
9441
|
+
function assertEnabledCompatibility(target, version, catalog) {
|
|
9442
|
+
for (const [name, enabled] of target) {
|
|
9443
|
+
if (!enabled)
|
|
9444
|
+
continue;
|
|
9445
|
+
const manifest = catalog.get(name);
|
|
9446
|
+
assertCompatible(version, manifest.windyRange, name);
|
|
9447
|
+
}
|
|
9448
|
+
}
|
|
9449
|
+
function assertEnabledConflicts(target, catalog) {
|
|
9450
|
+
for (const [name, enabled] of target) {
|
|
9451
|
+
if (!enabled)
|
|
9452
|
+
continue;
|
|
9453
|
+
const conflict3 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
|
|
9454
|
+
if (conflict3)
|
|
9455
|
+
throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict3}`);
|
|
9456
|
+
}
|
|
9457
|
+
}
|
|
9458
|
+
function assertCompatible(version, range, name) {
|
|
9459
|
+
if (!isVersionInCaretRange(version, range)) {
|
|
9460
|
+
throw new Error(`${name} \u8981\u6C42 Windy ${range}\uFF0C\u5F53\u524D\u4E3A ${version}`);
|
|
9461
|
+
}
|
|
9462
|
+
}
|
|
9463
|
+
|
|
9464
|
+
// src/module-lifecycle-plan.ts
|
|
9465
|
+
function reconcileProjectModuleRegistryPlan(plan, current, lifecycle) {
|
|
9466
|
+
const registryFile = plan.files.find(({ path: path2 }) => path2 === projectModuleRegistryPath);
|
|
9467
|
+
if (!registryFile) {
|
|
9468
|
+
throw new Error("\u6A21\u5757\u751F\u547D\u5468\u671F\u8BA1\u5212\u7F3A\u5C11 project-owned \u88C5\u914D\u9009\u62E9");
|
|
9469
|
+
}
|
|
9470
|
+
plan.conflicts = plan.conflicts.filter((conflict3) => !conflict3.startsWith(`${projectModuleRegistryPath}\uFF1A`));
|
|
9471
|
+
delete registryFile.conflict;
|
|
9472
|
+
if (lifecycle.action === "update") {
|
|
9473
|
+
registryFile.action = "preserve";
|
|
9474
|
+
registryFile.reason = "\u6A21\u5757\u66F4\u65B0\u4FDD\u7559\u5BA2\u6237\u88C5\u914D\u9009\u62E9";
|
|
9475
|
+
delete registryFile.content;
|
|
9476
|
+
return;
|
|
9477
|
+
}
|
|
9478
|
+
const removed = new Set(lifecycle.removedModules);
|
|
9479
|
+
const modules = current.modules.filter(({ name }) => !removed.has(name));
|
|
9480
|
+
let nextOrder = Math.max(0, ...modules.map(({ order }) => order)) + 100;
|
|
9481
|
+
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
9482
|
+
for (const name of lifecycle.addedModules) {
|
|
9483
|
+
if (modules.some((registration) => registration.name === name))
|
|
9484
|
+
continue;
|
|
9485
|
+
const manifest = catalog.get(name);
|
|
9486
|
+
if (!manifest)
|
|
9487
|
+
throw new Error(`\u672A\u77E5\u6A21\u5757\uFF1A${name}`);
|
|
9488
|
+
modules.push(newRegistration(name, manifest.runtimePackage, nextOrder));
|
|
9489
|
+
nextOrder += 100;
|
|
9490
|
+
}
|
|
9491
|
+
const registry = { schemaVersion: 1, modules };
|
|
9492
|
+
registryFile.action = "update";
|
|
9493
|
+
registryFile.reason = "\u6309 module name \u5408\u5E76\u9879\u76EE\u88C5\u914D\u9009\u62E9";
|
|
9494
|
+
registryFile.content = new TextEncoder().encode(`${JSON.stringify(registry, null, 2)}
|
|
9495
|
+
`);
|
|
9496
|
+
}
|
|
9497
|
+
function assertModulePlanUsesStableComposition(plan) {
|
|
9498
|
+
const unsafe = plan.files.filter(({ action, path: path2, reason }) => action !== "preserve" && (isCustomerApplicationOrHost(path2) || isDockerfile(path2) && reason !== "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355")).map(({ path: path2 }) => path2);
|
|
9499
|
+
if (unsafe.length === 0)
|
|
9500
|
+
return;
|
|
9501
|
+
throw new Error([
|
|
9502
|
+
"\u6A21\u5757\u5305/Host \u5C1A\u672A\u6EE1\u8DB3\u65B0\u534F\u8BAE\uFF0C\u62D2\u7EDD\u901A\u8FC7\u6A21\u677F\u518D\u751F\u6210\u6539\u5199\u5BA2\u6237 Admin \u6216 Host\uFF1A",
|
|
9503
|
+
...unsafe.map((path2) => ` ${path2}`)
|
|
9504
|
+
].join(`
|
|
9505
|
+
`));
|
|
9506
|
+
}
|
|
9507
|
+
function isDockerfile(path2) {
|
|
9508
|
+
return path2 === "apps/web/Dockerfile" || path2 === "apps/server/Dockerfile";
|
|
9509
|
+
}
|
|
9510
|
+
function isCustomerApplicationOrHost(path2) {
|
|
9511
|
+
return path2 === "apps/web/src" || path2.startsWith("apps/web/src/") || path2 === "apps/server/src/index.ts" || path2 === "apps/server/src/installed-business-modules.ts" || path2 === "apps/server/src/app" || path2.startsWith("apps/server/src/app/");
|
|
9512
|
+
}
|
|
9513
|
+
function newRegistration(name, runtimePackage, order) {
|
|
9514
|
+
return {
|
|
9515
|
+
name,
|
|
9516
|
+
package: runtimePackage,
|
|
9517
|
+
enabled: true,
|
|
9518
|
+
order,
|
|
9519
|
+
admin: { visible: true },
|
|
9520
|
+
config: {}
|
|
9521
|
+
};
|
|
9522
|
+
}
|
|
9523
|
+
|
|
9524
|
+
// src/module-lifecycle-resolver.ts
|
|
9525
|
+
import { access as access2 } from "fs/promises";
|
|
9526
|
+
import { resolve as resolve7 } from "path";
|
|
9527
|
+
async function resolveModuleLifecyclePlan(input) {
|
|
9236
9528
|
const known = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
9237
9529
|
const requested = input.action === "update" && input.requested.length === 0 ? [...input.installed] : input.requested;
|
|
9238
9530
|
if (!requested.length) {
|
|
@@ -9253,10 +9545,12 @@ async function resolveLifecyclePlan(input) {
|
|
|
9253
9545
|
const manifest = known.get(name);
|
|
9254
9546
|
assertWindyCompatible(input.windyVersion, manifest.windyRange, manifest.name);
|
|
9255
9547
|
}
|
|
9548
|
+
const addedModules = target.filter((name) => !input.installed.includes(name));
|
|
9549
|
+
assertDeploymentLifecycleSupported(addedModules, known);
|
|
9256
9550
|
return {
|
|
9257
9551
|
action: input.action,
|
|
9258
9552
|
requestedModules: requested,
|
|
9259
|
-
addedModules
|
|
9553
|
+
addedModules,
|
|
9260
9554
|
updatedModules: [],
|
|
9261
9555
|
removedModules: []
|
|
9262
9556
|
};
|
|
@@ -9266,6 +9560,7 @@ async function resolveLifecyclePlan(input) {
|
|
|
9266
9560
|
if (absent.length) {
|
|
9267
9561
|
throw new Error(`\u672A\u5B89\u88C5\u6A21\u5757\u4E0D\u80FD\u66F4\u65B0\uFF1A${absent.join("\u3001")}`);
|
|
9268
9562
|
}
|
|
9563
|
+
assertDeploymentLifecycleSupported(requested, known);
|
|
9269
9564
|
return {
|
|
9270
9565
|
action: input.action,
|
|
9271
9566
|
requestedModules: requested,
|
|
@@ -9279,6 +9574,7 @@ async function resolveLifecyclePlan(input) {
|
|
|
9279
9574
|
throw new Error(`\u6838\u5FC3\u6A21\u5757\u4E0D\u53EF\u5378\u8F7D\uFF1A${required.join("\u3001")}`);
|
|
9280
9575
|
}
|
|
9281
9576
|
const removed = requested.filter((name) => input.installed.includes(name));
|
|
9577
|
+
assertDeploymentLifecycleSupported(removed, known);
|
|
9282
9578
|
assertRemovalDependencies(input.installed, removed);
|
|
9283
9579
|
const dataDisposition = resolveDataDisposition(removed.map((name) => known.get(name).uninstallPolicy), readValue2(input.args, "--data-disposition"));
|
|
9284
9580
|
const dataPlan = readValue2(input.args, "--data-plan");
|
|
@@ -9298,7 +9594,13 @@ async function resolveLifecyclePlan(input) {
|
|
|
9298
9594
|
dataPlan
|
|
9299
9595
|
};
|
|
9300
9596
|
}
|
|
9301
|
-
function
|
|
9597
|
+
function assertDeploymentLifecycleSupported(names, catalog) {
|
|
9598
|
+
const unsupported = names.filter((name) => catalog.get(name)?.deploymentInstall === "project-composition-required");
|
|
9599
|
+
if (unsupported.length) {
|
|
9600
|
+
throw new Error(`${unsupported.join("\u3001")} \u5C1A\u672A\u63D0\u4F9B self-contained Server Adapter\uFF1B\u90E8\u7F72\u540E add/update/remove \u4F1A\u6539\u5199 project-owned \u7EC4\u5408\u58F0\u660E\uFF0C\u5F53\u524D fail closed`);
|
|
9601
|
+
}
|
|
9602
|
+
}
|
|
9603
|
+
function resolveModuleLifecycleTarget(installed, lifecycle) {
|
|
9302
9604
|
if (lifecycle.action === "add") {
|
|
9303
9605
|
return resolveModuleSelection({
|
|
9304
9606
|
requested: [...installed, ...lifecycle.addedModules],
|
|
@@ -9311,6 +9613,19 @@ function resolveTargetModules(installed, lifecycle) {
|
|
|
9311
9613
|
}
|
|
9312
9614
|
return installed;
|
|
9313
9615
|
}
|
|
9616
|
+
function readPositionalModules(args) {
|
|
9617
|
+
const valueFlags = new Set(["--data-disposition", "--data-plan", "--cwd"]);
|
|
9618
|
+
const output = [];
|
|
9619
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
9620
|
+
const value = args[index];
|
|
9621
|
+
if (valueFlags.has(value)) {
|
|
9622
|
+
index += 1;
|
|
9623
|
+
} else if (!value.startsWith("-")) {
|
|
9624
|
+
output.push(value);
|
|
9625
|
+
}
|
|
9626
|
+
}
|
|
9627
|
+
return [...new Set(output)];
|
|
9628
|
+
}
|
|
9314
9629
|
function resolveDataDisposition(policies, requested) {
|
|
9315
9630
|
const disposition = requested ?? strongestPolicy(policies);
|
|
9316
9631
|
if (disposition !== "retain-data" && disposition !== "archive-data" && disposition !== "manual") {
|
|
@@ -9346,27 +9661,219 @@ function assertWindyCompatible(version, range, moduleName) {
|
|
|
9346
9661
|
throw new Error(`${moduleName} \u8981\u6C42 Windy ${range}\uFF0C\u5F53\u524D\u4E3A ${version}`);
|
|
9347
9662
|
}
|
|
9348
9663
|
}
|
|
9349
|
-
function
|
|
9350
|
-
const
|
|
9351
|
-
|
|
9352
|
-
|
|
9664
|
+
function readValue2(args, flag) {
|
|
9665
|
+
const index = args.indexOf(flag);
|
|
9666
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
9667
|
+
}
|
|
9668
|
+
|
|
9669
|
+
// src/module-lifecycle-help.ts
|
|
9670
|
+
var moduleLifecycleHelpText = `create-windy module <\u547D\u4EE4> [\u9009\u9879]
|
|
9671
|
+
|
|
9672
|
+
\u547D\u4EE4\uFF1A
|
|
9673
|
+
module list [--cwd <\u76EE\u5F55>]
|
|
9674
|
+
module add <key...> [--dry-run] [--skip-install] [--yes]
|
|
9675
|
+
module enable <key...> [--dry-run] [--yes]
|
|
9676
|
+
module disable <key...> [--dry-run] [--yes]
|
|
9677
|
+
module update [key...] [--dry-run] [--skip-install] [--yes]
|
|
9678
|
+
module remove <key...> [--dry-run] [--skip-install] [--yes]
|
|
9679
|
+
[--data-disposition <\u7B56\u7565>] [--data-plan <\u6587\u4EF6>]
|
|
9680
|
+
[--confirm-data-disposition]
|
|
9681
|
+
|
|
9682
|
+
\u8FB9\u754C\uFF1A
|
|
9683
|
+
\u5F53\u524D\u5185\u7F6E\u6E90\u7801\u6A21\u5757\u53EA\u652F\u6301\u521B\u5EFA\u9879\u76EE\u65F6\u9009\u62E9
|
|
9684
|
+
\u90E8\u7F72\u540E add/update/remove \u4EC5\u5BF9 self-contained \u6A21\u5757\u5F00\u653E\uFF0C\u5426\u5219 fail closed
|
|
9685
|
+
system.settings\u3001system.storage\u3001system.data-governance \u4E0D\u652F\u6301 runtime disable
|
|
9686
|
+
\u5DF2\u90E8\u7F72\u9879\u76EE\u4E0D\u4F1A\u88AB\u81EA\u52A8\u6539\u5199
|
|
9687
|
+
|
|
9688
|
+
\u6B63\u5F0F\u53D8\u66F4\u5728\u4EA4\u4E92\u7EC8\u7AEF\u786E\u8BA4\u540E\u6267\u884C\uFF1B\u975E\u4EA4\u4E92\u73AF\u5883\u5FC5\u987B\u4F20\u5165 --yes\u3002`;
|
|
9689
|
+
function assertKnownModuleArguments(args) {
|
|
9690
|
+
const action = args[0];
|
|
9691
|
+
const allowed = new Set(["--cwd", "--help", "-h"]);
|
|
9692
|
+
if (action !== "list") {
|
|
9693
|
+
allowed.add("--dry-run");
|
|
9694
|
+
allowed.add("--yes");
|
|
9695
|
+
}
|
|
9696
|
+
if (action === "add" || action === "update" || action === "remove") {
|
|
9697
|
+
allowed.add("--skip-install");
|
|
9698
|
+
}
|
|
9699
|
+
if (action === "remove") {
|
|
9700
|
+
allowed.add("--data-disposition");
|
|
9701
|
+
allowed.add("--data-plan");
|
|
9702
|
+
allowed.add("--confirm-data-disposition");
|
|
9703
|
+
}
|
|
9704
|
+
const valueFlags = new Set(["--cwd", "--data-disposition", "--data-plan"]);
|
|
9705
|
+
for (let index = 1;index < args.length; index += 1) {
|
|
9353
9706
|
const value = args[index];
|
|
9354
|
-
if (
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9707
|
+
if (!value.startsWith("-"))
|
|
9708
|
+
continue;
|
|
9709
|
+
if (!allowed.has(value))
|
|
9710
|
+
throw new Error(`\u672A\u77E5 module \u53C2\u6570\uFF1A${value}`);
|
|
9711
|
+
if (!valueFlags.has(value))
|
|
9712
|
+
continue;
|
|
9713
|
+
const next = args[index + 1];
|
|
9714
|
+
if (!next || next.startsWith("-")) {
|
|
9715
|
+
throw new Error(`${value} \u7F3A\u5C11\u53C2\u6570\u503C`);
|
|
9358
9716
|
}
|
|
9717
|
+
index += 1;
|
|
9359
9718
|
}
|
|
9360
|
-
return [...new Set(output)];
|
|
9361
9719
|
}
|
|
9362
|
-
|
|
9720
|
+
|
|
9721
|
+
// src/module-lifecycle-confirmation.ts
|
|
9722
|
+
import { createInterface as createInterface3 } from "readline/promises";
|
|
9723
|
+
async function confirmModuleMutation(args, dependencies, log) {
|
|
9724
|
+
if (args.includes("--yes"))
|
|
9725
|
+
return true;
|
|
9726
|
+
const isTTY = dependencies.isTTY ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
9727
|
+
if (!isTTY) {
|
|
9728
|
+
throw new Error("\u975E\u4EA4\u4E92\u73AF\u5883\u6B63\u5F0F\u53D8\u66F4\u5FC5\u987B\u4F20\u5165 --yes");
|
|
9729
|
+
}
|
|
9730
|
+
const confirm = dependencies.confirm ?? promptForConfirmation;
|
|
9731
|
+
const accepted = await confirm("\u786E\u8BA4\u6267\u884C\u4EE5\u4E0A\u6A21\u5757\u8BA1\u5212\uFF1F");
|
|
9732
|
+
if (!accepted)
|
|
9733
|
+
log("\u5DF2\u53D6\u6D88\uFF1A\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
|
|
9734
|
+
return accepted;
|
|
9735
|
+
}
|
|
9736
|
+
async function promptForConfirmation(message) {
|
|
9737
|
+
const readline3 = createInterface3({
|
|
9738
|
+
input: process.stdin,
|
|
9739
|
+
output: process.stdout
|
|
9740
|
+
});
|
|
9741
|
+
try {
|
|
9742
|
+
const answer = await readline3.question(`${message} [y/N] `);
|
|
9743
|
+
return answer.trim().toLowerCase() === "y";
|
|
9744
|
+
} finally {
|
|
9745
|
+
readline3.close();
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9748
|
+
|
|
9749
|
+
// src/module-lifecycle.ts
|
|
9750
|
+
async function runModuleLifecycleCommand(args, projectDirectory, dependencies = {}) {
|
|
9751
|
+
const log = dependencies.log ?? console.log;
|
|
9752
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
9753
|
+
log(moduleLifecycleHelpText);
|
|
9754
|
+
return;
|
|
9755
|
+
}
|
|
9756
|
+
const action = args[0];
|
|
9757
|
+
if (!isAction(action)) {
|
|
9758
|
+
throw new Error("module \u53EA\u652F\u6301 list\u3001add\u3001enable\u3001disable\u3001update\u3001remove");
|
|
9759
|
+
}
|
|
9760
|
+
assertKnownModuleArguments(args);
|
|
9761
|
+
const provenance = await readGenerationProvenance(projectDirectory);
|
|
9762
|
+
const installed = provenance.modules.map(({ name }) => name);
|
|
9763
|
+
const registrySnapshot = await readProjectModuleRegistrySnapshot(projectDirectory, installed);
|
|
9764
|
+
if (action === "list") {
|
|
9765
|
+
printModuleList(provenance.modules, registrySnapshot.registry.modules, log);
|
|
9766
|
+
return;
|
|
9767
|
+
}
|
|
9768
|
+
const cliVersion = dependencies.cliVersion ?? (await readTemplateMetadata(await resolveTemplateRoot())).generatorVersion;
|
|
9769
|
+
if (provenance.generatorVersion !== cliVersion || provenance.windyVersion !== cliVersion) {
|
|
9770
|
+
throw new Error(`module \u547D\u4EE4\u8981\u6C42 CLI \u4E0E\u9879\u76EE Windy \u7248\u672C\u4E00\u81F4\uFF1A\u9879\u76EE ${provenance.windyVersion}\uFF0CCLI ${cliVersion}\uFF1B\u8BF7\u5148\u8FD0\u884C bun run windy update`);
|
|
9771
|
+
}
|
|
9772
|
+
const requested = readPositionalModules(args.slice(1));
|
|
9773
|
+
if (action === "enable" || action === "disable") {
|
|
9774
|
+
const activation = planProjectModuleActivation({
|
|
9775
|
+
action,
|
|
9776
|
+
requestedModules: requested,
|
|
9777
|
+
windyVersion: provenance.windyVersion,
|
|
9778
|
+
expectedRegistryHash: registrySnapshot.hash,
|
|
9779
|
+
registry: registrySnapshot.registry
|
|
9780
|
+
});
|
|
9781
|
+
printActivationPlan(activation, log);
|
|
9782
|
+
if (!activation.changedModules.length) {
|
|
9783
|
+
log("\u6A21\u5757\u88C5\u914D\u5DF2\u6EE1\u8DB3\u8BF7\u6C42\uFF0C\u65E0\u9700\u4FEE\u6539");
|
|
9784
|
+
return;
|
|
9785
|
+
}
|
|
9786
|
+
if (args.includes("--dry-run")) {
|
|
9787
|
+
log(`
|
|
9788
|
+
\u6F14\u7EC3\u5B8C\u6210\uFF1A\u672A\u5199\u5165\u9879\u76EE\u6587\u4EF6`);
|
|
9789
|
+
return;
|
|
9790
|
+
}
|
|
9791
|
+
if (!await confirmModuleMutation(args, dependencies, log))
|
|
9792
|
+
return;
|
|
9793
|
+
await applyProjectModuleActivation(projectDirectory, activation);
|
|
9794
|
+
log(`
|
|
9795
|
+
\u6A21\u5757${action === "enable" ? "\u542F\u7528" : "\u505C\u7528"}\u5B8C\u6210`);
|
|
9796
|
+
return;
|
|
9797
|
+
}
|
|
9798
|
+
const lifecycle = await resolveModuleLifecyclePlan({
|
|
9799
|
+
action,
|
|
9800
|
+
requested,
|
|
9801
|
+
installed,
|
|
9802
|
+
windyVersion: provenance.windyVersion,
|
|
9803
|
+
args,
|
|
9804
|
+
projectDirectory
|
|
9805
|
+
});
|
|
9806
|
+
printDataPlan(lifecycle, log);
|
|
9807
|
+
if (!hasChanges(lifecycle)) {
|
|
9808
|
+
log("\u6A21\u5757\u96C6\u5408\u5DF2\u6EE1\u8DB3\u8BF7\u6C42\uFF0C\u65E0\u9700\u4FEE\u6539");
|
|
9809
|
+
return;
|
|
9810
|
+
}
|
|
9811
|
+
const targetModules = resolveModuleLifecycleTarget(installed, lifecycle);
|
|
9812
|
+
const updater = dependencies.updater ?? dependencies.updaterFactory?.({
|
|
9813
|
+
skipInstall: args.includes("--skip-install")
|
|
9814
|
+
}) ?? new DefaultStarterUpdater({
|
|
9815
|
+
skipInstall: args.includes("--skip-install")
|
|
9816
|
+
});
|
|
9817
|
+
const plan = await updater.plan({
|
|
9818
|
+
projectDirectory,
|
|
9819
|
+
targetVersion: provenance.windyVersion,
|
|
9820
|
+
targetModules,
|
|
9821
|
+
lifecycle
|
|
9822
|
+
});
|
|
9823
|
+
try {
|
|
9824
|
+
reconcileProjectModuleRegistryPlan(plan, registrySnapshot.registry, lifecycle);
|
|
9825
|
+
printModulePlan(plan, log);
|
|
9826
|
+
assertModulePlanUsesStableComposition(plan);
|
|
9827
|
+
} catch (error) {
|
|
9828
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9829
|
+
throw error;
|
|
9830
|
+
}
|
|
9831
|
+
if (args.includes("--dry-run")) {
|
|
9832
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9833
|
+
log(`
|
|
9834
|
+
\u6F14\u7EC3\u5B8C\u6210\uFF1A\u672A\u5199\u5165\u9879\u76EE\u6587\u4EF6`);
|
|
9835
|
+
return;
|
|
9836
|
+
}
|
|
9837
|
+
if (action === "remove" && !args.includes("--confirm-data-disposition")) {
|
|
9838
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9839
|
+
throw new Error("\u5378\u8F7D\u524D\u5FC5\u987B\u5BA1\u9605\u6570\u636E\u5904\u7F6E\u8BA1\u5212\u5E76\u4F20\u5165 --confirm-data-disposition");
|
|
9840
|
+
}
|
|
9841
|
+
if (plan.conflicts.length) {
|
|
9842
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9843
|
+
throw new Error("\u5B58\u5728\u6A21\u5757\u751F\u547D\u5468\u671F\u51B2\u7A81\uFF0C\u9879\u76EE\u672A\u88AB\u4FEE\u6539");
|
|
9844
|
+
}
|
|
9845
|
+
let confirmed;
|
|
9846
|
+
try {
|
|
9847
|
+
confirmed = await confirmModuleMutation(args, dependencies, log);
|
|
9848
|
+
} catch (error) {
|
|
9849
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9850
|
+
throw error;
|
|
9851
|
+
}
|
|
9852
|
+
if (!confirmed) {
|
|
9853
|
+
await rm9(plan.temporaryRoot, { recursive: true, force: true });
|
|
9854
|
+
return;
|
|
9855
|
+
}
|
|
9856
|
+
const result2 = await updater.apply(plan);
|
|
9857
|
+
const report = await updater.verify(result2);
|
|
9858
|
+
log(`
|
|
9859
|
+
\u6A21\u5757${actionLabel(action)}\u5B8C\u6210\uFF1A${requested.join("\u3001")}`);
|
|
9860
|
+
log(`\u62A5\u544A\uFF1A${report.reportPath}`);
|
|
9861
|
+
}
|
|
9862
|
+
function printModuleList(installed, registered, log) {
|
|
9363
9863
|
const installedVersions = new Map(installed.map(({ name, version }) => [name, version]));
|
|
9864
|
+
const catalog = new Map(moduleDistributionCatalog.map((manifest) => [manifest.name, manifest]));
|
|
9364
9865
|
log("Windy \u6A21\u5757\uFF1A");
|
|
9866
|
+
for (const registration of [...registered].sort((left, right) => left.order - right.order)) {
|
|
9867
|
+
const manifest = catalog.get(registration.name);
|
|
9868
|
+
const installedVersion = installedVersions.get(registration.name);
|
|
9869
|
+
const status = registration.enabled ? "installed" : "disabled";
|
|
9870
|
+
log(` ${status.padEnd(9)} ${registration.name}@${installedVersion}\uFF08catalog ${manifest.version}\uFF09`);
|
|
9871
|
+
}
|
|
9365
9872
|
for (const manifest of moduleDistributionCatalog) {
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
const
|
|
9369
|
-
log(` ${status.padEnd(9)} ${version}`);
|
|
9873
|
+
if (installedVersions.has(manifest.name))
|
|
9874
|
+
continue;
|
|
9875
|
+
const status = manifest.deploymentInstall === "supported" ? "available" : "creation-only";
|
|
9876
|
+
log(` ${status.padEnd(9)} ${manifest.name}@${manifest.version}\uFF08catalog ${manifest.version}\uFF09`);
|
|
9370
9877
|
}
|
|
9371
9878
|
}
|
|
9372
9879
|
function printDataPlan(lifecycle, log) {
|
|
@@ -9379,6 +9886,11 @@ function printDataPlan(lifecycle, log) {
|
|
|
9379
9886
|
if (lifecycle.dataPlan)
|
|
9380
9887
|
log(` \u8FD0\u7EF4\u5904\u7F6E\u6587\u6863\uFF1A${lifecycle.dataPlan}`);
|
|
9381
9888
|
}
|
|
9889
|
+
function printActivationPlan(plan, log) {
|
|
9890
|
+
log(`\u6A21\u5757\u88C5\u914D\u8BA1\u5212\uFF1A${plan.action} ${plan.requestedModules.join("\u3001")}`);
|
|
9891
|
+
log(` \u53EA\u5199\u5165 windy.modules.json`);
|
|
9892
|
+
log(` \u72B6\u6001\u53D8\u5316\uFF1A${plan.changedModules.join("\u3001") || "\u65E0"}`);
|
|
9893
|
+
}
|
|
9382
9894
|
function printModulePlan(plan, log) {
|
|
9383
9895
|
const changed = plan.files.filter(({ action }) => action !== "preserve");
|
|
9384
9896
|
log(`\u6A21\u5757\u6587\u4EF6\u8BA1\u5212\uFF1A${changed.length} \u4E2A\u53D8\u66F4\uFF1B${plan.conflicts.length} \u4E2A\u51B2\u7A81`);
|
|
@@ -9391,12 +9903,8 @@ function printModulePlan(plan, log) {
|
|
|
9391
9903
|
function hasChanges(lifecycle) {
|
|
9392
9904
|
return lifecycle.addedModules.length > 0 || lifecycle.updatedModules.length > 0 || lifecycle.removedModules.length > 0;
|
|
9393
9905
|
}
|
|
9394
|
-
function readValue2(args, flag) {
|
|
9395
|
-
const index = args.indexOf(flag);
|
|
9396
|
-
return index >= 0 ? args[index + 1] : undefined;
|
|
9397
|
-
}
|
|
9398
9906
|
function isAction(value) {
|
|
9399
|
-
return value === "list" || value === "add" || value === "update" || value === "remove";
|
|
9907
|
+
return value === "list" || value === "add" || value === "enable" || value === "disable" || value === "update" || value === "remove";
|
|
9400
9908
|
}
|
|
9401
9909
|
function actionLabel(action) {
|
|
9402
9910
|
return action === "add" ? "\u5B89\u88C5" : action === "update" ? "\u66F4\u65B0" : "\u5378\u8F7D";
|
|
@@ -9629,20 +10137,20 @@ import {
|
|
|
9629
10137
|
cp,
|
|
9630
10138
|
mkdir as mkdir9,
|
|
9631
10139
|
mkdtemp as mkdtemp4,
|
|
9632
|
-
readFile as
|
|
10140
|
+
readFile as readFile23,
|
|
9633
10141
|
readdir as readdir9,
|
|
9634
10142
|
rename as rename2,
|
|
9635
10143
|
rm as rm11,
|
|
9636
|
-
writeFile as
|
|
10144
|
+
writeFile as writeFile14
|
|
9637
10145
|
} from "fs/promises";
|
|
9638
|
-
import { dirname as dirname9, join as
|
|
10146
|
+
import { dirname as dirname9, join as join27, relative as relative6 } from "path";
|
|
9639
10147
|
|
|
9640
10148
|
// src/module-schema/config.ts
|
|
9641
|
-
import { readFile as
|
|
10149
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
9642
10150
|
import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolve9 } from "path";
|
|
9643
10151
|
async function readModuleSchemaLineageConfig(projectDirectory, configPath) {
|
|
9644
10152
|
const absolutePath = resolveProjectPath(projectDirectory, configPath);
|
|
9645
|
-
const parsed = JSON.parse(await
|
|
10153
|
+
const parsed = JSON.parse(await readFile22(absolutePath, "utf8"));
|
|
9646
10154
|
if (!isConfig(parsed)) {
|
|
9647
10155
|
throw new Error("Module schema lineage \u914D\u7F6E\u65E0\u6548");
|
|
9648
10156
|
}
|
|
@@ -9776,17 +10284,17 @@ async function handoffModuleSchemaLineages(options) {
|
|
|
9776
10284
|
async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
9777
10285
|
const outputs = [];
|
|
9778
10286
|
for (const [index, module3] of config.modules.entries()) {
|
|
9779
|
-
const output =
|
|
10287
|
+
const output = join27(temporaryRoot, `module-${index}`);
|
|
9780
10288
|
await mkdir9(output, { recursive: true });
|
|
9781
|
-
const generatedConfig =
|
|
10289
|
+
const generatedConfig = join27(temporaryRoot, `module-${index}.config.ts`);
|
|
9782
10290
|
await writeDrizzleConfig(generatedConfig, project, module3.schema, relative6(temporaryRoot, output));
|
|
9783
10291
|
await execute(generatedConfig, temporaryRoot);
|
|
9784
10292
|
const sqlFiles = await listSqlFiles(output);
|
|
9785
10293
|
if (sqlFiles.length !== 1) {
|
|
9786
10294
|
throw new Error(`${module3.key} baseline \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration`);
|
|
9787
10295
|
}
|
|
9788
|
-
await
|
|
9789
|
-
await
|
|
10296
|
+
await writeFile14(join27(output, sqlFiles[0]), metadataOnlySql("module"));
|
|
10297
|
+
await writeFile14(join27(output, "lineage.json"), `${JSON.stringify({
|
|
9790
10298
|
schemaVersion: 1,
|
|
9791
10299
|
moduleKey: module3.key,
|
|
9792
10300
|
schema: module3.schema,
|
|
@@ -9800,25 +10308,25 @@ async function stageModuleLineages(project, temporaryRoot, config, execute) {
|
|
|
9800
10308
|
}
|
|
9801
10309
|
async function stagePlatformLineage(project, temporaryRoot, config, execute) {
|
|
9802
10310
|
const source = resolveProjectPath(project, config.platform.out);
|
|
9803
|
-
const output =
|
|
10311
|
+
const output = join27(temporaryRoot, "platform");
|
|
9804
10312
|
await cp(source, output, { recursive: true });
|
|
9805
10313
|
const before = new Set(await listSqlFiles(output));
|
|
9806
|
-
const generatedConfig =
|
|
10314
|
+
const generatedConfig = join27(temporaryRoot, "platform.config.ts");
|
|
9807
10315
|
await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative6(temporaryRoot, output));
|
|
9808
10316
|
await execute(generatedConfig, temporaryRoot);
|
|
9809
10317
|
const created = (await listSqlFiles(output)).filter((path2) => !before.has(path2));
|
|
9810
10318
|
if (created.length !== 1) {
|
|
9811
10319
|
throw new Error("\u5E73\u53F0 lineage handoff \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration");
|
|
9812
10320
|
}
|
|
9813
|
-
const sqlPath =
|
|
10321
|
+
const sqlPath = join27(output, created[0]);
|
|
9814
10322
|
const allowed = config.modules.flatMap(({ legacyPlatformTables }) => legacyPlatformTables);
|
|
9815
|
-
validatePlatformHandoffSql(await
|
|
9816
|
-
await
|
|
10323
|
+
validatePlatformHandoffSql(await readFile23(sqlPath, "utf8"), allowed);
|
|
10324
|
+
await writeFile14(sqlPath, metadataOnlySql("platform"));
|
|
9817
10325
|
return output;
|
|
9818
10326
|
}
|
|
9819
10327
|
async function installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform) {
|
|
9820
10328
|
const platform = resolveProjectPath(project, config.platform.out);
|
|
9821
|
-
const backup =
|
|
10329
|
+
const backup = join27(temporaryRoot, "platform-backup");
|
|
9822
10330
|
const installed = [];
|
|
9823
10331
|
await rename2(platform, backup);
|
|
9824
10332
|
try {
|
|
@@ -9842,7 +10350,7 @@ async function installStagedLineages(project, temporaryRoot, config, stagedModul
|
|
|
9842
10350
|
}
|
|
9843
10351
|
async function writeDrizzleConfig(path2, project, schemas, out) {
|
|
9844
10352
|
const absoluteSchemas = schemas.map((schema) => resolveProjectPath(project, schema));
|
|
9845
|
-
await
|
|
10353
|
+
await writeFile14(path2, `import { defineConfig } from "drizzle-kit";
|
|
9846
10354
|
export default defineConfig(${JSON.stringify({
|
|
9847
10355
|
dialect: "postgresql",
|
|
9848
10356
|
schema: absoluteSchemas,
|
|
@@ -9865,9 +10373,9 @@ async function validateSchemaSources(project, config) {
|
|
|
9865
10373
|
}
|
|
9866
10374
|
}
|
|
9867
10375
|
async function createTemporaryRoot(project) {
|
|
9868
|
-
const windy =
|
|
10376
|
+
const windy = join27(project, ".windy");
|
|
9869
10377
|
await mkdir9(windy, { recursive: true });
|
|
9870
|
-
return await mkdtemp4(
|
|
10378
|
+
return await mkdtemp4(join27(windy, "module-schema-handoff-"));
|
|
9871
10379
|
}
|
|
9872
10380
|
async function listSqlFiles(root) {
|
|
9873
10381
|
return (await readdir9(root)).filter((path2) => path2.endsWith(".sql")).sort();
|