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