opkg 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -186
- package/assets/openpackage_ascii_dark.png +0 -0
- package/assets/openpackage_ascii_light.png +0 -0
- package/dist/commands/add.js +34 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/apply.js +16 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/delete.js +1 -1
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/install.js +177 -8
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/list.js +2 -2
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/new.js +125 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/pack.js +7 -13
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/pull.js +1 -1
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.js +1 -1
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/remove.js +63 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/save.js +11 -17
- package/dist/commands/save.js.map +1 -1
- package/dist/commands/set.js +33 -0
- package/dist/commands/set.js.map +1 -0
- package/dist/commands/show.js +16 -94
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/status.js +26 -701
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/uninstall.js +14 -427
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/constants/index.js +72 -16
- package/dist/constants/index.js.map +1 -1
- package/dist/core/add/add-conflict-handler.js +1 -8
- package/dist/core/add/add-conflict-handler.js.map +1 -1
- package/dist/core/add/add-pipeline.js +12 -10
- package/dist/core/add/add-pipeline.js.map +1 -1
- package/dist/core/add/add-to-source-pipeline.js +123 -0
- package/dist/core/add/add-to-source-pipeline.js.map +1 -0
- package/dist/core/add/package-index-updater.js +77 -78
- package/dist/core/add/package-index-updater.js.map +1 -1
- package/dist/core/add/platform-path-transformer.js +6 -4
- package/dist/core/add/platform-path-transformer.js.map +1 -1
- package/dist/core/add/source-collector.js +2 -3
- package/dist/core/add/source-collector.js.map +1 -1
- package/dist/core/apply/apply-pipeline.js +110 -0
- package/dist/core/apply/apply-pipeline.js.map +1 -0
- package/dist/core/dependency-resolver.js +263 -21
- package/dist/core/dependency-resolver.js.map +1 -1
- package/dist/core/discovery/file-discovery.js +1 -2
- package/dist/core/discovery/file-discovery.js.map +1 -1
- package/dist/core/discovery/platform-files-discovery.js +33 -18
- package/dist/core/discovery/platform-files-discovery.js.map +1 -1
- package/dist/core/flows/flow-executor.js +974 -0
- package/dist/core/flows/flow-executor.js.map +1 -0
- package/dist/core/flows/flow-inverter.js +442 -0
- package/dist/core/flows/flow-inverter.js.map +1 -0
- package/dist/core/flows/flow-key-extractor.js +101 -0
- package/dist/core/flows/flow-key-extractor.js.map +1 -0
- package/dist/core/flows/flow-key-mapper.js +382 -0
- package/dist/core/flows/flow-key-mapper.js.map +1 -0
- package/dist/core/flows/flow-transforms.js +632 -0
- package/dist/core/flows/flow-transforms.js.map +1 -0
- package/dist/core/flows/map-pipeline/context.js +73 -0
- package/dist/core/flows/map-pipeline/context.js.map +1 -0
- package/dist/core/flows/map-pipeline/index.js +156 -0
- package/dist/core/flows/map-pipeline/index.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/copy.js +104 -0
- package/dist/core/flows/map-pipeline/operations/copy.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/pipe.js +70 -0
- package/dist/core/flows/map-pipeline/operations/pipe.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/rename.js +102 -0
- package/dist/core/flows/map-pipeline/operations/rename.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/set.js +50 -0
- package/dist/core/flows/map-pipeline/operations/set.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/switch.js +79 -0
- package/dist/core/flows/map-pipeline/operations/switch.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/transform.js +543 -0
- package/dist/core/flows/map-pipeline/operations/transform.js.map +1 -0
- package/dist/core/flows/map-pipeline/operations/unset.js +65 -0
- package/dist/core/flows/map-pipeline/operations/unset.js.map +1 -0
- package/dist/core/flows/map-pipeline/types.js +8 -0
- package/dist/core/flows/map-pipeline/types.js.map +1 -0
- package/dist/core/flows/map-pipeline/utils.js +278 -0
- package/dist/core/flows/map-pipeline/utils.js.map +1 -0
- package/dist/core/flows/platform-converter.js +328 -0
- package/dist/core/flows/platform-converter.js.map +1 -0
- package/dist/core/flows/source-resolver.js +192 -0
- package/dist/core/flows/source-resolver.js.map +1 -0
- package/dist/core/flows/toml-domain-transforms.js +23 -0
- package/dist/core/flows/toml-domain-transforms.js.map +1 -0
- package/dist/core/install/bulk-install-pipeline.js +68 -7
- package/dist/core/install/bulk-install-pipeline.js.map +1 -1
- package/dist/core/install/canonical-plan.js +3 -3
- package/dist/core/install/canonical-plan.js.map +1 -1
- package/dist/core/install/dry-run.js +3 -3
- package/dist/core/install/dry-run.js.map +1 -1
- package/dist/core/install/flow-based-installer.js +1158 -0
- package/dist/core/install/flow-based-installer.js.map +1 -0
- package/dist/core/install/flow-workspace-tracker.js +111 -0
- package/dist/core/install/flow-workspace-tracker.js.map +1 -0
- package/dist/core/install/format-detector.js +228 -0
- package/dist/core/install/format-detector.js.map +1 -0
- package/dist/core/install/git-package-loader.js +20 -0
- package/dist/core/install/git-package-loader.js.map +1 -0
- package/dist/core/install/install-errors.js +1 -1
- package/dist/core/install/install-errors.js.map +1 -1
- package/dist/core/install/install-flow.js +34 -14
- package/dist/core/install/install-flow.js.map +1 -1
- package/dist/core/install/install-pipeline.js +52 -17
- package/dist/core/install/install-pipeline.js.map +1 -1
- package/dist/core/install/install-reporting.js +26 -8
- package/dist/core/install/install-reporting.js.map +1 -1
- package/dist/core/install/local-source-resolution.js +103 -0
- package/dist/core/install/local-source-resolution.js.map +1 -0
- package/dist/core/install/marketplace-handler.js +221 -0
- package/dist/core/install/marketplace-handler.js.map +1 -0
- package/dist/core/install/path-install-pipeline.js +241 -0
- package/dist/core/install/path-install-pipeline.js.map +1 -0
- package/dist/core/install/path-package-loader.js +116 -0
- package/dist/core/install/path-package-loader.js.map +1 -0
- package/dist/core/install/plugin-detector.js +72 -0
- package/dist/core/install/plugin-detector.js.map +1 -0
- package/dist/core/install/plugin-to-universal-converter.js +218 -0
- package/dist/core/install/plugin-to-universal-converter.js.map +1 -0
- package/dist/core/install/plugin-transformer.js +191 -0
- package/dist/core/install/plugin-transformer.js.map +1 -0
- package/dist/core/install/version-selection.js +1 -1
- package/dist/core/install/version-selection.js.map +1 -1
- package/dist/core/openpackage.js +40 -22
- package/dist/core/openpackage.js.map +1 -1
- package/dist/core/pack/pack-output.js +62 -0
- package/dist/core/pack/pack-output.js.map +1 -0
- package/dist/core/pack/pack-pipeline.js +186 -0
- package/dist/core/pack/pack-pipeline.js.map +1 -0
- package/dist/core/package-context.js +45 -70
- package/dist/core/package-context.js.map +1 -1
- package/dist/core/package-creation.js +203 -0
- package/dist/core/package-creation.js.map +1 -0
- package/dist/core/package.js +20 -6
- package/dist/core/package.js.map +1 -1
- package/dist/core/platforms.js +665 -209
- package/dist/core/platforms.js.map +1 -1
- package/dist/core/push/push-context.js +1 -1
- package/dist/core/push/push-context.js.map +1 -1
- package/dist/core/push/push-upload.js +2 -2
- package/dist/core/push/push-upload.js.map +1 -1
- package/dist/core/registry.js +6 -6
- package/dist/core/registry.js.map +1 -1
- package/dist/core/remote-pull.js +2 -2
- package/dist/core/remote-pull.js.map +1 -1
- package/dist/core/remove/removal-collector.js +52 -0
- package/dist/core/remove/removal-collector.js.map +1 -0
- package/dist/core/remove/removal-confirmation.js +39 -0
- package/dist/core/remove/removal-confirmation.js.map +1 -0
- package/dist/core/remove/remove-from-source-pipeline.js +173 -0
- package/dist/core/remove/remove-from-source-pipeline.js.map +1 -0
- package/dist/core/save/constants.js +3 -3
- package/dist/core/save/constants.js.map +1 -1
- package/dist/core/save/flow-based-saver.js +270 -0
- package/dist/core/save/flow-based-saver.js.map +1 -0
- package/dist/core/save/name-resolution.js +1 -1
- package/dist/core/save/name-resolution.js.map +1 -1
- package/dist/core/save/package-yml-generator.js +4 -5
- package/dist/core/save/package-yml-generator.js.map +1 -1
- package/dist/core/save/save-candidate-builder.js +215 -0
- package/dist/core/save/save-candidate-builder.js.map +1 -0
- package/dist/core/save/save-candidate-loader.js +12 -11
- package/dist/core/save/save-candidate-loader.js.map +1 -1
- package/dist/core/save/save-conflict-analyzer.js +150 -0
- package/dist/core/save/save-conflict-analyzer.js.map +1 -0
- package/dist/core/save/save-conflict-resolution.js +28 -14
- package/dist/core/save/save-conflict-resolution.js.map +1 -1
- package/dist/core/save/save-conflict-resolver.js +31 -275
- package/dist/core/save/save-conflict-resolver.js.map +1 -1
- package/dist/core/save/save-group-builder.js +52 -0
- package/dist/core/save/save-group-builder.js.map +1 -0
- package/dist/core/save/save-interactive-resolver.js +190 -0
- package/dist/core/save/save-interactive-resolver.js.map +1 -0
- package/dist/core/save/save-pipeline.js +58 -34
- package/dist/core/save/save-pipeline.js.map +1 -1
- package/dist/core/save/save-platform-handler.js +53 -0
- package/dist/core/save/save-platform-handler.js.map +1 -0
- package/dist/core/save/save-resolution-executor.js +145 -0
- package/dist/core/save/save-resolution-executor.js.map +1 -0
- package/dist/core/save/save-result-reporter.js +167 -0
- package/dist/core/save/save-result-reporter.js.map +1 -0
- package/dist/core/save/save-to-source-pipeline.js +154 -0
- package/dist/core/save/save-to-source-pipeline.js.map +1 -0
- package/dist/core/save/save-versioning.js +4 -4
- package/dist/core/save/save-versioning.js.map +1 -1
- package/dist/core/save/save-write-coordinator.js +204 -0
- package/dist/core/save/save-write-coordinator.js.map +1 -0
- package/dist/core/save/save-yml-resolution.js +28 -216
- package/dist/core/save/save-yml-resolution.js.map +1 -1
- package/dist/core/save/workspace-rename.js +7 -8
- package/dist/core/save/workspace-rename.js.map +1 -1
- package/dist/core/set/set-output.js +72 -0
- package/dist/core/set/set-output.js.map +1 -0
- package/dist/core/set/set-pipeline.js +361 -0
- package/dist/core/set/set-pipeline.js.map +1 -0
- package/dist/core/set/set-types.js +5 -0
- package/dist/core/set/set-types.js.map +1 -0
- package/dist/core/show/package-resolver.js +257 -0
- package/dist/core/show/package-resolver.js.map +1 -0
- package/dist/core/show/scope-discovery.js +165 -0
- package/dist/core/show/scope-discovery.js.map +1 -0
- package/dist/core/show/show-output.js +168 -0
- package/dist/core/show/show-output.js.map +1 -0
- package/dist/core/show/show-pipeline.js +113 -0
- package/dist/core/show/show-pipeline.js.map +1 -0
- package/dist/core/show/show-types.js +5 -0
- package/dist/core/show/show-types.js.map +1 -0
- package/dist/core/source-resolution/dependency-graph.js +104 -0
- package/dist/core/source-resolution/dependency-graph.js.map +1 -0
- package/dist/core/source-resolution/resolve-mutable-source.js +109 -0
- package/dist/core/source-resolution/resolve-mutable-source.js.map +1 -0
- package/dist/core/source-resolution/resolve-package-source.js +29 -0
- package/dist/core/source-resolution/resolve-package-source.js.map +1 -0
- package/dist/core/source-resolution/resolve-registry-version.js +35 -0
- package/dist/core/source-resolution/resolve-registry-version.js.map +1 -0
- package/dist/core/source-resolution/types.js.map +1 -0
- package/dist/core/status/status-file-discovery.js +23 -12
- package/dist/core/status/status-file-discovery.js.map +1 -1
- package/dist/core/status/status-pipeline.js +134 -0
- package/dist/core/status/status-pipeline.js.map +1 -0
- package/dist/core/sync/platform-sync-summary.js +27 -0
- package/dist/core/sync/platform-sync-summary.js.map +1 -0
- package/dist/core/uninstall/flow-aware-uninstaller.js +189 -0
- package/dist/core/uninstall/flow-aware-uninstaller.js.map +1 -0
- package/dist/core/uninstall/uninstall-file-discovery.js +11 -6
- package/dist/core/uninstall/uninstall-file-discovery.js.map +1 -1
- package/dist/core/uninstall/uninstall-pipeline.js +141 -0
- package/dist/core/uninstall/uninstall-pipeline.js.map +1 -0
- package/dist/core/universal-patterns.js +64 -0
- package/dist/core/universal-patterns.js.map +1 -0
- package/dist/index.js +99 -6
- package/dist/index.js.map +1 -1
- package/dist/types/flows.js +8 -0
- package/dist/types/flows.js.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/platform-flows.js +8 -0
- package/dist/types/platform-flows.js.map +1 -0
- package/dist/types/workspace-index.js +6 -0
- package/dist/types/workspace-index.js.map +1 -0
- package/dist/utils/custom-path-resolution.js +160 -0
- package/dist/utils/custom-path-resolution.js.map +1 -0
- package/dist/utils/dependency-coverage.js +1 -1
- package/dist/utils/dependency-coverage.js.map +1 -1
- package/dist/utils/file-processing.js +1 -1
- package/dist/utils/flow-index-installer.js +209 -0
- package/dist/utils/flow-index-installer.js.map +1 -0
- package/dist/utils/formatters.js +47 -1
- package/dist/utils/formatters.js.map +1 -1
- package/dist/utils/fs.js +17 -0
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/git-clone-registry.js +88 -0
- package/dist/utils/git-clone-registry.js.map +1 -0
- package/dist/utils/git-clone.js +69 -0
- package/dist/utils/git-clone.js.map +1 -0
- package/dist/utils/git-spec.js +96 -0
- package/dist/utils/git-spec.js.map +1 -0
- package/dist/utils/http-client.js +7 -0
- package/dist/utils/http-client.js.map +1 -1
- package/dist/utils/index-based-installer.js +356 -163
- package/dist/utils/index-based-installer.js.map +1 -1
- package/dist/utils/install-conflict-handler.js +2 -2
- package/dist/utils/install-conflict-handler.js.map +1 -1
- package/dist/utils/install-file-discovery.js +18 -13
- package/dist/utils/install-file-discovery.js.map +1 -1
- package/dist/utils/install-helpers.js +43 -20
- package/dist/utils/install-helpers.js.map +1 -1
- package/dist/utils/jsonc.js +23 -1
- package/dist/utils/jsonc.js.map +1 -1
- package/dist/utils/manifest-paths.js +1 -1
- package/dist/utils/manifest-paths.js.map +1 -1
- package/dist/utils/markdown-frontmatter.js +46 -0
- package/dist/utils/markdown-frontmatter.js.map +1 -1
- package/dist/utils/package-copy.js +5 -103
- package/dist/utils/package-copy.js.map +1 -1
- package/dist/utils/package-filters.js +9 -105
- package/dist/utils/package-filters.js.map +1 -1
- package/dist/utils/package-index-yml.js +27 -6
- package/dist/utils/package-index-yml.js.map +1 -1
- package/dist/utils/package-input.js +98 -0
- package/dist/utils/package-input.js.map +1 -0
- package/dist/utils/package-management.js +80 -28
- package/dist/utils/package-management.js.map +1 -1
- package/dist/utils/package-name-resolution.js +327 -0
- package/dist/utils/package-name-resolution.js.map +1 -0
- package/dist/utils/package-name.js +18 -16
- package/dist/utils/package-name.js.map +1 -1
- package/dist/utils/package-versioning.js +2 -33
- package/dist/utils/package-versioning.js.map +1 -1
- package/dist/utils/package-yml.js +19 -28
- package/dist/utils/package-yml.js.map +1 -1
- package/dist/utils/path-resolution.js +102 -0
- package/dist/utils/path-resolution.js.map +1 -0
- package/dist/utils/paths.js +6 -6
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/platform-file.js +36 -24
- package/dist/utils/platform-file.js.map +1 -1
- package/dist/utils/platform-mapper.js +222 -68
- package/dist/utils/platform-mapper.js.map +1 -1
- package/dist/utils/platform-root-files.js +44 -0
- package/dist/utils/platform-root-files.js.map +1 -0
- package/dist/utils/platform-utils.js +35 -54
- package/dist/utils/platform-utils.js.map +1 -1
- package/dist/utils/platform-yaml-merge.js +20 -140
- package/dist/utils/platform-yaml-merge.js.map +1 -1
- package/dist/utils/prompts.js +92 -7
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/registry-entry-filter.js +50 -27
- package/dist/utils/registry-entry-filter.js.map +1 -1
- package/dist/utils/registry-paths.js +5 -4
- package/dist/utils/registry-paths.js.map +1 -1
- package/dist/utils/scope-resolution.js +156 -0
- package/dist/utils/scope-resolution.js.map +1 -0
- package/dist/utils/source-mutability.js +15 -0
- package/dist/utils/source-mutability.js.map +1 -0
- package/dist/utils/tarball.js +29 -4
- package/dist/utils/tarball.js.map +1 -1
- package/dist/utils/version-ranges.js +1 -32
- package/dist/utils/version-ranges.js.map +1 -1
- package/dist/utils/workspace-index-helpers.js +28 -0
- package/dist/utils/workspace-index-helpers.js.map +1 -0
- package/dist/utils/workspace-index-ownership.js +100 -0
- package/dist/utils/workspace-index-ownership.js.map +1 -0
- package/dist/utils/workspace-index-yml.js +173 -0
- package/dist/utils/workspace-index-yml.js.map +1 -0
- package/examples/custom-subdirs-platform.jsonc +157 -0
- package/package.json +7 -2
- package/platforms.jsonc +531 -84
- package/schemas/map-pipeline-v1.json +256 -0
- package/schemas/platforms-v1.json +400 -0
- package/specs/README.md +88 -0
- package/specs/add/README.md +166 -0
- package/specs/agents-claude.md +570 -0
- package/specs/agents-opencode.md +622 -0
- package/specs/apply/README.md +21 -0
- package/specs/apply/apply-behavior.md +58 -0
- package/specs/apply/apply-command.md +51 -0
- package/specs/apply/conflicts.md +41 -0
- package/specs/apply/index-effects.md +81 -0
- package/specs/architecture.md +107 -0
- package/specs/auth/README.md +17 -0
- package/specs/auth/auth-http-contract.md +25 -0
- package/specs/auth/cli/credentials.md +39 -0
- package/specs/auth/cli/login.md +32 -0
- package/specs/auth/cli/logout.md +16 -0
- package/specs/claude-mcp.md +1065 -0
- package/specs/claude-plugins-marketplace.md +363 -0
- package/specs/claude-plugins.md +413 -0
- package/specs/cli-options.md +52 -0
- package/specs/codex-mcp.md +114 -0
- package/specs/commands-overview.md +175 -0
- package/specs/directory-layout.md +95 -0
- package/specs/install/README.md +12 -4
- package/specs/install/git-sources.md +230 -0
- package/specs/install/install-behavior.md +483 -73
- package/specs/install/package-yml-canonical.md +67 -35
- package/specs/install/version-resolution.md +69 -115
- package/specs/new/README.md +769 -0
- package/specs/new/SUMMARY.md +310 -0
- package/specs/new/scope-behavior.md +793 -0
- package/specs/pack/README.md +77 -0
- package/specs/pack/package-name-resolution.md +330 -0
- package/specs/package/README.md +18 -17
- package/specs/package/nested-packages-and-parent-packages.md +32 -31
- package/specs/package/package-index-yml.md +95 -101
- package/specs/package/package-root-layout.md +64 -46
- package/specs/package/registry-payload-and-copy.md +50 -44
- package/specs/package/universal-content.md +33 -56
- package/specs/package-sources.md +248 -0
- package/specs/platforms/README.md +52 -0
- package/specs/platforms/configuration.md +571 -0
- package/specs/platforms/detection.md +552 -0
- package/specs/platforms/directory-layout.md +599 -0
- package/specs/platforms/examples.md +1146 -0
- package/specs/platforms/flow-reference.md +1240 -0
- package/specs/platforms/flows.md +1488 -0
- package/specs/platforms/map-pipeline.md +801 -0
- package/specs/platforms/overview.md +349 -0
- package/specs/platforms/specification.md +700 -0
- package/specs/platforms/troubleshooting.md +697 -0
- package/specs/platforms/universal-converter.md +520 -0
- package/specs/push/README.md +1 -0
- package/specs/push/push-behavior.md +11 -3
- package/specs/push/push-remote-upload.md +1 -1
- package/specs/push/push-scoping.md +1 -1
- package/specs/push/push-version-selection.md +1 -1
- package/specs/registry.md +111 -0
- package/specs/remove/README.md +257 -0
- package/specs/save/README.md +21 -17
- package/specs/save/save-conflict-resolution.md +205 -83
- package/specs/save/save-file-discovery.md +6 -4
- package/specs/save/save-frontmatter-overrides.md +11 -15
- package/specs/save/save-modes-inputs.md +9 -39
- package/specs/save/save-naming-scoping.md +4 -4
- package/specs/save/save-package-detection.md +13 -13
- package/specs/save/save-registry-sync.md +16 -106
- package/specs/save/save-versioning.md +80 -0
- package/specs/scope-management.md +92 -0
- package/specs/set/README.md +520 -0
- package/specs/set/set-behavior.md +563 -0
- package/specs/show/README.md +483 -0
- package/specs/show/show-remote.md +494 -0
- package/specs/status/README.md +38 -0
- package/specs/uninstall/README.md +231 -0
- package/dist/commands/duplicate.js +0 -69
- package/dist/commands/duplicate.js.map +0 -1
- package/dist/commands/init.js +0 -117
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/prune.js +0 -357
- package/dist/commands/prune.js.map +0 -1
- package/dist/commands/tui.js +0 -61
- package/dist/commands/tui.js.map +0 -1
- package/dist/core/install/index.js +0 -3
- package/dist/core/install/index.js.map +0 -1
- package/dist/core/push/push-single-file.js +0 -56
- package/dist/core/push/push-single-file.js.map +0 -1
- package/dist/core/save/package-detection.js +0 -147
- package/dist/core/save/package-detection.js.map +0 -1
- package/dist/core/save/save-single-file.js +0 -124
- package/dist/core/save/save-single-file.js.map +0 -1
- package/dist/core/token-store.js +0 -73
- package/dist/core/token-store.js.map +0 -1
- package/dist/tui/app.js +0 -95
- package/dist/tui/app.js.map +0 -1
- package/dist/tui/components/package-list.js +0 -73
- package/dist/tui/components/package-list.js.map +0 -1
- package/dist/tui/controller.js +0 -365
- package/dist/tui/controller.js.map +0 -1
- package/dist/tui/index.js +0 -12
- package/dist/tui/index.js.map +0 -1
- package/dist/tui/services/file-index.js +0 -64
- package/dist/tui/services/file-index.js.map +0 -1
- package/dist/tui/services/packages.js +0 -18
- package/dist/tui/services/packages.js.map +0 -1
- package/dist/tui/services/save.js +0 -21
- package/dist/tui/services/save.js.map +0 -1
- package/dist/tui/state/app-state.js +0 -15
- package/dist/tui/state/app-state.js.map +0 -1
- package/dist/tui/state.js +0 -17
- package/dist/tui/state.js.map +0 -1
- package/dist/tui/types.js.map +0 -1
- package/dist/tui/views/add-file-modal.js +0 -129
- package/dist/tui/views/add-file-modal.js.map +0 -1
- package/dist/tui/views/file-preview.js +0 -44
- package/dist/tui/views/file-preview.js.map +0 -1
- package/dist/tui/views/list-packages.js +0 -73
- package/dist/tui/views/list-packages.js.map +0 -1
- package/dist/tui/views/main-menu.js +0 -29
- package/dist/tui/views/main-menu.js.map +0 -1
- package/dist/tui/views/manage-view.js +0 -81
- package/dist/tui/views/manage-view.js.map +0 -1
- package/dist/tui/views/package-hub.js +0 -120
- package/dist/tui/views/package-hub.js.map +0 -1
- package/dist/tui/views/placeholder.js +0 -24
- package/dist/tui/views/placeholder.js.map +0 -1
- package/dist/utils/bun-bootstrap.js +0 -72
- package/dist/utils/bun-bootstrap.js.map +0 -1
- package/dist/utils/entity-id.js +0 -19
- package/dist/utils/entity-id.js.map +0 -1
- package/dist/utils/package-local-files.js +0 -5
- package/dist/utils/package-local-files.js.map +0 -1
- package/dist/utils/path-matching.js +0 -74
- package/dist/utils/path-matching.js.map +0 -1
- package/dist/utils/root-file-operations.js +0 -39
- package/dist/utils/root-file-operations.js.map +0 -1
- package/dist/utils/root-file-transformer.js +0 -27
- package/dist/utils/root-file-transformer.js.map +0 -1
- package/dist/utils/yaml-frontmatter.js +0 -25
- package/dist/utils/yaml-frontmatter.js.map +0 -1
- package/specs/auth/auth-device-flow.md +0 -70
- package/specs/login/login-device-flow.md +0 -70
- package/specs/platforms.md +0 -193
- package/specs/save-pack-versioning.md +0 -224
- package/specs/save-pack.md +0 -68
- /package/dist/{tui → core/source-resolution}/types.js +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core responsibility: Build candidate groups from local and workspace candidates
|
|
3
|
+
* Input: Local and workspace candidates
|
|
4
|
+
* Output: Groups organized by registry path
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build candidate groups from local and workspace candidates
|
|
8
|
+
*
|
|
9
|
+
* Groups candidates by registry path, associating:
|
|
10
|
+
* - One optional local (source) candidate
|
|
11
|
+
* - Zero or more workspace candidates
|
|
12
|
+
*/
|
|
13
|
+
export function buildCandidateGroups(localCandidates, workspaceCandidates) {
|
|
14
|
+
const map = new Map();
|
|
15
|
+
// Add local candidates
|
|
16
|
+
for (const candidate of localCandidates) {
|
|
17
|
+
const group = ensureGroup(map, candidate.registryPath);
|
|
18
|
+
group.local = candidate;
|
|
19
|
+
}
|
|
20
|
+
// Add workspace candidates
|
|
21
|
+
for (const candidate of workspaceCandidates) {
|
|
22
|
+
const group = ensureGroup(map, candidate.registryPath);
|
|
23
|
+
group.workspace.push(candidate);
|
|
24
|
+
}
|
|
25
|
+
return Array.from(map.values());
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Filter groups to only those with workspace candidates
|
|
29
|
+
*
|
|
30
|
+
* Since save is workspace → source, we only care about groups
|
|
31
|
+
* that have workspace candidates to save.
|
|
32
|
+
*/
|
|
33
|
+
export function filterGroupsWithWorkspace(groups) {
|
|
34
|
+
return groups.filter(group => group.workspace.length > 0);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Ensure a group exists for the given registry path
|
|
38
|
+
*
|
|
39
|
+
* Helper function to get or create a group in the map.
|
|
40
|
+
*/
|
|
41
|
+
function ensureGroup(map, registryPath) {
|
|
42
|
+
let group = map.get(registryPath);
|
|
43
|
+
if (!group) {
|
|
44
|
+
group = {
|
|
45
|
+
registryPath,
|
|
46
|
+
workspace: []
|
|
47
|
+
};
|
|
48
|
+
map.set(registryPath, group);
|
|
49
|
+
}
|
|
50
|
+
return group;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=save-group-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-group-builder.js","sourceRoot":"","sources":["../../../src/core/save/save-group-builder.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,eAAgC,EAChC,mBAAoC;IAEpC,MAAM,GAAG,GAAG,IAAI,GAAG,EAA8B,CAAC;IAElD,uBAAuB;IACvB,KAAK,MAAM,SAAS,IAAI,eAAe,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QACvD,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IAC1B,CAAC;IAED,2BAA2B;IAC3B,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QACvD,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA4B;IAE5B,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAClB,GAAoC,EACpC,YAAoB;IAEpB,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG;YACN,YAAY;YACZ,SAAS,EAAE,EAAE;SACd,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { safePrompts } from '../../utils/prompts.js';
|
|
3
|
+
import { sortCandidatesByMtime } from './save-conflict-analyzer.js';
|
|
4
|
+
import { logger } from '../../utils/logger.js';
|
|
5
|
+
import { exists, readTextFile } from '../../utils/fs.js';
|
|
6
|
+
import { calculateFileHash } from '../../utils/hash-utils.js';
|
|
7
|
+
import { createPlatformSpecificRegistryPath } from '../../utils/platform-specific-paths.js';
|
|
8
|
+
/**
|
|
9
|
+
* Run interactive resolution flow
|
|
10
|
+
*
|
|
11
|
+
* Enhanced with parity checking to skip files that already match source.
|
|
12
|
+
*/
|
|
13
|
+
export async function resolveInteractively(input) {
|
|
14
|
+
const { registryPath, workspaceCandidates, group, packageRoot } = input;
|
|
15
|
+
// Sort by mtime descending (newest first), with alphabetical tie-breaker
|
|
16
|
+
const sortedCandidates = sortCandidatesByMtime(workspaceCandidates);
|
|
17
|
+
// Display header
|
|
18
|
+
displayConflictHeader(registryPath, sortedCandidates);
|
|
19
|
+
// Track selections
|
|
20
|
+
let universalSelected = null;
|
|
21
|
+
const platformSpecificCandidates = [];
|
|
22
|
+
const skippedCandidates = [];
|
|
23
|
+
// Iterate through each candidate
|
|
24
|
+
for (const candidate of sortedCandidates) {
|
|
25
|
+
// Check if candidate is already at parity with source
|
|
26
|
+
const parityCheck = await isAtParity(candidate, group, packageRoot);
|
|
27
|
+
if (parityCheck.atParity) {
|
|
28
|
+
console.log(`\n ✓ ${candidate.displayPath}`);
|
|
29
|
+
console.log(` ${parityCheck.reason} - auto-skipping\n`);
|
|
30
|
+
skippedCandidates.push(candidate);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// If universal already selected, check if this candidate is identical
|
|
34
|
+
if (universalSelected && candidate.contentHash === universalSelected.contentHash) {
|
|
35
|
+
console.log(`\n ✓ ${candidate.displayPath}`);
|
|
36
|
+
console.log(` Identical to universal - auto-skipping\n`);
|
|
37
|
+
skippedCandidates.push(candidate);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
// Prompt for action
|
|
41
|
+
const action = await promptCandidateAction(candidate, registryPath, universalSelected !== null);
|
|
42
|
+
// Handle action
|
|
43
|
+
switch (action) {
|
|
44
|
+
case 'universal':
|
|
45
|
+
universalSelected = candidate;
|
|
46
|
+
console.log(`\n ✓ Selected as universal: ${candidate.displayPath}\n`);
|
|
47
|
+
break;
|
|
48
|
+
case 'platform-specific':
|
|
49
|
+
platformSpecificCandidates.push(candidate);
|
|
50
|
+
console.log(`\n ✓ Marked as platform-specific: ${candidate.displayPath}\n`);
|
|
51
|
+
break;
|
|
52
|
+
case 'skip':
|
|
53
|
+
skippedCandidates.push(candidate);
|
|
54
|
+
console.log(`\n ✓ Skipped: ${candidate.displayPath}\n`);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Display summary
|
|
59
|
+
displayResolutionSummary(universalSelected, platformSpecificCandidates, skippedCandidates);
|
|
60
|
+
return {
|
|
61
|
+
selectedCandidate: universalSelected,
|
|
62
|
+
platformSpecificCandidates
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if candidate is already at parity with source
|
|
67
|
+
*
|
|
68
|
+
* A candidate is at parity if it matches either:
|
|
69
|
+
* 1. The universal source file (same content hash)
|
|
70
|
+
* 2. Its corresponding platform-specific source file (if exists)
|
|
71
|
+
*
|
|
72
|
+
* Returns true if no action is needed for this candidate.
|
|
73
|
+
*/
|
|
74
|
+
async function isAtParity(candidate, group, packageRoot) {
|
|
75
|
+
// Check universal parity
|
|
76
|
+
if (group.local && candidate.contentHash === group.local.contentHash) {
|
|
77
|
+
return {
|
|
78
|
+
atParity: true,
|
|
79
|
+
reason: 'Already matches universal'
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Check platform-specific parity (if candidate has platform)
|
|
83
|
+
if (candidate.platform && candidate.platform !== 'ai') {
|
|
84
|
+
const platformPath = createPlatformSpecificRegistryPath(group.registryPath, candidate.platform);
|
|
85
|
+
if (platformPath) {
|
|
86
|
+
const platformFullPath = join(packageRoot, platformPath);
|
|
87
|
+
// Check if platform-specific file exists
|
|
88
|
+
if (await exists(platformFullPath)) {
|
|
89
|
+
try {
|
|
90
|
+
const platformContent = await readTextFile(platformFullPath);
|
|
91
|
+
const platformHash = await calculateFileHash(platformContent);
|
|
92
|
+
if (candidate.contentHash === platformHash) {
|
|
93
|
+
return {
|
|
94
|
+
atParity: true,
|
|
95
|
+
reason: 'Already matches platform-specific file'
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// If we can't read the platform file, treat as not at parity
|
|
101
|
+
// This is safer - user will be prompted
|
|
102
|
+
logger.debug(`Could not read platform file ${platformFullPath}: ${error}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { atParity: false };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Prompt for action on a single candidate
|
|
111
|
+
*
|
|
112
|
+
* Shows different options based on whether universal is already selected:
|
|
113
|
+
* - Before universal: [Set as universal] [Mark as platform-specific] [Skip]
|
|
114
|
+
* - After universal: [Mark as platform-specific] [Skip]
|
|
115
|
+
*/
|
|
116
|
+
async function promptCandidateAction(candidate, registryPath, universalAlreadySelected) {
|
|
117
|
+
const candidateLabel = formatCandidateLabel(candidate, true);
|
|
118
|
+
// Build options based on state
|
|
119
|
+
const choices = universalAlreadySelected
|
|
120
|
+
? [
|
|
121
|
+
{ title: 'Mark as platform-specific', value: 'platform-specific' },
|
|
122
|
+
{ title: 'Skip', value: 'skip' }
|
|
123
|
+
]
|
|
124
|
+
: [
|
|
125
|
+
{ title: 'Set as universal', value: 'universal' },
|
|
126
|
+
{ title: 'Mark as platform-specific', value: 'platform-specific' },
|
|
127
|
+
{ title: 'Skip', value: 'skip' }
|
|
128
|
+
];
|
|
129
|
+
const response = await safePrompts({
|
|
130
|
+
type: 'select',
|
|
131
|
+
name: 'action',
|
|
132
|
+
message: ` ${candidateLabel}\n What should we do with this file?`,
|
|
133
|
+
choices,
|
|
134
|
+
hint: 'Arrow keys to navigate, Enter to select'
|
|
135
|
+
});
|
|
136
|
+
return response.action;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Display conflict resolution header
|
|
140
|
+
*/
|
|
141
|
+
function displayConflictHeader(registryPath, candidates) {
|
|
142
|
+
console.log(`\n⚠️ Multiple workspace versions found for ${registryPath}`);
|
|
143
|
+
console.log(` Resolving conflicts for ${candidates.length} file(s)...\n`);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Display resolution summary
|
|
147
|
+
*/
|
|
148
|
+
function displayResolutionSummary(universal, platformSpecific, skipped) {
|
|
149
|
+
console.log('─'.repeat(60));
|
|
150
|
+
console.log('Resolution summary:');
|
|
151
|
+
if (universal) {
|
|
152
|
+
console.log(` ✓ Universal: ${universal.displayPath}`);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log(' ℹ No universal content selected');
|
|
156
|
+
}
|
|
157
|
+
if (platformSpecific.length > 0) {
|
|
158
|
+
console.log(` ✓ Platform-specific: ${platformSpecific.length} file(s)`);
|
|
159
|
+
platformSpecific.forEach(c => {
|
|
160
|
+
const platform = c.platform ? `(${c.platform})` : '';
|
|
161
|
+
console.log(` • ${c.displayPath} ${platform}`);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (skipped.length > 0) {
|
|
165
|
+
console.log(` • Skipped: ${skipped.length} file(s)`);
|
|
166
|
+
}
|
|
167
|
+
console.log('─'.repeat(60) + '\n');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Format candidate label for display
|
|
171
|
+
*
|
|
172
|
+
* Shows: path, platform (if any), timestamp, and newest indicator
|
|
173
|
+
*/
|
|
174
|
+
function formatCandidateLabel(candidate, includeTimestamp = false) {
|
|
175
|
+
const parts = [];
|
|
176
|
+
// Path
|
|
177
|
+
parts.push(candidate.displayPath);
|
|
178
|
+
// Platform (if present)
|
|
179
|
+
if (candidate.platform && candidate.platform !== 'ai') {
|
|
180
|
+
parts.push(`(${candidate.platform})`);
|
|
181
|
+
}
|
|
182
|
+
// Timestamp
|
|
183
|
+
if (includeTimestamp) {
|
|
184
|
+
const date = new Date(candidate.mtime);
|
|
185
|
+
const timestamp = date.toLocaleString();
|
|
186
|
+
parts.push(`[${timestamp}]`);
|
|
187
|
+
}
|
|
188
|
+
return parts.join(' ');
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=save-interactive-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-interactive-resolver.js","sourceRoot":"","sources":["../../../src/core/save/save-interactive-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PACKAGE_PATHS, UNVERSIONED } from '../../constants/index.js';
|
|
2
2
|
import { ensureRegistryDirectories } from '../directory.js';
|
|
3
3
|
import { logger } from '../../utils/logger.js';
|
|
4
|
-
import { addPackageToYml, createWorkspacePackageYml } from '../../utils/package-management.js';
|
|
4
|
+
import { addPackageToYml, createWorkspacePackageYml, isPathBasedDependency } from '../../utils/package-management.js';
|
|
5
5
|
import { performPlatformSync } from '../sync/platform-sync.js';
|
|
6
6
|
import { LOG_PREFIXES, ERROR_MESSAGES, MODE_LABELS } from './constants.js';
|
|
7
7
|
import { isPackageTransitivelyCovered } from '../../utils/dependency-coverage.js';
|
|
@@ -12,14 +12,17 @@ import { savePackageToRegistry } from './package-saver.js';
|
|
|
12
12
|
import { isUnversionedVersion, packageVersionExists } from '../../utils/package-versioning.js';
|
|
13
13
|
import { deleteWorkspaceWipCopies } from './workspace-wip-cleanup.js';
|
|
14
14
|
import { writePackageYml } from '../../utils/package-yml.js';
|
|
15
|
-
import {
|
|
15
|
+
import { printPlatformSyncSummary } from '../sync/platform-sync-summary.js';
|
|
16
16
|
import { resolveWorkspaceNames } from './name-resolution.js';
|
|
17
17
|
import { resolvePackageFilesWithConflicts } from './save-conflict-resolution.js';
|
|
18
|
+
import { getDetectedPlatforms } from '../platforms.js';
|
|
19
|
+
import { buildIndexMappingForPackageFiles, loadOtherPackageIndexes } from '../../utils/index-based-installer.js';
|
|
20
|
+
import { getPackageIndexPath } from '../../utils/package-index-yml.js';
|
|
18
21
|
import { detectPackageContext, getNoPackageDetectedMessage, getPackageYmlPath, getPackageFilesDir, getPackageRootDir } from '../package-context.js';
|
|
19
22
|
import { applyWorkspacePackageRename } from './workspace-rename.js';
|
|
20
23
|
export async function runSavePipeline(packageName, options) {
|
|
21
24
|
const cwd = process.cwd();
|
|
22
|
-
const { mode, force, rename } = options;
|
|
25
|
+
const { mode, force, rename, apply = false } = options;
|
|
23
26
|
const { op, opCap } = MODE_LABELS[mode];
|
|
24
27
|
// Use unified detection
|
|
25
28
|
const detectedContext = await detectPackageContext(cwd, packageName);
|
|
@@ -67,7 +70,7 @@ export async function runSavePipeline(packageName, options) {
|
|
|
67
70
|
let nextStable;
|
|
68
71
|
if (isUnversioned) {
|
|
69
72
|
if (mode === 'stable') {
|
|
70
|
-
throw new Error('
|
|
73
|
+
throw new Error('openpackage.yml must contain a semver version to pack a release.');
|
|
71
74
|
}
|
|
72
75
|
targetVersion = UNVERSIONED;
|
|
73
76
|
}
|
|
@@ -92,10 +95,10 @@ export async function runSavePipeline(packageName, options) {
|
|
|
92
95
|
const bumpedConfig = { ...packageContext.config, version: nextStable };
|
|
93
96
|
await writePackageYml(packageContext.packageYmlPath, bumpedConfig);
|
|
94
97
|
packageContext = { ...packageContext, config: bumpedConfig, version: nextStable };
|
|
95
|
-
console.log(`✓ Updated
|
|
98
|
+
console.log(`✓ Updated openpackage.yml.version to ${nextStable} for the next cycle`);
|
|
96
99
|
}
|
|
97
100
|
catch (error) {
|
|
98
|
-
logger.warn(`Failed to auto-bump
|
|
101
|
+
logger.warn(`Failed to auto-bump openpackage.yml before save: ${String(error)}`);
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
if (mode === 'stable' && !force) {
|
|
@@ -111,20 +114,52 @@ export async function runSavePipeline(packageName, options) {
|
|
|
111
114
|
return { success: false, error: registrySave.error || `${opCap} operation failed` };
|
|
112
115
|
}
|
|
113
116
|
await deleteWorkspaceWipCopies(effectiveConfig.name, workspaceTag, mode === 'wip' ? { keepVersion: targetVersion } : undefined);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
let syncResult;
|
|
118
|
+
if (apply) {
|
|
119
|
+
syncResult = await performPlatformSync(cwd, effectiveConfig.name, effectiveConfig.version, packageFiles, {
|
|
120
|
+
force,
|
|
121
|
+
conflictStrategy: force ? 'overwrite' : 'ask',
|
|
122
|
+
skipRootSync: packageContext.location === 'root',
|
|
123
|
+
packageLocation: packageContext.location
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// Always write/update the workspace-local package index on save (wip or stable).
|
|
127
|
+
// The index records concrete workspace paths that exist today; apply/install will expand it later.
|
|
128
|
+
try {
|
|
129
|
+
const detectedPlatforms = await getDetectedPlatforms(cwd);
|
|
130
|
+
const otherIndexes = await loadOtherPackageIndexes(cwd, effectiveConfig.name);
|
|
131
|
+
const mapping = await buildIndexMappingForPackageFiles(cwd, packageFiles, detectedPlatforms, indexRecord, otherIndexes);
|
|
132
|
+
await writePackageIndex({
|
|
133
|
+
path: getPackageIndexPath(cwd, effectiveConfig.name, packageContext.location),
|
|
134
|
+
packageName: effectiveConfig.name,
|
|
135
|
+
workspace: { hash: workspaceHash, version: effectiveConfig.version },
|
|
136
|
+
files: mapping
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logger.warn(`Failed to update openpackage.index.yml for ${effectiveConfig.name}: ${String(error)}`);
|
|
141
|
+
}
|
|
120
142
|
if (packageContext.location !== 'root') {
|
|
143
|
+
// Skip saving path-based dependencies - they're linked, not copied
|
|
144
|
+
const isPathBased = await isPathBasedDependency(cwd, effectiveConfig.name);
|
|
145
|
+
if (isPathBased) {
|
|
146
|
+
console.log(`ℹ️ Skipping '${effectiveConfig.name}' (linked from path)`);
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
data: {
|
|
150
|
+
config: effectiveConfig,
|
|
151
|
+
packageFiles,
|
|
152
|
+
syncResult
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
121
156
|
const covered = await isPackageTransitivelyCovered(cwd, effectiveConfig.name);
|
|
122
157
|
if (!covered) {
|
|
123
158
|
const versionForYml = isUnversioned ? undefined : effectiveConfig.version;
|
|
124
159
|
await addPackageToYml(cwd, effectiveConfig.name, versionForYml, false, undefined, true);
|
|
125
160
|
}
|
|
126
161
|
else {
|
|
127
|
-
logger.debug(`Skipping addition of ${effectiveConfig.name} to
|
|
162
|
+
logger.debug(`Skipping addition of ${effectiveConfig.name} to openpackage.yml; already covered transitively.`);
|
|
128
163
|
}
|
|
129
164
|
}
|
|
130
165
|
if (mode === 'stable' && indexRecord) {
|
|
@@ -133,30 +168,19 @@ export async function runSavePipeline(packageName, options) {
|
|
|
133
168
|
workspace: { hash: workspaceHash, version: effectiveConfig.version }
|
|
134
169
|
});
|
|
135
170
|
}
|
|
136
|
-
|
|
171
|
+
printPlatformSyncSummary({
|
|
172
|
+
actionLabel: LOG_PREFIXES.SAVED.replace(/^✓\s*/, ''),
|
|
173
|
+
packageContext,
|
|
174
|
+
version: effectiveConfig.version,
|
|
175
|
+
packageFiles,
|
|
176
|
+
syncResult: apply ? syncResult : undefined,
|
|
177
|
+
noSyncHint: apply
|
|
178
|
+
? undefined
|
|
179
|
+
: 'ℹ️ Apply skipped. Run `opkg apply` or `opkg save --apply` to sync platforms.'
|
|
180
|
+
});
|
|
137
181
|
return {
|
|
138
182
|
success: true,
|
|
139
183
|
data: { config: effectiveConfig, packageFiles, syncResult }
|
|
140
184
|
};
|
|
141
185
|
}
|
|
142
|
-
function printSummary(packageContext, version, packageFiles, syncResult) {
|
|
143
|
-
const name = packageContext.config.name;
|
|
144
|
-
const type = packageContext.location === 'root' ? 'root package' : 'package';
|
|
145
|
-
console.log(`${LOG_PREFIXES.SAVED} ${name}@${version} (${type}, ${packageFiles.length} files):`);
|
|
146
|
-
if (packageFiles.length > 0) {
|
|
147
|
-
for (const path of [...packageFiles.map(f => f.path)].sort()) {
|
|
148
|
-
console.log(` ├── ${formatRegistryPathForDisplay(path)}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
const printList = (label, files) => {
|
|
152
|
-
if (files.length === 0)
|
|
153
|
-
return;
|
|
154
|
-
console.log(`✓ Platform sync ${label} ${files.length} files:`);
|
|
155
|
-
for (const f of [...files].sort())
|
|
156
|
-
console.log(` ├── ${f}`);
|
|
157
|
-
};
|
|
158
|
-
printList('created', syncResult.created);
|
|
159
|
-
printList('updated', syncResult.updated);
|
|
160
|
-
printList('removed', syncResult.deleted ?? []);
|
|
161
|
-
}
|
|
162
186
|
//# sourceMappingURL=save-pipeline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"save-pipeline.js","sourceRoot":"","sources":["../../../src/core/save/save-pipeline.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"save-pipeline.js","sourceRoot":"","sources":["../../../src/core/save/save-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { exists } from '../../utils/fs.js';
|
|
3
|
+
import { createPlatformSpecificRegistryPath } from '../../utils/platform-specific-paths.js';
|
|
4
|
+
import { logger } from '../../utils/logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Core responsibility: Platform-specific candidate management
|
|
7
|
+
* Input: Candidates
|
|
8
|
+
* Output: Pruning platform-specific candidates when they already exist in source
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Prune workspace candidates that have existing platform files
|
|
12
|
+
*
|
|
13
|
+
* This function removes workspace candidates from groups when a
|
|
14
|
+
* platform-specific file already exists in the source. This prevents
|
|
15
|
+
* overwriting existing platform-specific files with universal content.
|
|
16
|
+
*
|
|
17
|
+
* Mutates the groups in place.
|
|
18
|
+
*/
|
|
19
|
+
export async function pruneExistingPlatformCandidates(packageRoot, groups) {
|
|
20
|
+
for (const group of groups) {
|
|
21
|
+
if (!group.local) {
|
|
22
|
+
// No local file means no platform files could exist yet
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const filtered = [];
|
|
26
|
+
for (const candidate of group.workspace) {
|
|
27
|
+
const platform = candidate.platform;
|
|
28
|
+
// Keep non-platform candidates
|
|
29
|
+
if (!platform || platform === 'ai') {
|
|
30
|
+
filtered.push(candidate);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Check if platform-specific file exists
|
|
34
|
+
const platformPath = createPlatformSpecificRegistryPath(group.registryPath, platform);
|
|
35
|
+
if (!platformPath) {
|
|
36
|
+
filtered.push(candidate);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const platformFullPath = join(packageRoot, platformPath);
|
|
40
|
+
const hasPlatformFile = await exists(platformFullPath);
|
|
41
|
+
if (hasPlatformFile) {
|
|
42
|
+
// Platform-specific file exists - prune this candidate
|
|
43
|
+
logger.debug(`Skipping workspace candidate ${candidate.displayPath} for ${group.registryPath} ` +
|
|
44
|
+
`because local platform-specific file (${platformPath}) already exists`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// No existing platform file - keep candidate
|
|
48
|
+
filtered.push(candidate);
|
|
49
|
+
}
|
|
50
|
+
group.workspace = filtered;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=save-platform-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-platform-handler.js","sourceRoot":"","sources":["../../../src/core/save/save-platform-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,kCAAkC,EAAE,MAAM,wCAAwC,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/C;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,WAAmB,EACnB,MAA4B;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACjB,wDAAwD;YACxD,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAoB,EAAE,CAAC;QAErC,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;YAEpC,+BAA+B;YAC/B,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,yCAAyC;YACzC,MAAM,YAAY,GAAG,kCAAkC,CAAC,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YACtF,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACzD,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAEvD,IAAI,eAAe,EAAE,CAAC;gBACpB,uDAAuD;gBACvD,MAAM,CAAC,KAAK,CACV,gCAAgC,SAAS,CAAC,WAAW,QAAQ,KAAK,CAAC,YAAY,GAAG;oBAClF,yCAAyC,YAAY,kBAAkB,CACxE,CAAC;gBACF,SAAS;YACX,CAAC;YAED,6CAA6C;YAC7C,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QAED,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC7B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
import { getNewestCandidate, sortCandidatesByMtime } from './save-conflict-analyzer.js';
|
|
3
|
+
import { resolveInteractively } from './save-interactive-resolver.js';
|
|
4
|
+
/**
|
|
5
|
+
* Core responsibility: Execute resolution strategy and return results
|
|
6
|
+
* Input: Analysis + candidates
|
|
7
|
+
* Output: Resolution result (selection + platform-specific)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Execute resolution for a group based on analysis
|
|
11
|
+
*
|
|
12
|
+
* This is the main entry point for resolution execution.
|
|
13
|
+
* It delegates to specific resolution functions based on strategy.
|
|
14
|
+
*/
|
|
15
|
+
export async function executeResolution(group, analysis, packageRoot) {
|
|
16
|
+
const strategy = analysis.recommendedStrategy;
|
|
17
|
+
// Skip if no action needed
|
|
18
|
+
if (strategy === 'skip') {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// Sort candidates by mtime for consistent ordering
|
|
22
|
+
const sortedCandidates = sortCandidatesByMtime(analysis.uniqueWorkspaceCandidates);
|
|
23
|
+
switch (strategy) {
|
|
24
|
+
case 'write-single':
|
|
25
|
+
return resolveSingle(sortedCandidates[0]);
|
|
26
|
+
case 'write-newest':
|
|
27
|
+
return resolveIdentical(sortedCandidates);
|
|
28
|
+
case 'force-newest':
|
|
29
|
+
return resolveForce(sortedCandidates, group.registryPath);
|
|
30
|
+
case 'interactive':
|
|
31
|
+
return resolveInteractive(group.registryPath, sortedCandidates, analysis.isRootFile, group, packageRoot);
|
|
32
|
+
default:
|
|
33
|
+
logger.warn(`Unknown resolution strategy: ${strategy}`);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Auto-resolve: single candidate
|
|
39
|
+
*
|
|
40
|
+
* Only one workspace candidate exists - use it.
|
|
41
|
+
*/
|
|
42
|
+
function resolveSingle(candidate) {
|
|
43
|
+
return {
|
|
44
|
+
selection: candidate,
|
|
45
|
+
platformSpecific: [],
|
|
46
|
+
strategy: 'write-single',
|
|
47
|
+
wasInteractive: false
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Auto-resolve: multiple identical candidates (pick newest)
|
|
52
|
+
*
|
|
53
|
+
* All workspace candidates have identical content.
|
|
54
|
+
* Pick the newest one by mtime.
|
|
55
|
+
*/
|
|
56
|
+
function resolveIdentical(candidates) {
|
|
57
|
+
const newest = getNewestCandidate(candidates);
|
|
58
|
+
return {
|
|
59
|
+
selection: newest,
|
|
60
|
+
platformSpecific: [],
|
|
61
|
+
strategy: 'write-newest',
|
|
62
|
+
wasInteractive: false
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Force-resolve: pick newest without prompting
|
|
67
|
+
*
|
|
68
|
+
* Multiple differing candidates, but --force flag is set.
|
|
69
|
+
* Auto-select the newest by mtime without user interaction.
|
|
70
|
+
*
|
|
71
|
+
* Handles tie-breaking: if multiple files have the same mtime,
|
|
72
|
+
* selects first alphabetically by displayPath.
|
|
73
|
+
*/
|
|
74
|
+
function resolveForce(candidates, registryPath) {
|
|
75
|
+
const newest = getNewestCandidate(candidates);
|
|
76
|
+
// Check if there are ties (multiple with same mtime as newest)
|
|
77
|
+
const maxMtime = newest.mtime;
|
|
78
|
+
const tiedCandidates = candidates.filter(c => c.mtime === maxMtime);
|
|
79
|
+
if (tiedCandidates.length > 1) {
|
|
80
|
+
// Tie situation - log detailed explanation
|
|
81
|
+
logger.info(`Force mode: Multiple files have same modification time (${formatTimestamp(maxMtime)})`);
|
|
82
|
+
logger.info(` Auto-selecting first alphabetically: ${newest.displayPath}`);
|
|
83
|
+
logger.info(' Tied files:');
|
|
84
|
+
tiedCandidates.forEach(c => {
|
|
85
|
+
const marker = c === newest ? '→' : ' ';
|
|
86
|
+
logger.info(` ${marker} ${c.displayPath}`);
|
|
87
|
+
});
|
|
88
|
+
// Log skipped tied files
|
|
89
|
+
const skippedTied = tiedCandidates.filter(c => c !== newest);
|
|
90
|
+
skippedTied.forEach(c => {
|
|
91
|
+
logger.info(` Skipping: ${c.displayPath} (tied, not alphabetically first)`);
|
|
92
|
+
});
|
|
93
|
+
// Log older files
|
|
94
|
+
const olderFiles = candidates.filter(c => c.mtime < maxMtime);
|
|
95
|
+
olderFiles.forEach(c => {
|
|
96
|
+
logger.info(` Skipping: ${c.displayPath} (older)`);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Clear winner - simple logging
|
|
101
|
+
logger.info(`Force mode: Auto-selecting newest (${newest.displayPath})`);
|
|
102
|
+
// Log what we're skipping
|
|
103
|
+
const skipped = candidates.filter(c => c !== newest);
|
|
104
|
+
if (skipped.length > 0) {
|
|
105
|
+
skipped.forEach(c => {
|
|
106
|
+
logger.info(` Skipping: ${c.displayPath} (older)`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
selection: newest,
|
|
112
|
+
platformSpecific: [], // Force mode doesn't auto-create platform-specific
|
|
113
|
+
strategy: 'force-newest',
|
|
114
|
+
wasInteractive: false
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Interactive resolve: prompt user
|
|
119
|
+
*
|
|
120
|
+
* Multiple differing candidates require user input.
|
|
121
|
+
* Delegates to interactive resolver for UI flow.
|
|
122
|
+
*/
|
|
123
|
+
async function resolveInteractive(registryPath, candidates, isRootFile, group, packageRoot) {
|
|
124
|
+
const result = await resolveInteractively({
|
|
125
|
+
registryPath,
|
|
126
|
+
workspaceCandidates: candidates,
|
|
127
|
+
isRootFile,
|
|
128
|
+
group,
|
|
129
|
+
packageRoot
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
selection: result.selectedCandidate,
|
|
133
|
+
platformSpecific: result.platformSpecificCandidates,
|
|
134
|
+
strategy: 'interactive',
|
|
135
|
+
wasInteractive: true
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Format timestamp for human-readable display
|
|
140
|
+
*/
|
|
141
|
+
function formatTimestamp(mtime) {
|
|
142
|
+
const date = new Date(mtime);
|
|
143
|
+
return date.toLocaleString();
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=save-resolution-executor.js.map
|