@untangle-code/cli 0.0.0-stage → 0.1.1
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/LICENSE +661 -0
- package/NOTICE +90 -0
- package/README.md +451 -2
- package/THIRD_PARTY_LICENSES.md +152 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +167 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/command.d.ts +69 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +82 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/deadline.d.ts +33 -0
- package/dist/cli/deadline.d.ts.map +1 -0
- package/dist/cli/deadline.js +49 -0
- package/dist/cli/deadline.js.map +1 -0
- package/dist/cli/embedder-deadline.d.ts +72 -0
- package/dist/cli/embedder-deadline.d.ts.map +1 -0
- package/dist/cli/embedder-deadline.js +117 -0
- package/dist/cli/embedder-deadline.js.map +1 -0
- package/dist/cli/exit.d.ts +71 -0
- package/dist/cli/exit.d.ts.map +1 -0
- package/dist/cli/exit.js +81 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/graphs.d.ts +65 -0
- package/dist/cli/graphs.d.ts.map +1 -0
- package/dist/cli/graphs.js +108 -0
- package/dist/cli/graphs.js.map +1 -0
- package/dist/cli/index-freshness.d.ts +13 -0
- package/dist/cli/index-freshness.d.ts.map +1 -0
- package/dist/cli/index-freshness.js +226 -0
- package/dist/cli/index-freshness.js.map +1 -0
- package/dist/cli/index-refresh.d.ts +10 -0
- package/dist/cli/index-refresh.d.ts.map +1 -0
- package/dist/cli/index-refresh.js +76 -0
- package/dist/cli/index-refresh.js.map +1 -0
- package/dist/cli/index-state.d.ts +184 -0
- package/dist/cli/index-state.d.ts.map +1 -0
- package/dist/cli/index-state.js +852 -0
- package/dist/cli/index-state.js.map +1 -0
- package/dist/cli/io.d.ts +29 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +42 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/cli/language-support.d.ts +77 -0
- package/dist/cli/language-support.d.ts.map +1 -0
- package/dist/cli/language-support.js +152 -0
- package/dist/cli/language-support.js.map +1 -0
- package/dist/cli/renewing-lease.d.ts +26 -0
- package/dist/cli/renewing-lease.d.ts.map +1 -0
- package/dist/cli/renewing-lease.js +102 -0
- package/dist/cli/renewing-lease.js.map +1 -0
- package/dist/cli/search-graph-enrichment.d.ts +16 -0
- package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
- package/dist/cli/search-graph-enrichment.js +428 -0
- package/dist/cli/search-graph-enrichment.js.map +1 -0
- package/dist/cli/system.d.ts +34 -0
- package/dist/cli/system.d.ts.map +1 -0
- package/dist/cli/system.js +89 -0
- package/dist/cli/system.js.map +1 -0
- package/dist/cli/vector-store-policy.d.ts +116 -0
- package/dist/cli/vector-store-policy.d.ts.map +1 -0
- package/dist/cli/vector-store-policy.js +160 -0
- package/dist/cli/vector-store-policy.js.map +1 -0
- package/dist/cli/version.d.ts +3 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +3 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/workspace.d.ts +105 -0
- package/dist/cli/workspace.d.ts.map +1 -0
- package/dist/cli/workspace.js +215 -0
- package/dist/cli/workspace.js.map +1 -0
- package/dist/commands/complexity.d.ts +72 -0
- package/dist/commands/complexity.d.ts.map +1 -0
- package/dist/commands/complexity.js +580 -0
- package/dist/commands/complexity.js.map +1 -0
- package/dist/commands/doctor.d.ts +66 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +764 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.languages.d.ts +37 -0
- package/dist/commands/doctor.languages.d.ts.map +1 -0
- package/dist/commands/doctor.languages.js +143 -0
- package/dist/commands/doctor.languages.js.map +1 -0
- package/dist/commands/doctor.storage.d.ts +17 -0
- package/dist/commands/doctor.storage.d.ts.map +1 -0
- package/dist/commands/doctor.storage.js +91 -0
- package/dist/commands/doctor.storage.js.map +1 -0
- package/dist/commands/extensions/add.d.ts +10 -0
- package/dist/commands/extensions/add.d.ts.map +1 -0
- package/dist/commands/extensions/add.js +213 -0
- package/dist/commands/extensions/add.js.map +1 -0
- package/dist/commands/extensions/configure.d.ts +5 -0
- package/dist/commands/extensions/configure.d.ts.map +1 -0
- package/dist/commands/extensions/configure.js +58 -0
- package/dist/commands/extensions/configure.js.map +1 -0
- package/dist/commands/extensions/container.d.ts +15 -0
- package/dist/commands/extensions/container.d.ts.map +1 -0
- package/dist/commands/extensions/container.js +135 -0
- package/dist/commands/extensions/container.js.map +1 -0
- package/dist/commands/extensions/context.d.ts +37 -0
- package/dist/commands/extensions/context.d.ts.map +1 -0
- package/dist/commands/extensions/context.js +72 -0
- package/dist/commands/extensions/context.js.map +1 -0
- package/dist/commands/extensions/enable.d.ts +6 -0
- package/dist/commands/extensions/enable.d.ts.map +1 -0
- package/dist/commands/extensions/enable.js +180 -0
- package/dist/commands/extensions/enable.js.map +1 -0
- package/dist/commands/extensions/environment.d.ts +74 -0
- package/dist/commands/extensions/environment.d.ts.map +1 -0
- package/dist/commands/extensions/environment.js +168 -0
- package/dist/commands/extensions/environment.js.map +1 -0
- package/dist/commands/extensions/feature-scan.d.ts +48 -0
- package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
- package/dist/commands/extensions/feature-scan.js +156 -0
- package/dist/commands/extensions/feature-scan.js.map +1 -0
- package/dist/commands/extensions/invoke.d.ts +60 -0
- package/dist/commands/extensions/invoke.d.ts.map +1 -0
- package/dist/commands/extensions/invoke.js +275 -0
- package/dist/commands/extensions/invoke.js.map +1 -0
- package/dist/commands/extensions/list.d.ts +5 -0
- package/dist/commands/extensions/list.d.ts.map +1 -0
- package/dist/commands/extensions/list.js +125 -0
- package/dist/commands/extensions/list.js.map +1 -0
- package/dist/commands/extensions/logs.d.ts +5 -0
- package/dist/commands/extensions/logs.d.ts.map +1 -0
- package/dist/commands/extensions/logs.js +74 -0
- package/dist/commands/extensions/logs.js.map +1 -0
- package/dist/commands/extensions/provision.d.ts +36 -0
- package/dist/commands/extensions/provision.d.ts.map +1 -0
- package/dist/commands/extensions/provision.js +137 -0
- package/dist/commands/extensions/provision.js.map +1 -0
- package/dist/commands/extensions/remove.d.ts +5 -0
- package/dist/commands/extensions/remove.d.ts.map +1 -0
- package/dist/commands/extensions/remove.js +77 -0
- package/dist/commands/extensions/remove.js.map +1 -0
- package/dist/commands/extensions/render.d.ts +16 -0
- package/dist/commands/extensions/render.d.ts.map +1 -0
- package/dist/commands/extensions/render.js +25 -0
- package/dist/commands/extensions/render.js.map +1 -0
- package/dist/commands/extensions/run.d.ts +30 -0
- package/dist/commands/extensions/run.d.ts.map +1 -0
- package/dist/commands/extensions/run.js +292 -0
- package/dist/commands/extensions/run.js.map +1 -0
- package/dist/commands/extensions/secret-store.d.ts +15 -0
- package/dist/commands/extensions/secret-store.d.ts.map +1 -0
- package/dist/commands/extensions/secret-store.js +164 -0
- package/dist/commands/extensions/secret-store.js.map +1 -0
- package/dist/commands/extensions/setup.d.ts +17 -0
- package/dist/commands/extensions/setup.d.ts.map +1 -0
- package/dist/commands/extensions/setup.js +94 -0
- package/dist/commands/extensions/setup.js.map +1 -0
- package/dist/commands/extensions/source.d.ts +47 -0
- package/dist/commands/extensions/source.d.ts.map +1 -0
- package/dist/commands/extensions/source.js +142 -0
- package/dist/commands/extensions/source.js.map +1 -0
- package/dist/commands/extensions/state.d.ts +62 -0
- package/dist/commands/extensions/state.d.ts.map +1 -0
- package/dist/commands/extensions/state.js +177 -0
- package/dist/commands/extensions/state.js.map +1 -0
- package/dist/commands/extensions/status.d.ts +9 -0
- package/dist/commands/extensions/status.d.ts.map +1 -0
- package/dist/commands/extensions/status.js +239 -0
- package/dist/commands/extensions/status.js.map +1 -0
- package/dist/commands/extensions.d.ts +3 -0
- package/dist/commands/extensions.d.ts.map +1 -0
- package/dist/commands/extensions.js +223 -0
- package/dist/commands/extensions.js.map +1 -0
- package/dist/commands/flow/index.d.ts +3 -0
- package/dist/commands/flow/index.d.ts.map +1 -0
- package/dist/commands/flow/index.js +295 -0
- package/dist/commands/flow/index.js.map +1 -0
- package/dist/commands/flow/limits.d.ts +12 -0
- package/dist/commands/flow/limits.d.ts.map +1 -0
- package/dist/commands/flow/limits.js +13 -0
- package/dist/commands/flow/limits.js.map +1 -0
- package/dist/commands/flow/output.d.ts +8 -0
- package/dist/commands/flow/output.d.ts.map +1 -0
- package/dist/commands/flow/output.js +11 -0
- package/dist/commands/flow/output.js.map +1 -0
- package/dist/commands/flow/render.d.ts +51 -0
- package/dist/commands/flow/render.d.ts.map +1 -0
- package/dist/commands/flow/render.js +220 -0
- package/dist/commands/flow/render.js.map +1 -0
- package/dist/commands/flow/select.d.ts +31 -0
- package/dist/commands/flow/select.d.ts.map +1 -0
- package/dist/commands/flow/select.js +62 -0
- package/dist/commands/flow/select.js.map +1 -0
- package/dist/commands/graph/boundaries-input.d.ts +26 -0
- package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
- package/dist/commands/graph/boundaries-input.js +54 -0
- package/dist/commands/graph/boundaries-input.js.map +1 -0
- package/dist/commands/graph/boundaries.d.ts +4 -0
- package/dist/commands/graph/boundaries.d.ts.map +1 -0
- package/dist/commands/graph/boundaries.js +141 -0
- package/dist/commands/graph/boundaries.js.map +1 -0
- package/dist/commands/graph/bounds.d.ts +16 -0
- package/dist/commands/graph/bounds.d.ts.map +1 -0
- package/dist/commands/graph/bounds.js +22 -0
- package/dist/commands/graph/bounds.js.map +1 -0
- package/dist/commands/graph/category-clusters.d.ts +20 -0
- package/dist/commands/graph/category-clusters.d.ts.map +1 -0
- package/dist/commands/graph/category-clusters.js +158 -0
- package/dist/commands/graph/category-clusters.js.map +1 -0
- package/dist/commands/graph/feature-3d.d.ts +22 -0
- package/dist/commands/graph/feature-3d.d.ts.map +1 -0
- package/dist/commands/graph/feature-3d.js +114 -0
- package/dist/commands/graph/feature-3d.js.map +1 -0
- package/dist/commands/graph/feature-clusters.d.ts +17 -0
- package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
- package/dist/commands/graph/feature-clusters.js +94 -0
- package/dist/commands/graph/feature-clusters.js.map +1 -0
- package/dist/commands/graph/feature-html.d.ts +26 -0
- package/dist/commands/graph/feature-html.d.ts.map +1 -0
- package/dist/commands/graph/feature-html.js +314 -0
- package/dist/commands/graph/feature-html.js.map +1 -0
- package/dist/commands/graph/feature-map.d.ts +31 -0
- package/dist/commands/graph/feature-map.d.ts.map +1 -0
- package/dist/commands/graph/feature-map.js +217 -0
- package/dist/commands/graph/feature-map.js.map +1 -0
- package/dist/commands/graph/feature-model.d.ts +55 -0
- package/dist/commands/graph/feature-model.d.ts.map +1 -0
- package/dist/commands/graph/feature-model.js +167 -0
- package/dist/commands/graph/feature-model.js.map +1 -0
- package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
- package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
- package/dist/commands/graph/feature-untangle-motion.js +155 -0
- package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
- package/dist/commands/graph/index.d.ts +3 -0
- package/dist/commands/graph/index.d.ts.map +1 -0
- package/dist/commands/graph/index.js +414 -0
- package/dist/commands/graph/index.js.map +1 -0
- package/dist/commands/graph/render.d.ts +63 -0
- package/dist/commands/graph/render.d.ts.map +1 -0
- package/dist/commands/graph/render.js +352 -0
- package/dist/commands/graph/render.js.map +1 -0
- package/dist/commands/graph/select.d.ts +34 -0
- package/dist/commands/graph/select.d.ts.map +1 -0
- package/dist/commands/graph/select.js +55 -0
- package/dist/commands/graph/select.js.map +1 -0
- package/dist/commands/index/index.d.ts +6 -0
- package/dist/commands/index/index.d.ts.map +1 -0
- package/dist/commands/index/index.js +461 -0
- package/dist/commands/index/index.js.map +1 -0
- package/dist/commands/index/render.d.ts +53 -0
- package/dist/commands/index/render.d.ts.map +1 -0
- package/dist/commands/index/render.js +205 -0
- package/dist/commands/index/render.js.map +1 -0
- package/dist/commands/index/target.d.ts +34 -0
- package/dist/commands/index/target.d.ts.map +1 -0
- package/dist/commands/index/target.js +97 -0
- package/dist/commands/index/target.js.map +1 -0
- package/dist/commands/index-watch.d.ts +30 -0
- package/dist/commands/index-watch.d.ts.map +1 -0
- package/dist/commands/index-watch.js +138 -0
- package/dist/commands/index-watch.js.map +1 -0
- package/dist/commands/init/command.d.ts +25 -0
- package/dist/commands/init/command.d.ts.map +1 -0
- package/dist/commands/init/command.js +198 -0
- package/dist/commands/init/command.js.map +1 -0
- package/dist/commands/init/config-draft.d.ts +48 -0
- package/dist/commands/init/config-draft.d.ts.map +1 -0
- package/dist/commands/init/config-draft.js +201 -0
- package/dist/commands/init/config-draft.js.map +1 -0
- package/dist/commands/init/diff.d.ts +33 -0
- package/dist/commands/init/diff.d.ts.map +1 -0
- package/dist/commands/init/diff.js +109 -0
- package/dist/commands/init/diff.js.map +1 -0
- package/dist/commands/init/http-probe.d.ts +26 -0
- package/dist/commands/init/http-probe.d.ts.map +1 -0
- package/dist/commands/init/http-probe.js +144 -0
- package/dist/commands/init/http-probe.js.map +1 -0
- package/dist/commands/init/ignore-rules.d.ts +70 -0
- package/dist/commands/init/ignore-rules.d.ts.map +1 -0
- package/dist/commands/init/ignore-rules.js +146 -0
- package/dist/commands/init/ignore-rules.js.map +1 -0
- package/dist/commands/init/index.d.ts +33 -0
- package/dist/commands/init/index.d.ts.map +1 -0
- package/dist/commands/init/index.js +32 -0
- package/dist/commands/init/index.js.map +1 -0
- package/dist/commands/init/integrations-apply.d.ts +50 -0
- package/dist/commands/init/integrations-apply.d.ts.map +1 -0
- package/dist/commands/init/integrations-apply.js +452 -0
- package/dist/commands/init/integrations-apply.js.map +1 -0
- package/dist/commands/init/integrations-plan.d.ts +68 -0
- package/dist/commands/init/integrations-plan.d.ts.map +1 -0
- package/dist/commands/init/integrations-plan.js +515 -0
- package/dist/commands/init/integrations-plan.js.map +1 -0
- package/dist/commands/init/integrations.d.ts +5 -0
- package/dist/commands/init/integrations.d.ts.map +1 -0
- package/dist/commands/init/integrations.js +4 -0
- package/dist/commands/init/integrations.js.map +1 -0
- package/dist/commands/init/languages.d.ts +55 -0
- package/dist/commands/init/languages.d.ts.map +1 -0
- package/dist/commands/init/languages.js +245 -0
- package/dist/commands/init/languages.js.map +1 -0
- package/dist/commands/init/product-context.d.ts +63 -0
- package/dist/commands/init/product-context.d.ts.map +1 -0
- package/dist/commands/init/product-context.js +390 -0
- package/dist/commands/init/product-context.js.map +1 -0
- package/dist/commands/init/render.d.ts +38 -0
- package/dist/commands/init/render.d.ts.map +1 -0
- package/dist/commands/init/render.js +501 -0
- package/dist/commands/init/render.js.map +1 -0
- package/dist/commands/init/report.d.ts +24 -0
- package/dist/commands/init/report.d.ts.map +1 -0
- package/dist/commands/init/report.js +163 -0
- package/dist/commands/init/report.js.map +1 -0
- package/dist/commands/init/run.d.ts +71 -0
- package/dist/commands/init/run.d.ts.map +1 -0
- package/dist/commands/init/run.js +253 -0
- package/dist/commands/init/run.js.map +1 -0
- package/dist/commands/init/services.d.ts +82 -0
- package/dist/commands/init/services.d.ts.map +1 -0
- package/dist/commands/init/services.js +209 -0
- package/dist/commands/init/services.js.map +1 -0
- package/dist/commands/init/storage.d.ts +8 -0
- package/dist/commands/init/storage.d.ts.map +1 -0
- package/dist/commands/init/storage.js +102 -0
- package/dist/commands/init/storage.js.map +1 -0
- package/dist/commands/init/toml.d.ts +65 -0
- package/dist/commands/init/toml.d.ts.map +1 -0
- package/dist/commands/init/toml.js +159 -0
- package/dist/commands/init/toml.js.map +1 -0
- package/dist/commands/init/topology.d.ts +54 -0
- package/dist/commands/init/topology.d.ts.map +1 -0
- package/dist/commands/init/topology.js +146 -0
- package/dist/commands/init/topology.js.map +1 -0
- package/dist/commands/init/types.d.ts +334 -0
- package/dist/commands/init/types.d.ts.map +1 -0
- package/dist/commands/init/types.js +31 -0
- package/dist/commands/init/types.js.map +1 -0
- package/dist/commands/init/wizard-terminal.d.ts +36 -0
- package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
- package/dist/commands/init/wizard-terminal.js +163 -0
- package/dist/commands/init/wizard-terminal.js.map +1 -0
- package/dist/commands/init/wizard.d.ts +25 -0
- package/dist/commands/init/wizard.d.ts.map +1 -0
- package/dist/commands/init/wizard.js +358 -0
- package/dist/commands/init/wizard.js.map +1 -0
- package/dist/commands/mcp.d.ts +4 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +111 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/product-test-runner.d.ts +4 -0
- package/dist/commands/product-test-runner.d.ts.map +1 -0
- package/dist/commands/product-test-runner.js +85 -0
- package/dist/commands/product-test-runner.js.map +1 -0
- package/dist/commands/product.d.ts +16 -0
- package/dist/commands/product.d.ts.map +1 -0
- package/dist/commands/product.js +262 -0
- package/dist/commands/product.js.map +1 -0
- package/dist/commands/query.d.ts +114 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +783 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/scan.d.ts +10 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +302 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sdd.d.ts +24 -0
- package/dist/commands/sdd.d.ts.map +1 -0
- package/dist/commands/sdd.js +195 -0
- package/dist/commands/sdd.js.map +1 -0
- package/dist/commands/unavailable.d.ts +40 -0
- package/dist/commands/unavailable.d.ts.map +1 -0
- package/dist/commands/unavailable.js +73 -0
- package/dist/commands/unavailable.js.map +1 -0
- package/dist/commands/watch/analyze.d.ts +69 -0
- package/dist/commands/watch/analyze.d.ts.map +1 -0
- package/dist/commands/watch/analyze.js +402 -0
- package/dist/commands/watch/analyze.js.map +1 -0
- package/dist/commands/watch/cli.d.ts +8 -0
- package/dist/commands/watch/cli.d.ts.map +1 -0
- package/dist/commands/watch/cli.js +97 -0
- package/dist/commands/watch/cli.js.map +1 -0
- package/dist/commands/watch/delta.d.ts +46 -0
- package/dist/commands/watch/delta.d.ts.map +1 -0
- package/dist/commands/watch/delta.js +170 -0
- package/dist/commands/watch/delta.js.map +1 -0
- package/dist/commands/watch/events.d.ts +214 -0
- package/dist/commands/watch/events.d.ts.map +1 -0
- package/dist/commands/watch/events.js +13 -0
- package/dist/commands/watch/events.js.map +1 -0
- package/dist/commands/watch/index.d.ts +19 -0
- package/dist/commands/watch/index.d.ts.map +1 -0
- package/dist/commands/watch/index.js +15 -0
- package/dist/commands/watch/index.js.map +1 -0
- package/dist/commands/watch/options.d.ts +43 -0
- package/dist/commands/watch/options.d.ts.map +1 -0
- package/dist/commands/watch/options.js +193 -0
- package/dist/commands/watch/options.js.map +1 -0
- package/dist/commands/watch/render.d.ts +26 -0
- package/dist/commands/watch/render.d.ts.map +1 -0
- package/dist/commands/watch/render.js +175 -0
- package/dist/commands/watch/render.js.map +1 -0
- package/dist/commands/watch/run.d.ts +14 -0
- package/dist/commands/watch/run.d.ts.map +1 -0
- package/dist/commands/watch/run.js +460 -0
- package/dist/commands/watch/run.js.map +1 -0
- package/dist/commands/watch/runtime.d.ts +67 -0
- package/dist/commands/watch/runtime.d.ts.map +1 -0
- package/dist/commands/watch/runtime.js +149 -0
- package/dist/commands/watch/runtime.js.map +1 -0
- package/dist/commands/watch-command.d.ts +3 -0
- package/dist/commands/watch-command.d.ts.map +1 -0
- package/dist/commands/watch-command.js +273 -0
- package/dist/commands/watch-command.js.map +1 -0
- package/dist/entry-point.d.ts +11 -0
- package/dist/entry-point.d.ts.map +1 -0
- package/dist/entry-point.js +65 -0
- package/dist/entry-point.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/boundaries-schema.d.ts +262 -0
- package/dist/mcp/boundaries-schema.d.ts.map +1 -0
- package/dist/mcp/boundaries-schema.js +183 -0
- package/dist/mcp/boundaries-schema.js.map +1 -0
- package/dist/mcp/default-runtime.d.ts +16 -0
- package/dist/mcp/default-runtime.d.ts.map +1 -0
- package/dist/mcp/default-runtime.js +718 -0
- package/dist/mcp/default-runtime.js.map +1 -0
- package/dist/mcp/envelope.d.ts +13 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +29 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/output-schemas.d.ts +5928 -0
- package/dist/mcp/output-schemas.d.ts.map +1 -0
- package/dist/mcp/output-schemas.js +2814 -0
- package/dist/mcp/output-schemas.js.map +1 -0
- package/dist/mcp/path-sandbox.d.ts +35 -0
- package/dist/mcp/path-sandbox.d.ts.map +1 -0
- package/dist/mcp/path-sandbox.js +128 -0
- package/dist/mcp/path-sandbox.js.map +1 -0
- package/dist/mcp/server.d.ts +155 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +257 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +20 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +71 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/mcp/tools.d.ts +355 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +319 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +15 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +45 -0
- package/dist/mcp/types.js.map +1 -0
- package/package.json +99 -3
- package/src/cli/args.ts +231 -0
- package/src/cli/command.ts +146 -0
- package/src/cli/deadline.ts +56 -0
- package/src/cli/embedder-deadline.ts +187 -0
- package/src/cli/exit.ts +94 -0
- package/src/cli/graphs.ts +191 -0
- package/src/cli/index-freshness.ts +303 -0
- package/src/cli/index-refresh.ts +125 -0
- package/src/cli/index-state.ts +1217 -0
- package/src/cli/io.ts +56 -0
- package/src/cli/language-support.ts +203 -0
- package/src/cli/renewing-lease.ts +121 -0
- package/src/cli/search-graph-enrichment.ts +639 -0
- package/src/cli/system.ts +94 -0
- package/src/cli/vector-store-policy.ts +213 -0
- package/src/cli/version.ts +2 -0
- package/src/cli/workspace.ts +324 -0
- package/src/commands/complexity.ts +776 -0
- package/src/commands/doctor.languages.ts +187 -0
- package/src/commands/doctor.storage.ts +124 -0
- package/src/commands/doctor.ts +946 -0
- package/src/commands/extensions/add.ts +312 -0
- package/src/commands/extensions/configure.ts +82 -0
- package/src/commands/extensions/container.ts +209 -0
- package/src/commands/extensions/context.ts +109 -0
- package/src/commands/extensions/enable.ts +237 -0
- package/src/commands/extensions/environment.ts +218 -0
- package/src/commands/extensions/feature-scan.ts +232 -0
- package/src/commands/extensions/invoke.ts +368 -0
- package/src/commands/extensions/list.ts +158 -0
- package/src/commands/extensions/logs.ts +104 -0
- package/src/commands/extensions/provision.ts +206 -0
- package/src/commands/extensions/remove.ts +110 -0
- package/src/commands/extensions/render.ts +32 -0
- package/src/commands/extensions/run.ts +386 -0
- package/src/commands/extensions/secret-store.ts +223 -0
- package/src/commands/extensions/setup.ts +140 -0
- package/src/commands/extensions/source.ts +189 -0
- package/src/commands/extensions/state.ts +252 -0
- package/src/commands/extensions/status.ts +320 -0
- package/src/commands/extensions.ts +280 -0
- package/src/commands/flow/index.ts +402 -0
- package/src/commands/flow/limits.ts +14 -0
- package/src/commands/flow/output.ts +16 -0
- package/src/commands/flow/render.ts +318 -0
- package/src/commands/flow/select.ts +101 -0
- package/src/commands/graph/boundaries-input.ts +63 -0
- package/src/commands/graph/boundaries.ts +182 -0
- package/src/commands/graph/bounds.ts +25 -0
- package/src/commands/graph/category-clusters.ts +194 -0
- package/src/commands/graph/feature-3d.ts +141 -0
- package/src/commands/graph/feature-clusters.ts +125 -0
- package/src/commands/graph/feature-html.ts +336 -0
- package/src/commands/graph/feature-map.ts +270 -0
- package/src/commands/graph/feature-model.ts +234 -0
- package/src/commands/graph/feature-untangle-motion.ts +192 -0
- package/src/commands/graph/index.ts +562 -0
- package/src/commands/graph/render.ts +503 -0
- package/src/commands/graph/select.ts +77 -0
- package/src/commands/index/index.ts +595 -0
- package/src/commands/index/render.ts +325 -0
- package/src/commands/index/target.ts +136 -0
- package/src/commands/index-watch.ts +206 -0
- package/src/commands/init/command.ts +238 -0
- package/src/commands/init/config-draft.ts +235 -0
- package/src/commands/init/diff.ts +117 -0
- package/src/commands/init/http-probe.ts +150 -0
- package/src/commands/init/ignore-rules.ts +170 -0
- package/src/commands/init/index.ts +63 -0
- package/src/commands/init/integrations-apply.ts +618 -0
- package/src/commands/init/integrations-plan.ts +634 -0
- package/src/commands/init/integrations.ts +8 -0
- package/src/commands/init/languages.ts +320 -0
- package/src/commands/init/product-context.ts +576 -0
- package/src/commands/init/render.ts +598 -0
- package/src/commands/init/report.ts +204 -0
- package/src/commands/init/run.ts +349 -0
- package/src/commands/init/services.ts +271 -0
- package/src/commands/init/storage.ts +136 -0
- package/src/commands/init/toml.ts +174 -0
- package/src/commands/init/topology.ts +192 -0
- package/src/commands/init/types.ts +366 -0
- package/src/commands/init/wizard-terminal.ts +206 -0
- package/src/commands/init/wizard.ts +450 -0
- package/src/commands/mcp.ts +123 -0
- package/src/commands/product-test-runner.ts +80 -0
- package/src/commands/product.ts +331 -0
- package/src/commands/query.ts +1032 -0
- package/src/commands/scan.ts +360 -0
- package/src/commands/sdd.ts +243 -0
- package/src/commands/unavailable.ts +92 -0
- package/src/commands/watch/README.md +160 -0
- package/src/commands/watch/analyze.ts +600 -0
- package/src/commands/watch/cli.ts +108 -0
- package/src/commands/watch/delta.ts +186 -0
- package/src/commands/watch/events.ts +235 -0
- package/src/commands/watch/index.ts +53 -0
- package/src/commands/watch/options.ts +234 -0
- package/src/commands/watch/render.ts +240 -0
- package/src/commands/watch/run.ts +553 -0
- package/src/commands/watch/runtime.ts +167 -0
- package/src/commands/watch-command.ts +294 -0
- package/src/entry-point.ts +67 -0
- package/src/index.ts +291 -0
- package/src/mcp/boundaries-schema.ts +193 -0
- package/src/mcp/default-runtime.ts +1034 -0
- package/src/mcp/envelope.ts +57 -0
- package/src/mcp/index.ts +28 -0
- package/src/mcp/output-schemas.ts +3071 -0
- package/src/mcp/path-sandbox.ts +156 -0
- package/src/mcp/server.ts +358 -0
- package/src/mcp/stdio.ts +92 -0
- package/src/mcp/tools.ts +563 -0
- package/src/mcp/types.ts +66 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `untangle extensions list`
|
|
3
|
+
*
|
|
4
|
+
* Shows what is installed for THIS user: name, license, status, last run.
|
|
5
|
+
*
|
|
6
|
+
* The listing is also where the two silences E4 forbids are broken. A
|
|
7
|
+
* manifest that was found but rejected, and a manifest that was found but
|
|
8
|
+
* deliberately not loaded — a project-local one above all — both appear with
|
|
9
|
+
* their reason. So do the roots that were searched, including the ones that
|
|
10
|
+
* do not exist: "no extensions" must be a statement about a place, not an
|
|
11
|
+
* unexplained blank.
|
|
12
|
+
*/
|
|
13
|
+
import { compareCodepoints } from "@untangle-code/domain";
|
|
14
|
+
|
|
15
|
+
import { boolFlag, stringFlag, type ParsedArgs } from "../../cli/args.js";
|
|
16
|
+
import { EXIT } from "../../cli/exit.js";
|
|
17
|
+
import { line, note, type Io } from "../../cli/io.js";
|
|
18
|
+
|
|
19
|
+
import { gateFor, loadExtensionContext } from "./context.js";
|
|
20
|
+
import type { ExtensionEnvironmentV1 } from "./environment.js";
|
|
21
|
+
import { emitJson, renderTable } from "./render.js";
|
|
22
|
+
import type { LastRunRecordV1 } from "./state.js";
|
|
23
|
+
|
|
24
|
+
interface ListRowV1 {
|
|
25
|
+
id: string;
|
|
26
|
+
displayName: string;
|
|
27
|
+
category: string;
|
|
28
|
+
invocation: string[];
|
|
29
|
+
outputFormat: string;
|
|
30
|
+
license: { spdxId: string; usageRestriction: string; gateStatus: string; gateReason: string };
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
status: string;
|
|
33
|
+
networkAccess: string;
|
|
34
|
+
/** The manifest pin (X6); null when the extension is not container-invoked. */
|
|
35
|
+
pin: { image: string; digest: string } | null;
|
|
36
|
+
manifestPath: string;
|
|
37
|
+
origin: string;
|
|
38
|
+
lastRun?: LastRunRecordV1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runList(
|
|
42
|
+
environment: ExtensionEnvironmentV1,
|
|
43
|
+
args: ParsedArgs,
|
|
44
|
+
io: Io,
|
|
45
|
+
format: "text" | "json",
|
|
46
|
+
): Promise<number> {
|
|
47
|
+
const context = await loadExtensionContext(environment);
|
|
48
|
+
const categoryFilter = stringFlag(args, "category")
|
|
49
|
+
?.split(",")
|
|
50
|
+
.map((entry) => entry.trim())
|
|
51
|
+
.filter((entry) => entry !== "");
|
|
52
|
+
const enabledOnly = boolFlag(args, "enabled-only");
|
|
53
|
+
|
|
54
|
+
const rows: ListRowV1[] = [];
|
|
55
|
+
for (const extension of context.discovery.extensions) {
|
|
56
|
+
const manifest = extension.manifest;
|
|
57
|
+
if (categoryFilter !== undefined && !categoryFilter.includes(manifest.category)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const enabled = context.state.enabled.includes(manifest.id);
|
|
61
|
+
if (enabledOnly && !enabled) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const gate = gateFor(context, extension);
|
|
65
|
+
const lastRun = context.state.lastRuns[manifest.id];
|
|
66
|
+
rows.push({
|
|
67
|
+
id: manifest.id,
|
|
68
|
+
displayName: manifest.displayName,
|
|
69
|
+
category: manifest.category,
|
|
70
|
+
invocation: manifest.invocation,
|
|
71
|
+
outputFormat: manifest.outputFormat,
|
|
72
|
+
license: {
|
|
73
|
+
spdxId: manifest.license.spdxId,
|
|
74
|
+
usageRestriction: manifest.license.usageRestriction,
|
|
75
|
+
gateStatus: gate.tool.status,
|
|
76
|
+
gateReason: gate.tool.reason,
|
|
77
|
+
},
|
|
78
|
+
enabled,
|
|
79
|
+
status: statusOf(enabled, gate.allowed, gate.tool.status),
|
|
80
|
+
networkAccess: manifest.networkAccess,
|
|
81
|
+
pin:
|
|
82
|
+
manifest.container === undefined
|
|
83
|
+
? null
|
|
84
|
+
: { image: manifest.container.image, digest: manifest.container.digest },
|
|
85
|
+
manifestPath: extension.manifestPath,
|
|
86
|
+
origin: extension.origin,
|
|
87
|
+
...(lastRun === undefined ? {} : { lastRun }),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
rows.sort((left, right) => compareCodepoints(left.id, right.id));
|
|
91
|
+
|
|
92
|
+
if (format === "json") {
|
|
93
|
+
emitJson(io, {
|
|
94
|
+
command: "extensions list",
|
|
95
|
+
rootsScanned: context.discovery.rootsScanned,
|
|
96
|
+
projectRootsExcluded: environment.projectRoots,
|
|
97
|
+
extensions: rows,
|
|
98
|
+
rejected: context.discovery.rejected,
|
|
99
|
+
ignored: context.discovery.ignored,
|
|
100
|
+
warnings: context.warnings,
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
if (rows.length === 0) {
|
|
104
|
+
line(io, "no extensions installed.");
|
|
105
|
+
} else {
|
|
106
|
+
for (const rendered of renderTable(
|
|
107
|
+
["ID", "LICENSE", "RESTRICTION", "STATUS", "LAST RUN"],
|
|
108
|
+
rows.map((row) => [
|
|
109
|
+
row.id,
|
|
110
|
+
row.license.spdxId,
|
|
111
|
+
row.license.usageRestriction,
|
|
112
|
+
row.status,
|
|
113
|
+
describeLastRun(row.lastRun),
|
|
114
|
+
]),
|
|
115
|
+
)) {
|
|
116
|
+
line(io, rendered);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
line(io, "");
|
|
120
|
+
line(io, "roots searched (project directories are never searched):");
|
|
121
|
+
for (const root of context.discovery.rootsScanned) {
|
|
122
|
+
line(io, ` ${root.root}${root.exists ? "" : " (does not exist)"}`);
|
|
123
|
+
}
|
|
124
|
+
if (environment.projectRoots.length > 0) {
|
|
125
|
+
line(io, ` excluded as project directories: ${environment.projectRoots.join(", ")}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (const rejected of context.discovery.rejected) {
|
|
130
|
+
note(io, `rejected ${rejected.manifestPath}:`);
|
|
131
|
+
for (const issue of rejected.issues) {
|
|
132
|
+
note(io, ` ${issue.field}: ${issue.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const ignored of context.discovery.ignored) {
|
|
136
|
+
note(io, `ignored ${ignored.manifestPath} (${ignored.reason}): ${ignored.detail}`);
|
|
137
|
+
}
|
|
138
|
+
for (const warning of context.warnings) {
|
|
139
|
+
note(io, `warning: ${warning}`);
|
|
140
|
+
}
|
|
141
|
+
return EXIT.ok;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function statusOf(enabled: boolean, gateAllowed: boolean, gateStatus: string): string {
|
|
145
|
+
if (!gateAllowed) {
|
|
146
|
+
return `blocked (license ${gateStatus})`;
|
|
147
|
+
}
|
|
148
|
+
return enabled ? "enabled" : "installed, not enabled";
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function describeLastRun(lastRun: LastRunRecordV1 | undefined): string {
|
|
152
|
+
if (lastRun === undefined) {
|
|
153
|
+
return "never";
|
|
154
|
+
}
|
|
155
|
+
const when = lastRun.finishedAt ?? lastRun.startedAt;
|
|
156
|
+
const suffix = lastRun.errorCode === undefined ? "" : ` ${lastRun.errorCode}`;
|
|
157
|
+
return `${when} ${lastRun.exitStatus}${suffix} (${String(lastRun.findingsTotal)} findings)`;
|
|
158
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `untangle extensions logs <id>`
|
|
3
|
+
*
|
|
4
|
+
* Liest ausschliesslich die Logs des EIGENEN Containers (extensions.md §11.1).
|
|
5
|
+
* Die Besitzprobe liegt im Container-Adapter: ohne beide Labels wird nichts
|
|
6
|
+
* gelesen, auch wenn ein Container des erwarteten Namens existiert. Der Name
|
|
7
|
+
* `untangle-ext-<id>` ist vorhersagbar, und niemand hindert einen fremden
|
|
8
|
+
* Container daran, so zu heissen.
|
|
9
|
+
*/
|
|
10
|
+
import {
|
|
11
|
+
defaultProcessLimits,
|
|
12
|
+
createNodeProcessRunner,
|
|
13
|
+
redactSecrets,
|
|
14
|
+
} from "@untangle-code/extension-runtime";
|
|
15
|
+
|
|
16
|
+
import { integerFlag, type ParsedArgs } from "../../cli/args.js";
|
|
17
|
+
import { EXIT, OperationalError, UsageError } from "../../cli/exit.js";
|
|
18
|
+
import { line, type Io } from "../../cli/io.js";
|
|
19
|
+
|
|
20
|
+
import { createContainerCli } from "./container.js";
|
|
21
|
+
import { explainMissing, findExtension, loadExtensionContext } from "./context.js";
|
|
22
|
+
import type { ExtensionEnvironmentV1 } from "./environment.js";
|
|
23
|
+
import { composeFilePath } from "./provision.js";
|
|
24
|
+
import { emitJson } from "./render.js";
|
|
25
|
+
import { readStoredSecrets } from "./secret-store.js";
|
|
26
|
+
|
|
27
|
+
export async function runLogs(
|
|
28
|
+
environment: ExtensionEnvironmentV1,
|
|
29
|
+
args: ParsedArgs,
|
|
30
|
+
io: Io,
|
|
31
|
+
format: "text" | "json",
|
|
32
|
+
): Promise<number> {
|
|
33
|
+
const extensionId = args.positionals[1];
|
|
34
|
+
if (extensionId === undefined) {
|
|
35
|
+
throw new UsageError(
|
|
36
|
+
"`untangle extensions logs` needs an extension id.",
|
|
37
|
+
"Run `untangle extensions list` to see the installed ids.",
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const context = await loadExtensionContext(environment);
|
|
41
|
+
const extension = findExtension(context, extensionId);
|
|
42
|
+
if (extension === null) {
|
|
43
|
+
throw new OperationalError(
|
|
44
|
+
explainMissing(context, extensionId),
|
|
45
|
+
"Install it first: untangle extensions add --from=<path-or-url>",
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const manifest = extension.manifest;
|
|
49
|
+
if (manifest.container === undefined) {
|
|
50
|
+
throw new OperationalError(
|
|
51
|
+
`"${extensionId}" declares no container; there are no container logs to read.`,
|
|
52
|
+
"Logs exist only for extensions Untangle provisions as a container.",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const tail = integerFlag(args, "tail", 200);
|
|
57
|
+
if (tail <= 0) {
|
|
58
|
+
throw new UsageError("--tail expects a positive number of lines.", "Example: --tail=200");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Include bootstrap credentials and stored values even when an environment
|
|
62
|
+
// override is active: old credentials can still occur in retained logs.
|
|
63
|
+
const stored = await readStoredSecrets(environment, manifest);
|
|
64
|
+
const secrets = manifest.secrets.flatMap((secret) =>
|
|
65
|
+
[stored[secret.name], environment.env[secret.envVar]].filter((value): value is string =>
|
|
66
|
+
Boolean(value),
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
const containerCli = createContainerCli({
|
|
70
|
+
processRunner: createNodeProcessRunner(environment.clock),
|
|
71
|
+
limits: { ...defaultProcessLimits(), timeoutMs: 60_000 },
|
|
72
|
+
...(environment.env["UNTANGLE_CONTAINER_CLI"] === undefined
|
|
73
|
+
? {}
|
|
74
|
+
: { command: environment.env["UNTANGLE_CONTAINER_CLI"] }),
|
|
75
|
+
});
|
|
76
|
+
const result = await containerCli.logs({
|
|
77
|
+
manifest,
|
|
78
|
+
composeFilePath: composeFilePath(environment.userDataDir, manifest.id),
|
|
79
|
+
tail,
|
|
80
|
+
});
|
|
81
|
+
result.detail = redactSecrets(result.detail, secrets);
|
|
82
|
+
result.text = redactSecrets(result.text, secrets);
|
|
83
|
+
|
|
84
|
+
if (format === "json") {
|
|
85
|
+
emitJson(io, {
|
|
86
|
+
command: "extensions logs",
|
|
87
|
+
extensionId,
|
|
88
|
+
ok: result.ok,
|
|
89
|
+
detail: result.detail,
|
|
90
|
+
lines: result.text === "" ? [] : result.text.split("\n"),
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
if (!result.ok) {
|
|
94
|
+
throw new OperationalError(
|
|
95
|
+
`No logs were read for "${extensionId}": ${result.detail}`,
|
|
96
|
+
`Check the container with untangle extensions status ${extensionId}`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
for (const entry of result.text.split("\n")) {
|
|
100
|
+
line(io, entry);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result.ok ? EXIT.ok : EXIT.operational;
|
|
104
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bereitstellung eines Container-Dienstes aus dem Manifest (extensions.md §6.2).
|
|
3
|
+
*
|
|
4
|
+
* Der Ablauf ist bewusst kurz und ohne Werkzeugwissen:
|
|
5
|
+
*
|
|
6
|
+
* Manifest → Compose-Datei rendern → up → Healthcheck des Manifests
|
|
7
|
+
*
|
|
8
|
+
* Die Compose-Datei entsteht bei jedem Lauf neu aus dem validierten Manifest.
|
|
9
|
+
* Damit gilt der gepinnte Digest wirklich, die Ports binden wirklich an
|
|
10
|
+
* Loopback und die Labels sind wirklich gesetzt — statt in einer mitgebrachten
|
|
11
|
+
* YAML behauptet zu werden, die Untangle nicht geprueft hat.
|
|
12
|
+
*
|
|
13
|
+
* Auf die Gesundheit wartet Untangle SELBST, ueber den Healthcheck aus dem
|
|
14
|
+
* Manifest, statt einen in den Container zu rendern. Ein Healthcheck im
|
|
15
|
+
* Container muesste voraussetzen, welches Programm darin liegt, um eine URL
|
|
16
|
+
* abzufragen — genau das Werkzeugwissen, das X9 aus dem Quelltext heraushaelt.
|
|
17
|
+
*/
|
|
18
|
+
import { dirname, join } from "node:path";
|
|
19
|
+
|
|
20
|
+
import type { ExtensionManifestV1, FileSystemPort } from "@untangle-code/domain";
|
|
21
|
+
import {
|
|
22
|
+
renderComposeFile,
|
|
23
|
+
type ContainerRuntimePort,
|
|
24
|
+
type ContainerStateV1,
|
|
25
|
+
type HttpRunnerPort,
|
|
26
|
+
type ProcessLimitsV1,
|
|
27
|
+
} from "@untangle-code/extension-runtime";
|
|
28
|
+
|
|
29
|
+
/** Ort der gerenderten Datei: im Nutzer-Datenverzeichnis, nie im Projekt. */
|
|
30
|
+
export function composeFilePath(userDataDirectory: string, extensionId: string): string {
|
|
31
|
+
return join(userDataDirectory, "extensions", extensionId, "compose.yaml");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Der erste Hostport des Manifests, mit optionaler Ueberschreibung. */
|
|
35
|
+
export function primaryHostPort(
|
|
36
|
+
manifest: ExtensionManifestV1,
|
|
37
|
+
overrides: Readonly<Record<string, number>> = {},
|
|
38
|
+
): number | undefined {
|
|
39
|
+
const port = manifest.container?.ports[0];
|
|
40
|
+
if (port === undefined) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return overrides[port.name] ?? port.hostPortDefault;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ProvisionDeps {
|
|
47
|
+
fs: FileSystemPort;
|
|
48
|
+
container: ContainerRuntimePort;
|
|
49
|
+
httpRunner: HttpRunnerPort;
|
|
50
|
+
limits: ProcessLimitsV1;
|
|
51
|
+
/** Wartepause zwischen zwei Gesundheitsproben; injiziert, damit Tests nicht schlafen. */
|
|
52
|
+
wait: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ProvisionResultV1 {
|
|
56
|
+
/** True, wenn der Dienst am Ende gesund erreichbar ist. */
|
|
57
|
+
healthy: boolean;
|
|
58
|
+
/** Was getan wurde — auch wenn nichts getan wurde (E4). */
|
|
59
|
+
steps: string[];
|
|
60
|
+
state: ContainerStateV1;
|
|
61
|
+
detail: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Startet den Dienst, falls noetig, und wartet auf seine Gesundheit.
|
|
66
|
+
*
|
|
67
|
+
* Ein bereits laufender, Untangle gehoerender Container wird NICHT neu
|
|
68
|
+
* gestartet: der Lauf soll den Dienst benutzen, nicht bewirtschaften.
|
|
69
|
+
*/
|
|
70
|
+
export async function provisionContainer(
|
|
71
|
+
deps: ProvisionDeps,
|
|
72
|
+
input: {
|
|
73
|
+
manifest: ExtensionManifestV1;
|
|
74
|
+
userDataDirectory: string;
|
|
75
|
+
hostPorts?: Readonly<Record<string, number>>;
|
|
76
|
+
workspacePath?: string;
|
|
77
|
+
signal?: AbortSignal;
|
|
78
|
+
},
|
|
79
|
+
): Promise<ProvisionResultV1> {
|
|
80
|
+
const steps: string[] = [];
|
|
81
|
+
const manifest = input.manifest;
|
|
82
|
+
const container = manifest.container;
|
|
83
|
+
if (container === undefined) {
|
|
84
|
+
const state: ContainerStateV1 = {
|
|
85
|
+
exists: false,
|
|
86
|
+
running: false,
|
|
87
|
+
ownedByUntangle: false,
|
|
88
|
+
detail: "the manifest declares no container block",
|
|
89
|
+
};
|
|
90
|
+
return { healthy: false, steps, state, detail: state.detail };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const runtime = await deps.container.available(
|
|
94
|
+
input.signal === undefined ? {} : { signal: input.signal },
|
|
95
|
+
);
|
|
96
|
+
steps.push(runtime.detail);
|
|
97
|
+
if (!runtime.available) {
|
|
98
|
+
return {
|
|
99
|
+
healthy: false,
|
|
100
|
+
steps,
|
|
101
|
+
state: {
|
|
102
|
+
exists: false,
|
|
103
|
+
running: false,
|
|
104
|
+
ownedByUntangle: false,
|
|
105
|
+
detail: runtime.detail,
|
|
106
|
+
},
|
|
107
|
+
detail: runtime.detail,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const path = composeFilePath(input.userDataDirectory, manifest.id);
|
|
112
|
+
const yaml = renderComposeFile({
|
|
113
|
+
manifest,
|
|
114
|
+
...(input.hostPorts === undefined ? {} : { hostPorts: input.hostPorts }),
|
|
115
|
+
...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
|
|
116
|
+
});
|
|
117
|
+
await deps.fs.mkdir(dirname(path), { recursive: true });
|
|
118
|
+
await deps.fs.writeFile(path, new TextEncoder().encode(yaml));
|
|
119
|
+
steps.push(`rendered ${path} from the manifest (image pinned to ${container.digest})`);
|
|
120
|
+
|
|
121
|
+
let state = await deps.container.inspect(
|
|
122
|
+
manifest,
|
|
123
|
+
input.signal === undefined ? {} : { signal: input.signal },
|
|
124
|
+
);
|
|
125
|
+
if (state.exists && !state.ownedByUntangle) {
|
|
126
|
+
steps.push(state.detail);
|
|
127
|
+
return { healthy: false, steps, state, detail: state.detail };
|
|
128
|
+
}
|
|
129
|
+
if (state.running) {
|
|
130
|
+
steps.push("the container was already running; Untangle did not restart it");
|
|
131
|
+
} else {
|
|
132
|
+
const up = await deps.container.up(
|
|
133
|
+
{ manifest, composeFilePath: path },
|
|
134
|
+
input.signal === undefined ? {} : { signal: input.signal },
|
|
135
|
+
);
|
|
136
|
+
steps.push(up.detail);
|
|
137
|
+
if (!up.ok) {
|
|
138
|
+
return { healthy: false, steps, state, detail: up.detail };
|
|
139
|
+
}
|
|
140
|
+
state = await deps.container.inspect(
|
|
141
|
+
manifest,
|
|
142
|
+
input.signal === undefined ? {} : { signal: input.signal },
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const health = await waitForHealth(deps, {
|
|
147
|
+
manifest,
|
|
148
|
+
...(input.hostPorts === undefined ? {} : { hostPorts: input.hostPorts }),
|
|
149
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
150
|
+
});
|
|
151
|
+
steps.push(health.detail);
|
|
152
|
+
return { healthy: health.healthy, steps, state, detail: health.detail };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Fragt den Healthcheck des Manifests ab, bis er antwortet oder die erklaerten
|
|
157
|
+
* Versuche erschoepft sind. Ein Dienst, der lange startet, ist kein Fehler —
|
|
158
|
+
* ein Dienst, der nie antwortet, schon, und dann steht der Grund da.
|
|
159
|
+
*/
|
|
160
|
+
async function waitForHealth(
|
|
161
|
+
deps: ProvisionDeps,
|
|
162
|
+
input: {
|
|
163
|
+
manifest: ExtensionManifestV1;
|
|
164
|
+
hostPorts?: Readonly<Record<string, number>>;
|
|
165
|
+
signal?: AbortSignal;
|
|
166
|
+
},
|
|
167
|
+
): Promise<{ healthy: boolean; detail: string }> {
|
|
168
|
+
const check = input.manifest.container?.healthcheck;
|
|
169
|
+
if (check === undefined || check.kind !== "http" || check.httpPath === undefined) {
|
|
170
|
+
return {
|
|
171
|
+
healthy: true,
|
|
172
|
+
detail:
|
|
173
|
+
"the manifest declares no http healthcheck; Untangle treats the container as ready " +
|
|
174
|
+
"without probing and says so rather than implying it checked",
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const port = primaryHostPort(input.manifest, input.hostPorts ?? {});
|
|
178
|
+
if (port === undefined) {
|
|
179
|
+
return { healthy: false, detail: "the manifest declares a healthcheck but no port" };
|
|
180
|
+
}
|
|
181
|
+
const url = `http://127.0.0.1:${String(port)}${check.httpPath}`;
|
|
182
|
+
let lastDetail = "no probe was made";
|
|
183
|
+
for (let attempt = 1; attempt <= check.retries; attempt += 1) {
|
|
184
|
+
const response = await deps.httpRunner.request(
|
|
185
|
+
{ url, method: "GET" },
|
|
186
|
+
{ ...deps.limits, timeoutMs: check.timeoutMs },
|
|
187
|
+
input.signal === undefined ? {} : { signal: input.signal },
|
|
188
|
+
);
|
|
189
|
+
if (response.outcome === "completed" && (response.status ?? 500) < 400) {
|
|
190
|
+
return {
|
|
191
|
+
healthy: true,
|
|
192
|
+
detail: `healthcheck ${url} answered ${String(response.status)} after ${String(attempt)} attempt(s)`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
lastDetail = `attempt ${String(attempt)}: ${response.outcome}${
|
|
196
|
+
response.status === undefined ? "" : ` (status ${String(response.status)})`
|
|
197
|
+
}`;
|
|
198
|
+
if (attempt < check.retries) {
|
|
199
|
+
await deps.wait(check.intervalMs, input.signal);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
healthy: false,
|
|
204
|
+
detail: `healthcheck ${url} did not answer within ${String(check.retries)} attempts — ${lastDetail}`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `untangle extensions remove <id>`
|
|
3
|
+
*
|
|
4
|
+
* Deletes one installed extension directory from the user's extension root.
|
|
5
|
+
*
|
|
6
|
+
* Two guards. The directory must lie inside a resolved extension root — the
|
|
7
|
+
* command deletes recursively, and a recursive delete driven by an id from
|
|
8
|
+
* the command line has to prove where it is pointing. And it must not lie
|
|
9
|
+
* inside a project directory, which would mean the boundary was crossed
|
|
10
|
+
* earlier and deleting is not the right repair.
|
|
11
|
+
*
|
|
12
|
+
* The license acknowledgment is kept by default. It is a personal declaration
|
|
13
|
+
* about a tool's terms, not a property of the installed file, and
|
|
14
|
+
* re-installing the same tool should not quietly need a fresh one. Dropping
|
|
15
|
+
* it is `--revoke-license`, what extensions.md §9.3 calls revocation.
|
|
16
|
+
*/
|
|
17
|
+
import { dirname } from "node:path";
|
|
18
|
+
|
|
19
|
+
import { boolFlag, type ParsedArgs } from "../../cli/args.js";
|
|
20
|
+
import { EXIT, OperationalError, UsageError } from "../../cli/exit.js";
|
|
21
|
+
import { line, note, type Io } from "../../cli/io.js";
|
|
22
|
+
|
|
23
|
+
import { explainMissing, findExtension, loadExtensionContext } from "./context.js";
|
|
24
|
+
import { isInsideAnyRoot, type ExtensionEnvironmentV1 } from "./environment.js";
|
|
25
|
+
import { emitJson } from "./render.js";
|
|
26
|
+
import { removeAcknowledgments, saveAcknowledgments, saveCliState } from "./state.js";
|
|
27
|
+
|
|
28
|
+
export async function runRemove(
|
|
29
|
+
environment: ExtensionEnvironmentV1,
|
|
30
|
+
args: ParsedArgs,
|
|
31
|
+
io: Io,
|
|
32
|
+
format: "text" | "json",
|
|
33
|
+
): Promise<number> {
|
|
34
|
+
const extensionId = args.positionals[1];
|
|
35
|
+
if (extensionId === undefined) {
|
|
36
|
+
throw new UsageError(
|
|
37
|
+
"`untangle extensions remove` needs an extension id.",
|
|
38
|
+
"Run `untangle extensions list` to see the installed ids.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const context = await loadExtensionContext(environment);
|
|
43
|
+
const extension = findExtension(context, extensionId);
|
|
44
|
+
if (extension === null) {
|
|
45
|
+
throw new OperationalError(
|
|
46
|
+
explainMissing(context, extensionId),
|
|
47
|
+
"Run `untangle extensions list` to see what is installed and why something was rejected.",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const directory = dirname(extension.manifestPath);
|
|
52
|
+
if (!isInsideAnyRoot(directory, environment.roots)) {
|
|
53
|
+
throw new OperationalError(
|
|
54
|
+
`Refusing to delete "${directory}": it is not inside a resolved extension root ` +
|
|
55
|
+
`(${environment.roots.join(", ")}).`,
|
|
56
|
+
"Delete the directory yourself if that is really what you want.",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (isInsideAnyRoot(directory, environment.projectRoots)) {
|
|
60
|
+
throw new OperationalError(
|
|
61
|
+
`Refusing to delete "${directory}": it lies inside a project directory.`,
|
|
62
|
+
"Extensions are user-profile artifacts; remove this one with your own tools.",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await environment.fs.remove(directory, { recursive: true });
|
|
67
|
+
|
|
68
|
+
const statePath = await saveCliState(environment.fs, environment.userDataDir, {
|
|
69
|
+
...context.state,
|
|
70
|
+
enabled: context.state.enabled.filter((id) => id !== extensionId),
|
|
71
|
+
lastRuns: Object.fromEntries(
|
|
72
|
+
Object.entries(context.state.lastRuns).filter(([id]) => id !== extensionId),
|
|
73
|
+
),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
let acknowledgmentFile: string | undefined;
|
|
77
|
+
const revoked = boolFlag(args, "revoke-license");
|
|
78
|
+
if (revoked) {
|
|
79
|
+
acknowledgmentFile = await saveAcknowledgments(
|
|
80
|
+
environment.fs,
|
|
81
|
+
environment.userDataDir,
|
|
82
|
+
removeAcknowledgments(context.acknowledgments, extensionId),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (format === "json") {
|
|
87
|
+
emitJson(io, {
|
|
88
|
+
command: "extensions remove",
|
|
89
|
+
extensionId,
|
|
90
|
+
removedDirectory: directory,
|
|
91
|
+
stateFile: statePath,
|
|
92
|
+
licenseAcknowledgment: revoked ? "revoked" : "kept",
|
|
93
|
+
acknowledgmentFile,
|
|
94
|
+
warnings: context.warnings,
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
line(io, `removed "${extensionId}"`);
|
|
98
|
+
line(io, ` directory ${directory}`);
|
|
99
|
+
line(
|
|
100
|
+
io,
|
|
101
|
+
revoked
|
|
102
|
+
? ` license acknowledgment revoked in ${String(acknowledgmentFile)}`
|
|
103
|
+
: " license acknowledgment kept (use --revoke-license to drop it)",
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
for (const warning of context.warnings) {
|
|
107
|
+
note(io, `warning: ${warning}`);
|
|
108
|
+
}
|
|
109
|
+
return EXIT.ok;
|
|
110
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two output shapes the extension commands share.
|
|
3
|
+
*
|
|
4
|
+
* Payload goes to stdout, everything else to stderr (see `cli/io.ts`), so
|
|
5
|
+
* `--format=json | jq` stays usable while warnings remain visible.
|
|
6
|
+
*/
|
|
7
|
+
import { line, type Io } from "../../cli/io.js";
|
|
8
|
+
|
|
9
|
+
/** Writes one JSON document to stdout. */
|
|
10
|
+
export function emitJson(io: Io, value: unknown): void {
|
|
11
|
+
line(io, JSON.stringify(value, null, 2));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Renders a table padded to the widest cell per column. Padding counts code
|
|
16
|
+
* units, which is what a fixed-width terminal measures for the ASCII
|
|
17
|
+
* identifiers, SPDX ids and paths shown here.
|
|
18
|
+
*/
|
|
19
|
+
export function renderTable(
|
|
20
|
+
header: readonly string[],
|
|
21
|
+
rows: readonly (readonly string[])[],
|
|
22
|
+
): string[] {
|
|
23
|
+
const widths = header.map((cell, column) =>
|
|
24
|
+
rows.reduce((widest, row) => Math.max(widest, (row[column] ?? "").length), cell.length),
|
|
25
|
+
);
|
|
26
|
+
const render = (cells: readonly string[]): string =>
|
|
27
|
+
cells
|
|
28
|
+
.map((cell, column) => cell.padEnd(widths[column] ?? 0))
|
|
29
|
+
.join(" ")
|
|
30
|
+
.trimEnd();
|
|
31
|
+
return [render(header), render(widths.map((width) => "-".repeat(width))), ...rows.map(render)];
|
|
32
|
+
}
|