@canonical/pragma-cli 0.18.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 +377 -0
- package/package.json +78 -0
- package/src/bin.test.ts +52 -0
- package/src/bin.ts +19 -0
- package/src/compile-validation.runner.ts +137 -0
- package/src/compile-validation.ts +192 -0
- package/src/completions/computeSocketPath.test.ts +26 -0
- package/src/completions/computeSocketPath.ts +16 -0
- package/src/completions/constants.ts +18 -0
- package/src/completions/handleQuery.test.ts +93 -0
- package/src/completions/handleQuery.ts +30 -0
- package/src/completions/index.ts +14 -0
- package/src/completions/queryCompletions.test.ts +100 -0
- package/src/completions/queryCompletions.ts +61 -0
- package/src/completions/querySocket.test.ts +70 -0
- package/src/completions/querySocket.ts +44 -0
- package/src/completions/startCompletionsServer.test.ts +74 -0
- package/src/completions/startCompletionsServer.ts +75 -0
- package/src/completions/startCompletionsServer.unit.test.ts +131 -0
- package/src/completions/waitForSocket.test.ts +27 -0
- package/src/completions/waitForSocket.ts +27 -0
- package/src/config/configExists.ts +14 -0
- package/src/config/index.ts +6 -0
- package/src/config/readConfig.test.ts +152 -0
- package/src/config/readConfig.ts +64 -0
- package/src/config/resolveConfigPath.test.ts +20 -0
- package/src/config/resolveConfigPath.ts +11 -0
- package/src/config/types.ts +26 -0
- package/src/config/writeConfig.ts +49 -0
- package/src/constants.ts +78 -0
- package/src/domains/block/blockConfig.ts +53 -0
- package/src/domains/block/commands/index.ts +4 -0
- package/src/domains/block/commands/list.test.ts +111 -0
- package/src/domains/block/commands/list.ts +69 -0
- package/src/domains/block/commands/lookup.test.ts +187 -0
- package/src/domains/block/commands/lookup.ts +199 -0
- package/src/domains/block/formatters/index.ts +4 -0
- package/src/domains/block/formatters/list.test.ts +107 -0
- package/src/domains/block/formatters/list.ts +64 -0
- package/src/domains/block/formatters/lookup.test.ts +317 -0
- package/src/domains/block/formatters/lookup.ts +354 -0
- package/src/domains/block/formatters/types.ts +16 -0
- package/src/domains/block/helpers/index.ts +4 -0
- package/src/domains/block/helpers/resolveAspects.test.ts +64 -0
- package/src/domains/block/helpers/resolveAspects.ts +35 -0
- package/src/domains/block/index.ts +25 -0
- package/src/domains/block/mcp/index.ts +2 -0
- package/src/domains/block/mcp/specs.ts +199 -0
- package/src/domains/block/operations/index.ts +4 -0
- package/src/domains/block/operations/list.test.ts +80 -0
- package/src/domains/block/operations/list.ts +72 -0
- package/src/domains/block/operations/lookup.test.ts +108 -0
- package/src/domains/block/operations/lookup.ts +359 -0
- package/src/domains/block/orchestration/blockEmptyError.ts +19 -0
- package/src/domains/block/orchestration/buildBlockFilters.ts +12 -0
- package/src/domains/block/orchestration/enrichBlocks.ts +37 -0
- package/src/domains/block/orchestration/index.ts +5 -0
- package/src/domains/block/orchestration/resolveBlockList.ts +39 -0
- package/src/domains/block/orchestration/resolveBlockLookup.ts +21 -0
- package/src/domains/block/types.ts +30 -0
- package/src/domains/config/commands/channel.test.ts +101 -0
- package/src/domains/config/commands/channel.ts +80 -0
- package/src/domains/config/commands/index.ts +4 -0
- package/src/domains/config/commands/show.test.ts +61 -0
- package/src/domains/config/commands/show.ts +51 -0
- package/src/domains/config/commands/tier.test.ts +84 -0
- package/src/domains/config/commands/tier.ts +78 -0
- package/src/domains/config/formatters/channel.test.ts +56 -0
- package/src/domains/config/formatters/channel.ts +34 -0
- package/src/domains/config/formatters/index.ts +4 -0
- package/src/domains/config/formatters/show.test.ts +126 -0
- package/src/domains/config/formatters/show.ts +66 -0
- package/src/domains/config/formatters/tier.test.ts +70 -0
- package/src/domains/config/formatters/tier.ts +40 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/mcp/index.ts +2 -0
- package/src/domains/config/mcp/specs.ts +108 -0
- package/src/domains/config/operations/index.ts +5 -0
- package/src/domains/config/operations/show.test.ts +60 -0
- package/src/domains/config/operations/show.ts +42 -0
- package/src/domains/config/operations/types.ts +13 -0
- package/src/domains/config/operations/validateChannel.test.ts +36 -0
- package/src/domains/config/operations/validateChannel.ts +24 -0
- package/src/domains/config/operations/validateTier.test.ts +56 -0
- package/src/domains/config/operations/validateTier.ts +35 -0
- package/src/domains/create/commands/component.test.ts +166 -0
- package/src/domains/create/commands/component.ts +129 -0
- package/src/domains/create/commands/index.ts +3 -0
- package/src/domains/create/commands/package.test.ts +35 -0
- package/src/domains/create/commands/package.ts +21 -0
- package/src/domains/create/index.ts +15 -0
- package/src/domains/create/mcp/index.ts +2 -0
- package/src/domains/create/mcp/specs.ts +174 -0
- package/src/domains/doctor/commands/doctor.test.ts +75 -0
- package/src/domains/doctor/commands/doctor.ts +43 -0
- package/src/domains/doctor/commands/index.ts +2 -0
- package/src/domains/doctor/formatters/doctor.test.ts +117 -0
- package/src/domains/doctor/formatters/doctor.ts +84 -0
- package/src/domains/doctor/formatters/index.ts +2 -0
- package/src/domains/doctor/index.ts +9 -0
- package/src/domains/doctor/mcp/index.ts +2 -0
- package/src/domains/doctor/mcp/specs.ts +88 -0
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +28 -0
- package/src/domains/doctor/operations/checks/checkKeStore.ts +38 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +65 -0
- package/src/domains/doctor/operations/checks/checkNodeVersion.ts +25 -0
- package/src/domains/doctor/operations/checks/checkPragmaVersion.ts +20 -0
- package/src/domains/doctor/operations/checks/checkShellCompletions.ts +42 -0
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +64 -0
- package/src/domains/doctor/operations/checks/index.ts +8 -0
- package/src/domains/doctor/operations/checks.test.ts +151 -0
- package/src/domains/doctor/operations/index.ts +3 -0
- package/src/domains/doctor/operations/runChecks.test.ts +89 -0
- package/src/domains/doctor/operations/runChecks.ts +38 -0
- package/src/domains/doctor/operations/types.ts +20 -0
- package/src/domains/graph/commands/index.ts +4 -0
- package/src/domains/graph/commands/inspect.test.ts +94 -0
- package/src/domains/graph/commands/inspect.ts +63 -0
- package/src/domains/graph/commands/query.test.ts +92 -0
- package/src/domains/graph/commands/query.ts +60 -0
- package/src/domains/graph/formatters/index.ts +4 -0
- package/src/domains/graph/formatters/inspect.ts +45 -0
- package/src/domains/graph/formatters/query.ts +37 -0
- package/src/domains/graph/helpers/index.ts +3 -0
- package/src/domains/graph/helpers/resolveUri.ts +70 -0
- package/src/domains/graph/index.ts +22 -0
- package/src/domains/graph/mcp/index.ts +2 -0
- package/src/domains/graph/mcp/specs.ts +82 -0
- package/src/domains/graph/operations/executeQuery.test.ts +68 -0
- package/src/domains/graph/operations/executeQuery.ts +32 -0
- package/src/domains/graph/operations/index.ts +4 -0
- package/src/domains/graph/operations/inspectUri.test.ts +101 -0
- package/src/domains/graph/operations/inspectUri.ts +61 -0
- package/src/domains/info/commands/index.ts +4 -0
- package/src/domains/info/commands/info.test.ts +88 -0
- package/src/domains/info/commands/info.ts +47 -0
- package/src/domains/info/commands/upgrade.test.ts +183 -0
- package/src/domains/info/commands/upgrade.ts +150 -0
- package/src/domains/info/constants.test.ts +22 -0
- package/src/domains/info/constants.ts +15 -0
- package/src/domains/info/formatters/index.ts +8 -0
- package/src/domains/info/formatters/info.test.ts +173 -0
- package/src/domains/info/formatters/info.ts +116 -0
- package/src/domains/info/formatters/upgrade.test.ts +133 -0
- package/src/domains/info/formatters/upgrade.ts +68 -0
- package/src/domains/info/index.ts +7 -0
- package/src/domains/info/operations/checkRegistryVersion.test.ts +124 -0
- package/src/domains/info/operations/checkRegistryVersion.ts +45 -0
- package/src/domains/info/operations/collectInfo.test.ts +111 -0
- package/src/domains/info/operations/collectInfo.ts +68 -0
- package/src/domains/info/operations/collectStoreSummary.test.ts +61 -0
- package/src/domains/info/operations/collectStoreSummary.ts +42 -0
- package/src/domains/info/operations/index.ts +5 -0
- package/src/domains/info/types.test-d.ts +35 -0
- package/src/domains/info/types.ts +46 -0
- package/src/domains/llm/commands/index.ts +3 -0
- package/src/domains/llm/commands/llm.ts +37 -0
- package/src/domains/llm/data/commandReference.ts +25 -0
- package/src/domains/llm/data/decisionTrees.ts +46 -0
- package/src/domains/llm/data/index.ts +4 -0
- package/src/domains/llm/formatters/index.ts +3 -0
- package/src/domains/llm/formatters/orientation.ts +53 -0
- package/src/domains/llm/index.ts +8 -0
- package/src/domains/llm/llmCommand.test.ts +93 -0
- package/src/domains/llm/mcp/index.ts +2 -0
- package/src/domains/llm/mcp/specs.ts +87 -0
- package/src/domains/llm/operations/collectContext.ts +47 -0
- package/src/domains/llm/operations/index.ts +3 -0
- package/src/domains/llm/types.ts +32 -0
- package/src/domains/modifier/commands/index.ts +4 -0
- package/src/domains/modifier/commands/list.test.ts +57 -0
- package/src/domains/modifier/commands/list.ts +33 -0
- package/src/domains/modifier/commands/lookup.test.ts +91 -0
- package/src/domains/modifier/commands/lookup.ts +105 -0
- package/src/domains/modifier/formatters/index.ts +4 -0
- package/src/domains/modifier/formatters/list.test.ts +38 -0
- package/src/domains/modifier/formatters/list.ts +35 -0
- package/src/domains/modifier/formatters/lookup.test.ts +33 -0
- package/src/domains/modifier/formatters/lookup.ts +38 -0
- package/src/domains/modifier/index.ts +22 -0
- package/src/domains/modifier/mcp/index.ts +2 -0
- package/src/domains/modifier/mcp/specs.ts +97 -0
- package/src/domains/modifier/operations/index.ts +4 -0
- package/src/domains/modifier/operations/list.test.ts +39 -0
- package/src/domains/modifier/operations/list.ts +41 -0
- package/src/domains/modifier/operations/lookup.test.ts +37 -0
- package/src/domains/modifier/operations/lookup.ts +57 -0
- package/src/domains/modifier/orchestration/index.ts +3 -0
- package/src/domains/modifier/orchestration/modifierEmptyError.ts +10 -0
- package/src/domains/modifier/orchestration/resolveModifierList.ts +16 -0
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +20 -0
- package/src/domains/modifier/types.ts +5 -0
- package/src/domains/ontology/commands/index.ts +4 -0
- package/src/domains/ontology/commands/list.test.ts +82 -0
- package/src/domains/ontology/commands/list.ts +46 -0
- package/src/domains/ontology/commands/show.test.ts +103 -0
- package/src/domains/ontology/commands/show.ts +66 -0
- package/src/domains/ontology/formatters/index.ts +4 -0
- package/src/domains/ontology/formatters/list.ts +37 -0
- package/src/domains/ontology/formatters/show.ts +74 -0
- package/src/domains/ontology/helpers/findNamespace.ts +23 -0
- package/src/domains/ontology/helpers/index.ts +7 -0
- package/src/domains/ontology/helpers/queryClasses.ts +50 -0
- package/src/domains/ontology/helpers/queryProperties.ts +57 -0
- package/src/domains/ontology/helpers/resolvePrefix.ts +45 -0
- package/src/domains/ontology/index.ts +26 -0
- package/src/domains/ontology/mcp/index.ts +2 -0
- package/src/domains/ontology/mcp/specs.ts +93 -0
- package/src/domains/ontology/operations/index.ts +5 -0
- package/src/domains/ontology/operations/listOntologies.test.ts +45 -0
- package/src/domains/ontology/operations/listOntologies.ts +101 -0
- package/src/domains/ontology/operations/showOntology.test.ts +65 -0
- package/src/domains/ontology/operations/showOntology.ts +41 -0
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +39 -0
- package/src/domains/ontology/operations/showOntologyRaw.ts +50 -0
- package/src/domains/setup/commands/all.ts +58 -0
- package/src/domains/setup/commands/completions.ts +85 -0
- package/src/domains/setup/commands/entrypoints.test.ts +170 -0
- package/src/domains/setup/commands/index.ts +6 -0
- package/src/domains/setup/commands/lsp.ts +49 -0
- package/src/domains/setup/commands/mcp.ts +119 -0
- package/src/domains/setup/commands/skills.test.ts +64 -0
- package/src/domains/setup/commands/skills.ts +106 -0
- package/src/domains/setup/formatters/index.ts +2 -0
- package/src/domains/setup/formatters/skills.test.ts +103 -0
- package/src/domains/setup/formatters/skills.ts +112 -0
- package/src/domains/setup/formatters/types.ts +7 -0
- package/src/domains/setup/helpers/completionScripts.test.ts +58 -0
- package/src/domains/setup/helpers/completionScripts.ts +92 -0
- package/src/domains/setup/helpers/constants.ts +2 -0
- package/src/domains/setup/helpers/detectShell.test.ts +48 -0
- package/src/domains/setup/helpers/detectShell.ts +20 -0
- package/src/domains/setup/helpers/index.ts +12 -0
- package/src/domains/setup/helpers/runSetupTask.test.ts +279 -0
- package/src/domains/setup/helpers/runSetupTask.ts +229 -0
- package/src/domains/setup/index.ts +33 -0
- package/src/domains/setup/operations/index.ts +6 -0
- package/src/domains/setup/operations/setupAll.test.ts +48 -0
- package/src/domains/setup/operations/setupAll.ts +41 -0
- package/src/domains/setup/operations/setupCompletions.test.ts +94 -0
- package/src/domains/setup/operations/setupCompletions.ts +54 -0
- package/src/domains/setup/operations/setupLsp.test.ts +29 -0
- package/src/domains/setup/operations/setupLsp.ts +17 -0
- package/src/domains/setup/operations/setupMcp.test.ts +115 -0
- package/src/domains/setup/operations/setupMcp.ts +108 -0
- package/src/domains/setup/operations/setupSkills.test.ts +191 -0
- package/src/domains/setup/operations/setupSkills.ts +160 -0
- package/src/domains/setup/types.ts +18 -0
- package/src/domains/shared/ToolSpec.ts +49 -0
- package/src/domains/shared/bootStore.ts +77 -0
- package/src/domains/shared/buildQuery.ts +18 -0
- package/src/domains/shared/compactUri.test.ts +21 -0
- package/src/domains/shared/compactUri.ts +16 -0
- package/src/domains/shared/context.ts +15 -0
- package/src/domains/shared/contracts.ts +113 -0
- package/src/domains/shared/extractLocalName.test.ts +21 -0
- package/src/domains/shared/extractLocalName.ts +14 -0
- package/src/domains/shared/filters/buildChannelFilter.test.ts +52 -0
- package/src/domains/shared/filters/buildChannelFilter.ts +41 -0
- package/src/domains/shared/filters/buildFilterConfig.ts +16 -0
- package/src/domains/shared/filters/buildFilters.test.ts +33 -0
- package/src/domains/shared/filters/buildFilters.ts +30 -0
- package/src/domains/shared/filters/buildTierFilter.test.ts +78 -0
- package/src/domains/shared/filters/buildTierFilter.ts +69 -0
- package/src/domains/shared/filters/describeFilters.ts +14 -0
- package/src/domains/shared/filters/index.ts +10 -0
- package/src/domains/shared/formatters.ts +35 -0
- package/src/domains/shared/lookupMany.ts +45 -0
- package/src/domains/shared/namespaces.ts +18 -0
- package/src/domains/shared/packages.ts +76 -0
- package/src/domains/shared/prefixes.ts +37 -0
- package/src/domains/shared/runtime.ts +62 -0
- package/src/domains/shared/types.test-d.ts +127 -0
- package/src/domains/shared/types.ts +348 -0
- package/src/domains/skill/commands/index.ts +2 -0
- package/src/domains/skill/commands/list.test.ts +111 -0
- package/src/domains/skill/commands/list.ts +69 -0
- package/src/domains/skill/formatters/index.ts +2 -0
- package/src/domains/skill/formatters/list.test.ts +140 -0
- package/src/domains/skill/formatters/list.ts +119 -0
- package/src/domains/skill/formatters/types.ts +8 -0
- package/src/domains/skill/helpers/index.ts +6 -0
- package/src/domains/skill/helpers/parseFrontmatter.test.ts +122 -0
- package/src/domains/skill/helpers/parseFrontmatter.ts +112 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +34 -0
- package/src/domains/skill/index.ts +19 -0
- package/src/domains/skill/mcp/index.ts +2 -0
- package/src/domains/skill/mcp/specs.ts +38 -0
- package/src/domains/skill/operations/discover.test.ts +145 -0
- package/src/domains/skill/operations/discover.ts +68 -0
- package/src/domains/skill/operations/index.ts +4 -0
- package/src/domains/skill/operations/list.test.ts +68 -0
- package/src/domains/skill/operations/list.ts +47 -0
- package/src/domains/skill/types.ts +25 -0
- package/src/domains/standard/commands/categories.test.ts +70 -0
- package/src/domains/standard/commands/categories.ts +48 -0
- package/src/domains/standard/commands/index.ts +5 -0
- package/src/domains/standard/commands/list.test.ts +105 -0
- package/src/domains/standard/commands/list.ts +81 -0
- package/src/domains/standard/commands/lookup.test.ts +135 -0
- package/src/domains/standard/commands/lookup.ts +127 -0
- package/src/domains/standard/formatters/categories.test.ts +44 -0
- package/src/domains/standard/formatters/categories.ts +38 -0
- package/src/domains/standard/formatters/index.ts +6 -0
- package/src/domains/standard/formatters/list.test.ts +166 -0
- package/src/domains/standard/formatters/list.ts +156 -0
- package/src/domains/standard/formatters/lookup.test.ts +95 -0
- package/src/domains/standard/formatters/lookup.ts +86 -0
- package/src/domains/standard/formatters/types.ts +31 -0
- package/src/domains/standard/index.ts +32 -0
- package/src/domains/standard/mcp/index.ts +2 -0
- package/src/domains/standard/mcp/specs.ts +197 -0
- package/src/domains/standard/operations/categories.test.ts +61 -0
- package/src/domains/standard/operations/categories.ts +38 -0
- package/src/domains/standard/operations/index.ts +5 -0
- package/src/domains/standard/operations/list.test.ts +75 -0
- package/src/domains/standard/operations/list.ts +64 -0
- package/src/domains/standard/operations/lookup.test.ts +58 -0
- package/src/domains/standard/operations/lookup.ts +142 -0
- package/src/domains/standard/orchestration/buildStandardFilters.ts +11 -0
- package/src/domains/standard/orchestration/index.ts +4 -0
- package/src/domains/standard/orchestration/resolveStandardList.ts +42 -0
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +20 -0
- package/src/domains/standard/orchestration/standardEmptyError.ts +19 -0
- package/src/domains/standard/types.ts +15 -0
- package/src/domains/tier/commands/index.ts +3 -0
- package/src/domains/tier/commands/list.test.ts +67 -0
- package/src/domains/tier/commands/list.ts +43 -0
- package/src/domains/tier/formatters/index.ts +3 -0
- package/src/domains/tier/formatters/list.test.ts +33 -0
- package/src/domains/tier/formatters/list.ts +40 -0
- package/src/domains/tier/index.ts +17 -0
- package/src/domains/tier/mcp/index.ts +2 -0
- package/src/domains/tier/mcp/specs.ts +38 -0
- package/src/domains/tier/operations/index.ts +3 -0
- package/src/domains/tier/operations/list.test.ts +32 -0
- package/src/domains/tier/operations/list.ts +33 -0
- package/src/domains/token/commands/add-config.test.ts +68 -0
- package/src/domains/token/commands/add-config.ts +62 -0
- package/src/domains/token/commands/index.ts +5 -0
- package/src/domains/token/commands/list.test.ts +82 -0
- package/src/domains/token/commands/list.ts +45 -0
- package/src/domains/token/commands/lookup.test.ts +125 -0
- package/src/domains/token/commands/lookup.ts +121 -0
- package/src/domains/token/formatters/index.ts +4 -0
- package/src/domains/token/formatters/list.test.ts +37 -0
- package/src/domains/token/formatters/list.ts +37 -0
- package/src/domains/token/formatters/lookup.test.ts +61 -0
- package/src/domains/token/formatters/lookup.ts +72 -0
- package/src/domains/token/index.ts +32 -0
- package/src/domains/token/mcp/index.ts +2 -0
- package/src/domains/token/mcp/specs.ts +145 -0
- package/src/domains/token/operations/add-config.test.ts +68 -0
- package/src/domains/token/operations/add-config.ts +61 -0
- package/src/domains/token/operations/index.ts +7 -0
- package/src/domains/token/operations/list.test.ts +50 -0
- package/src/domains/token/operations/list.ts +52 -0
- package/src/domains/token/operations/lookup.test.ts +42 -0
- package/src/domains/token/operations/lookup.ts +66 -0
- package/src/domains/token/orchestration/index.ts +3 -0
- package/src/domains/token/orchestration/resolveTokenList.ts +17 -0
- package/src/domains/token/orchestration/resolveTokenLookup.ts +20 -0
- package/src/domains/token/orchestration/tokenEmptyError.ts +17 -0
- package/src/domains/token/types.ts +6 -0
- package/src/error/PragmaError.test.ts +121 -0
- package/src/error/PragmaError.ts +164 -0
- package/src/error/constants.ts +12 -0
- package/src/error/index.ts +4 -0
- package/src/error/types.ts +41 -0
- package/src/index.ts +141 -0
- package/src/mcp/createMcpServer.test.ts +41 -0
- package/src/mcp/createMcpServer.ts +53 -0
- package/src/mcp/error/buildRecovery.test.ts +37 -0
- package/src/mcp/error/buildRecovery.ts +17 -0
- package/src/mcp/error/index.ts +12 -0
- package/src/mcp/error/serializeError.test.ts +121 -0
- package/src/mcp/error/serializeError.ts +31 -0
- package/src/mcp/error/serializeErrorPayload.test.ts +38 -0
- package/src/mcp/error/serializeErrorPayload.ts +27 -0
- package/src/mcp/error/types.ts +51 -0
- package/src/mcp/index.ts +15 -0
- package/src/mcp/registerResources.test.ts +236 -0
- package/src/mcp/registerResources.ts +303 -0
- package/src/mcp/runMcpServer.test.ts +66 -0
- package/src/mcp/runMcpServer.ts +24 -0
- package/src/mcp/tools/index.ts +55 -0
- package/src/mcp/tools/registerFromSpec.ts +97 -0
- package/src/mcp/tools/registerTools.test.ts +1124 -0
- package/src/mcp/types.ts +62 -0
- package/src/mcp/utils/estimateTokens.test.ts +14 -0
- package/src/mcp/utils/estimateTokens.ts +9 -0
- package/src/mcp/utils/index.ts +11 -0
- package/src/mcp/utils/wrapTool.test.ts +108 -0
- package/src/mcp/utils/wrapTool.ts +81 -0
- package/src/package-manager/constants.ts +29 -0
- package/src/package-manager/detectInstallSource.test.ts +23 -0
- package/src/package-manager/detectInstallSource.ts +111 -0
- package/src/package-manager/detectLocalInstall.test.ts +16 -0
- package/src/package-manager/detectLocalInstall.ts +43 -0
- package/src/package-manager/detectPackageManager.test.ts +81 -0
- package/src/package-manager/detectPackageManager.ts +30 -0
- package/src/package-manager/index.ts +6 -0
- package/src/package-manager/types.ts +12 -0
- package/src/pipeline/collectCommands.test.ts +37 -0
- package/src/pipeline/collectCommands.ts +47 -0
- package/src/pipeline/constants.ts +14 -0
- package/src/pipeline/createProgram.test.ts +112 -0
- package/src/pipeline/createProgram.ts +70 -0
- package/src/pipeline/formatTerminal.test.ts +43 -0
- package/src/pipeline/formatTerminal.ts +53 -0
- package/src/pipeline/index.ts +19 -0
- package/src/pipeline/mapExitCode.test.ts +41 -0
- package/src/pipeline/mapExitCode.ts +12 -0
- package/src/pipeline/parseGlobalFlags.ts +21 -0
- package/src/pipeline/renderError.test.ts +151 -0
- package/src/pipeline/renderError.ts +114 -0
- package/src/pipeline/resolveCommandKind.test.ts +68 -0
- package/src/pipeline/resolveCommandKind.ts +71 -0
- package/src/pipeline/runCli.orchestration.test.ts +418 -0
- package/src/pipeline/runCli.test.ts +70 -0
- package/src/pipeline/runCli.ts +215 -0
- package/src/pipeline/types.ts +17 -0
- package/src/testing/cli.ts +43 -0
- package/src/testing/createTestMcpClient.ts +64 -0
- package/src/testing/dsFixtures.ts +506 -0
- package/src/testing/fixtures/canonical-config.json +4 -0
- package/src/testing/fixtures/canonical.ttl +437 -0
- package/src/testing/fixtures/filtered-config.json +4 -0
- package/src/testing/fixtures.ts +34 -0
- package/src/testing/helpers/assertParity.ts +28 -0
- package/src/testing/helpers/createTestMcpClient.ts +40 -0
- package/src/testing/helpers/createTestRuntime.ts +67 -0
- package/src/testing/index.ts +8 -0
- package/src/testing/integration/agent-session.test.ts +148 -0
- package/src/testing/integration/boot.test.ts +67 -0
- package/src/testing/integration/mcp-surface.test.ts +574 -0
- package/src/testing/integration/parity.test.ts +192 -0
- package/src/testing/store.ts +39 -0
- package/src/testing/types.ts +20 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ListParams } from "../../shared/contracts.js";
|
|
2
|
+
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
3
|
+
import type { Disclosure } from "../../shared/types.js";
|
|
4
|
+
import { listBlocks } from "../operations/index.js";
|
|
5
|
+
import type { BlockListContract } from "../types.js";
|
|
6
|
+
import blockEmptyError from "./blockEmptyError.js";
|
|
7
|
+
import buildBlockFilters from "./buildBlockFilters.js";
|
|
8
|
+
import enrichBlocks from "./enrichBlocks.js";
|
|
9
|
+
|
|
10
|
+
export default async function resolveBlockList(
|
|
11
|
+
rt: Pick<PragmaRuntime, "store" | "config">,
|
|
12
|
+
params: ListParams,
|
|
13
|
+
): Promise<BlockListContract> {
|
|
14
|
+
const filters = buildBlockFilters(rt, params.allTiers);
|
|
15
|
+
const disclosure: Disclosure = params.detailed
|
|
16
|
+
? { level: "detailed" }
|
|
17
|
+
: params.digest
|
|
18
|
+
? { level: "digest" }
|
|
19
|
+
: { level: "summary" };
|
|
20
|
+
const summaries = await listBlocks(rt.store, filters);
|
|
21
|
+
|
|
22
|
+
if (summaries.length === 0) {
|
|
23
|
+
throw blockEmptyError(filters, params.allTiers);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const items =
|
|
27
|
+
disclosure.level === "summary"
|
|
28
|
+
? summaries
|
|
29
|
+
: await enrichBlocks(summaries, rt.store, filters, disclosure);
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
params,
|
|
33
|
+
result: {
|
|
34
|
+
items,
|
|
35
|
+
filters,
|
|
36
|
+
disclosure,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LookupContract, LookupResult } from "../../shared/contracts.js";
|
|
2
|
+
import lookupMany from "../../shared/lookupMany.js";
|
|
3
|
+
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
4
|
+
import type { BlockDetailed, FilterConfig } from "../../shared/types.js";
|
|
5
|
+
import { lookupBlock } from "../operations/index.js";
|
|
6
|
+
|
|
7
|
+
export default async function resolveBlockLookup(
|
|
8
|
+
store: Pick<PragmaRuntime, "store">["store"],
|
|
9
|
+
queries: readonly string[],
|
|
10
|
+
filters: FilterConfig,
|
|
11
|
+
): Promise<LookupContract<BlockDetailed>> {
|
|
12
|
+
const result: LookupResult<BlockDetailed> = await lookupMany(
|
|
13
|
+
queries,
|
|
14
|
+
(query) => lookupBlock(store, query, filters),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
params: { names: queries },
|
|
19
|
+
result,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Block domain types.
|
|
3
|
+
*
|
|
4
|
+
* Reused across block commands, formatters, and aspect resolution.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ListContract } from "../shared/contracts.js";
|
|
8
|
+
import type { BlockDetailed, BlockSummary } from "../shared/types.js";
|
|
9
|
+
|
|
10
|
+
/** Flags controlling which detail aspects are included in block output. */
|
|
11
|
+
export interface AspectFlags {
|
|
12
|
+
readonly anatomy: boolean;
|
|
13
|
+
readonly modifiers: boolean;
|
|
14
|
+
readonly tokens: boolean;
|
|
15
|
+
readonly implementations: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BlockListDigest extends BlockSummary {
|
|
19
|
+
readonly summary: string | null;
|
|
20
|
+
readonly implementationPaths: readonly {
|
|
21
|
+
framework: string;
|
|
22
|
+
path: string;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type BlockListContract = ListContract<
|
|
27
|
+
BlockSummary,
|
|
28
|
+
BlockListDigest,
|
|
29
|
+
BlockDetailed
|
|
30
|
+
>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { Store } from "@canonical/ke";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { readConfig } from "#config";
|
|
7
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
8
|
+
import buildChannelCommand from "./channel.js";
|
|
9
|
+
|
|
10
|
+
function makeCtx(cwd: string): PragmaContext {
|
|
11
|
+
return {
|
|
12
|
+
cwd,
|
|
13
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
14
|
+
store: {} as Store,
|
|
15
|
+
config: { tier: undefined, channel: "normal" },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("config channel command", () => {
|
|
20
|
+
let dir: string;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
dir = mkdtempSync(join(tmpdir(), "pragma-cmd-channel-"));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
rmSync(dir, { recursive: true, force: true });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("sets channel to experimental", async () => {
|
|
31
|
+
const ctx = makeCtx(dir);
|
|
32
|
+
const cmd = buildChannelCommand(ctx);
|
|
33
|
+
const result = await cmd.execute({ value: "experimental" }, ctx);
|
|
34
|
+
|
|
35
|
+
expect(result.tag).toBe("output");
|
|
36
|
+
const config = readConfig(dir);
|
|
37
|
+
expect(config.channel).toBe("experimental");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("renders set output", async () => {
|
|
41
|
+
const ctx = makeCtx(dir);
|
|
42
|
+
const cmd = buildChannelCommand(ctx);
|
|
43
|
+
const result = await cmd.execute({ value: "prerelease" }, ctx);
|
|
44
|
+
|
|
45
|
+
expect(result.tag).toBe("output");
|
|
46
|
+
if (result.tag === "output") {
|
|
47
|
+
const text = result.render.plain(result.value);
|
|
48
|
+
expect(text).toBe('Set channel to "prerelease".');
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("resets channel via --reset flag", async () => {
|
|
53
|
+
writeFileSync(
|
|
54
|
+
join(dir, "pragma.config.json"),
|
|
55
|
+
'{"channel":"experimental"}',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const ctx = makeCtx(dir);
|
|
59
|
+
const cmd = buildChannelCommand(ctx);
|
|
60
|
+
const result = await cmd.execute({ reset: true }, ctx);
|
|
61
|
+
|
|
62
|
+
expect(result.tag).toBe("output");
|
|
63
|
+
const config = readConfig(dir);
|
|
64
|
+
expect(config.channel).toBe("normal");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("renders reset output", async () => {
|
|
68
|
+
const ctx = makeCtx(dir);
|
|
69
|
+
const cmd = buildChannelCommand(ctx);
|
|
70
|
+
const result = await cmd.execute({ reset: true }, ctx);
|
|
71
|
+
|
|
72
|
+
expect(result.tag).toBe("output");
|
|
73
|
+
if (result.tag === "output") {
|
|
74
|
+
const text = result.render.plain(result.value);
|
|
75
|
+
expect(text).toBe("Reset channel to default.");
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("shows current channel when no args", async () => {
|
|
80
|
+
writeFileSync(join(dir, "pragma.config.json"), '{"channel":"prerelease"}');
|
|
81
|
+
|
|
82
|
+
const ctx = makeCtx(dir);
|
|
83
|
+
const cmd = buildChannelCommand(ctx);
|
|
84
|
+
const result = await cmd.execute({}, ctx);
|
|
85
|
+
|
|
86
|
+
expect(result.tag).toBe("output");
|
|
87
|
+
if (result.tag === "output") {
|
|
88
|
+
expect(result.value).toBe("prerelease");
|
|
89
|
+
const text = result.render.plain(result.value);
|
|
90
|
+
expect(text).toBe("Current channel: prerelease");
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("throws INVALID_INPUT for invalid channel", async () => {
|
|
95
|
+
const ctx = makeCtx(dir);
|
|
96
|
+
const cmd = buildChannelCommand(ctx);
|
|
97
|
+
await expect(cmd.execute({ value: "aggressive" }, ctx)).rejects.toThrow(
|
|
98
|
+
'Invalid channel "aggressive"',
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CommandDefinition,
|
|
3
|
+
type CommandResult,
|
|
4
|
+
createOutputResult,
|
|
5
|
+
} from "@canonical/cli-core";
|
|
6
|
+
import { readConfig, writeConfig } from "#config";
|
|
7
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
8
|
+
import { selectFormatter } from "../../shared/formatters.js";
|
|
9
|
+
import { channelFormatters } from "../formatters/index.js";
|
|
10
|
+
import { validateChannel } from "../operations/index.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Build the `pragma config channel` command definition.
|
|
14
|
+
*
|
|
15
|
+
* Supports three modes: set a channel value, reset to default, or
|
|
16
|
+
* query the current channel when no arguments are provided.
|
|
17
|
+
*
|
|
18
|
+
* @param ctx - Pragma context providing cwd and formatter selection.
|
|
19
|
+
* @returns The command definition for `pragma config channel`.
|
|
20
|
+
* @note Impure
|
|
21
|
+
*/
|
|
22
|
+
export default function buildChannelCommand(
|
|
23
|
+
ctx: PragmaContext,
|
|
24
|
+
): CommandDefinition {
|
|
25
|
+
return {
|
|
26
|
+
path: ["config", "channel"],
|
|
27
|
+
description: "Set or reset the release channel",
|
|
28
|
+
parameters: [
|
|
29
|
+
{
|
|
30
|
+
name: "value",
|
|
31
|
+
description: "Channel (normal, experimental, prerelease)",
|
|
32
|
+
type: "string",
|
|
33
|
+
positional: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "reset",
|
|
37
|
+
description: "Reset channel to normal",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
default: false,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
meta: {
|
|
43
|
+
examples: [
|
|
44
|
+
"pragma config channel experimental",
|
|
45
|
+
"pragma config channel --reset",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
execute: async (
|
|
49
|
+
params: Record<string, unknown>,
|
|
50
|
+
): Promise<CommandResult> => {
|
|
51
|
+
const reset = params.reset === true;
|
|
52
|
+
const value = params.value as string | undefined;
|
|
53
|
+
|
|
54
|
+
if (reset) {
|
|
55
|
+
writeConfig(ctx.cwd, { channel: undefined });
|
|
56
|
+
const format = selectFormatter(ctx, channelFormatters.reset);
|
|
57
|
+
return createOutputResult("Reset channel to default.", {
|
|
58
|
+
plain: format,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!value) {
|
|
63
|
+
const config = readConfig(ctx.cwd);
|
|
64
|
+
const format = selectFormatter(ctx, channelFormatters.query);
|
|
65
|
+
return createOutputResult(config.channel, {
|
|
66
|
+
plain: format,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const channel = validateChannel(value);
|
|
71
|
+
|
|
72
|
+
writeConfig(ctx.cwd, { channel });
|
|
73
|
+
const format = selectFormatter(ctx, channelFormatters.set);
|
|
74
|
+
return createOutputResult(
|
|
75
|
+
{ field: "channel", value: channel },
|
|
76
|
+
{ plain: format },
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { Store } from "@canonical/ke";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
6
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
7
|
+
import buildShowCommand from "./show.js";
|
|
8
|
+
|
|
9
|
+
function makeCtx(cwd: string): PragmaContext {
|
|
10
|
+
return {
|
|
11
|
+
cwd,
|
|
12
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
13
|
+
store: {} as Store,
|
|
14
|
+
config: { tier: undefined, channel: "normal" },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("config show command", () => {
|
|
19
|
+
let dir: string;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
dir = mkdtempSync(join(tmpdir(), "pragma-cmd-show-"));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("renders show output with defaults", async () => {
|
|
30
|
+
const ctx = makeCtx(dir);
|
|
31
|
+
const cmd = buildShowCommand(ctx);
|
|
32
|
+
const result = await cmd.execute({}, ctx);
|
|
33
|
+
|
|
34
|
+
expect(result.tag).toBe("output");
|
|
35
|
+
if (result.tag === "output") {
|
|
36
|
+
const text = result.render.plain(result.value);
|
|
37
|
+
expect(text).toContain("tier: (none — all tiers visible)");
|
|
38
|
+
expect(text).toContain("channel: normal (stable)");
|
|
39
|
+
expect(text).toContain("config file: (not found)");
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("renders show output with configured values", async () => {
|
|
44
|
+
writeFileSync(
|
|
45
|
+
join(dir, "pragma.config.json"),
|
|
46
|
+
'{"tier":"apps/lxd","channel":"experimental"}',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const ctx = makeCtx(dir);
|
|
50
|
+
const cmd = buildShowCommand(ctx);
|
|
51
|
+
const result = await cmd.execute({}, ctx);
|
|
52
|
+
|
|
53
|
+
expect(result.tag).toBe("output");
|
|
54
|
+
if (result.tag === "output") {
|
|
55
|
+
const text = result.render.plain(result.value);
|
|
56
|
+
expect(text).toContain("tier: apps/lxd (global → apps → apps/lxd)");
|
|
57
|
+
expect(text).toContain("channel: experimental (stable + experimental)");
|
|
58
|
+
expect(text).toContain("config file:");
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CommandDefinition,
|
|
3
|
+
type CommandResult,
|
|
4
|
+
createOutputResult,
|
|
5
|
+
} from "@canonical/cli-core";
|
|
6
|
+
import { configExists, readConfig, resolveConfigPath } from "#config";
|
|
7
|
+
import { detectInstallSource } from "#package-manager";
|
|
8
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
9
|
+
import { selectFormatter } from "../../shared/formatters.js";
|
|
10
|
+
import { showFormatters } from "../formatters/index.js";
|
|
11
|
+
import { resolveConfigShow } from "../operations/index.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the `pragma config show` command definition.
|
|
15
|
+
*
|
|
16
|
+
* Displays the resolved configuration including tier, channel,
|
|
17
|
+
* package manager, and config file location.
|
|
18
|
+
*
|
|
19
|
+
* @param ctx - Pragma context providing cwd and formatter selection.
|
|
20
|
+
* @returns The command definition for `pragma config show`.
|
|
21
|
+
* @note Impure
|
|
22
|
+
*/
|
|
23
|
+
export default function buildShowCommand(
|
|
24
|
+
ctx: PragmaContext,
|
|
25
|
+
): CommandDefinition {
|
|
26
|
+
return {
|
|
27
|
+
path: ["config", "show"],
|
|
28
|
+
description: "Display resolved configuration",
|
|
29
|
+
parameters: [],
|
|
30
|
+
meta: {
|
|
31
|
+
examples: ["pragma config show"],
|
|
32
|
+
},
|
|
33
|
+
execute: async (): Promise<CommandResult> => {
|
|
34
|
+
const config = readConfig(ctx.cwd);
|
|
35
|
+
const install = detectInstallSource();
|
|
36
|
+
const cfgPath = resolveConfigPath(ctx.cwd);
|
|
37
|
+
const cfgExists = configExists(ctx.cwd);
|
|
38
|
+
|
|
39
|
+
const data = resolveConfigShow(config, {
|
|
40
|
+
packageManager: install.packageManager,
|
|
41
|
+
installSource: install.label,
|
|
42
|
+
configFilePath: cfgPath,
|
|
43
|
+
configFileExists: cfgExists,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return createOutputResult(data, {
|
|
47
|
+
plain: selectFormatter(ctx, showFormatters),
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { Store } from "@canonical/ke";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { readConfig } from "#config";
|
|
7
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
8
|
+
import buildTierCommand from "./tier.js";
|
|
9
|
+
|
|
10
|
+
function makeCtx(cwd: string): PragmaContext {
|
|
11
|
+
return {
|
|
12
|
+
cwd,
|
|
13
|
+
globalFlags: { llm: false, format: "text" as const, verbose: false },
|
|
14
|
+
store: {} as Store,
|
|
15
|
+
config: { tier: undefined, channel: "normal" },
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("config tier command", () => {
|
|
20
|
+
let dir: string;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
dir = mkdtempSync(join(tmpdir(), "pragma-cmd-tier-"));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
rmSync(dir, { recursive: true, force: true });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("resets tier via --reset flag", async () => {
|
|
31
|
+
writeFileSync(
|
|
32
|
+
join(dir, "pragma.config.json"),
|
|
33
|
+
'{"tier":"apps/lxd","channel":"normal"}',
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const ctx = makeCtx(dir);
|
|
37
|
+
const cmd = buildTierCommand(ctx);
|
|
38
|
+
const result = await cmd.execute({ reset: true }, ctx);
|
|
39
|
+
|
|
40
|
+
expect(result.tag).toBe("output");
|
|
41
|
+
const config = readConfig(dir);
|
|
42
|
+
expect(config.tier).toBeUndefined();
|
|
43
|
+
expect(config.channel).toBe("normal");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("renders reset output", async () => {
|
|
47
|
+
const ctx = makeCtx(dir);
|
|
48
|
+
const cmd = buildTierCommand(ctx);
|
|
49
|
+
const result = await cmd.execute({ reset: true }, ctx);
|
|
50
|
+
|
|
51
|
+
expect(result.tag).toBe("output");
|
|
52
|
+
if (result.tag === "output") {
|
|
53
|
+
const text = result.render.plain(result.value);
|
|
54
|
+
expect(text).toBe("Reset tier to default.");
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("shows current tier when no args", async () => {
|
|
59
|
+
writeFileSync(join(dir, "pragma.config.json"), '{"tier":"apps"}');
|
|
60
|
+
|
|
61
|
+
const ctx = makeCtx(dir);
|
|
62
|
+
const cmd = buildTierCommand(ctx);
|
|
63
|
+
const result = await cmd.execute({}, ctx);
|
|
64
|
+
|
|
65
|
+
expect(result.tag).toBe("output");
|
|
66
|
+
if (result.tag === "output") {
|
|
67
|
+
expect(result.value).toBe("apps");
|
|
68
|
+
const text = result.render.plain(result.value);
|
|
69
|
+
expect(text).toBe("Current tier: apps");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("shows no tier message when none set", async () => {
|
|
74
|
+
const ctx = makeCtx(dir);
|
|
75
|
+
const cmd = buildTierCommand(ctx);
|
|
76
|
+
const result = await cmd.execute({}, ctx);
|
|
77
|
+
|
|
78
|
+
expect(result.tag).toBe("output");
|
|
79
|
+
if (result.tag === "output") {
|
|
80
|
+
const text = result.render.plain(result.value);
|
|
81
|
+
expect(text).toBe("No tier set (all tiers visible).");
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CommandDefinition,
|
|
3
|
+
type CommandResult,
|
|
4
|
+
createOutputResult,
|
|
5
|
+
} from "@canonical/cli-core";
|
|
6
|
+
import { readConfig, writeConfig } from "#config";
|
|
7
|
+
import type { PragmaContext } from "../../shared/context.js";
|
|
8
|
+
import { selectFormatter } from "../../shared/formatters.js";
|
|
9
|
+
import { tierFormatters } from "../formatters/index.js";
|
|
10
|
+
import { validateTier } from "../operations/index.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Build the `pragma config tier` command definition.
|
|
14
|
+
*
|
|
15
|
+
* Supports three modes: set a tier path (validated against the ontology),
|
|
16
|
+
* reset to default, or query the current tier.
|
|
17
|
+
*
|
|
18
|
+
* @param ctx - Pragma context providing cwd, store, and formatter selection.
|
|
19
|
+
* @returns The command definition for `pragma config tier`.
|
|
20
|
+
* @note Impure
|
|
21
|
+
*/
|
|
22
|
+
export default function buildTierCommand(
|
|
23
|
+
ctx: PragmaContext,
|
|
24
|
+
): CommandDefinition {
|
|
25
|
+
return {
|
|
26
|
+
path: ["config", "tier"],
|
|
27
|
+
description: "Set or reset the active tier",
|
|
28
|
+
parameters: [
|
|
29
|
+
{
|
|
30
|
+
name: "path",
|
|
31
|
+
description: "Tier path (e.g., global, apps, apps/lxd)",
|
|
32
|
+
type: "string",
|
|
33
|
+
positional: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "reset",
|
|
37
|
+
description: "Reset tier to default (all tiers visible)",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
default: false,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
meta: {
|
|
43
|
+
examples: ["pragma config tier apps/lxd", "pragma config tier --reset"],
|
|
44
|
+
},
|
|
45
|
+
execute: async (
|
|
46
|
+
params: Record<string, unknown>,
|
|
47
|
+
): Promise<CommandResult> => {
|
|
48
|
+
const reset = params.reset === true;
|
|
49
|
+
const tierPath = params.path as string | undefined;
|
|
50
|
+
|
|
51
|
+
if (reset) {
|
|
52
|
+
writeConfig(ctx.cwd, { tier: undefined });
|
|
53
|
+
const format = selectFormatter(ctx, tierFormatters.reset);
|
|
54
|
+
return createOutputResult("Reset tier to default.", {
|
|
55
|
+
plain: format,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!tierPath) {
|
|
60
|
+
const config = readConfig(ctx.cwd);
|
|
61
|
+
const format = selectFormatter(ctx, tierFormatters.query);
|
|
62
|
+
return createOutputResult(config.tier, {
|
|
63
|
+
plain: format,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Validate tier against ontology
|
|
68
|
+
await validateTier(ctx.store, tierPath);
|
|
69
|
+
|
|
70
|
+
writeConfig(ctx.cwd, { tier: tierPath });
|
|
71
|
+
const format = selectFormatter(ctx, tierFormatters.set);
|
|
72
|
+
return createOutputResult(
|
|
73
|
+
{ field: "tier", value: tierPath },
|
|
74
|
+
{ plain: format },
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import formatters from "./channel.js";
|
|
3
|
+
|
|
4
|
+
describe("channelFormatters.set", () => {
|
|
5
|
+
const data = { field: "channel", value: "experimental" };
|
|
6
|
+
|
|
7
|
+
it("plain renders set message", () => {
|
|
8
|
+
expect(formatters.set.plain(data)).toBe('Set channel to "experimental".');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("llm renders set message", () => {
|
|
12
|
+
expect(formatters.set.llm(data)).toBe('Set channel to "experimental".');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("json returns valid JSON", () => {
|
|
16
|
+
const parsed = JSON.parse(formatters.set.json(data));
|
|
17
|
+
expect(parsed.field).toBe("channel");
|
|
18
|
+
expect(parsed.value).toBe("experimental");
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("channelFormatters.reset", () => {
|
|
23
|
+
it("plain renders reset message", () => {
|
|
24
|
+
expect(formatters.reset.plain("")).toBe("Reset channel to default.");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("llm renders reset message", () => {
|
|
28
|
+
expect(formatters.reset.llm("")).toBe("Reset channel to default.");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("json returns valid JSON", () => {
|
|
32
|
+
const parsed = JSON.parse(formatters.reset.json(""));
|
|
33
|
+
expect(parsed.field).toBe("channel");
|
|
34
|
+
expect(parsed.reset).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe("channelFormatters.query", () => {
|
|
39
|
+
it("plain shows current channel", () => {
|
|
40
|
+
expect(formatters.query.plain("prerelease")).toBe(
|
|
41
|
+
"Current channel: prerelease",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("llm shows current channel", () => {
|
|
46
|
+
expect(formatters.query.llm("prerelease")).toBe(
|
|
47
|
+
"Current channel: prerelease",
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("json returns valid JSON", () => {
|
|
52
|
+
const parsed = JSON.parse(formatters.query.json("prerelease"));
|
|
53
|
+
expect(parsed.field).toBe("channel");
|
|
54
|
+
expect(parsed.value).toBe("prerelease");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Formatters } from "../../shared/formatters.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Formatter sets for `pragma config channel` output, grouped by branch:
|
|
5
|
+
*
|
|
6
|
+
* - **set** formats the confirmation after setting a channel (plain/llm/json).
|
|
7
|
+
* - **reset** formats the confirmation after resetting to default (plain/llm/json).
|
|
8
|
+
* - **query** formats the current channel value (plain/llm/json).
|
|
9
|
+
*/
|
|
10
|
+
const channelFormatters = {
|
|
11
|
+
set: {
|
|
12
|
+
plain: (d: { field: string; value: string }) =>
|
|
13
|
+
`Set ${d.field} to "${d.value}".`,
|
|
14
|
+
llm: (d: { field: string; value: string }) =>
|
|
15
|
+
`Set ${d.field} to "${d.value}".`,
|
|
16
|
+
json: (d: { field: string; value: string }) =>
|
|
17
|
+
JSON.stringify({ field: d.field, value: d.value }),
|
|
18
|
+
} satisfies Formatters<{ field: string; value: string }>,
|
|
19
|
+
|
|
20
|
+
reset: {
|
|
21
|
+
plain: () => "Reset channel to default.",
|
|
22
|
+
llm: () => "Reset channel to default.",
|
|
23
|
+
json: () => JSON.stringify({ field: "channel", reset: true }),
|
|
24
|
+
} satisfies Formatters<string>,
|
|
25
|
+
|
|
26
|
+
query: {
|
|
27
|
+
plain: (channel: string) => `Current channel: ${channel}`,
|
|
28
|
+
llm: (channel: string) => `Current channel: ${channel}`,
|
|
29
|
+
json: (channel: string) =>
|
|
30
|
+
JSON.stringify({ field: "channel", value: channel }),
|
|
31
|
+
} satisfies Formatters<string>,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default channelFormatters;
|