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,563 @@
|
|
|
1
|
+
# Set Command Behavior Specification
|
|
2
|
+
|
|
3
|
+
## Pipeline Overview
|
|
4
|
+
|
|
5
|
+
The set command follows a clear pipeline:
|
|
6
|
+
|
|
7
|
+
1. **Input Validation** - Validate mode and options
|
|
8
|
+
2. **Package Resolution** - Locate the target package
|
|
9
|
+
3. **Manifest Loading** - Parse current `openpackage.yml`
|
|
10
|
+
4. **Update Determination** - Collect field updates (interactive or flags)
|
|
11
|
+
5. **Change Detection** - Compare old vs new values
|
|
12
|
+
6. **Field Validation** - Validate all update values
|
|
13
|
+
7. **Confirmation** - Show diff and confirm (if interactive)
|
|
14
|
+
8. **Manifest Update** - Apply changes and write file
|
|
15
|
+
9. **Success Display** - Show results
|
|
16
|
+
|
|
17
|
+
## Mode Detection
|
|
18
|
+
|
|
19
|
+
### Interactive Mode
|
|
20
|
+
|
|
21
|
+
**Triggered when:**
|
|
22
|
+
- No field flags provided (`--ver`, `--name`, etc.)
|
|
23
|
+
- Not in `--non-interactive` mode
|
|
24
|
+
|
|
25
|
+
**Behavior:**
|
|
26
|
+
- Prompts for each field
|
|
27
|
+
- Shows current values as defaults
|
|
28
|
+
- Empty input = keep current value
|
|
29
|
+
- Returns only changed fields
|
|
30
|
+
- Requires confirmation before writing
|
|
31
|
+
|
|
32
|
+
**Example:**
|
|
33
|
+
```bash
|
|
34
|
+
opkg set my-package
|
|
35
|
+
# → Enters interactive prompt mode
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Batch Mode
|
|
39
|
+
|
|
40
|
+
**Triggered when:**
|
|
41
|
+
- One or more field flags provided
|
|
42
|
+
- May or may not be in `--non-interactive` mode
|
|
43
|
+
|
|
44
|
+
**Behavior:**
|
|
45
|
+
- Extracts values from CLI options
|
|
46
|
+
- No prompting
|
|
47
|
+
- Processes only specified fields
|
|
48
|
+
- Shows diff
|
|
49
|
+
- Writes immediately (no confirmation)
|
|
50
|
+
|
|
51
|
+
**Example:**
|
|
52
|
+
```bash
|
|
53
|
+
opkg set my-package --ver 1.2.0 --author "Jane Doe"
|
|
54
|
+
# → Batch update of specified fields
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Non-Interactive Mode
|
|
58
|
+
|
|
59
|
+
**Triggered when:**
|
|
60
|
+
- `--non-interactive` flag provided
|
|
61
|
+
|
|
62
|
+
**Validation:**
|
|
63
|
+
- Must have at least one field flag
|
|
64
|
+
- Errors immediately if no flags
|
|
65
|
+
|
|
66
|
+
**Behavior:**
|
|
67
|
+
- Same as batch mode
|
|
68
|
+
- No prompts or confirmations
|
|
69
|
+
- Fails fast on errors
|
|
70
|
+
|
|
71
|
+
**Example:**
|
|
72
|
+
```bash
|
|
73
|
+
opkg set my-package --ver 1.0.0 --non-interactive
|
|
74
|
+
# → Batch update, no prompts, suitable for CI/CD
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Package Resolution Strategy
|
|
78
|
+
|
|
79
|
+
### When No Package Argument Provided
|
|
80
|
+
|
|
81
|
+
**Search order:**
|
|
82
|
+
1. Check for `openpackage.yml` in current directory
|
|
83
|
+
2. Error if not found
|
|
84
|
+
|
|
85
|
+
**Code path:**
|
|
86
|
+
```typescript
|
|
87
|
+
const manifestPath = path.join(cwd, 'openpackage.yml');
|
|
88
|
+
if (!(await exists(manifestPath))) {
|
|
89
|
+
throw new Error('No openpackage.yml found in current directory');
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### When Package Name Provided
|
|
94
|
+
|
|
95
|
+
**Search order:**
|
|
96
|
+
1. Workspace packages: `.openpackage/packages/<name>/`
|
|
97
|
+
2. Global packages: `~/.openpackage/packages/<name>/`
|
|
98
|
+
3. Error if not found (registry excluded)
|
|
99
|
+
|
|
100
|
+
**Code path:**
|
|
101
|
+
```typescript
|
|
102
|
+
const resolved = await resolveMutableSource({
|
|
103
|
+
cwd,
|
|
104
|
+
packageName: packageInput
|
|
105
|
+
});
|
|
106
|
+
// Searches workspace → global, rejects registry
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Source Type Detection
|
|
110
|
+
|
|
111
|
+
After resolution, determine source type for display:
|
|
112
|
+
|
|
113
|
+
- **`cwd`** - Package in current directory
|
|
114
|
+
- **`workspace`** - Package in `.openpackage/packages/`
|
|
115
|
+
- **`global`** - Package in `~/.openpackage/packages/`
|
|
116
|
+
|
|
117
|
+
## Update Extraction
|
|
118
|
+
|
|
119
|
+
### From CLI Options (Batch Mode)
|
|
120
|
+
|
|
121
|
+
**Process:**
|
|
122
|
+
1. Check each option field
|
|
123
|
+
2. If defined, extract value
|
|
124
|
+
3. Apply transformations:
|
|
125
|
+
- **name**: Normalize to lowercase
|
|
126
|
+
- **keywords**: Split by whitespace, filter empty
|
|
127
|
+
- **version**: Use as-is (validated later)
|
|
128
|
+
- Others: Use as-is
|
|
129
|
+
|
|
130
|
+
**Code snippet:**
|
|
131
|
+
```typescript
|
|
132
|
+
if (options.name !== undefined) {
|
|
133
|
+
updates.name = normalizePackageName(options.name);
|
|
134
|
+
}
|
|
135
|
+
if (options.ver !== undefined) {
|
|
136
|
+
updates.version = options.ver;
|
|
137
|
+
}
|
|
138
|
+
if (options.keywords !== undefined) {
|
|
139
|
+
updates.keywords = options.keywords.trim().split(/\s+/).filter(k => k.length > 0);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### From Interactive Prompts
|
|
144
|
+
|
|
145
|
+
**Process:**
|
|
146
|
+
1. Display current config
|
|
147
|
+
2. Prompt for each field with current value as default
|
|
148
|
+
3. Compare response to current value
|
|
149
|
+
4. Return only changed fields
|
|
150
|
+
|
|
151
|
+
**Prompt flow:**
|
|
152
|
+
```
|
|
153
|
+
Current package: my-package
|
|
154
|
+
Version: 1.0.0
|
|
155
|
+
Path: /path/to/package
|
|
156
|
+
|
|
157
|
+
Leave blank to keep current value, or enter new value:
|
|
158
|
+
|
|
159
|
+
Name [my-package]:
|
|
160
|
+
Version [1.0.0]: 1.1.0
|
|
161
|
+
Description [My package]: Updated description
|
|
162
|
+
Keywords [test demo]: test demo updated
|
|
163
|
+
Author [John Doe]:
|
|
164
|
+
License [MIT]:
|
|
165
|
+
Homepage []: https://example.com
|
|
166
|
+
Private [false]:
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Change detection:**
|
|
170
|
+
- Compare normalized response to current value
|
|
171
|
+
- For keywords, parse and compare arrays
|
|
172
|
+
- For booleans, compare boolean values
|
|
173
|
+
- Only include changed fields in result
|
|
174
|
+
|
|
175
|
+
## Change Detection
|
|
176
|
+
|
|
177
|
+
**Algorithm:**
|
|
178
|
+
```typescript
|
|
179
|
+
for (const [field, newValue] of Object.entries(updates)) {
|
|
180
|
+
const oldValue = currentConfig[field];
|
|
181
|
+
|
|
182
|
+
if (Array.isArray(newValue) && Array.isArray(oldValue)) {
|
|
183
|
+
if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
|
|
184
|
+
changes.push({ field, oldValue, newValue });
|
|
185
|
+
}
|
|
186
|
+
} else if (oldValue !== newValue) {
|
|
187
|
+
changes.push({ field, oldValue, newValue });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Special cases:**
|
|
193
|
+
- **Arrays (keywords)**: Deep comparison via JSON.stringify
|
|
194
|
+
- **Undefined vs empty**: Treat as different
|
|
195
|
+
- **Boolean flags**: Compare boolean values
|
|
196
|
+
|
|
197
|
+
**Result:**
|
|
198
|
+
- Array of `ConfigChange` objects
|
|
199
|
+
- Each contains: `field`, `oldValue`, `newValue`
|
|
200
|
+
- Empty array if no changes
|
|
201
|
+
|
|
202
|
+
## Field Validation
|
|
203
|
+
|
|
204
|
+
### Version Validation
|
|
205
|
+
|
|
206
|
+
**Rules:**
|
|
207
|
+
- Must be valid semantic version
|
|
208
|
+
- Checked using `semver.valid()`
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
```typescript
|
|
212
|
+
if (updates.version !== undefined) {
|
|
213
|
+
if (!semver.valid(updates.version)) {
|
|
214
|
+
throw new ValidationError(
|
|
215
|
+
`Invalid version format: "${updates.version}"\n` +
|
|
216
|
+
`Version must be valid semver (e.g., 1.0.0, 2.1.3-beta.1)`
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Name Validation
|
|
223
|
+
|
|
224
|
+
**Rules:**
|
|
225
|
+
- Must pass `validatePackageName()`
|
|
226
|
+
- Automatically normalized to lowercase
|
|
227
|
+
|
|
228
|
+
**Example:**
|
|
229
|
+
```typescript
|
|
230
|
+
if (updates.name !== undefined) {
|
|
231
|
+
validatePackageName(updates.name);
|
|
232
|
+
// Throws ValidationError if invalid
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Homepage Validation
|
|
237
|
+
|
|
238
|
+
**Rules:**
|
|
239
|
+
- Must be valid URL format
|
|
240
|
+
- Empty/whitespace-only strings skip validation
|
|
241
|
+
|
|
242
|
+
**Example:**
|
|
243
|
+
```typescript
|
|
244
|
+
if (updates.homepage !== undefined && updates.homepage.trim().length > 0) {
|
|
245
|
+
try {
|
|
246
|
+
new URL(updates.homepage);
|
|
247
|
+
} catch {
|
|
248
|
+
throw new ValidationError(`Invalid homepage URL: "${updates.homepage}"`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Other Fields
|
|
254
|
+
|
|
255
|
+
**No validation:**
|
|
256
|
+
- `description` - Any string
|
|
257
|
+
- `keywords` - Already parsed and filtered
|
|
258
|
+
- `author` - Any string
|
|
259
|
+
- `license` - Any string (should be valid SPDX, but not enforced)
|
|
260
|
+
- `private` - Boolean (type-safe)
|
|
261
|
+
|
|
262
|
+
## Manifest Update Strategy
|
|
263
|
+
|
|
264
|
+
### No Changes Scenario
|
|
265
|
+
|
|
266
|
+
**When:** Change detection returns empty array
|
|
267
|
+
|
|
268
|
+
**Behavior:**
|
|
269
|
+
1. Display "No changes made" message
|
|
270
|
+
2. Return success immediately
|
|
271
|
+
3. Don't write file
|
|
272
|
+
|
|
273
|
+
**Code:**
|
|
274
|
+
```typescript
|
|
275
|
+
if (changes.length === 0) {
|
|
276
|
+
displayNoChanges(packageName);
|
|
277
|
+
return { success: true, data: { updatedFields: [] } };
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### With Changes Scenario
|
|
282
|
+
|
|
283
|
+
**Process:**
|
|
284
|
+
1. Show change diff
|
|
285
|
+
2. Confirm (if interactive and not force)
|
|
286
|
+
3. Merge updates into current config
|
|
287
|
+
4. Write updated YAML
|
|
288
|
+
|
|
289
|
+
**Merge strategy:**
|
|
290
|
+
```typescript
|
|
291
|
+
const updatedConfig = {
|
|
292
|
+
...currentConfig,
|
|
293
|
+
...updates
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**YAML serialization:**
|
|
298
|
+
- Uses `writePackageYml()` from existing utils
|
|
299
|
+
- Maintains formatting consistency
|
|
300
|
+
- Preserves field order where possible
|
|
301
|
+
|
|
302
|
+
## Confirmation Flow
|
|
303
|
+
|
|
304
|
+
### When Confirmation Required
|
|
305
|
+
|
|
306
|
+
**Conditions:**
|
|
307
|
+
- Interactive mode (field flags not provided)
|
|
308
|
+
- Not force mode (`--force` not present)
|
|
309
|
+
- Changes detected
|
|
310
|
+
|
|
311
|
+
**Prompt:**
|
|
312
|
+
```
|
|
313
|
+
📝 Changes to apply:
|
|
314
|
+
version: 1.0.0 → 1.1.0
|
|
315
|
+
description: Old → New
|
|
316
|
+
|
|
317
|
+
Apply these changes? (y/n):
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Behavior:**
|
|
321
|
+
- Default: `true` (Enter = yes)
|
|
322
|
+
- `n` or `N`: Cancel operation
|
|
323
|
+
- Any other input: Proceed
|
|
324
|
+
|
|
325
|
+
### When Confirmation Skipped
|
|
326
|
+
|
|
327
|
+
**Conditions:**
|
|
328
|
+
- Batch mode (field flags provided)
|
|
329
|
+
- Force mode (`--force` present)
|
|
330
|
+
- Non-interactive mode
|
|
331
|
+
|
|
332
|
+
**Behavior:**
|
|
333
|
+
- Show diff
|
|
334
|
+
- Apply changes immediately
|
|
335
|
+
- No prompt
|
|
336
|
+
|
|
337
|
+
## File Writing
|
|
338
|
+
|
|
339
|
+
### Write Process
|
|
340
|
+
|
|
341
|
+
1. **Serialize to YAML**
|
|
342
|
+
```typescript
|
|
343
|
+
const content = serializePackageYml(updatedConfig);
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
2. **Write to file**
|
|
347
|
+
```typescript
|
|
348
|
+
await writeTextFile(manifestPath, content);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
3. **Atomic operation**
|
|
352
|
+
- Write completes or fails entirely
|
|
353
|
+
- No partial writes
|
|
354
|
+
|
|
355
|
+
### Error Handling During Write
|
|
356
|
+
|
|
357
|
+
**Possible errors:**
|
|
358
|
+
- File system permissions
|
|
359
|
+
- Disk space
|
|
360
|
+
- File locked by another process
|
|
361
|
+
|
|
362
|
+
**Behavior:**
|
|
363
|
+
- Catch exception
|
|
364
|
+
- Return failure result with error message
|
|
365
|
+
- File remains in original state (no partial update)
|
|
366
|
+
|
|
367
|
+
## Output Display
|
|
368
|
+
|
|
369
|
+
### Change Diff Format
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
📝 Changes to apply:
|
|
373
|
+
field: oldValue → newValue
|
|
374
|
+
field: oldValue → newValue
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Value formatting:**
|
|
378
|
+
- `(not set)` for undefined/null
|
|
379
|
+
- `[]` for empty arrays
|
|
380
|
+
- `[item1, item2]` for arrays
|
|
381
|
+
- `true`/`false` for booleans
|
|
382
|
+
- Plain string for strings
|
|
383
|
+
|
|
384
|
+
### Success Format
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
✓ Updated <package-name> manifest
|
|
388
|
+
Path: <display-path>
|
|
389
|
+
Type: <source-type> package
|
|
390
|
+
Updated: <field1>, <field2>, ...
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Path display:**
|
|
394
|
+
- Relative path if within CWD
|
|
395
|
+
- Absolute path if outside CWD
|
|
396
|
+
- Tilde notation for home directory
|
|
397
|
+
|
|
398
|
+
### No Changes Format
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
✓ No changes made to <package-name>
|
|
402
|
+
Manifest unchanged
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Error Scenarios
|
|
406
|
+
|
|
407
|
+
### Early Validation Errors
|
|
408
|
+
|
|
409
|
+
**Before file operations:**
|
|
410
|
+
- Non-interactive without flags
|
|
411
|
+
- Package not found
|
|
412
|
+
- No openpackage.yml in CWD
|
|
413
|
+
|
|
414
|
+
**Behavior:**
|
|
415
|
+
- Throw error immediately
|
|
416
|
+
- No file operations attempted
|
|
417
|
+
- Clear error message
|
|
418
|
+
|
|
419
|
+
### Field Validation Errors
|
|
420
|
+
|
|
421
|
+
**After change detection:**
|
|
422
|
+
- Invalid version format
|
|
423
|
+
- Invalid package name
|
|
424
|
+
- Invalid homepage URL
|
|
425
|
+
|
|
426
|
+
**Behavior:**
|
|
427
|
+
- Throw error before confirmation
|
|
428
|
+
- No file operations attempted
|
|
429
|
+
- Specific validation message
|
|
430
|
+
|
|
431
|
+
### File Operation Errors
|
|
432
|
+
|
|
433
|
+
**During write:**
|
|
434
|
+
- Permission denied
|
|
435
|
+
- Disk full
|
|
436
|
+
- File locked
|
|
437
|
+
|
|
438
|
+
**Behavior:**
|
|
439
|
+
- Catch exception
|
|
440
|
+
- Return failure result
|
|
441
|
+
- Preserve original file
|
|
442
|
+
|
|
443
|
+
## State Transitions
|
|
444
|
+
|
|
445
|
+
### State Machine
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
START
|
|
449
|
+
↓
|
|
450
|
+
INPUT_VALIDATION
|
|
451
|
+
↓ (valid)
|
|
452
|
+
PACKAGE_RESOLUTION
|
|
453
|
+
↓ (found)
|
|
454
|
+
MANIFEST_LOADING
|
|
455
|
+
↓ (loaded)
|
|
456
|
+
UPDATE_DETERMINATION
|
|
457
|
+
↓ (interactive or flags)
|
|
458
|
+
CHANGE_DETECTION
|
|
459
|
+
↓ (changes detected)
|
|
460
|
+
FIELD_VALIDATION
|
|
461
|
+
↓ (valid)
|
|
462
|
+
CONFIRMATION
|
|
463
|
+
↓ (confirmed)
|
|
464
|
+
MANIFEST_UPDATE
|
|
465
|
+
↓ (written)
|
|
466
|
+
SUCCESS_DISPLAY
|
|
467
|
+
↓
|
|
468
|
+
END
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Exit points:**
|
|
472
|
+
- Input validation failure
|
|
473
|
+
- Package not found
|
|
474
|
+
- No changes detected (success)
|
|
475
|
+
- Field validation failure
|
|
476
|
+
- User cancellation
|
|
477
|
+
- Write failure
|
|
478
|
+
|
|
479
|
+
## Side Effects
|
|
480
|
+
|
|
481
|
+
### File System Changes
|
|
482
|
+
|
|
483
|
+
**Modified:**
|
|
484
|
+
- Target package's `openpackage.yml`
|
|
485
|
+
|
|
486
|
+
**Not Modified:**
|
|
487
|
+
- Package directory structure
|
|
488
|
+
- Package files/content
|
|
489
|
+
- Workspace index
|
|
490
|
+
- Registry snapshots
|
|
491
|
+
|
|
492
|
+
### State Changes
|
|
493
|
+
|
|
494
|
+
**Local:**
|
|
495
|
+
- Package manifest updated in place
|
|
496
|
+
- Timestamp updated on file
|
|
497
|
+
|
|
498
|
+
**No Remote Changes:**
|
|
499
|
+
- Registry not affected
|
|
500
|
+
- Remote not contacted
|
|
501
|
+
- No network operations
|
|
502
|
+
|
|
503
|
+
## Concurrency Considerations
|
|
504
|
+
|
|
505
|
+
**File locking:**
|
|
506
|
+
- No explicit locking implemented
|
|
507
|
+
- Race condition possible if multiple processes modify same manifest
|
|
508
|
+
- Last write wins
|
|
509
|
+
|
|
510
|
+
**Recommendations:**
|
|
511
|
+
- Don't run multiple `set` commands on same package simultaneously
|
|
512
|
+
- CI/CD should serialize set operations
|
|
513
|
+
|
|
514
|
+
## Performance Characteristics
|
|
515
|
+
|
|
516
|
+
**Time complexity:**
|
|
517
|
+
- O(1) for package resolution
|
|
518
|
+
- O(n) for interactive prompts (n = number of fields)
|
|
519
|
+
- O(1) for validation
|
|
520
|
+
- O(1) for file write
|
|
521
|
+
|
|
522
|
+
**Space complexity:**
|
|
523
|
+
- O(1) memory usage
|
|
524
|
+
- Small YAML files (~1-5 KB typical)
|
|
525
|
+
|
|
526
|
+
**Typical execution time:**
|
|
527
|
+
- < 100ms for batch mode
|
|
528
|
+
- Human-dependent for interactive mode
|
|
529
|
+
|
|
530
|
+
## Idempotency
|
|
531
|
+
|
|
532
|
+
**Behavior:**
|
|
533
|
+
- Running same command twice with same values = no-op on second run
|
|
534
|
+
- Change detection prevents unnecessary writes
|
|
535
|
+
- Safe to retry
|
|
536
|
+
|
|
537
|
+
**Example:**
|
|
538
|
+
```bash
|
|
539
|
+
opkg set my-package --ver 1.0.0 # Updates version
|
|
540
|
+
opkg set my-package --ver 1.0.0 # No changes detected
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
## Testing Strategy
|
|
544
|
+
|
|
545
|
+
**Unit tests:**
|
|
546
|
+
- Package resolution
|
|
547
|
+
- Update extraction
|
|
548
|
+
- Change detection
|
|
549
|
+
- Field validation
|
|
550
|
+
- Manifest merging
|
|
551
|
+
|
|
552
|
+
**Integration tests:**
|
|
553
|
+
- End-to-end pipeline
|
|
554
|
+
- CWD package updates
|
|
555
|
+
- Workspace package updates
|
|
556
|
+
- Error scenarios
|
|
557
|
+
- No-op scenarios
|
|
558
|
+
|
|
559
|
+
**Manual tests:**
|
|
560
|
+
- Interactive mode flow
|
|
561
|
+
- Confirmation prompts
|
|
562
|
+
- Output formatting
|
|
563
|
+
- Edge cases
|