@untangle-code/cli 0.0.0-stage → 0.1.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/LICENSE +661 -0
- package/NOTICE +90 -0
- package/README.md +424 -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,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared read path of the extension commands.
|
|
3
|
+
*
|
|
4
|
+
* Every command starts from the same picture: which manifests were found in
|
|
5
|
+
* the user roots, which were rejected and why, which were deliberately
|
|
6
|
+
* ignored and why, which acknowledgments exist, and what the CLI recorded
|
|
7
|
+
* about earlier runs. Building that once keeps `list`, `run` and `enable`
|
|
8
|
+
* from drifting apart in what they consider "installed".
|
|
9
|
+
*/
|
|
10
|
+
import {
|
|
11
|
+
discoverExtensions,
|
|
12
|
+
evaluateLicenseGate,
|
|
13
|
+
loadLicenseAcknowledgments,
|
|
14
|
+
type ExtensionDiscoveryResultV1,
|
|
15
|
+
type LicenseAcknowledgmentV1,
|
|
16
|
+
type LicenseGateDecisionV1,
|
|
17
|
+
type LoadedExtensionV1,
|
|
18
|
+
} from "@untangle-code/extension-runtime";
|
|
19
|
+
|
|
20
|
+
import type { ExtensionEnvironmentV1 } from "./environment.js";
|
|
21
|
+
import { loadCliState, type CliStateV1 } from "./state.js";
|
|
22
|
+
|
|
23
|
+
export interface ExtensionContextV1 {
|
|
24
|
+
discovery: ExtensionDiscoveryResultV1;
|
|
25
|
+
acknowledgments: LicenseAcknowledgmentV1[];
|
|
26
|
+
state: CliStateV1;
|
|
27
|
+
/** Everything that was skipped, unreadable or ignored, with its reason (E4). */
|
|
28
|
+
warnings: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Reads discovery, acknowledgments and CLI state in one go. */
|
|
32
|
+
export async function loadExtensionContext(
|
|
33
|
+
environment: ExtensionEnvironmentV1,
|
|
34
|
+
): Promise<ExtensionContextV1> {
|
|
35
|
+
const discovery = await discoverExtensions(environment.fs, {
|
|
36
|
+
roots: environment.roots,
|
|
37
|
+
projectRoots: environment.projectRoots,
|
|
38
|
+
});
|
|
39
|
+
const acknowledgments = await loadLicenseAcknowledgments(environment.fs, {
|
|
40
|
+
userDataDirectory: environment.userDataDir,
|
|
41
|
+
projectRoots: environment.projectRoots,
|
|
42
|
+
});
|
|
43
|
+
const state = await loadCliState(environment.fs, environment.userDataDir);
|
|
44
|
+
return {
|
|
45
|
+
discovery,
|
|
46
|
+
acknowledgments: acknowledgments.acknowledgments,
|
|
47
|
+
state: state.state,
|
|
48
|
+
warnings: [...acknowledgments.warnings, ...state.warnings],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Finds a loaded extension by id, or null. */
|
|
53
|
+
export function findExtension(
|
|
54
|
+
context: ExtensionContextV1,
|
|
55
|
+
extensionId: string,
|
|
56
|
+
): LoadedExtensionV1 | null {
|
|
57
|
+
return context.discovery.extensions.find((entry) => entry.manifest.id === extensionId) ?? null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Evaluates both gates for one extension against the stored acknowledgments.
|
|
62
|
+
*
|
|
63
|
+
* `ruleset` is the effective ruleset of the intended run; without one the
|
|
64
|
+
* manifest's `defaultRuleset` applies, which is what the runtime would use.
|
|
65
|
+
*/
|
|
66
|
+
export function gateFor(
|
|
67
|
+
context: ExtensionContextV1,
|
|
68
|
+
extension: LoadedExtensionV1,
|
|
69
|
+
ruleset?: string,
|
|
70
|
+
): LicenseGateDecisionV1 {
|
|
71
|
+
const effective = ruleset ?? extension.manifest.defaultRuleset;
|
|
72
|
+
return evaluateLicenseGate({
|
|
73
|
+
extension,
|
|
74
|
+
acknowledgments: context.acknowledgments,
|
|
75
|
+
...(effective === undefined ? {} : { ruleset: effective }),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Explains why an id is not installed, naming the manifests that were
|
|
81
|
+
* rejected or ignored for it. "Not found" without a reason is exactly the
|
|
82
|
+
* silent skip E4 forbids.
|
|
83
|
+
*/
|
|
84
|
+
export function explainMissing(context: ExtensionContextV1, extensionId: string): string {
|
|
85
|
+
const rejected = context.discovery.rejected.filter(
|
|
86
|
+
(entry) =>
|
|
87
|
+
entry.directoryName === extensionId || entry.manifestPath.includes(`/${extensionId}/`),
|
|
88
|
+
);
|
|
89
|
+
if (rejected.length > 0) {
|
|
90
|
+
const reasons = rejected
|
|
91
|
+
.flatMap((entry) => entry.issues.map((issue) => `${issue.field}: ${issue.message}`))
|
|
92
|
+
.join("; ");
|
|
93
|
+
return `extension "${extensionId}" has a manifest but it was rejected — ${reasons}`;
|
|
94
|
+
}
|
|
95
|
+
const ignored = context.discovery.ignored.filter((entry) =>
|
|
96
|
+
entry.manifestPath.includes(`/${extensionId}/`),
|
|
97
|
+
);
|
|
98
|
+
if (ignored.length > 0) {
|
|
99
|
+
const reasons = ignored.map((entry) => `${entry.reason}: ${entry.detail}`).join("; ");
|
|
100
|
+
return `extension "${extensionId}" was found but not loaded — ${reasons}`;
|
|
101
|
+
}
|
|
102
|
+
const roots = context.discovery.rootsScanned
|
|
103
|
+
.map((entry) => `${entry.root}${entry.exists ? "" : " (does not exist)"}`)
|
|
104
|
+
.join(", ");
|
|
105
|
+
return (
|
|
106
|
+
`no extension "${extensionId}" is installed; searched: ${roots}. ` +
|
|
107
|
+
`Install one with: untangle extensions add --from <path-or-url>`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `untangle extensions enable <id>` / `disable <id>`
|
|
3
|
+
*
|
|
4
|
+
* These exist because the runtime's license gate prints them. When a gate is
|
|
5
|
+
* unacknowledged the runtime hands back the exact command that would grant
|
|
6
|
+
* the acknowledgment (extensions.md §9.5), and a printed command that does
|
|
7
|
+
* not exist is worse than no hint at all.
|
|
8
|
+
*
|
|
9
|
+
* `enable` records the opt-in and, with the acknowledgment flags, the
|
|
10
|
+
* personal license declaration. It starts nothing: no process, no pull, no
|
|
11
|
+
* container (X1). `disable` reverses the opt-in and, with `--revoke-license`,
|
|
12
|
+
* the declaration (§9.3).
|
|
13
|
+
*
|
|
14
|
+
* The tool gate and the ruleset gate are separate. `--acknowledge-license`
|
|
15
|
+
* covers the tool ONLY; a restricted ruleset still needs its own
|
|
16
|
+
* `--acknowledge-ruleset=<id>`, which is repeatable.
|
|
17
|
+
*/
|
|
18
|
+
import {
|
|
19
|
+
buildAcknowledgment,
|
|
20
|
+
createNodeProcessRunner,
|
|
21
|
+
defaultProcessLimits,
|
|
22
|
+
} from "@untangle-code/extension-runtime";
|
|
23
|
+
|
|
24
|
+
import { boolFlag, listFlag, type ParsedArgs } from "../../cli/args.js";
|
|
25
|
+
import { EXIT, OperationalError, UsageError } from "../../cli/exit.js";
|
|
26
|
+
import { line, note, type Io } from "../../cli/io.js";
|
|
27
|
+
|
|
28
|
+
import { createContainerCli } from "./container.js";
|
|
29
|
+
import { explainMissing, findExtension, gateFor, loadExtensionContext } from "./context.js";
|
|
30
|
+
import type { ExtensionEnvironmentV1 } from "./environment.js";
|
|
31
|
+
import { composeFilePath } from "./provision.js";
|
|
32
|
+
import { emitJson } from "./render.js";
|
|
33
|
+
import {
|
|
34
|
+
revokeAcknowledgments,
|
|
35
|
+
saveAcknowledgments,
|
|
36
|
+
saveCliState,
|
|
37
|
+
upsertAcknowledgment,
|
|
38
|
+
} from "./state.js";
|
|
39
|
+
|
|
40
|
+
export async function runEnable(
|
|
41
|
+
environment: ExtensionEnvironmentV1,
|
|
42
|
+
args: ParsedArgs,
|
|
43
|
+
io: Io,
|
|
44
|
+
format: "text" | "json",
|
|
45
|
+
): Promise<number> {
|
|
46
|
+
const extensionId = args.positionals[1];
|
|
47
|
+
if (extensionId === undefined) {
|
|
48
|
+
throw new UsageError(
|
|
49
|
+
"`untangle extensions enable` needs an extension id.",
|
|
50
|
+
"Run `untangle extensions list` to see the installed ids.",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const context = await loadExtensionContext(environment);
|
|
54
|
+
const extension = findExtension(context, extensionId);
|
|
55
|
+
if (extension === null) {
|
|
56
|
+
throw new OperationalError(
|
|
57
|
+
explainMissing(context, extensionId),
|
|
58
|
+
"Install it first: untangle extensions add --from=<path-or-url>",
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let acknowledgments = context.acknowledgments;
|
|
63
|
+
const acknowledgedNow: string[] = [];
|
|
64
|
+
if (boolFlag(args, "acknowledge-license")) {
|
|
65
|
+
acknowledgments = upsertAcknowledgment(
|
|
66
|
+
acknowledgments,
|
|
67
|
+
buildAcknowledgment({
|
|
68
|
+
manifest: extension.manifest,
|
|
69
|
+
acknowledgedAt: environment.clock.nowIso(),
|
|
70
|
+
acknowledgedBy: environment.userName,
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
acknowledgedNow.push(`tool:${extensionId}`);
|
|
74
|
+
}
|
|
75
|
+
for (const ruleset of listFlag(args, "acknowledge-ruleset")) {
|
|
76
|
+
acknowledgments = upsertAcknowledgment(
|
|
77
|
+
acknowledgments,
|
|
78
|
+
buildAcknowledgment({
|
|
79
|
+
manifest: extension.manifest,
|
|
80
|
+
ruleset,
|
|
81
|
+
acknowledgedAt: environment.clock.nowIso(),
|
|
82
|
+
acknowledgedBy: environment.userName,
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
acknowledgedNow.push(`ruleset:${ruleset}`);
|
|
86
|
+
}
|
|
87
|
+
let acknowledgmentFile: string | undefined;
|
|
88
|
+
if (acknowledgedNow.length > 0) {
|
|
89
|
+
acknowledgmentFile = await saveAcknowledgments(
|
|
90
|
+
environment.fs,
|
|
91
|
+
environment.userDataDir,
|
|
92
|
+
acknowledgments,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const enabled = context.state.enabled.includes(extensionId)
|
|
97
|
+
? context.state.enabled
|
|
98
|
+
: [...context.state.enabled, extensionId];
|
|
99
|
+
const statePath = await saveCliState(environment.fs, environment.userDataDir, {
|
|
100
|
+
...context.state,
|
|
101
|
+
enabled,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const gate = gateFor({ ...context, acknowledgments }, extension);
|
|
105
|
+
|
|
106
|
+
if (format === "json") {
|
|
107
|
+
emitJson(io, {
|
|
108
|
+
command: "extensions enable",
|
|
109
|
+
extensionId,
|
|
110
|
+
enabled: true,
|
|
111
|
+
started: false,
|
|
112
|
+
stateFile: statePath,
|
|
113
|
+
acknowledgedNow,
|
|
114
|
+
acknowledgmentFile,
|
|
115
|
+
licenseGate: {
|
|
116
|
+
allowed: gate.allowed,
|
|
117
|
+
tool: { status: gate.tool.status, reason: gate.tool.reason },
|
|
118
|
+
rulesets: gate.rulesets.map((entry) => ({
|
|
119
|
+
ruleset: entry.ruleset,
|
|
120
|
+
status: entry.status,
|
|
121
|
+
reason: entry.reason,
|
|
122
|
+
})),
|
|
123
|
+
acknowledgeCommands: gate.acknowledgeCommands,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
line(io, `enabled "${extensionId}" — nothing was started (X1).`);
|
|
128
|
+
line(io, ` state ${statePath}`);
|
|
129
|
+
line(io, ` license ${gate.tool.status} — ${gate.tool.reason}`);
|
|
130
|
+
for (const entry of gate.rulesets) {
|
|
131
|
+
line(io, ` ruleset ${entry.ruleset}: ${entry.status} — ${entry.reason}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!gate.allowed) {
|
|
136
|
+
note(io, "The license gate is still open; run:");
|
|
137
|
+
for (const command of gate.acknowledgeCommands) {
|
|
138
|
+
note(io, ` ${command}`);
|
|
139
|
+
}
|
|
140
|
+
return EXIT.environment;
|
|
141
|
+
}
|
|
142
|
+
return EXIT.ok;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function runDisable(
|
|
146
|
+
environment: ExtensionEnvironmentV1,
|
|
147
|
+
args: ParsedArgs,
|
|
148
|
+
io: Io,
|
|
149
|
+
format: "text" | "json",
|
|
150
|
+
): Promise<number> {
|
|
151
|
+
const extensionId = args.positionals[1];
|
|
152
|
+
if (extensionId === undefined) {
|
|
153
|
+
throw new UsageError(
|
|
154
|
+
"`untangle extensions disable` needs an extension id.",
|
|
155
|
+
"Run `untangle extensions list` to see the installed ids.",
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
// Die Flag-Pruefung steht VOR jeder Zustandsaenderung. Zuvor lag sie danach:
|
|
159
|
+
// ein Aufruf, den die CLI im selben Atemzug als Aufruffehler zurueckwies,
|
|
160
|
+
// hatte die Extension bereits deaktiviert. Ein abgelehnter Befehl darf nichts
|
|
161
|
+
// getan haben.
|
|
162
|
+
const removeContainer = boolFlag(args, "remove-container");
|
|
163
|
+
const removeVolumes = boolFlag(args, "remove-volumes");
|
|
164
|
+
if (removeVolumes && !removeContainer) {
|
|
165
|
+
throw new UsageError(
|
|
166
|
+
"--remove-volumes only applies together with --remove-container.",
|
|
167
|
+
`Run untangle extensions disable ${extensionId} --remove-container --remove-volumes`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const context = await loadExtensionContext(environment);
|
|
172
|
+
const statePath = await saveCliState(environment.fs, environment.userDataDir, {
|
|
173
|
+
...context.state,
|
|
174
|
+
enabled: context.state.enabled.filter((id) => id !== extensionId),
|
|
175
|
+
});
|
|
176
|
+
// `--remove-container` fasst NUR den eigenen Container an; die Besitzprobe
|
|
177
|
+
// liegt im Adapter und laesst einen fremden gleichen Namens unberuehrt.
|
|
178
|
+
// Volumes bleiben ohne die zweite, ausdrueckliche Anweisung erhalten: ein
|
|
179
|
+
// geloeschtes Volume ist die einzige hier moegliche Handlung, die Arbeit
|
|
180
|
+
// vernichtet, die niemand wiederherstellen kann.
|
|
181
|
+
let containerDetail: string | undefined;
|
|
182
|
+
if (removeContainer) {
|
|
183
|
+
const installed = findExtension(context, extensionId);
|
|
184
|
+
const manifest = installed?.manifest;
|
|
185
|
+
if (manifest?.container === undefined) {
|
|
186
|
+
containerDetail = `"${extensionId}" declares no container; nothing to remove`;
|
|
187
|
+
} else {
|
|
188
|
+
const containerCli = createContainerCli({
|
|
189
|
+
processRunner: createNodeProcessRunner(environment.clock),
|
|
190
|
+
limits: { ...defaultProcessLimits(), timeoutMs: 120_000 },
|
|
191
|
+
...(environment.env["UNTANGLE_CONTAINER_CLI"] === undefined
|
|
192
|
+
? {}
|
|
193
|
+
: { command: environment.env["UNTANGLE_CONTAINER_CLI"] }),
|
|
194
|
+
});
|
|
195
|
+
const down = await containerCli.down({
|
|
196
|
+
manifest,
|
|
197
|
+
composeFilePath: composeFilePath(environment.userDataDir, manifest.id),
|
|
198
|
+
removeVolumes,
|
|
199
|
+
});
|
|
200
|
+
containerDetail = down.detail;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let acknowledgmentFile: string | undefined;
|
|
205
|
+
const revoked = boolFlag(args, "revoke-license");
|
|
206
|
+
if (revoked) {
|
|
207
|
+
acknowledgmentFile = await saveAcknowledgments(
|
|
208
|
+
environment.fs,
|
|
209
|
+
environment.userDataDir,
|
|
210
|
+
revokeAcknowledgments(context.acknowledgments, extensionId, environment.clock.nowIso()),
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (format === "json") {
|
|
215
|
+
emitJson(io, {
|
|
216
|
+
command: "extensions disable",
|
|
217
|
+
extensionId,
|
|
218
|
+
enabled: false,
|
|
219
|
+
stateFile: statePath,
|
|
220
|
+
licenseAcknowledgment: revoked ? "revoked" : "kept",
|
|
221
|
+
acknowledgmentFile,
|
|
222
|
+
...(containerDetail === undefined ? {} : { container: containerDetail }),
|
|
223
|
+
});
|
|
224
|
+
} else {
|
|
225
|
+
line(io, `disabled "${extensionId}".`);
|
|
226
|
+
line(
|
|
227
|
+
io,
|
|
228
|
+
revoked
|
|
229
|
+
? ` license acknowledgment revoked in ${String(acknowledgmentFile)}`
|
|
230
|
+
: " license acknowledgment kept (use --revoke-license to drop it)",
|
|
231
|
+
);
|
|
232
|
+
if (containerDetail !== undefined) {
|
|
233
|
+
line(io, ` container ${containerDetail}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return EXIT.ok;
|
|
237
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ports and locations the extension commands run against.
|
|
3
|
+
*
|
|
4
|
+
* Everything the commands touch arrives here as data or as a port: the file
|
|
5
|
+
* system, the clock, randomness, the search roots, the user data directory
|
|
6
|
+
* and — the load-bearing one — the PROJECT roots.
|
|
7
|
+
*
|
|
8
|
+
* ## Why project roots exist at all
|
|
9
|
+
*
|
|
10
|
+
* A manifest describes how to start a program. If Untangle read manifests
|
|
11
|
+
* from the working directory, `git clone` of a stranger's repository would be
|
|
12
|
+
* enough to put a tool definition in front of the runtime, and one
|
|
13
|
+
* `untangle extensions run` away from executing it. So project directories
|
|
14
|
+
* are a boundary, not a search path: `discoverExtensions` never scans them,
|
|
15
|
+
* and `loadExtensionFrom` refuses a path inside one unless the user types
|
|
16
|
+
* `--allow-project-local` in that very invocation.
|
|
17
|
+
*
|
|
18
|
+
* The same reasoning puts license acknowledgments in the user data directory
|
|
19
|
+
* (extensions.md §9.2): a `.untangle/` file can be committed, and a committed
|
|
20
|
+
* acknowledgment would inherit one person's declaration to a whole team.
|
|
21
|
+
*/
|
|
22
|
+
import { homedir, userInfo } from "node:os";
|
|
23
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
24
|
+
|
|
25
|
+
import type { Clock, FileSystemPort, Random } from "@untangle-code/domain";
|
|
26
|
+
import {
|
|
27
|
+
isInsideDirectory,
|
|
28
|
+
resolveExtensionRoots,
|
|
29
|
+
userDataDirectory,
|
|
30
|
+
type ExtensionPathEnvironmentV1,
|
|
31
|
+
} from "@untangle-code/extension-runtime";
|
|
32
|
+
import { NodeFileSystem } from "@untangle-code/scanner/node-fs";
|
|
33
|
+
|
|
34
|
+
import { systemClock, systemRandom } from "../../cli/system.js";
|
|
35
|
+
|
|
36
|
+
export interface ExtensionEnvironmentV1 {
|
|
37
|
+
fs: FileSystemPort;
|
|
38
|
+
clock: Clock;
|
|
39
|
+
random: Random;
|
|
40
|
+
/** Directory the user invoked the CLI from, canonicalized where possible. */
|
|
41
|
+
cwd: string;
|
|
42
|
+
/** Search roots for user-installed extensions; `roots[0]` is the install target. */
|
|
43
|
+
roots: string[];
|
|
44
|
+
/** OS-specific user data directory (holds the acknowledgment file). */
|
|
45
|
+
userDataDir: string;
|
|
46
|
+
/** Directories that MUST NOT be scanned for manifests. */
|
|
47
|
+
projectRoots: string[];
|
|
48
|
+
/** OS user name — an acknowledgment is a personal declaration. */
|
|
49
|
+
userName: string;
|
|
50
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CreateExtensionEnvironmentOptions {
|
|
54
|
+
cwd: string;
|
|
55
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
56
|
+
fs?: FileSystemPort;
|
|
57
|
+
clock?: Clock;
|
|
58
|
+
random?: Random;
|
|
59
|
+
homeDir?: string;
|
|
60
|
+
platform?: string;
|
|
61
|
+
userName?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function createExtensionEnvironment(
|
|
65
|
+
options: CreateExtensionEnvironmentOptions,
|
|
66
|
+
): Promise<ExtensionEnvironmentV1> {
|
|
67
|
+
const fs = options.fs ?? new NodeFileSystem();
|
|
68
|
+
const cwd = await canonicalize(fs, resolve(options.cwd));
|
|
69
|
+
const platform = options.platform ?? process.platform;
|
|
70
|
+
const pathEnvironment: ExtensionPathEnvironmentV1 = {
|
|
71
|
+
homeDir: options.homeDir ?? homeDirFrom(options.env, platform),
|
|
72
|
+
platform,
|
|
73
|
+
env: options.env,
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
fs,
|
|
77
|
+
clock: options.clock ?? systemClock,
|
|
78
|
+
random: options.random ?? systemRandom,
|
|
79
|
+
cwd,
|
|
80
|
+
roots: await Promise.all(
|
|
81
|
+
resolveExtensionRoots(pathEnvironment).map((root) => canonicalize(fs, root)),
|
|
82
|
+
),
|
|
83
|
+
userDataDir: userDataDirectory(pathEnvironment),
|
|
84
|
+
projectRoots: await discoverProjectRoots(fs, cwd, pathEnvironment.homeDir),
|
|
85
|
+
userName: options.userName ?? safeUserName(),
|
|
86
|
+
env: options.env,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Marker files that identify a directory as somebody's PROJECT rather than
|
|
92
|
+
* part of the user profile. `.git` is the decisive one — the threat this
|
|
93
|
+
* boundary exists for is a cloned repository — and the two Untangle markers
|
|
94
|
+
* cover a project that was shipped as an archive rather than a clone.
|
|
95
|
+
*/
|
|
96
|
+
const PROJECT_MARKERS = [".git", ".untangle.json", ".untangle"] as const;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Determines which directories must be treated as project directories.
|
|
100
|
+
*
|
|
101
|
+
* Walks from `start` up to the filesystem root and collects every directory
|
|
102
|
+
* carrying a project marker; if at least one is found, `start` itself joins
|
|
103
|
+
* the list, because the working directory inside a project is part of that
|
|
104
|
+
* project.
|
|
105
|
+
*
|
|
106
|
+
* Two deliberate exclusions:
|
|
107
|
+
*
|
|
108
|
+
* - **The home directory is never a project root.** A dotfiles repository in
|
|
109
|
+
* `$HOME` is ordinary, and treating `$HOME` as a project would put
|
|
110
|
+
* `~/.untangle/extensions` inside a project directory — which would make the
|
|
111
|
+
* user's own extension root unscannable the moment they ran the CLI from
|
|
112
|
+
* their home directory. The boundary is meant to keep a stranger's
|
|
113
|
+
* repository out, not to lock people out of their own profile.
|
|
114
|
+
* - **A directory with no marker anywhere above it yields no project roots at
|
|
115
|
+
* all.** Without a marker there is no project to protect, and a bare
|
|
116
|
+
* directory the user made themselves is theirs. The consequence is stated
|
|
117
|
+
* openly: `add --from ./manifest.toml` in such a directory is NOT refused.
|
|
118
|
+
* A cloned repository always carries `.git`, so the case the boundary exists
|
|
119
|
+
* for is still covered.
|
|
120
|
+
*/
|
|
121
|
+
export async function discoverProjectRoots(
|
|
122
|
+
fs: FileSystemPort,
|
|
123
|
+
start: string,
|
|
124
|
+
homeDir?: string,
|
|
125
|
+
): Promise<string[]> {
|
|
126
|
+
const home = homeDir === undefined ? undefined : resolve(homeDir);
|
|
127
|
+
const found: string[] = [];
|
|
128
|
+
let current = start;
|
|
129
|
+
for (;;) {
|
|
130
|
+
if (current !== home && (await hasProjectMarker(fs, current))) {
|
|
131
|
+
found.push(current);
|
|
132
|
+
}
|
|
133
|
+
const parent = dirname(current);
|
|
134
|
+
if (parent === current) {
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
current = parent;
|
|
138
|
+
}
|
|
139
|
+
if (found.length === 0) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
return found.includes(start) ? found : [start, ...found];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function hasProjectMarker(fs: FileSystemPort, directory: string): Promise<boolean> {
|
|
146
|
+
for (const marker of PROJECT_MARKERS) {
|
|
147
|
+
if ((await fs.stat(join(directory, marker))) !== null) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** True when `candidate` lies inside any of `roots`. */
|
|
155
|
+
export function isInsideAnyRoot(candidate: string, roots: readonly string[]): boolean {
|
|
156
|
+
return roots.some((root) => isInsideDirectory(candidate, root));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Resolves a user-supplied path against the working directory. */
|
|
160
|
+
export function resolveUserPath(cwd: string, path: string): string {
|
|
161
|
+
return isAbsolute(path) ? path : resolve(cwd, path);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Canonical form of a path, with symlinks resolved.
|
|
166
|
+
*
|
|
167
|
+
* This is not cosmetic. `isProjectLocalManifest` and `isInsideDirectory`
|
|
168
|
+
* compare LEXICALLY and say so: they never resolve symlinks, and the caller is
|
|
169
|
+
* expected to hand them canonical paths. Skipping this step would leave the
|
|
170
|
+
* project boundary trivially escapable — a symlink, or on macOS merely the
|
|
171
|
+
* `/var` → `/private/var` alias, is enough to make a path inside a project
|
|
172
|
+
* compare as if it were outside one.
|
|
173
|
+
*
|
|
174
|
+
* A path that does not exist yet still gets canonicalized as far as it does
|
|
175
|
+
* exist: the deepest existing ancestor is resolved and the remaining segments
|
|
176
|
+
* are re-appended. Failing the whole command over a not-yet-created file would
|
|
177
|
+
* be worse than a partially canonical answer, and the ancestor is the part
|
|
178
|
+
* that decides containment.
|
|
179
|
+
*/
|
|
180
|
+
export async function canonicalize(fs: FileSystemPort, path: string): Promise<string> {
|
|
181
|
+
const tail: string[] = [];
|
|
182
|
+
let current = resolve(path);
|
|
183
|
+
for (;;) {
|
|
184
|
+
try {
|
|
185
|
+
const real = await fs.realPath(current);
|
|
186
|
+
return tail.length === 0 ? real : join(real, ...tail.reverse());
|
|
187
|
+
} catch {
|
|
188
|
+
const parent = dirname(current);
|
|
189
|
+
if (parent === current) {
|
|
190
|
+
return resolve(path);
|
|
191
|
+
}
|
|
192
|
+
tail.push(basename(current));
|
|
193
|
+
current = parent;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The home directory as the COMMAND CONTEXT sees it.
|
|
200
|
+
*
|
|
201
|
+
* `os.homedir()` reads the process environment, not the environment handed to
|
|
202
|
+
* this command. Preferring the context keeps the extension root, the
|
|
203
|
+
* acknowledgment file and the state file inside whatever profile the caller
|
|
204
|
+
* declared — which is what makes these commands testable without writing into
|
|
205
|
+
* the real user profile.
|
|
206
|
+
*/
|
|
207
|
+
function homeDirFrom(env: Readonly<Record<string, string | undefined>>, platform: string): string {
|
|
208
|
+
const fromEnv = platform === "win32" ? env["USERPROFILE"] : env["HOME"];
|
|
209
|
+
return fromEnv !== undefined && fromEnv.trim() !== "" ? fromEnv : homedir();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function safeUserName(): string {
|
|
213
|
+
try {
|
|
214
|
+
return userInfo().username;
|
|
215
|
+
} catch {
|
|
216
|
+
return "unknown";
|
|
217
|
+
}
|
|
218
|
+
}
|