@bleedingdev/modern-js-ultramodern-create 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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 +43 -74
- package/dist/cjs/cli/package-source.cjs +2 -2
- package/dist/cjs/cli/project-setup.cjs +2 -22
- package/dist/cjs/index.cjs +9 -1
- package/dist/cjs/locale/en.cjs +2 -1
- package/dist/cjs/locale/zh.cjs +2 -1
- package/dist/cjs/ultramodern-package-source.cjs +13 -9
- package/dist/cjs/ultramodern-release-cohort.cjs +6 -21
- package/dist/cjs/ultramodern-tooling/commands/cloudflare-output-verify.cjs +49 -56
- package/dist/cjs/ultramodern-tooling/commands/context.cjs +11 -29
- package/dist/cjs/ultramodern-tooling/commands/routes-generate-app.cjs +67 -0
- package/dist/cjs/ultramodern-tooling/commands/routes-generate.cjs +24 -53
- package/dist/cjs/ultramodern-tooling/commands/validate.cjs +5 -11
- package/dist/cjs/ultramodern-tooling/commands.cjs +15 -8
- package/dist/cjs/ultramodern-tooling/config/index.cjs +10 -24
- package/dist/cjs/ultramodern-tooling/config/load.cjs +12 -10
- package/dist/cjs/ultramodern-tooling/config/metadata.cjs +34 -32
- package/dist/cjs/ultramodern-tooling/config/normalize.cjs +165 -164
- package/dist/cjs/ultramodern-workspace/add-shell.cjs +118 -118
- package/dist/cjs/ultramodern-workspace/add-vertical/execute.cjs +121 -25
- package/dist/cjs/ultramodern-workspace/add-vertical/plan.cjs +14 -160
- package/dist/cjs/ultramodern-workspace/add-vertical/preflight.cjs +16 -48
- package/dist/cjs/ultramodern-workspace/add-vertical/preview.cjs +78 -0
- package/dist/cjs/ultramodern-workspace/add-vertical/shell-files.cjs +87 -24
- package/dist/cjs/ultramodern-workspace/add-vertical/topology.cjs +4 -1
- package/dist/cjs/ultramodern-workspace/add-vertical/transaction.cjs +378 -45
- package/dist/cjs/ultramodern-workspace/add-vertical/workspace-state.cjs +21 -44
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +0 -9
- package/dist/cjs/ultramodern-workspace/api/client.cjs +5 -5
- package/dist/cjs/ultramodern-workspace/api/contracts.cjs +2 -2
- package/dist/cjs/ultramodern-workspace/api/rpc.cjs +20 -18
- package/dist/cjs/ultramodern-workspace/api/service.cjs +49 -24
- package/dist/cjs/ultramodern-workspace/api/shared.cjs +28 -18
- package/dist/cjs/ultramodern-workspace/app-files.cjs +3 -23
- package/dist/cjs/ultramodern-workspace/backend-federation.cjs +27 -27
- package/dist/cjs/ultramodern-workspace/contracts.cjs +14 -183
- package/dist/cjs/ultramodern-workspace/delivery-unit-schema/surfaces.cjs +85 -0
- package/dist/cjs/ultramodern-workspace/delivery-unit-schema/types.cjs +8 -85
- package/dist/cjs/ultramodern-workspace/delivery-unit-stamp.cjs +16 -4
- package/dist/cjs/ultramodern-workspace/delivery-unit-sync.cjs +27 -17
- package/dist/cjs/ultramodern-workspace/delivery-unit.cjs +16 -10
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +66 -433
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +0 -4
- package/dist/cjs/ultramodern-workspace/fs-io.cjs +37 -2
- package/dist/cjs/ultramodern-workspace/generation-result.cjs +4 -4
- package/dist/cjs/ultramodern-workspace/index.cjs +2 -5
- package/dist/cjs/ultramodern-workspace/mf-validation/constants.cjs +0 -6
- package/dist/cjs/ultramodern-workspace/mf-validation/discovery.cjs +6 -6
- package/dist/cjs/{ultramodern-tooling/commands/migrate-strict-effect/generated-patches.cjs → ultramodern-workspace/mf-validation/exposes.cjs} +13 -17
- package/dist/cjs/ultramodern-workspace/mf-validation/inspect.cjs +26 -7
- package/dist/cjs/ultramodern-workspace/mf-validation/object-literal.cjs +21 -122
- package/dist/cjs/ultramodern-workspace/mf-validation/path-utils.cjs +37 -38
- package/dist/cjs/ultramodern-workspace/mf-validation/syntax.cjs +93 -153
- package/dist/cjs/ultramodern-workspace/mf-validation.cjs +4 -0
- package/dist/cjs/ultramodern-workspace/module-federation/config.cjs +24 -29
- package/dist/cjs/ultramodern-workspace/module-federation/reexport-module.cjs +39 -58
- package/dist/cjs/ultramodern-workspace/module-federation/remote-refs.cjs +1 -43
- package/dist/cjs/ultramodern-workspace/package-json.cjs +63 -37
- package/dist/cjs/ultramodern-workspace/patch-inventory.cjs +104 -0
- package/dist/cjs/ultramodern-workspace/policy.cjs +3 -577
- package/dist/cjs/ultramodern-workspace/public-surface.cjs +3 -3
- package/dist/cjs/ultramodern-workspace/routes.cjs +2 -11
- package/dist/cjs/ultramodern-workspace/shared-patches.cjs +12 -2
- package/dist/cjs/ultramodern-workspace/shells.cjs +0 -70
- package/dist/cjs/ultramodern-workspace/tooling-command-catalog.cjs +27 -41
- package/dist/cjs/ultramodern-workspace/tsconfigs.cjs +8 -2
- package/dist/cjs/ultramodern-workspace/validation/architecture.cjs +397 -0
- package/dist/cjs/ultramodern-workspace/validation/assertions.cjs +140 -0
- package/dist/cjs/ultramodern-workspace/validation/types.cjs +18 -0
- package/dist/cjs/ultramodern-workspace/validation/workspace.cjs +344 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +81 -45
- package/dist/cjs/ultramodern-workspace/workspace-artifact-ownership.cjs +183 -0
- package/dist/cjs/ultramodern-workspace/workspace-script-plan.cjs +36 -25
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +11 -200
- package/dist/cjs/ultramodern-workspace/workspace-validation-contract.cjs +62 -373
- package/dist/cjs/ultramodern-workspace/write-app.cjs +19 -11
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +20 -50
- package/dist/cjs/ultramodern-workspace/zerops.cjs +2 -0
- package/dist/esm/cli/package-source.js +3 -3
- package/dist/esm/cli/project-setup.js +2 -22
- package/dist/esm/index.js +10 -2
- package/dist/esm/locale/en.js +2 -1
- package/dist/esm/locale/zh.js +2 -1
- package/dist/esm/ultramodern-package-source.js +14 -4
- package/dist/esm/ultramodern-release-cohort.js +5 -14
- package/dist/esm/ultramodern-tooling/commands/cloudflare-output-verify.js +49 -56
- package/dist/esm/ultramodern-tooling/commands/context.js +10 -26
- package/dist/esm/ultramodern-tooling/commands/routes-generate-app.js +35 -0
- package/dist/esm/ultramodern-tooling/commands/routes-generate.js +25 -54
- package/dist/esm/ultramodern-tooling/commands/validate.js +6 -12
- package/dist/esm/ultramodern-tooling/commands.js +15 -9
- package/dist/esm/ultramodern-tooling/config/index.js +0 -2
- package/dist/esm/ultramodern-tooling/config/load.js +9 -9
- package/dist/esm/ultramodern-tooling/config/metadata.js +33 -28
- package/dist/esm/ultramodern-tooling/config/normalize.js +159 -156
- package/dist/esm/ultramodern-workspace/add-shell.js +124 -123
- package/dist/esm/ultramodern-workspace/add-vertical/execute.js +119 -27
- package/dist/esm/ultramodern-workspace/add-vertical/plan.js +16 -150
- package/dist/esm/ultramodern-workspace/add-vertical/preflight.js +15 -47
- package/dist/esm/ultramodern-workspace/add-vertical/preview.js +40 -0
- package/dist/esm/ultramodern-workspace/add-vertical/shell-files.js +87 -25
- package/dist/esm/ultramodern-workspace/add-vertical/topology.js +4 -1
- package/dist/esm/ultramodern-workspace/add-vertical/transaction.js +373 -46
- package/dist/esm/ultramodern-workspace/add-vertical/workspace-state.js +17 -34
- package/dist/esm/ultramodern-workspace/add-vertical.js +1 -1
- package/dist/esm/ultramodern-workspace/api/client.js +5 -5
- package/dist/esm/ultramodern-workspace/api/contracts.js +2 -2
- package/dist/esm/ultramodern-workspace/api/rpc.js +20 -18
- package/dist/esm/ultramodern-workspace/api/service.js +49 -24
- package/dist/esm/ultramodern-workspace/api/shared.js +28 -18
- package/dist/esm/ultramodern-workspace/app-files.js +3 -23
- package/dist/esm/ultramodern-workspace/backend-federation.js +5 -5
- package/dist/esm/ultramodern-workspace/contracts.js +14 -180
- package/dist/esm/ultramodern-workspace/delivery-unit-schema/surfaces.js +41 -0
- package/dist/esm/ultramodern-workspace/delivery-unit-schema/types.js +1 -75
- package/dist/esm/ultramodern-workspace/delivery-unit-stamp.js +16 -4
- package/dist/esm/ultramodern-workspace/delivery-unit-sync.js +28 -18
- package/dist/esm/ultramodern-workspace/delivery-unit.js +12 -6
- package/dist/esm/ultramodern-workspace/demo-components.js +67 -428
- package/dist/esm/ultramodern-workspace/descriptors.js +1 -2
- package/dist/esm/ultramodern-workspace/fs-io.js +37 -2
- package/dist/esm/ultramodern-workspace/generation-result.js +3 -3
- package/dist/esm/ultramodern-workspace/index.js +1 -1
- package/dist/esm/ultramodern-workspace/mf-validation/constants.js +1 -4
- package/dist/esm/ultramodern-workspace/mf-validation/discovery.js +7 -7
- package/dist/esm/ultramodern-workspace/mf-validation/exposes.js +14 -0
- package/dist/esm/ultramodern-workspace/mf-validation/inspect.js +27 -8
- package/dist/esm/ultramodern-workspace/mf-validation/object-literal.js +22 -123
- package/dist/esm/ultramodern-workspace/mf-validation/path-utils.js +36 -34
- package/dist/esm/ultramodern-workspace/mf-validation/syntax.js +83 -143
- package/dist/esm/ultramodern-workspace/mf-validation.js +1 -0
- package/dist/esm/ultramodern-workspace/module-federation/config.js +25 -30
- package/dist/esm/ultramodern-workspace/module-federation/reexport-module.js +39 -58
- package/dist/esm/ultramodern-workspace/module-federation/remote-refs.js +1 -43
- package/dist/esm/ultramodern-workspace/package-json.js +58 -32
- package/dist/esm/ultramodern-workspace/patch-inventory.js +66 -0
- package/dist/esm/ultramodern-workspace/policy.js +2 -564
- package/dist/esm/ultramodern-workspace/public-surface.js +3 -3
- package/dist/esm/ultramodern-workspace/routes.js +2 -11
- package/dist/esm/ultramodern-workspace/shared-patches.js +2 -2
- package/dist/esm/ultramodern-workspace/shells.js +3 -67
- package/dist/esm/ultramodern-workspace/tooling-command-catalog.js +22 -37
- package/dist/esm/ultramodern-workspace/tsconfigs.js +9 -3
- package/dist/esm/ultramodern-workspace/validation/architecture.js +348 -0
- package/dist/esm/ultramodern-workspace/validation/assertions.js +65 -0
- package/dist/esm/ultramodern-workspace/validation/types.js +0 -0
- package/dist/esm/ultramodern-workspace/validation/workspace.js +286 -0
- package/dist/esm/ultramodern-workspace/versions.js +74 -29
- package/dist/esm/ultramodern-workspace/workspace-artifact-ownership.js +128 -0
- package/dist/esm/ultramodern-workspace/workspace-script-plan.js +35 -27
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +10 -190
- package/dist/esm/ultramodern-workspace/workspace-validation-contract.js +65 -376
- package/dist/esm/ultramodern-workspace/write-app.js +18 -10
- package/dist/esm/ultramodern-workspace/write-workspace.js +25 -52
- package/dist/esm/ultramodern-workspace/zerops.js +2 -0
- package/dist/esm-node/cli/package-source.js +3 -3
- package/dist/esm-node/cli/project-setup.js +2 -22
- package/dist/esm-node/index.js +10 -2
- package/dist/esm-node/locale/en.js +2 -1
- package/dist/esm-node/locale/zh.js +2 -1
- package/dist/esm-node/ultramodern-package-source.js +14 -4
- package/dist/esm-node/ultramodern-release-cohort.js +5 -14
- package/dist/esm-node/ultramodern-tooling/commands/cloudflare-output-verify.js +49 -56
- package/dist/esm-node/ultramodern-tooling/commands/context.js +10 -26
- package/dist/esm-node/ultramodern-tooling/commands/routes-generate-app.js +36 -0
- package/dist/esm-node/ultramodern-tooling/commands/routes-generate.js +25 -54
- package/dist/esm-node/ultramodern-tooling/commands/validate.js +6 -12
- package/dist/esm-node/ultramodern-tooling/commands.js +15 -9
- package/dist/esm-node/ultramodern-tooling/config/index.js +0 -2
- package/dist/esm-node/ultramodern-tooling/config/load.js +9 -9
- package/dist/esm-node/ultramodern-tooling/config/metadata.js +33 -28
- package/dist/esm-node/ultramodern-tooling/config/normalize.js +159 -156
- package/dist/esm-node/ultramodern-workspace/add-shell.js +124 -123
- package/dist/esm-node/ultramodern-workspace/add-vertical/execute.js +119 -27
- package/dist/esm-node/ultramodern-workspace/add-vertical/plan.js +16 -150
- package/dist/esm-node/ultramodern-workspace/add-vertical/preflight.js +15 -47
- package/dist/esm-node/ultramodern-workspace/add-vertical/preview.js +41 -0
- package/dist/esm-node/ultramodern-workspace/add-vertical/shell-files.js +87 -25
- package/dist/esm-node/ultramodern-workspace/add-vertical/topology.js +4 -1
- package/dist/esm-node/ultramodern-workspace/add-vertical/transaction.js +373 -46
- package/dist/esm-node/ultramodern-workspace/add-vertical/workspace-state.js +17 -34
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +1 -1
- package/dist/esm-node/ultramodern-workspace/api/client.js +5 -5
- package/dist/esm-node/ultramodern-workspace/api/contracts.js +2 -2
- package/dist/esm-node/ultramodern-workspace/api/rpc.js +20 -18
- package/dist/esm-node/ultramodern-workspace/api/service.js +49 -24
- package/dist/esm-node/ultramodern-workspace/api/shared.js +28 -18
- package/dist/esm-node/ultramodern-workspace/app-files.js +3 -23
- package/dist/esm-node/ultramodern-workspace/backend-federation.js +5 -5
- package/dist/esm-node/ultramodern-workspace/contracts.js +14 -180
- package/dist/esm-node/ultramodern-workspace/delivery-unit-schema/surfaces.js +42 -0
- package/dist/esm-node/ultramodern-workspace/delivery-unit-schema/types.js +1 -75
- package/dist/esm-node/ultramodern-workspace/delivery-unit-stamp.js +16 -4
- package/dist/esm-node/ultramodern-workspace/delivery-unit-sync.js +28 -18
- package/dist/esm-node/ultramodern-workspace/delivery-unit.js +12 -6
- package/dist/esm-node/ultramodern-workspace/demo-components.js +67 -428
- package/dist/esm-node/ultramodern-workspace/descriptors.js +1 -2
- package/dist/esm-node/ultramodern-workspace/fs-io.js +37 -2
- package/dist/esm-node/ultramodern-workspace/generation-result.js +3 -3
- package/dist/esm-node/ultramodern-workspace/index.js +1 -1
- package/dist/esm-node/ultramodern-workspace/mf-validation/constants.js +1 -4
- package/dist/esm-node/ultramodern-workspace/mf-validation/discovery.js +7 -7
- package/dist/esm-node/ultramodern-workspace/mf-validation/exposes.js +15 -0
- package/dist/esm-node/ultramodern-workspace/mf-validation/inspect.js +27 -8
- package/dist/esm-node/ultramodern-workspace/mf-validation/object-literal.js +22 -123
- package/dist/esm-node/ultramodern-workspace/mf-validation/path-utils.js +36 -34
- package/dist/esm-node/ultramodern-workspace/mf-validation/syntax.js +83 -143
- package/dist/esm-node/ultramodern-workspace/mf-validation.js +1 -0
- package/dist/esm-node/ultramodern-workspace/module-federation/config.js +25 -30
- package/dist/esm-node/ultramodern-workspace/module-federation/reexport-module.js +39 -58
- package/dist/esm-node/ultramodern-workspace/module-federation/remote-refs.js +1 -43
- package/dist/esm-node/ultramodern-workspace/package-json.js +58 -32
- package/dist/esm-node/ultramodern-workspace/patch-inventory.js +67 -0
- package/dist/esm-node/ultramodern-workspace/policy.js +2 -564
- package/dist/esm-node/ultramodern-workspace/public-surface.js +3 -3
- package/dist/esm-node/ultramodern-workspace/routes.js +2 -11
- package/dist/esm-node/ultramodern-workspace/shared-patches.js +2 -2
- package/dist/esm-node/ultramodern-workspace/shells.js +3 -67
- package/dist/esm-node/ultramodern-workspace/tooling-command-catalog.js +22 -37
- package/dist/esm-node/ultramodern-workspace/tsconfigs.js +9 -3
- package/dist/esm-node/ultramodern-workspace/validation/architecture.js +349 -0
- package/dist/esm-node/ultramodern-workspace/validation/assertions.js +66 -0
- package/dist/esm-node/ultramodern-workspace/validation/types.js +1 -0
- package/dist/esm-node/ultramodern-workspace/validation/workspace.js +287 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +74 -29
- package/dist/esm-node/ultramodern-workspace/workspace-artifact-ownership.js +129 -0
- package/dist/esm-node/ultramodern-workspace/workspace-script-plan.js +35 -27
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +10 -190
- package/dist/esm-node/ultramodern-workspace/workspace-validation-contract.js +65 -376
- package/dist/esm-node/ultramodern-workspace/write-app.js +18 -10
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +25 -52
- package/dist/esm-node/ultramodern-workspace/zerops.js +2 -0
- package/dist/types/cli/project-setup.d.ts +1 -1
- package/dist/types/locale/en.d.ts +1 -0
- package/dist/types/locale/index.d.ts +2 -0
- package/dist/types/locale/zh.d.ts +1 -0
- package/dist/types/ultramodern-package-source.d.ts +2 -4
- package/dist/types/ultramodern-release-cohort.d.ts +1 -3
- package/dist/types/ultramodern-tooling/commands/cloudflare-output-verify.d.ts +2 -2
- package/dist/types/ultramodern-tooling/commands/context.d.ts +4 -1
- package/dist/types/ultramodern-tooling/commands/routes-generate-app.d.ts +1 -0
- package/dist/types/ultramodern-tooling/commands/routes-generate.d.ts +1 -1
- package/dist/types/ultramodern-tooling/commands/validate.d.ts +1 -1
- package/dist/types/ultramodern-tooling/config/index.d.ts +0 -2
- package/dist/types/ultramodern-tooling/config/load.d.ts +10 -2
- package/dist/types/ultramodern-tooling/config/metadata.d.ts +2 -2
- package/dist/types/ultramodern-tooling/config/normalize.d.ts +19 -19
- package/dist/types/ultramodern-tooling/config/types.d.ts +2 -9
- package/dist/types/ultramodern-workspace/add-shell.d.ts +1 -1
- package/dist/types/ultramodern-workspace/add-vertical/execute.d.ts +1 -0
- package/dist/types/ultramodern-workspace/add-vertical/preflight.d.ts +4 -3
- package/dist/types/ultramodern-workspace/add-vertical/preview.d.ts +4 -0
- package/dist/types/ultramodern-workspace/add-vertical/shell-files.d.ts +7 -2
- package/dist/types/ultramodern-workspace/add-vertical/transaction.d.ts +32 -6
- package/dist/types/ultramodern-workspace/add-vertical/workspace-state.d.ts +10 -7
- package/dist/types/ultramodern-workspace/add-vertical.d.ts +1 -1
- package/dist/types/ultramodern-workspace/api/client.d.ts +3 -1
- package/dist/types/ultramodern-workspace/api/rpc.d.ts +1 -1
- package/dist/types/ultramodern-workspace/api/service.d.ts +3 -1
- package/dist/types/ultramodern-workspace/api/shared.d.ts +2 -0
- package/dist/types/ultramodern-workspace/backend-federation.d.ts +1 -1
- package/dist/types/ultramodern-workspace/contracts.d.ts +1 -3
- package/dist/types/ultramodern-workspace/delivery-unit-schema/surfaces.d.ts +17 -0
- package/dist/types/ultramodern-workspace/delivery-unit-schema/types.d.ts +3 -68
- package/dist/types/ultramodern-workspace/delivery-unit-stamp.d.ts +2 -2
- package/dist/types/ultramodern-workspace/delivery-unit.d.ts +3 -3
- package/dist/types/ultramodern-workspace/demo-components.d.ts +0 -3
- package/dist/types/ultramodern-workspace/descriptors.d.ts +0 -1
- package/dist/types/ultramodern-workspace/fs-io.d.ts +1 -1
- package/dist/types/ultramodern-workspace/index.d.ts +1 -1
- package/dist/types/ultramodern-workspace/mf-validation/constants.d.ts +0 -1
- package/dist/types/ultramodern-workspace/mf-validation/exposes.d.ts +11 -0
- package/dist/types/ultramodern-workspace/mf-validation/path-utils.d.ts +2 -3
- package/dist/types/ultramodern-workspace/mf-validation/syntax.d.ts +4 -3
- package/dist/types/ultramodern-workspace/mf-validation/types.d.ts +1 -0
- package/dist/types/ultramodern-workspace/mf-validation.d.ts +1 -0
- package/dist/types/ultramodern-workspace/module-federation/config.d.ts +1 -1
- package/dist/types/ultramodern-workspace/module-federation/reexport-module.d.ts +2 -2
- package/dist/types/ultramodern-workspace/package-json.d.ts +1 -1
- package/dist/types/ultramodern-workspace/patch-inventory.d.ts +10 -0
- package/dist/types/ultramodern-workspace/policy.d.ts +31 -209
- package/dist/types/ultramodern-workspace/routes.d.ts +6 -1
- package/dist/types/ultramodern-workspace/shells.d.ts +2 -15
- package/dist/types/ultramodern-workspace/tooling-command-catalog.d.ts +8 -7
- package/dist/types/ultramodern-workspace/types.d.ts +9 -9
- package/dist/types/ultramodern-workspace/validation/architecture.d.ts +2 -0
- package/dist/types/ultramodern-workspace/validation/assertions.d.ts +14 -0
- package/dist/types/ultramodern-workspace/validation/types.d.ts +9 -0
- package/dist/types/ultramodern-workspace/validation/workspace.d.ts +6 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +73 -28
- package/dist/types/ultramodern-workspace/workspace-artifact-ownership.d.ts +18 -0
- package/dist/types/ultramodern-workspace/workspace-script-plan.d.ts +4 -5
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +8 -13
- package/dist/types/ultramodern-workspace/workspace-validation-contract.d.ts +22 -188
- package/dist/types/ultramodern-workspace/write-workspace.d.ts +1 -3
- package/package.json +18 -11
- package/{template-workspace/.modernjs/release-cohort.json → release-cohort.json} +88 -40
- package/template-workspace/.codex/skills/rspack-tracing/scripts/analyze_trace.js +1 -1
- package/template-workspace/README.md.handlebars +20 -35
- package/template-workspace/oxfmt.config.ts +3 -0
- package/template-workspace/pnpm-workspace.yaml.handlebars +0 -24
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +4 -4
- package/templates/packages/shared-contracts-index.ts +4 -332
- package/templates/workspace/apps/modern.config.shared-module-federation.ts.handlebars +10 -0
- package/templates/workspace/apps/modern.config.ts.handlebars +13 -27
- package/templates/workspace/apps/shared/src/routes/ultramodern-route-metadata.ts.handlebars +21 -11
- package/templates/workspace/apps/shell-super-app/src/routes/[lang]/page.tsx.handlebars +20 -20
- package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.helpers.tsx.handlebars +4 -6
- package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.imports.tsx.handlebars +2 -2
- package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.tsx.handlebars +11 -11
- package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.worker.helpers.tsx.handlebars +1 -1
- package/templates/workspace/apps/shell-super-app/src/routes/vertical-components.worker.imports.tsx.handlebars +1 -1
- package/templates/workspace-scripts/generate-node-backend-federation.mjs +68 -77
- package/templates/workspace-scripts/generate-public-surface-assets.mjs +107 -207
- package/templates/workspace-scripts/materialize-zerops-runtime.mjs +12 -19
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +53 -444
- package/templates/workspace-scripts/proof-node-backend-federation.mjs +212 -91
- package/templates/workspace-scripts/{proof-workerd-ssr.mts → proof-workerd-ssr.mjs} +434 -239
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +25 -7
- package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +45 -147
- package/templates/workspace-scripts/ultramodern-typecheck.mjs +1 -1
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/api-metadata.cjs +0 -212
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/declaration-patches.cjs +0 -47
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/dependency-usage.cjs +0 -112
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-backend-federation.cjs +0 -55
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.cjs +0 -102
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.cjs +0 -195
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxfmt.cjs +0 -146
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxlint.cjs +0 -110
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-removal.cjs +0 -67
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.cjs +0 -307
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-zerops.cjs +0 -58
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts.cjs +0 -71
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/generated-ui-source.cjs +0 -151
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/help.cjs +0 -67
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/install.cjs +0 -52
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/io.cjs +0 -447
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.cjs +0 -323
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/package-source.cjs +0 -87
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.cjs +0 -612
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.cjs +0 -376
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/policy-constants.cjs +0 -73
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/react-router-retirement.cjs +0 -215
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.cjs +0 -135
- package/dist/cjs/ultramodern-tooling/commands/migrate-strict-effect.cjs +0 -454
- package/dist/cjs/ultramodern-tooling/config/constants.cjs +0 -48
- package/dist/cjs/ultramodern-tooling/config/synthesize.cjs +0 -157
- package/dist/cjs/ultramodern-workspace/delivery-unit-schema/up-projection.cjs +0 -188
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/api-metadata.js +0 -154
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/declaration-patches.js +0 -9
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/dependency-usage.js +0 -63
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-backend-federation.js +0 -7
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +0 -47
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +0 -146
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxfmt.js +0 -97
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxlint.js +0 -61
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-removal.js +0 -16
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.js +0 -258
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-zerops.js +0 -10
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts.js +0 -8
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-patches.js +0 -15
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/generated-ui-source.js +0 -100
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/help.js +0 -29
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/install.js +0 -14
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/io.js +0 -385
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +0 -276
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/package-source.js +0 -49
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +0 -559
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +0 -329
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/policy-constants.js +0 -19
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/react-router-retirement.js +0 -148
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +0 -80
- package/dist/esm/ultramodern-tooling/commands/migrate-strict-effect.js +0 -405
- package/dist/esm/ultramodern-tooling/config/constants.js +0 -4
- package/dist/esm/ultramodern-tooling/config/synthesize.js +0 -108
- package/dist/esm/ultramodern-workspace/delivery-unit-schema/up-projection.js +0 -129
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/api-metadata.js +0 -155
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/declaration-patches.js +0 -10
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/dependency-usage.js +0 -64
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-backend-federation.js +0 -8
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.js +0 -48
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.js +0 -147
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxfmt.js +0 -98
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxlint.js +0 -62
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-removal.js +0 -17
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.js +0 -259
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-zerops.js +0 -11
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts.js +0 -9
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-patches.js +0 -16
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/generated-ui-source.js +0 -101
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/help.js +0 -30
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/install.js +0 -15
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/io.js +0 -386
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.js +0 -277
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/package-source.js +0 -50
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.js +0 -560
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.js +0 -330
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/policy-constants.js +0 -20
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/react-router-retirement.js +0 -149
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.js +0 -81
- package/dist/esm-node/ultramodern-tooling/commands/migrate-strict-effect.js +0 -406
- package/dist/esm-node/ultramodern-tooling/config/constants.js +0 -5
- package/dist/esm-node/ultramodern-tooling/config/synthesize.js +0 -109
- package/dist/esm-node/ultramodern-workspace/delivery-unit-schema/up-projection.js +0 -130
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/api-metadata.d.ts +0 -12
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/declaration-patches.d.ts +0 -4
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/dependency-usage.d.ts +0 -1
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-backend-federation.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-build-identity.d.ts +0 -5
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-modern-configs.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxfmt.d.ts +0 -2
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-oxlint.d.ts +0 -2
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-removal.d.ts +0 -4
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-typescript.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts-zerops.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-artifacts.d.ts +0 -8
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-patches.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/generated-ui-source.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/help.d.ts +0 -1
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/install.d.ts +0 -2
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/io.d.ts +0 -26
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/package-cohort.d.ts +0 -25
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/package-source.d.ts +0 -3
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/pnpm-policy.d.ts +0 -26
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/pnpm-yaml.d.ts +0 -26
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/policy-constants.d.ts +0 -6
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/react-router-retirement.d.ts +0 -37
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect/toolchain-pins.d.ts +0 -4
- package/dist/types/ultramodern-tooling/commands/migrate-strict-effect.d.ts +0 -2
- package/dist/types/ultramodern-tooling/config/constants.d.ts +0 -3
- package/dist/types/ultramodern-tooling/config/synthesize.d.ts +0 -5
- package/dist/types/ultramodern-workspace/delivery-unit-schema/up-projection.d.ts +0 -189
- package/template-workspace/patches/@module-federation__bridge-react@2.9.0.patch +0 -47
- package/template-workspace/patches/@module-federation__dts-plugin@2.9.0.patch +0 -26
- package/template-workspace/patches/@module-federation__modern-js-v3@2.9.0.patch +0 -268
- package/template-workspace/patches/@module-federation__runtime-core@2.9.0.patch +0 -13
- package/template-workspace/patches/drizzle-orm-ts7-strict-declarations.patch +0 -471
- package/template-workspace/patches/msgpackr@2.1.0.patch +0 -30
- package/template-workspace/patches/zod@4.5.4.patch +0 -56
- package/templates/workspace-scripts/check-ultramodern-api-boundaries.mts +0 -779
- package/templates/workspace-scripts/check-ultramodern-i18n-boundaries.mts +0 -9
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +0 -4109
|
@@ -11,7 +11,18 @@ class WorkspaceTransactionConflictError extends Error {
|
|
|
11
11
|
}
|
|
12
12
|
const __transactionTestHooks = {};
|
|
13
13
|
function isIgnoredRelativePath(relativePath) {
|
|
14
|
-
|
|
14
|
+
const segments = normalizePath(relativePath).split('/');
|
|
15
|
+
return segments.some((segment, index)=>{
|
|
16
|
+
if (1 === index && [
|
|
17
|
+
'apps',
|
|
18
|
+
'verticals',
|
|
19
|
+
'packages'
|
|
20
|
+
].includes(segments[0]) && [
|
|
21
|
+
'dist',
|
|
22
|
+
'coverage'
|
|
23
|
+
].includes(segment)) return false;
|
|
24
|
+
return ignoredSnapshotDirectories.has(segment);
|
|
25
|
+
});
|
|
15
26
|
}
|
|
16
27
|
function walkWorkspaceFiles(root, onFile) {
|
|
17
28
|
if (!node_fs.existsSync(root)) return;
|
|
@@ -22,26 +33,30 @@ function walkWorkspaceFiles(root, onFile) {
|
|
|
22
33
|
const entryPath = node_path.join(currentDir, entry.name);
|
|
23
34
|
const relativePath = normalizePath(node_path.relative(root, entryPath));
|
|
24
35
|
if (!isIgnoredRelativePath(relativePath)) if (entry.isDirectory()) collect(entryPath);
|
|
25
|
-
else if (entry.isFile()) onFile(relativePath, entryPath);
|
|
36
|
+
else if (entry.isFile() || entry.isSymbolicLink()) onFile(relativePath, entryPath);
|
|
26
37
|
else throw new WorkspaceTransactionConflictError(`Staged workspace contains an unsupported link or special file: ${relativePath}`);
|
|
27
38
|
}
|
|
28
39
|
};
|
|
29
40
|
collect(root);
|
|
30
41
|
}
|
|
31
|
-
function captureWorkspace(root) {
|
|
42
|
+
function captureWorkspace(root, publishedRoot = root) {
|
|
32
43
|
const files = new Map();
|
|
33
44
|
walkWorkspaceFiles(root, (relativePath, absolutePath)=>{
|
|
34
|
-
const stat = node_fs.
|
|
45
|
+
const stat = node_fs.lstatSync(absolutePath);
|
|
46
|
+
const target = stat.isSymbolicLink() ? node_fs.readlinkSync(absolutePath) : void 0;
|
|
35
47
|
files.set(relativePath, {
|
|
36
|
-
content: node_fs.readFileSync(absolutePath),
|
|
37
|
-
mode:
|
|
48
|
+
content: void 0 === target ? node_fs.readFileSync(absolutePath) : Buffer.from(node_path.isAbsolute(target) && isInside(root, target) ? node_path.join(publishedRoot, node_path.relative(root, target)) : target),
|
|
49
|
+
mode: 4095 & stat.mode,
|
|
50
|
+
...void 0 === target ? {} : {
|
|
51
|
+
symlink: true
|
|
52
|
+
}
|
|
38
53
|
});
|
|
39
54
|
});
|
|
40
55
|
return files;
|
|
41
56
|
}
|
|
42
57
|
function sameFile(left, right) {
|
|
43
58
|
if (void 0 === left || void 0 === right) return left === right;
|
|
44
|
-
return left.mode === right.mode && left.content.equals(right.content);
|
|
59
|
+
return left.symlink === right.symlink && left.mode === right.mode && left.content.equals(right.content);
|
|
45
60
|
}
|
|
46
61
|
function buildChangePlan(before, after) {
|
|
47
62
|
return [
|
|
@@ -67,7 +82,7 @@ function createTemporarySibling(root) {
|
|
|
67
82
|
node_fs.mkdirSync(parent, {
|
|
68
83
|
recursive: true
|
|
69
84
|
});
|
|
70
|
-
return node_fs.mkdtempSync(node_path.join(parent, `.${node_path.basename(absoluteRoot)}.ultramodern-stage-`));
|
|
85
|
+
return node_fs.realpathSync.native(node_fs.mkdtempSync(node_path.join(parent, `.${node_path.basename(absoluteRoot)}.ultramodern-stage-`)));
|
|
71
86
|
}
|
|
72
87
|
function removeOwnedTemporaryDirectory(temporaryRoot, identity) {
|
|
73
88
|
let current;
|
|
@@ -119,6 +134,7 @@ function assertFreshTarget(targetDir, expected) {
|
|
|
119
134
|
if ('empty' !== current.kind || current.dev !== expected.dev || current.ino !== expected.ino) throw new WorkspaceTransactionConflictError(`Workspace target changed during generation: ${targetDir}`);
|
|
120
135
|
}
|
|
121
136
|
function publishFileExclusive(sourcePath, targetPath) {
|
|
137
|
+
if (node_fs.lstatSync(sourcePath).isSymbolicLink()) return void node_fs.symlinkSync(node_fs.readlinkSync(sourcePath), targetPath);
|
|
122
138
|
try {
|
|
123
139
|
node_fs.linkSync(sourcePath, targetPath);
|
|
124
140
|
} catch (error) {
|
|
@@ -131,15 +147,36 @@ function publishFileExclusive(sourcePath, targetPath) {
|
|
|
131
147
|
node_fs.copyFileSync(sourcePath, targetPath, node_fs.constants.COPYFILE_EXCL);
|
|
132
148
|
}
|
|
133
149
|
}
|
|
150
|
+
function isInside(root, target) {
|
|
151
|
+
const relative = node_path.relative(root, target);
|
|
152
|
+
return '..' !== relative && !relative.startsWith(`..${node_path.sep}`) && !node_path.isAbsolute(relative);
|
|
153
|
+
}
|
|
134
154
|
function copyWorkspaceToStage(root, stagingRoot) {
|
|
155
|
+
walkWorkspaceFiles(root, (relativePath, absolutePath)=>{
|
|
156
|
+
if (!node_fs.lstatSync(absolutePath).isSymbolicLink()) return;
|
|
157
|
+
let target;
|
|
158
|
+
try {
|
|
159
|
+
target = node_fs.realpathSync.native(absolutePath);
|
|
160
|
+
} catch (cause) {
|
|
161
|
+
throw new WorkspaceTransactionConflictError(`Unsupported dangling or cyclic workspace link: ${relativePath}`, {
|
|
162
|
+
cause
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (!isInside(root, target) || isIgnoredRelativePath(node_path.relative(root, target))) throw new WorkspaceTransactionConflictError(`Workspace transaction conflict: link escapes the staged input: ${relativePath}`);
|
|
166
|
+
});
|
|
135
167
|
node_fs.cpSync(root, stagingRoot, {
|
|
136
168
|
mode: node_fs.constants.COPYFILE_FICLONE,
|
|
137
169
|
recursive: true,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
170
|
+
verbatimSymlinks: true,
|
|
171
|
+
filter: (sourcePath)=>!isIgnoredRelativePath(node_path.relative(root, sourcePath))
|
|
172
|
+
});
|
|
173
|
+
walkWorkspaceFiles(stagingRoot, (_relativePath, absolutePath)=>{
|
|
174
|
+
if (!node_fs.lstatSync(absolutePath).isSymbolicLink()) return;
|
|
175
|
+
const target = node_fs.readlinkSync(absolutePath);
|
|
176
|
+
if (node_path.isAbsolute(target)) {
|
|
177
|
+
const realTarget = node_fs.realpathSync.native(target);
|
|
178
|
+
node_fs.unlinkSync(absolutePath);
|
|
179
|
+
node_fs.symlinkSync(node_path.join(stagingRoot, node_path.relative(root, realTarget)), absolutePath);
|
|
143
180
|
}
|
|
144
181
|
});
|
|
145
182
|
}
|
|
@@ -159,6 +196,7 @@ function relocateStagedWorkspaceReferences(stagingRoot, workspaceRoot) {
|
|
|
159
196
|
const stagedPath = Buffer.from(stagingRoot);
|
|
160
197
|
const publishedPath = Buffer.from(workspaceRoot);
|
|
161
198
|
walkWorkspaceFiles(stagingRoot, (_relativePath, absolutePath)=>{
|
|
199
|
+
if (node_fs.lstatSync(absolutePath).isSymbolicLink()) return;
|
|
162
200
|
const content = node_fs.readFileSync(absolutePath);
|
|
163
201
|
if (!content.includes(stagedPath)) return;
|
|
164
202
|
node_fs.writeFileSync(absolutePath, replaceBuffer(content, stagedPath, publishedPath));
|
|
@@ -175,10 +213,13 @@ function readFilePath(absolutePath, displayPath) {
|
|
|
175
213
|
if ('ENOENT' === error.code) return;
|
|
176
214
|
throw error;
|
|
177
215
|
}
|
|
178
|
-
if (!stat.isFile()) throw new WorkspaceTransactionConflictError(`Workspace target changed type during generation: ${displayPath}`);
|
|
216
|
+
if (!stat.isFile() && !stat.isSymbolicLink()) throw new WorkspaceTransactionConflictError(`Workspace target changed type during generation: ${displayPath}`);
|
|
179
217
|
return {
|
|
180
|
-
content: node_fs.readFileSync(absolutePath),
|
|
181
|
-
mode:
|
|
218
|
+
content: stat.isSymbolicLink() ? Buffer.from(node_fs.readlinkSync(absolutePath)) : node_fs.readFileSync(absolutePath),
|
|
219
|
+
mode: 4095 & stat.mode,
|
|
220
|
+
...stat.isSymbolicLink() ? {
|
|
221
|
+
symlink: true
|
|
222
|
+
} : {}
|
|
182
223
|
};
|
|
183
224
|
}
|
|
184
225
|
function assertPreimage(root, change) {
|
|
@@ -210,6 +251,7 @@ function temporaryFilePath(root, relativePath, role) {
|
|
|
210
251
|
return node_path.join(node_path.dirname(targetPath), `.${node_path.basename(targetPath)}.ultramodern-${role}-${randomUUID()}.tmp`);
|
|
211
252
|
}
|
|
212
253
|
function writeTemporaryFile(filePath, file) {
|
|
254
|
+
if (file.symlink) return void node_fs.symlinkSync(file.content.toString(), filePath);
|
|
213
255
|
node_fs.writeFileSync(filePath, file.content, {
|
|
214
256
|
flag: 'wx',
|
|
215
257
|
mode: file.mode
|
|
@@ -225,19 +267,10 @@ function removeIfPresent(filePath) {
|
|
|
225
267
|
if ('ENOENT' !== error.code) throw error;
|
|
226
268
|
}
|
|
227
269
|
}
|
|
228
|
-
function prepareChanges(root,
|
|
229
|
-
for (const
|
|
230
|
-
ensureOwnedParentDirectories(root,
|
|
231
|
-
|
|
232
|
-
...change,
|
|
233
|
-
published: false
|
|
234
|
-
};
|
|
235
|
-
preparedChanges.push(prepared);
|
|
236
|
-
if (change.after) {
|
|
237
|
-
prepared.publishPath = temporaryFilePath(root, change.relativePath, 'publish');
|
|
238
|
-
writeTemporaryFile(prepared.publishPath, change.after);
|
|
239
|
-
}
|
|
240
|
-
if (change.before) prepared.rollbackPath = temporaryFilePath(root, change.relativePath, change.after ? 'rollback' : 'removed');
|
|
270
|
+
function prepareChanges(root, preparedChanges, createdDirectories) {
|
|
271
|
+
for (const prepared of preparedChanges){
|
|
272
|
+
ensureOwnedParentDirectories(root, prepared.relativePath, createdDirectories);
|
|
273
|
+
if (prepared.after && prepared.publishPath) writeTemporaryFile(prepared.publishPath, prepared.after);
|
|
241
274
|
}
|
|
242
275
|
}
|
|
243
276
|
function assertPublishedState(root, change) {
|
|
@@ -393,17 +426,278 @@ function publishChange(root, change) {
|
|
|
393
426
|
}
|
|
394
427
|
change.published = true;
|
|
395
428
|
}
|
|
396
|
-
|
|
429
|
+
const receiptSuffix = '.receipt.json';
|
|
430
|
+
function persistReceipt(receiptPath, receipt) {
|
|
431
|
+
const temporary = `${receiptPath}.next`;
|
|
432
|
+
const fd = node_fs.openSync(temporary, 'wx', 384);
|
|
433
|
+
try {
|
|
434
|
+
node_fs.writeFileSync(fd, JSON.stringify(receipt));
|
|
435
|
+
node_fs.fsyncSync(fd);
|
|
436
|
+
} finally{
|
|
437
|
+
node_fs.closeSync(fd);
|
|
438
|
+
}
|
|
439
|
+
node_fs.renameSync(temporary, receiptPath);
|
|
440
|
+
if ('win32' === process.platform) return;
|
|
441
|
+
const directory = node_fs.openSync(node_path.dirname(receiptPath), 'r');
|
|
442
|
+
try {
|
|
443
|
+
node_fs.fsyncSync(directory);
|
|
444
|
+
} finally{
|
|
445
|
+
node_fs.closeSync(directory);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function encodedReceipt(root, stagingRoot, changes, directories) {
|
|
449
|
+
const encode = (file)=>file ? {
|
|
450
|
+
...file,
|
|
451
|
+
content: file.content.toString('base64')
|
|
452
|
+
} : void 0;
|
|
453
|
+
const identity = (filePath)=>{
|
|
454
|
+
const { dev, ino } = node_fs.lstatSync(filePath);
|
|
455
|
+
return {
|
|
456
|
+
dev,
|
|
457
|
+
ino
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
return {
|
|
461
|
+
schema: 'ultramodern-workspace-transaction-v1',
|
|
462
|
+
root,
|
|
463
|
+
rootIdentity: identity(root),
|
|
464
|
+
stagingIdentity: identity(stagingRoot),
|
|
465
|
+
pid: process.pid,
|
|
466
|
+
state: 'publishing',
|
|
467
|
+
...directories ? {
|
|
468
|
+
purpose: 'fresh-empty',
|
|
469
|
+
directories
|
|
470
|
+
} : {},
|
|
471
|
+
changes: changes.map((change)=>({
|
|
472
|
+
...change,
|
|
473
|
+
before: encode(change.before),
|
|
474
|
+
after: encode(change.after)
|
|
475
|
+
}))
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function decodeReceipt(receiptPath, root) {
|
|
479
|
+
const stat = node_fs.lstatSync(receiptPath);
|
|
480
|
+
if (!stat.isFile() || stat.isSymbolicLink() || 'function' == typeof process.getuid && stat.uid !== process.getuid()) throw new WorkspaceTransactionConflictError(`Unsafe interrupted transaction receipt: ${receiptPath}`);
|
|
481
|
+
const receipt = JSON.parse(node_fs.readFileSync(receiptPath, 'utf8'));
|
|
482
|
+
const stagingRoot = receiptPath.slice(0, -receiptSuffix.length);
|
|
483
|
+
if ('ultramodern-workspace-transaction-v1' !== receipt.schema || receipt.root !== root || ![
|
|
484
|
+
'publishing',
|
|
485
|
+
'committed'
|
|
486
|
+
].includes(receipt.state) || !Number.isSafeInteger(receipt.pid) || receipt.pid <= 0 || !sameIdentity(node_fs.lstatSync(root), receipt.rootIdentity) || !sameIdentity(node_fs.lstatSync(stagingRoot), receipt.stagingIdentity) || !Array.isArray(receipt.changes)) throw new WorkspaceTransactionConflictError(`Unrecognized interrupted transaction receipt: ${receiptPath}`);
|
|
487
|
+
const paths = new Set();
|
|
488
|
+
const decode = (file)=>{
|
|
489
|
+
if (void 0 === file) return;
|
|
490
|
+
if (!file || 'string' != typeof file.content || !Number.isInteger(file.mode) || file.mode < 0 || file.mode > 4095 || void 0 !== file.symlink && true !== file.symlink || Buffer.from(file.content, 'base64').toString('base64') !== file.content) throw new WorkspaceTransactionConflictError(`Malformed interrupted transaction preimage: ${receiptPath}`);
|
|
491
|
+
return {
|
|
492
|
+
...file,
|
|
493
|
+
content: Buffer.from(file.content, 'base64')
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
const changes = receipt.changes.map((change)=>{
|
|
497
|
+
const relative = change.relativePath;
|
|
498
|
+
if ('string' != typeof relative || !relative || node_path.isAbsolute(relative) || normalizePath(node_path.normalize(relative)) !== relative || !isInside(root, node_path.resolve(root, relative)) || isIgnoredRelativePath(relative) || paths.has(relative)) throw new WorkspaceTransactionConflictError(`Unsafe interrupted transaction target: ${String(relative)}`);
|
|
499
|
+
paths.add(relative);
|
|
500
|
+
for (const temporary of [
|
|
501
|
+
change.publishPath,
|
|
502
|
+
change.rollbackPath
|
|
503
|
+
])if (void 0 !== temporary && ('string' != typeof temporary || node_path.dirname(temporary) !== node_path.dirname(node_path.join(root, relative)) || !node_path.basename(temporary).startsWith(`.${node_path.basename(relative)}.ultramodern-`) || !temporary.endsWith('.tmp'))) throw new WorkspaceTransactionConflictError(`Unsafe interrupted transaction temporary: ${String(temporary)}`);
|
|
504
|
+
return {
|
|
505
|
+
relativePath: relative,
|
|
506
|
+
before: decode(change.before),
|
|
507
|
+
after: decode(change.after),
|
|
508
|
+
publishPath: change.publishPath,
|
|
509
|
+
rollbackPath: change.rollbackPath,
|
|
510
|
+
published: false
|
|
511
|
+
};
|
|
512
|
+
});
|
|
513
|
+
if (void 0 !== receipt.purpose && 'fresh-empty' !== receipt.purpose) throw new WorkspaceTransactionConflictError(`Unknown transaction purpose: ${receiptPath}`);
|
|
514
|
+
if ('fresh-empty' === receipt.purpose) {
|
|
515
|
+
const expected = freshParentPaths(changes);
|
|
516
|
+
if (!Array.isArray(receipt.directories) || receipt.directories.length !== expected.length || changes.some((change)=>void 0 !== change.before || void 0 === change.after) || receipt.directories.some((directory, index)=>!directory || directory.relativePath !== expected[index] || 'string' != typeof directory.temporaryPath || node_path.dirname(directory.temporaryPath) !== stagingRoot || !/^\.ultramodern-directory-[\da-f-]+\.tmp$/u.test(node_path.basename(directory.temporaryPath)) || !Number.isInteger(directory.dev) || !Number.isInteger(directory.ino)) || new Set(receipt.directories.map((directory)=>directory.temporaryPath)).size !== expected.length) throw new WorkspaceTransactionConflictError(`Unsafe fresh transaction directories: ${receiptPath}`);
|
|
517
|
+
} else if (void 0 !== receipt.directories) throw new WorkspaceTransactionConflictError(`Unexpected transaction directories: ${receiptPath}`);
|
|
518
|
+
return {
|
|
519
|
+
receipt,
|
|
520
|
+
changes
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
function freshParentPaths(changes) {
|
|
524
|
+
const parents = new Set();
|
|
525
|
+
for (const change of changes){
|
|
526
|
+
const segments = change.relativePath.split('/');
|
|
527
|
+
for(let length = 1; length < segments.length; length++)parents.add(segments.slice(0, length).join('/'));
|
|
528
|
+
}
|
|
529
|
+
return [
|
|
530
|
+
...parents
|
|
531
|
+
].sort((left, right)=>left.split('/').length - right.split('/').length || left.localeCompare(right));
|
|
532
|
+
}
|
|
533
|
+
function stageFreshDirectories(stagingRoot, changes) {
|
|
534
|
+
return freshParentPaths(changes).map((relativePath)=>{
|
|
535
|
+
const temporaryPath = node_path.join(stagingRoot, `.ultramodern-directory-${randomUUID()}.tmp`);
|
|
536
|
+
node_fs.mkdirSync(temporaryPath, {
|
|
537
|
+
mode: 511 & node_fs.statSync(node_path.join(stagingRoot, relativePath)).mode
|
|
538
|
+
});
|
|
539
|
+
const { dev, ino } = node_fs.lstatSync(temporaryPath);
|
|
540
|
+
return {
|
|
541
|
+
relativePath,
|
|
542
|
+
temporaryPath,
|
|
543
|
+
dev,
|
|
544
|
+
ino
|
|
545
|
+
};
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
function assertFreshDirectoryAncestors(root, receipt, relativePath) {
|
|
549
|
+
const ancestors = relativePath.split('/').slice(0, -1);
|
|
550
|
+
for(let length = 0; length <= ancestors.length; length++){
|
|
551
|
+
const relative = ancestors.slice(0, length).join('/');
|
|
552
|
+
const expected = 0 === length ? receipt.rootIdentity : receipt.directories.find((directory)=>directory.relativePath === relative);
|
|
553
|
+
const candidate = node_path.join(root, relative);
|
|
554
|
+
const stat = node_fs.lstatSync(candidate);
|
|
555
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || !sameIdentity(stat, expected)) throw new WorkspaceTransactionConflictError(`Fresh transaction parent changed; preserved at ${candidate}`);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function publishFreshDirectory(root, receipt, directory) {
|
|
559
|
+
const target = node_path.join(root, directory.relativePath);
|
|
560
|
+
assertFreshDirectoryAncestors(root, receipt, directory.relativePath);
|
|
561
|
+
const staged = node_fs.lstatSync(directory.temporaryPath);
|
|
562
|
+
const stagingRoot = node_path.dirname(directory.temporaryPath);
|
|
563
|
+
if (!staged.isDirectory() || staged.isSymbolicLink() || !sameIdentity(staged, directory) || !sameIdentity(node_fs.lstatSync(stagingRoot), receipt.stagingIdentity)) throw new WorkspaceTransactionConflictError(`Fresh transaction staged directory changed: ${directory.temporaryPath}`);
|
|
564
|
+
if (node_fs.existsSync(target)) throw new WorkspaceTransactionConflictError(`Fresh transaction directory appeared: ${target}`);
|
|
565
|
+
node_fs.renameSync(directory.temporaryPath, target);
|
|
566
|
+
try {
|
|
567
|
+
assertFreshDirectoryAncestors(root, receipt, directory.relativePath);
|
|
568
|
+
const published = node_fs.lstatSync(target);
|
|
569
|
+
if (!published.isDirectory() || published.isSymbolicLink() || !sameIdentity(published, directory)) throw new WorkspaceTransactionConflictError(`Fresh transaction directory changed; preserved at ${target}`);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
throw new WorkspaceTransactionConflictError(`Fresh directory publication could not validate ownership at ${target}; no cleanup attempted through this path`, {
|
|
572
|
+
cause: error
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
function validateFreshDirectories(root, receipt, changes) {
|
|
577
|
+
const directories = receipt.directories;
|
|
578
|
+
const allowed = new Set(directories.map((directory)=>node_path.join(root, directory.relativePath)));
|
|
579
|
+
for (const change of changes){
|
|
580
|
+
allowed.add(node_path.join(root, change.relativePath));
|
|
581
|
+
if (change.publishPath) allowed.add(change.publishPath);
|
|
582
|
+
}
|
|
583
|
+
const liveDirectories = [
|
|
584
|
+
root
|
|
585
|
+
];
|
|
586
|
+
for (const directory of directories)for (const candidate of [
|
|
587
|
+
node_path.join(root, directory.relativePath),
|
|
588
|
+
directory.temporaryPath
|
|
589
|
+
]){
|
|
590
|
+
let stat;
|
|
591
|
+
try {
|
|
592
|
+
stat = node_fs.lstatSync(candidate);
|
|
593
|
+
} catch (error) {
|
|
594
|
+
if ('ENOENT' === error.code) continue;
|
|
595
|
+
throw error;
|
|
596
|
+
}
|
|
597
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || !sameIdentity(stat, directory)) throw new WorkspaceTransactionConflictError(`Fresh transaction directory changed; preserved at ${candidate}`);
|
|
598
|
+
if (candidate !== directory.temporaryPath) liveDirectories.push(candidate);
|
|
599
|
+
}
|
|
600
|
+
if ('committed' === receipt.state) return;
|
|
601
|
+
for (const directory of liveDirectories)for (const entry of node_fs.readdirSync(directory))if (!allowed.has(node_path.join(directory, entry))) throw new WorkspaceTransactionConflictError(`Fresh transaction conflicts with newer consumer path: ${node_path.join(directory, entry)}`);
|
|
602
|
+
}
|
|
603
|
+
function removeFreshDirectories(root, directories) {
|
|
604
|
+
for (const directory of [
|
|
605
|
+
...directories
|
|
606
|
+
].reverse()){
|
|
607
|
+
const target = node_path.join(root, directory.relativePath);
|
|
608
|
+
let stat;
|
|
609
|
+
try {
|
|
610
|
+
stat = node_fs.lstatSync(target);
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if ('ENOENT' === error.code) continue;
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || !sameIdentity(stat, directory)) throw new WorkspaceTransactionConflictError(`Fresh transaction directory changed; preserved at ${target}`);
|
|
616
|
+
node_fs.rmdirSync(target);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
function recoverFreshWorkspaceTransactions(root) {
|
|
620
|
+
try {
|
|
621
|
+
const stat = node_fs.lstatSync(root);
|
|
622
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) return;
|
|
623
|
+
} catch (error) {
|
|
624
|
+
if ('ENOENT' === error.code) return;
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
627
|
+
recoverWorkspaceTransactions(root, 'fresh-empty');
|
|
628
|
+
}
|
|
629
|
+
function recoverWorkspaceTransactions(root, purpose = 'update') {
|
|
630
|
+
const workspaceRoot = node_fs.realpathSync.native(root);
|
|
631
|
+
const parent = node_path.dirname(workspaceRoot);
|
|
632
|
+
const prefix = `.${node_path.basename(workspaceRoot)}.ultramodern-stage-`;
|
|
633
|
+
for (const entry of node_fs.readdirSync(parent).sort()){
|
|
634
|
+
if (!entry.startsWith(prefix) || !entry.endsWith(receiptSuffix)) continue;
|
|
635
|
+
const receiptPath = node_path.join(parent, entry);
|
|
636
|
+
const { receipt, changes } = decodeReceipt(receiptPath, workspaceRoot);
|
|
637
|
+
if ((receipt.purpose ?? 'update') === purpose) {
|
|
638
|
+
try {
|
|
639
|
+
process.kill(receipt.pid, 0);
|
|
640
|
+
throw new WorkspaceTransactionConflictError(`Workspace publication is still owned by process ${receipt.pid}: ${receiptPath}`);
|
|
641
|
+
} catch (error) {
|
|
642
|
+
if ('ESRCH' !== error.code) throw error;
|
|
643
|
+
}
|
|
644
|
+
if ('fresh-empty' === receipt.purpose) validateFreshDirectories(workspaceRoot, receipt, changes);
|
|
645
|
+
for (const change of changes){
|
|
646
|
+
if ('fresh-empty' !== receipt.purpose) ensureOwnedParentDirectories(workspaceRoot, change.relativePath, []);
|
|
647
|
+
for (const [temporary, expected] of [
|
|
648
|
+
[
|
|
649
|
+
change.publishPath,
|
|
650
|
+
change.after
|
|
651
|
+
],
|
|
652
|
+
[
|
|
653
|
+
change.rollbackPath,
|
|
654
|
+
change.before
|
|
655
|
+
]
|
|
656
|
+
])if (temporary && node_fs.existsSync(temporary) && !sameFile(readFilePath(temporary, temporary), expected)) throw new WorkspaceTransactionConflictError(`Interrupted transaction temporary changed; preserved at ${temporary}`);
|
|
657
|
+
if ('committed' === receipt.state) continue;
|
|
658
|
+
const current = readWorkspaceFile(workspaceRoot, change.relativePath);
|
|
659
|
+
if (!sameFile(current, change.before)) if (sameFile(current, change.after)) {
|
|
660
|
+
change.published = true;
|
|
661
|
+
if (change.before && change.rollbackPath && !node_fs.existsSync(change.rollbackPath)) writeTemporaryFile(change.rollbackPath, change.before);
|
|
662
|
+
} else if (void 0 === current && change.before && change.rollbackPath && node_fs.existsSync(change.rollbackPath)) {
|
|
663
|
+
if (!restoreQuarantinedPreimage(change, node_path.join(workspaceRoot, change.relativePath))) throw new WorkspaceTransactionConflictError(`Interrupted preimage cannot be restored: ${change.relativePath}`);
|
|
664
|
+
} else throw new WorkspaceTransactionConflictError(`Interrupted transaction conflicts with newer consumer bytes: ${change.relativePath}; receipt ${receiptPath}`);
|
|
665
|
+
}
|
|
666
|
+
if ('publishing' === receipt.state) rollbackPublishedChanges(workspaceRoot, changes);
|
|
667
|
+
cleanupPreparedChanges(changes, []);
|
|
668
|
+
if ('fresh-empty' === receipt.purpose && 'publishing' === receipt.state) removeFreshDirectories(workspaceRoot, receipt.directories);
|
|
669
|
+
removeOwnedTemporaryDirectory(receiptPath.slice(0, -receiptSuffix.length), receipt.stagingIdentity);
|
|
670
|
+
removeIfPresent(receiptPath);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
function publishChangePlan(root, stagingRoot, changes, emptyTarget) {
|
|
397
675
|
__transactionTestHooks.beforePublish?.({
|
|
398
676
|
workspaceRoot: root,
|
|
399
677
|
stagingRoot,
|
|
400
678
|
changedPaths: changes.map((change)=>change.relativePath)
|
|
401
679
|
});
|
|
680
|
+
if (emptyTarget) assertFreshTarget(root, emptyTarget);
|
|
402
681
|
for (const change of changes)assertPreimage(root, change);
|
|
682
|
+
if (0 === changes.length) return;
|
|
403
683
|
const createdDirectories = [];
|
|
404
|
-
const preparedChanges =
|
|
684
|
+
const preparedChanges = changes.map((change)=>({
|
|
685
|
+
...change,
|
|
686
|
+
published: false,
|
|
687
|
+
...change.after ? {
|
|
688
|
+
publishPath: temporaryFilePath(root, change.relativePath, 'publish')
|
|
689
|
+
} : {},
|
|
690
|
+
...change.before ? {
|
|
691
|
+
rollbackPath: temporaryFilePath(root, change.relativePath, 'rollback')
|
|
692
|
+
} : {}
|
|
693
|
+
}));
|
|
694
|
+
const receiptPath = `${stagingRoot}${receiptSuffix}`;
|
|
695
|
+
const directories = emptyTarget ? stageFreshDirectories(stagingRoot, changes) : void 0;
|
|
696
|
+
const receipt = encodedReceipt(root, stagingRoot, preparedChanges, directories);
|
|
697
|
+
persistReceipt(receiptPath, receipt);
|
|
405
698
|
try {
|
|
406
|
-
|
|
699
|
+
for (const directory of directories ?? [])publishFreshDirectory(root, receipt, directory);
|
|
700
|
+
prepareChanges(root, preparedChanges, createdDirectories);
|
|
407
701
|
for (const change of preparedChanges)assertPreimage(root, change);
|
|
408
702
|
preparedChanges.forEach((change, index)=>{
|
|
409
703
|
__transactionTestHooks.beforePublishPath?.({
|
|
@@ -412,36 +706,67 @@ function publishChangePlan(root, stagingRoot, changes) {
|
|
|
412
706
|
index
|
|
413
707
|
});
|
|
414
708
|
publishChange(root, change);
|
|
709
|
+
__transactionTestHooks.afterPublishPath?.({
|
|
710
|
+
workspaceRoot: root,
|
|
711
|
+
relativePath: change.relativePath,
|
|
712
|
+
index
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
persistReceipt(receiptPath, {
|
|
716
|
+
...receipt,
|
|
717
|
+
state: 'committed'
|
|
415
718
|
});
|
|
416
719
|
} catch (error) {
|
|
417
720
|
try {
|
|
721
|
+
if (directories) validateFreshDirectories(root, receipt, preparedChanges);
|
|
418
722
|
rollbackPublishedChanges(root, preparedChanges);
|
|
723
|
+
if (directories) {
|
|
724
|
+
cleanupPreparedChanges(preparedChanges, []);
|
|
725
|
+
removeFreshDirectories(root, directories);
|
|
726
|
+
}
|
|
419
727
|
} catch (rollbackError) {
|
|
420
|
-
throw new WorkspaceTransactionConflictError(
|
|
421
|
-
cause:
|
|
728
|
+
throw new WorkspaceTransactionConflictError(`Workspace transaction failed and concurrent target changes prevented a safe rollback; recovery receipt ${receiptPath}.`, {
|
|
729
|
+
cause: directories ? new AggregateError([
|
|
730
|
+
error,
|
|
731
|
+
rollbackError
|
|
732
|
+
], 'Fresh publication and rollback conflicts') : rollbackError
|
|
422
733
|
});
|
|
423
|
-
} finally{
|
|
424
|
-
cleanPreparedChanges(preparedChanges, createdDirectories);
|
|
425
734
|
}
|
|
735
|
+
cleanPreparedChanges(preparedChanges, createdDirectories);
|
|
736
|
+
if (!preparedChanges.some((change)=>change.preserveRollback || change.preservedPaths?.length)) removeIfPresent(receiptPath);
|
|
426
737
|
throw error;
|
|
427
738
|
}
|
|
428
739
|
cleanPreparedChanges(preparedChanges, []);
|
|
740
|
+
removeIfPresent(receiptPath);
|
|
429
741
|
}
|
|
430
|
-
function runWorkspaceTransaction(root, mutate) {
|
|
742
|
+
function runWorkspaceTransaction(root, mutate, options = {}) {
|
|
431
743
|
const workspaceRoot = node_fs.realpathSync.native(node_path.resolve(root));
|
|
432
744
|
if (!node_fs.statSync(workspaceRoot).isDirectory()) throw new Error(`Workspace root is not a directory: ${root}`);
|
|
745
|
+
if ('preview' !== options.mode) recoverWorkspaceTransactions(workspaceRoot);
|
|
433
746
|
const stagingRoot = createTemporarySibling(workspaceRoot);
|
|
434
747
|
const stagingIdentity = node_fs.lstatSync(stagingRoot);
|
|
748
|
+
const cleanup = ()=>{
|
|
749
|
+
if (!node_fs.existsSync(`${stagingRoot}${receiptSuffix}`)) cleanOwnedTemporaryDirectory(stagingRoot, stagingIdentity);
|
|
750
|
+
};
|
|
435
751
|
try {
|
|
436
752
|
copyWorkspaceToStage(workspaceRoot, stagingRoot);
|
|
437
|
-
const before = captureWorkspace(stagingRoot);
|
|
753
|
+
const before = captureWorkspace(stagingRoot, workspaceRoot);
|
|
754
|
+
const finish = (result)=>{
|
|
755
|
+
if (options.commitWhen && !options.commitWhen(result)) return result;
|
|
756
|
+
relocateStagedWorkspaceReferences(stagingRoot, root);
|
|
757
|
+
const changes = buildChangePlan(before, captureWorkspace(stagingRoot, workspaceRoot));
|
|
758
|
+
options.inspectChanges?.(changes);
|
|
759
|
+
if ('preview' !== options.mode) publishChangePlan(workspaceRoot, stagingRoot, changes);
|
|
760
|
+
return result;
|
|
761
|
+
};
|
|
438
762
|
const result = mutate(stagingRoot);
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
return
|
|
443
|
-
}
|
|
444
|
-
|
|
763
|
+
if (null !== result && ('object' == typeof result || 'function' == typeof result) && 'function' == typeof result.then) return Promise.resolve(result).then(finish).finally(cleanup);
|
|
764
|
+
const completed = finish(result);
|
|
765
|
+
cleanup();
|
|
766
|
+
return completed;
|
|
767
|
+
} catch (error) {
|
|
768
|
+
cleanup();
|
|
769
|
+
throw error;
|
|
445
770
|
}
|
|
446
771
|
}
|
|
447
772
|
function sameIdentity(stat, identity) {
|
|
@@ -482,6 +807,7 @@ function cleanEmptyTargetRollback(rollbackPath, expected) {
|
|
|
482
807
|
function publishFreshWorkspace(stagingRoot, workspaceRoot, target) {
|
|
483
808
|
assertFreshTarget(workspaceRoot, target);
|
|
484
809
|
if ('absent' === target.kind) return void node_fs.renameSync(stagingRoot, workspaceRoot);
|
|
810
|
+
if ('win32' === process.platform && currentDirectoryIs(workspaceRoot)) return void publishChangePlan(node_fs.realpathSync.native(workspaceRoot), stagingRoot, buildChangePlan(new Map(), captureWorkspace(stagingRoot, workspaceRoot)), target);
|
|
485
811
|
const rollbackPath = node_path.join(node_path.dirname(workspaceRoot), `.${node_path.basename(workspaceRoot)}.ultramodern-empty-${randomUUID()}.tmp`);
|
|
486
812
|
const restoreCwd = currentDirectoryIs(workspaceRoot);
|
|
487
813
|
node_fs.renameSync(workspaceRoot, rollbackPath);
|
|
@@ -510,6 +836,7 @@ function publishFreshWorkspace(stagingRoot, workspaceRoot, target) {
|
|
|
510
836
|
}
|
|
511
837
|
function runFreshWorkspaceTransaction(targetDir, generate) {
|
|
512
838
|
const workspaceRoot = node_path.resolve(targetDir);
|
|
839
|
+
recoverFreshWorkspaceTransactions(workspaceRoot);
|
|
513
840
|
const target = inspectFreshTarget(workspaceRoot);
|
|
514
841
|
const stagingRoot = createTemporarySibling(workspaceRoot);
|
|
515
842
|
const stagingIdentity = node_fs.lstatSync(stagingRoot);
|
|
@@ -523,7 +850,7 @@ function runFreshWorkspaceTransaction(targetDir, generate) {
|
|
|
523
850
|
publishFreshWorkspace(stagingRoot, workspaceRoot, target);
|
|
524
851
|
return result;
|
|
525
852
|
} finally{
|
|
526
|
-
cleanOwnedTemporaryDirectory(stagingRoot, stagingIdentity);
|
|
853
|
+
if (!node_fs.existsSync(`${stagingRoot}${receiptSuffix}`)) cleanOwnedTemporaryDirectory(stagingRoot, stagingIdentity);
|
|
527
854
|
}
|
|
528
855
|
}
|
|
529
|
-
export { WorkspaceTransactionConflictError, __transactionTestHooks, relocateStagedWorkspaceReferences, runFreshWorkspaceTransaction, runWorkspaceTransaction };
|
|
856
|
+
export { WorkspaceTransactionConflictError, __transactionTestHooks, recoverFreshWorkspaceTransactions, recoverWorkspaceTransactions, relocateStagedWorkspaceReferences, runFreshWorkspaceTransaction, runWorkspaceTransaction };
|
|
@@ -1,47 +1,35 @@
|
|
|
1
1
|
import node_fs from "node:fs";
|
|
2
2
|
import node_path from "node:path";
|
|
3
|
-
import { readUltramodernConfig } from "../../ultramodern-tooling/config.js";
|
|
4
|
-
import { ULTRAMODERN_CONFIG_PATH } from "../descriptors.js";
|
|
5
3
|
import { toKebabCase } from "../naming.js";
|
|
6
4
|
import { resolvePackageSource } from "../package-source.js";
|
|
7
5
|
import { FIRST_VERTICAL_PORT } from "./constants.js";
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
targetDir: workspaceRoot,
|
|
11
|
-
packageName: node_path.basename(workspaceRoot),
|
|
12
|
-
modernVersion,
|
|
13
|
-
packageSource
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
function existingTailwindEnabled(workspaceRoot) {
|
|
23
|
-
const compactPath = node_path.join(workspaceRoot, ULTRAMODERN_CONFIG_PATH);
|
|
24
|
-
if (node_fs.existsSync(compactPath)) return readUltramodernConfig(workspaceRoot).features.tailwind;
|
|
25
|
-
throw new Error(`Missing UltraModern workspace file: ${compactPath}`);
|
|
26
|
-
}
|
|
27
|
-
function existingBridgeConfig(workspaceRoot) {
|
|
28
|
-
const compactPath = node_path.join(workspaceRoot, ULTRAMODERN_CONFIG_PATH);
|
|
29
|
-
return node_fs.existsSync(compactPath) ? readUltramodernConfig(workspaceRoot).bridge : void 0;
|
|
6
|
+
function workspaceOperationSettings(options, config) {
|
|
7
|
+
const packageSource = options.packageSource ? resolvePackageSource({
|
|
8
|
+
targetDir: options.workspaceRoot,
|
|
9
|
+
packageName: node_path.basename(options.workspaceRoot),
|
|
10
|
+
modernVersion: options.modernVersion,
|
|
11
|
+
packageSource: options.packageSource
|
|
12
|
+
}) : config.packageSource;
|
|
13
|
+
if (!packageSource) throw new Error(`Missing UltraModern package source in workspace manifests: ${options.workspaceRoot}`);
|
|
14
|
+
return {
|
|
15
|
+
packageSource,
|
|
16
|
+
enableTailwind: options.enableTailwind ?? config.features.tailwind,
|
|
17
|
+
bridge: void 0
|
|
18
|
+
};
|
|
30
19
|
}
|
|
31
20
|
function assertValidVerticalName(name) {
|
|
32
21
|
const normalized = toKebabCase(name);
|
|
33
22
|
if (!normalized || normalized !== name) throw new Error(`Invalid Vertical name "${name}". Use lowercase kebab-case.`);
|
|
34
23
|
return normalized;
|
|
35
24
|
}
|
|
36
|
-
function configuredDevelopmentPorts(ports,
|
|
25
|
+
function configuredDevelopmentPorts(ports, _additionalShells = []) {
|
|
37
26
|
return [
|
|
38
27
|
...new Set([
|
|
39
|
-
...Object.values(ports)
|
|
40
|
-
...additionalShells.map((shell)=>shell.port)
|
|
28
|
+
...Object.values(ports)
|
|
41
29
|
].filter((value)=>'number' == typeof value && Number.isFinite(value)))
|
|
42
30
|
];
|
|
43
31
|
}
|
|
44
|
-
function assertGlobalPortUniqueness(ports,
|
|
32
|
+
function assertGlobalPortUniqueness(ports, _additionalShells = []) {
|
|
45
33
|
const owners = new Map();
|
|
46
34
|
for (const [id, value] of Object.entries(ports)){
|
|
47
35
|
if ('number' != typeof value || !Number.isFinite(value)) continue;
|
|
@@ -49,11 +37,6 @@ function assertGlobalPortUniqueness(ports, additionalShells = []) {
|
|
|
49
37
|
if (previous) throw new Error(`Duplicate development port "${value}" for ${previous} and ${id}.`);
|
|
50
38
|
owners.set(value, id);
|
|
51
39
|
}
|
|
52
|
-
for (const shell of additionalShells){
|
|
53
|
-
const previous = owners.get(shell.port);
|
|
54
|
-
if (previous) throw new Error(`Duplicate development port "${shell.port}" for ${previous} and ${shell.id}.`);
|
|
55
|
-
owners.set(shell.port, shell.id);
|
|
56
|
-
}
|
|
57
40
|
}
|
|
58
41
|
function nextAvailablePort(ports, additionalShells = [], minimumPort = FIRST_VERTICAL_PORT) {
|
|
59
42
|
const used = new Set(configuredDevelopmentPorts(ports, additionalShells));
|
|
@@ -64,4 +47,4 @@ function nextAvailablePort(ports, additionalShells = [], minimumPort = FIRST_VER
|
|
|
64
47
|
function assertCanCreate(workspaceRoot, relativePath) {
|
|
65
48
|
if (node_fs.existsSync(node_path.join(workspaceRoot, relativePath))) throw new Error(`Refusing to overwrite existing path: ${relativePath}`);
|
|
66
49
|
}
|
|
67
|
-
export { assertCanCreate, assertGlobalPortUniqueness, assertValidVerticalName, configuredDevelopmentPorts,
|
|
50
|
+
export { assertCanCreate, assertGlobalPortUniqueness, assertValidVerticalName, configuredDevelopmentPorts, nextAvailablePort, workspaceOperationSettings };
|
|
@@ -3,4 +3,4 @@ export { planUltramodernVertical } from "./add-vertical/plan.js";
|
|
|
3
3
|
export { prepareAddUltramodernVertical } from "./add-vertical/preflight.js";
|
|
4
4
|
export { rewriteShellAppFiles, updateRootWorkspaceScripts } from "./add-vertical/shell-files.js";
|
|
5
5
|
export { ownershipEntry, verticalTopologyEntry, verticalsFromTopology } from "./add-vertical/topology.js";
|
|
6
|
-
export { assertCanCreate, assertValidVerticalName,
|
|
6
|
+
export { assertCanCreate, assertValidVerticalName, nextAvailablePort } from "./add-vertical/workspace-state.js";
|