@automaton-labs/aib 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -257
- package/config/agent-dx-policy.default.json +31 -0
- package/config/control-plane-client.default.json +3 -0
- package/dist/agent-dx/agent-dx.js +805 -0
- package/dist/agent-dx/presentation.js +32 -0
- package/dist/alias-advisor/analyze.js +982 -0
- package/dist/alias-advisor/exact-text-cost.js +74 -0
- package/dist/alias-advisor/lexical.js +240 -0
- package/dist/alias-advisor/model.js +2 -0
- package/dist/alias-advisor/path-identity.js +49 -0
- package/dist/alias-advisor/ranking.js +171 -0
- package/dist/alias-advisor/token-estimator.js +85 -0
- package/dist/bin/aib.js +5 -1
- package/dist/bin/cli.js +811 -2
- package/dist/commands/add-missing-imports-preview-cache.js +99 -2
- package/dist/commands/add-missing-imports.js +241 -2
- package/dist/commands/apply-module-plan.js +1319 -3
- package/dist/commands/background-command.js +378 -0
- package/dist/commands/captured-input.js +74 -2
- package/dist/commands/config-command.js +314 -2
- package/dist/commands/config-output.js +357 -10
- package/dist/commands/control-plane-command.js +183 -0
- package/dist/commands/declaration-command.js +1209 -0
- package/dist/commands/declaration-execution-cache.js +79 -0
- package/dist/commands/declaration-format.js +221 -0
- package/dist/commands/declaration-preview-cache.js +114 -0
- package/dist/commands/diagnostics-command.js +70 -3
- package/dist/commands/doctor.js +137 -2
- package/dist/commands/execution-command.js +117 -1
- package/dist/commands/exports-star-collapse-command.js +178 -0
- package/dist/commands/exports-star-command.js +252 -0
- package/dist/commands/exports-star-preview-cache.js +84 -0
- package/dist/commands/feedback-command.js +176 -3
- package/dist/commands/file-move-to-dir-execution-cache.js +92 -0
- package/dist/commands/file-move-to-dir-preview-cache.js +125 -0
- package/dist/commands/file-move-to-dir-worker.js +54 -0
- package/dist/commands/file-move-to-dir.js +1073 -0
- package/dist/commands/file-mutation-runtime.js +102 -0
- package/dist/commands/file-mutation-worker-apply.js +180 -0
- package/dist/commands/file-refactor-batch-execution-cache.js +90 -0
- package/dist/commands/file-refactor-batch-preview-cache.js +125 -0
- package/dist/commands/file-refactor-batch-worker.js +54 -0
- package/dist/commands/file-refactor-batch.js +1154 -0
- package/dist/commands/file-rename-execution-cache.js +92 -0
- package/dist/commands/file-rename-preview-cache.js +125 -0
- package/dist/commands/file-rename-worker.js +54 -0
- package/dist/commands/file-rename.js +1053 -0
- package/dist/commands/file-text-edit-executor.js +205 -0
- package/dist/commands/find-importers.js +52 -1
- package/dist/commands/find-unused-imports.js +55 -1
- package/dist/commands/generate-docs-command.js +244 -6
- package/dist/commands/help-command.js +460 -7
- package/dist/commands/import-specifier-policy.js +391 -0
- package/dist/commands/imports-command.js +68 -1
- package/dist/commands/imports-rebase.js +1138 -0
- package/dist/commands/init-skill-usage.js +92 -3
- package/dist/commands/init-workspace.js +30 -1
- package/dist/commands/inspect-alias-candidates.js +413 -0
- package/dist/commands/inspect-cycles.js +811 -5
- package/dist/commands/inspect-direct-usages.js +98 -0
- package/dist/commands/inspect-duplicates-format.js +229 -0
- package/dist/commands/inspect-format-primitives.js +127 -0
- package/dist/commands/inspect-format.js +1590 -18
- package/dist/commands/inspect-graph.js +1553 -9
- package/dist/commands/inspect-imports.js +339 -2
- package/dist/commands/inspect-mixed-format.js +524 -0
- package/dist/commands/inspect-module-plan-format.js +216 -0
- package/dist/commands/inspect-module-plan-serialization.js +402 -0
- package/dist/commands/inspect-reference-path-format.js +157 -0
- package/dist/commands/inspect-request-values.js +599 -0
- package/dist/commands/inspect-selector-kind.js +21 -0
- package/dist/commands/inspect-selector.js +50 -0
- package/dist/commands/inspect-symbol-format.js +90 -0
- package/dist/commands/inspect-topology.js +435 -0
- package/dist/commands/inspect-tree.js +827 -5
- package/dist/commands/inspect-usages-detail.js +793 -0
- package/dist/commands/inspect-usages-evidence.js +31 -0
- package/dist/commands/inspect-usages-format.js +367 -0
- package/dist/commands/inspect.js +1450 -16
- package/dist/commands/internal-command.js +64 -0
- package/dist/commands/json-file-input.js +60 -1
- package/dist/commands/module-plan-cache.js +156 -2
- package/dist/commands/module-plan-standalone.js +208 -0
- package/dist/commands/module-plan-timeout.js +77 -1
- package/dist/commands/move-preview-cache.js +101 -2
- package/dist/commands/mutate-aggregate-output.js +996 -0
- package/dist/commands/mutate-child-execution.js +374 -0
- package/dist/commands/mutate-command.js +1394 -0
- package/dist/commands/mutate-declaration-output.js +313 -0
- package/dist/commands/mutate-domain-adapters.js +638 -0
- package/dist/commands/mutate-execution-cache.js +114 -0
- package/dist/commands/mutate-execution-status.js +598 -0
- package/dist/commands/mutate-failure-output.js +531 -0
- package/dist/commands/mutate-file-view.js +151 -0
- package/dist/commands/mutate-object-output.js +91 -0
- package/dist/commands/mutate-output-values.js +97 -0
- package/dist/commands/mutate-preview-cache.js +86 -0
- package/dist/commands/mutate-response-replay.js +153 -0
- package/dist/commands/mutate-result-projection.js +818 -0
- package/dist/commands/mutation-eta.js +28 -0
- package/dist/commands/mutation-execution-cache.js +140 -3
- package/dist/commands/mutation-recovery-journal.js +195 -0
- package/dist/commands/normalize-imports.js +1120 -4
- package/dist/commands/object-pack-command.js +546 -0
- package/dist/commands/object-pack-preview-cache.js +88 -0
- package/dist/commands/observability-command.js +47 -3
- package/dist/commands/ota-command.js +403 -0
- package/dist/commands/print-config.js +10 -1
- package/dist/commands/quick-read.js +1113 -11
- package/dist/commands/refactor-batch-builder.js +265 -1
- package/dist/commands/refactor-batch-execution-cache.js +85 -1
- package/dist/commands/refactor-batch-preview-cache.js +96 -2
- package/dist/commands/refactor-batch.js +461 -4
- package/dist/commands/rename-entities.js +794 -4
- package/dist/commands/rename-execution-cache.js +49 -1
- package/dist/commands/rename-input.js +22 -1
- package/dist/commands/rename-polling-policy.js +68 -0
- package/dist/commands/rename-preview-cache.js +96 -2
- package/dist/commands/result-view.js +993 -6
- package/dist/commands/reveal-command.js +445 -5
- package/dist/commands/selector-suggestions.js +93 -0
- package/dist/commands/session-workspace.js +1836 -31
- package/dist/commands/shared.js +2 -1
- package/dist/commands/skills-command.js +315 -0
- package/dist/commands/sync-command.js +59 -2
- package/dist/commands/worker-command.js +173 -0
- package/dist/commands/workspace-cache.js +55 -1
- package/dist/config/defaults.js +26 -1
- package/dist/config/env-vars.js +77 -1
- package/dist/config/glob-match.js +44 -1
- package/dist/config/import-rules.js +165 -1
- package/dist/config/local-config.js +293 -3
- package/dist/config/mutation-comments.js +51 -1
- package/dist/config/path-aliases.js +165 -1
- package/dist/config/path-display.js +84 -1
- package/dist/config/product-storage.js +37 -1
- package/dist/config/request-env.js +21 -0
- package/dist/config/request-routing-context.js +23 -0
- package/dist/config/resolve-command-alias.js +74 -1
- package/dist/config/resolve.js +24 -1
- package/dist/config/tsconfig-discovery.js +113 -1
- package/dist/config/typescript-preferences.js +131 -0
- package/dist/config/workspace-root.js +310 -3
- package/dist/config/workspace-state.js +254 -1
- package/dist/content/content-bundle.js +88 -1
- package/dist/diagnostics/module-plan-timeline.js +75 -2
- package/dist/diagnostics/readiness-text.js +45 -8
- package/dist/dsl/aib-dsl.js +838 -1
- package/dist/dsl/declaration-dsl.js +264 -0
- package/dist/dsl/file-move-to-dir-dsl.js +123 -0
- package/dist/dsl/file-refactor-batch-dsl.js +203 -0
- package/dist/dsl/file-rename-dsl.js +135 -0
- package/dist/dsl/mutate-dsl.js +746 -0
- package/dist/help/bootstrap.bash.md +742 -0
- package/dist/help/bootstrap.md +236 -437
- package/dist/help/bootstrap.pwsh.md +742 -0
- package/dist/help/docs/basics.md +1 -1
- package/dist/help/docs/config-setup.import-normalize.md +65 -65
- package/dist/help/docs/config-setup.import-rules.md +6 -5
- package/dist/help/docs/dsl.md +4 -3
- package/dist/help/docs/first-setup.md +6 -5
- package/dist/help/docs/help-protocol.md +4 -3
- package/dist/help/docs/import.base.md +38 -0
- package/dist/help/docs/import.rebase.md +85 -0
- package/dist/help/docs/inspect.aliasCandidates.md +39 -0
- package/dist/help/docs/inspect.code.md +5 -11
- package/dist/help/docs/inspect.deps.md +7 -7
- package/dist/help/docs/inspect.file.md +10 -18
- package/dist/help/docs/inspect.graph.md +6 -20
- package/dist/help/docs/{inspect.md → inspect.shared.md} +18 -17
- package/dist/help/docs/modulePlan.md +24 -28
- package/dist/help/docs/move.md +19 -22
- package/dist/help/docs/moveToDir.md +46 -0
- package/dist/help/docs/mutate.mixed.md +34 -0
- package/dist/help/docs/mutation.shared.md +55 -0
- package/dist/help/docs/patterns.md +3 -16
- package/dist/help/docs/qr.md +13 -22
- package/dist/help/docs/quick-map.md +36 -23
- package/dist/help/docs/recipe.file-layout.md +15 -0
- package/dist/help/docs/recipe.import-boundary.md +92 -0
- package/dist/help/docs/recipe.safe-artifact-probing.md +68 -0
- package/dist/help/docs/recipe.unfamiliar-area.md +64 -0
- package/dist/help/docs/recipes.md +20 -0
- package/dist/help/docs/rename.md +19 -27
- package/dist/help/docs/renameFile.md +36 -0
- package/dist/help/docs/rg.md +22 -0
- package/dist/help/docs/rules.md +26 -0
- package/dist/help/docs/selectors.md +3 -2
- package/dist/help/docs/session.md +1 -1
- package/dist/help/dsl/bootstrap.bash.md +742 -0
- package/dist/help/dsl/bootstrap.md +236 -437
- package/dist/help/dsl/bootstrap.pwsh.md +742 -0
- package/dist/help/dsl/docs/basics.md +1 -1
- package/dist/help/dsl/docs/config-setup.import-normalize.md +65 -65
- package/dist/help/dsl/docs/config-setup.import-rules.md +6 -5
- package/dist/help/dsl/docs/dsl.md +4 -3
- package/dist/help/dsl/docs/first-setup.md +6 -5
- package/dist/help/dsl/docs/help-protocol.md +4 -3
- package/dist/help/dsl/docs/import.base.md +38 -0
- package/dist/help/dsl/docs/import.rebase.md +85 -0
- package/dist/help/dsl/docs/inspect.aliasCandidates.md +39 -0
- package/dist/help/dsl/docs/inspect.code.md +5 -11
- package/dist/help/dsl/docs/inspect.deps.md +7 -7
- package/dist/help/dsl/docs/inspect.file.md +10 -18
- package/dist/help/dsl/docs/inspect.graph.md +6 -20
- package/dist/help/dsl/docs/{inspect.md → inspect.shared.md} +18 -17
- package/dist/help/dsl/docs/modulePlan.md +24 -28
- package/dist/help/dsl/docs/move.md +19 -22
- package/dist/help/dsl/docs/moveToDir.md +46 -0
- package/dist/help/dsl/docs/mutate.mixed.md +34 -0
- package/dist/help/dsl/docs/mutation.shared.md +55 -0
- package/dist/help/dsl/docs/patterns.md +3 -16
- package/dist/help/dsl/docs/qr.md +13 -22
- package/dist/help/dsl/docs/quick-map.md +36 -23
- package/dist/help/dsl/docs/recipe.file-layout.md +15 -0
- package/dist/help/dsl/docs/recipe.import-boundary.md +92 -0
- package/dist/help/dsl/docs/recipe.safe-artifact-probing.md +68 -0
- package/dist/help/dsl/docs/recipe.unfamiliar-area.md +64 -0
- package/dist/help/dsl/docs/recipes.md +20 -0
- package/dist/help/dsl/docs/rename.md +19 -27
- package/dist/help/dsl/docs/renameFile.md +36 -0
- package/dist/help/dsl/docs/rg.md +22 -0
- package/dist/help/dsl/docs/rules.md +26 -0
- package/dist/help/dsl/docs/selectors.md +3 -2
- package/dist/help/dsl/docs/session.md +1 -1
- package/dist/help/dsl/full.md +236 -437
- package/dist/help/dsl/help-index.md +49 -0
- package/dist/help/dsl/snippets/agents.md +2 -2
- package/dist/help/dsl/tokens/qr.inline.examples.md +2 -0
- package/dist/help/dsl/tokens/stdin.examples.bash.md +8 -0
- package/dist/help/dsl/tokens/stdin.examples.pwsh.md +8 -0
- package/dist/help/dsl/tokens/stdin.examples.with-qr.bash.md +12 -0
- package/dist/help/dsl/tokens/stdin.examples.with-qr.pwsh.md +12 -0
- package/dist/help/dsl/topics/basics.md +1 -1
- package/dist/help/dsl/topics/config-setup.import-normalize.md +65 -65
- package/dist/help/dsl/topics/config-setup.import-rules.md +6 -5
- package/dist/help/dsl/topics/dsl.md +4 -3
- package/dist/help/dsl/topics/first-setup.md +6 -5
- package/dist/help/dsl/topics/help-protocol.md +4 -3
- package/dist/help/dsl/topics/import.base.md +36 -0
- package/dist/help/dsl/topics/import.rebase.md +83 -0
- package/dist/help/dsl/topics/inspect.aliasCandidates.md +37 -0
- package/dist/help/dsl/topics/inspect.code.md +5 -11
- package/dist/help/dsl/topics/inspect.deps.md +7 -7
- package/dist/help/dsl/topics/inspect.file.md +10 -18
- package/dist/help/dsl/topics/inspect.graph.md +6 -20
- package/dist/help/dsl/topics/{inspect.md → inspect.shared.md} +18 -17
- package/dist/help/dsl/topics/modulePlan.md +21 -26
- package/dist/help/dsl/topics/move.md +17 -18
- package/dist/help/dsl/topics/moveToDir.md +44 -0
- package/dist/help/dsl/topics/mutate.mixed.md +32 -0
- package/dist/help/dsl/topics/mutation.shared.md +53 -0
- package/dist/help/dsl/topics/patterns.md +3 -16
- package/dist/help/dsl/topics/qr.md +13 -22
- package/dist/help/dsl/topics/quick-map.md +36 -23
- package/dist/help/dsl/topics/recipe.file-layout.md +13 -0
- package/dist/help/dsl/topics/recipe.import-boundary.md +90 -0
- package/dist/help/dsl/topics/recipe.safe-artifact-probing.md +66 -0
- package/dist/help/dsl/topics/recipe.unfamiliar-area.md +62 -0
- package/dist/help/dsl/topics/recipes.md +18 -0
- package/dist/help/dsl/topics/rename.md +15 -15
- package/dist/help/dsl/topics/renameFile.md +34 -0
- package/dist/help/dsl/topics/rg.md +20 -0
- package/dist/help/dsl/topics/rules.md +24 -0
- package/dist/help/dsl/topics/selectors.md +3 -2
- package/dist/help/dsl/topics/session.md +1 -1
- package/dist/help/full.md +236 -437
- package/dist/help/help-index.md +49 -0
- package/dist/help/help-meta.json +114 -48
- package/dist/help/index.md +76 -87
- package/dist/help/snippets/agents.md +2 -2
- package/dist/help/tokens/qr.inline.examples.md +2 -0
- package/dist/help/tokens/stdin.examples.bash.md +8 -0
- package/dist/help/tokens/stdin.examples.pwsh.md +8 -0
- package/dist/help/tokens/stdin.examples.with-qr.bash.md +12 -0
- package/dist/help/tokens/stdin.examples.with-qr.pwsh.md +12 -0
- package/dist/help/topics/basics.md +1 -1
- package/dist/help/topics/config-setup.import-normalize.md +65 -65
- package/dist/help/topics/config-setup.import-rules.md +6 -5
- package/dist/help/topics/dsl.md +4 -3
- package/dist/help/topics/first-setup.md +6 -5
- package/dist/help/topics/help-protocol.md +4 -3
- package/dist/help/topics/import.base.md +36 -0
- package/dist/help/topics/import.rebase.md +83 -0
- package/dist/help/topics/inspect.aliasCandidates.md +37 -0
- package/dist/help/topics/inspect.code.md +5 -11
- package/dist/help/topics/inspect.deps.md +7 -7
- package/dist/help/topics/inspect.file.md +10 -18
- package/dist/help/topics/inspect.graph.md +6 -20
- package/dist/help/topics/{inspect.md → inspect.shared.md} +18 -17
- package/dist/help/topics/modulePlan.md +21 -26
- package/dist/help/topics/move.md +17 -18
- package/dist/help/topics/moveToDir.md +44 -0
- package/dist/help/topics/mutate.mixed.md +32 -0
- package/dist/help/topics/mutation.shared.md +53 -0
- package/dist/help/topics/patterns.md +3 -16
- package/dist/help/topics/qr.md +13 -22
- package/dist/help/topics/quick-map.md +36 -23
- package/dist/help/topics/recipe.file-layout.md +13 -0
- package/dist/help/topics/recipe.import-boundary.md +90 -0
- package/dist/help/topics/recipe.safe-artifact-probing.md +66 -0
- package/dist/help/topics/recipe.unfamiliar-area.md +62 -0
- package/dist/help/topics/recipes.md +18 -0
- package/dist/help/topics/rename.md +15 -15
- package/dist/help/topics/renameFile.md +34 -0
- package/dist/help/topics/rg.md +20 -0
- package/dist/help/topics/rules.md +24 -0
- package/dist/help/topics/selectors.md +3 -2
- package/dist/help/topics/session.md +1 -1
- package/dist/host/capabilities.js +56 -0
- package/dist/imports/standalone-import-analysis.js +602 -0
- package/dist/imports/standalone-import-model.js +2 -0
- package/dist/imports/standalone-import-process.js +66 -0
- package/dist/imports/standalone-import-worker.js +27 -0
- package/dist/imports/standalone-ts-project.js +147 -0
- package/dist/inspect/inspect-duplicates-service.js +526 -0
- package/dist/inspect/inspect-reverse-module-closure.js +338 -0
- package/dist/inspect/inspect-source-ranges.js +82 -0
- package/dist/inspect/inspect-source-shape.js +649 -0
- package/dist/inspect/standalone-inspect-analysis.js +319 -0
- package/dist/inspect/standalone-inspect-model.js +9 -0
- package/dist/inspect/standalone-inspect-process.js +55 -0
- package/dist/inspect/standalone-inspect-usages.js +274 -0
- package/dist/inspect/standalone-inspect-worker.js +13 -0
- package/dist/metrics/central-metrics.js +101 -2
- package/dist/mutation/concrete-edit-plan.js +157 -0
- package/dist/mutation/exports-star-collapse-preview.js +361 -0
- package/dist/mutation/exports-star-expand-apply.js +373 -0
- package/dist/mutation/exports-star-expand-preview.js +807 -0
- package/dist/mutation/file-impact-scan.js +182 -0
- package/dist/mutation/file-mutation-discovery.js +674 -0
- package/dist/mutation/file-mutation-eta.js +99 -0
- package/dist/mutation/file-mutation-standalone-apply.js +584 -0
- package/dist/mutation/file-mutation-standalone-planner.js +500 -0
- package/dist/mutation/file-mutation-tsserver-session.js +473 -0
- package/dist/mutation/mutation-estimate.js +45 -0
- package/dist/mutation/mutation-plan.js +467 -0
- package/dist/mutation/object-mutation-foundation.js +2 -0
- package/dist/mutation/object-mutation-partition.js +148 -0
- package/dist/mutation/object-pack-semantic-apply.js +507 -0
- package/dist/mutation/object-pack-semantic-preview.js +984 -0
- package/dist/mutation/object-unpack-semantic-preview.js +993 -0
- package/dist/mutation/package-manifest-impact.js +176 -0
- package/dist/mutation/rename-owner-worker-child.js +37 -0
- package/dist/mutation/rename-owner-worker.js +122 -0
- package/dist/mutation/runtime-cycle-query.js +66 -0
- package/dist/mutation/semantic-execution-progress.js +63 -0
- package/dist/mutation/semantic-export-index.js +474 -0
- package/dist/mutation/semantic-impact-scan.js +434 -0
- package/dist/mutation/semantic-model.js +2 -0
- package/dist/mutation/semantic-move-best-effort-planner.js +209 -0
- package/dist/mutation/semantic-move-config-worker-child.js +61 -0
- package/dist/mutation/semantic-move-config-worker.js +449 -0
- package/dist/mutation/semantic-move-declarations.js +94 -0
- package/dist/mutation/semantic-move-metrics.js +119 -0
- package/dist/mutation/semantic-move-model.js +2 -0
- package/dist/mutation/semantic-move-owner-authority.js +122 -0
- package/dist/mutation/semantic-move-owner-candidates.js +300 -0
- package/dist/mutation/semantic-move-owner-divergence-harness.js +474 -0
- package/dist/mutation/semantic-move-owner-divergence-runner.js +162 -0
- package/dist/mutation/semantic-move-plan-hash.js +56 -0
- package/dist/mutation/semantic-move-policy.js +360 -0
- package/dist/mutation/semantic-move-process.js +218 -0
- package/dist/mutation/semantic-move-provider-diagnostics.js +27 -0
- package/dist/mutation/semantic-move-standalone-engine.js +919 -0
- package/dist/mutation/semantic-move-standalone-planner.js +1553 -0
- package/dist/mutation/semantic-move-transaction.js +639 -0
- package/dist/mutation/semantic-mutation-engine.js +478 -0
- package/dist/mutation/semantic-mutation-runtime.js +521 -0
- package/dist/mutation/semantic-planner-retry.js +26 -0
- package/dist/mutation/semantic-program-roots.js +69 -0
- package/dist/mutation/semantic-rename-commonjs.js +229 -0
- package/dist/mutation/semantic-rename-config-worker-child.js +46 -0
- package/dist/mutation/semantic-rename-config-worker.js +498 -0
- package/dist/mutation/semantic-rename-locations.js +192 -0
- package/dist/mutation/semantic-rename-model.js +2 -0
- package/dist/mutation/semantic-rename-process.js +210 -0
- package/dist/mutation/semantic-rename-standalone-engine.js +302 -0
- package/dist/mutation/semantic-rename-standalone-planner.js +567 -0
- package/dist/mutation/semantic-rename-transaction.js +333 -0
- package/dist/mutation/semantic-unused-import-cleanup.js +248 -0
- package/dist/mutation/semantic-worker-retry.js +40 -0
- package/dist/mutation/semantic-workspace.js +804 -0
- package/dist/mutation/targeted-import-canonicalizer.js +359 -0
- package/dist/observability/config.js +206 -1
- package/dist/observability/context.js +59 -1
- package/dist/observability/failure-snapshot.js +124 -2
- package/dist/observability/recent.js +63 -2
- package/dist/payloads/read-stdin-json.js +212 -1
- package/dist/rg-wrapper/core.js +714 -0
- package/dist/rg-wrapper/options.js +125 -0
- package/dist/rtk-wrapper/core.js +144 -0
- package/dist/rtk-wrapper/git-safety.js +203 -0
- package/dist/rtk-wrapper/output-adapter.js +106 -0
- package/dist/runtime/buffered-process.js +114 -0
- package/dist/runtime/bundled-node.js +97 -1
- package/dist/runtime/command-lifecycle.js +2 -0
- package/dist/runtime/input-source.js +238 -1
- package/dist/runtime/node-cli-identity.js +37 -0
- package/dist/runtime/run-command.js +191 -1
- package/dist/selectors/parse-entities.js +84 -1
- package/dist/semantic/semantic-context-pool.js +830 -0
- package/dist/semantic/semantic-context-provider.js +416 -0
- package/dist/semantic/semantic-resident-admission.js +38 -0
- package/dist/semantic/semantic-worker-child.js +40 -0
- package/dist/semantic/semantic-worker-manager.js +460 -0
- package/dist/semantic/semantic-worker-protocol.js +2 -0
- package/dist/semantic/semantic-worker-runtime.js +38 -0
- package/dist/semantic/workspace-semantic-context-pools.js +136 -0
- package/dist/session/client.js +359 -1
- package/dist/session/daemon-state.js +185 -0
- package/dist/session/external-tool-coordinator.js +88 -0
- package/dist/session/external-tool-request.js +52 -0
- package/dist/session/lane-owner.js +116 -0
- package/dist/session/paths.js +71 -1
- package/dist/session/runtime-lifecycle.js +225 -0
- package/dist/session/runtime-shutdown.js +95 -0
- package/dist/session/server.js +1194 -8
- package/dist/session/session-health.js +27 -0
- package/dist/shared/agent-text.js +29 -1
- package/dist/shared/errors.js +496 -30
- package/dist/shared/event-loop.js +6 -1
- package/dist/shared/hints.js +37 -1
- package/dist/shared/metrics.js +43 -1
- package/dist/shared/presentation.js +69 -4
- package/dist/shared/stdin-examples.js +77 -3
- package/dist/shared/stdout.js +6 -2
- package/dist/shared/types.js +23 -1
- package/dist/tool-runtime/runtime-tools.js +120 -0
- package/dist/topology/availability.js +663 -0
- package/dist/topology/cache.js +130 -0
- package/dist/topology/candidates.js +372 -0
- package/dist/topology/core.js +903 -0
- package/dist/topology/dependency-snapshot.js +189 -0
- package/dist/topology/model.js +2 -0
- package/dist/topology/scope.js +100 -0
- package/dist/topology/ts-oracle-batch.js +529 -0
- package/dist/topology/ts-oracle-host.js +69 -0
- package/dist/topology/ts-oracle-model.js +2 -0
- package/dist/topology/ts-oracle.js +224 -0
- package/dist/topology/tsconfig-loader.js +105 -0
- package/dist/topology/workspace-project-index.js +542 -0
- package/dist/tracing/config.js +192 -2
- package/dist/tracing/failure-summary.js +100 -0
- package/dist/tracing/trace.js +318 -5
- package/dist/tsc-wrapper/core.js +697 -0
- package/dist/workers/control-plane/aib-control-plane-worker.cjs +80 -0
- package/dist/workers/control-plane/client-config.default.json +3 -0
- package/dist/workers/lexical-worker-child.js +27 -0
- package/dist/workers/lexical-worker-manager.js +394 -0
- package/dist/workers/lexical-worker-protocol.js +2 -0
- package/dist/workers/lexical-worker-runtime.js +25 -0
- package/dist/workers/owned-one-shot-process.js +115 -0
- package/dist/workers/product-storage.js +23 -0
- package/dist/workers/registry.js +241 -0
- package/package.json +8 -11
- package/runtimes/tools/rg/darwin-arm64/rg +0 -0
- package/runtimes/tools/rg/darwin-x64/rg +0 -0
- package/runtimes/tools/rg/linux-arm64/rg +0 -0
- package/runtimes/tools/rg/linux-x64/rg +0 -0
- package/runtimes/tools/rg/manifest.json +36 -0
- package/runtimes/tools/rg/win32-x64/rg.exe +0 -0
- package/runtimes/tools/rtk/darwin-arm64/rtk +0 -0
- package/runtimes/tools/rtk/darwin-x64/rtk +0 -0
- package/runtimes/tools/rtk/linux-arm64/rtk +0 -0
- package/runtimes/tools/rtk/linux-x64/rtk +0 -0
- package/runtimes/tools/rtk/manifest.json +36 -0
- package/runtimes/tools/rtk/win32-x64/rtk.exe +0 -0
- package/scripts/postinstall.cjs +29 -29
- package/scripts/provision-runtime.cjs +411 -459
- package/dist/client/http-client.js +0 -1
- package/dist/client/transport-options.js +0 -1
- package/dist/client/websocket-client.js +0 -1
- package/dist/commands/entity-resolution.js +0 -1
- package/dist/commands/inspect-symbol-query.js +0 -1
- package/dist/commands/list-instances.js +0 -1
- package/dist/commands/module-plan-command.js +0 -1
- package/dist/commands/move-command.js +0 -1
- package/dist/commands/move-to-file.js +0 -2
- package/dist/commands/ping.js +0 -1
- package/dist/commands/refactor-command.js +0 -1
- package/dist/commands/rename-command.js +0 -1
- package/dist/commands/runtime-command.js +0 -4
- package/dist/commands/runtime-info.js +0 -1
- package/dist/commands/validate-module-plan.js +0 -2
- package/dist/compatibility/policy.js +0 -1
- package/dist/config/auto-start-ide.js +0 -1
- package/dist/discovery/registry.js +0 -1
- package/dist/discovery/select-instance.js +0 -1
- package/dist/help/docs/mutation.md +0 -50
- package/dist/help/docs/refactor.batch.md +0 -44
- package/dist/help/dsl/docs/mutation.md +0 -50
- package/dist/help/dsl/docs/refactor.batch.md +0 -44
- package/dist/help/dsl/topics/mutation.md +0 -48
- package/dist/help/dsl/topics/refactor.batch.md +0 -33
- package/dist/help/json/bootstrap.md +0 -1085
- package/dist/help/json/docs/basics.md +0 -15
- package/dist/help/json/docs/config-setup.aliases.md +0 -56
- package/dist/help/json/docs/config-setup.excludes.md +0 -45
- package/dist/help/json/docs/config-setup.import-normalize.md +0 -86
- package/dist/help/json/docs/config-setup.import-rules.md +0 -96
- package/dist/help/json/docs/config-setup.tsconfigs.md +0 -33
- package/dist/help/json/docs/dsl.md +0 -25
- package/dist/help/json/docs/first-setup.md +0 -292
- package/dist/help/json/docs/help-format.md +0 -9
- package/dist/help/json/docs/help-protocol.md +0 -26
- package/dist/help/json/docs/imports.normalize.md +0 -47
- package/dist/help/json/docs/inspect.code.md +0 -41
- package/dist/help/json/docs/inspect.cycles.md +0 -38
- package/dist/help/json/docs/inspect.deps.md +0 -46
- package/dist/help/json/docs/inspect.duplicates.md +0 -65
- package/dist/help/json/docs/inspect.exports.md +0 -40
- package/dist/help/json/docs/inspect.file.md +0 -38
- package/dist/help/json/docs/inspect.graph.md +0 -139
- package/dist/help/json/docs/inspect.imports.md +0 -15
- package/dist/help/json/docs/inspect.md +0 -88
- package/dist/help/json/docs/inspect.members.md +0 -32
- package/dist/help/json/docs/inspect.tree.md +0 -32
- package/dist/help/json/docs/inspect.usages.md +0 -61
- package/dist/help/json/docs/modulePlan.md +0 -73
- package/dist/help/json/docs/move.md +0 -56
- package/dist/help/json/docs/mutation.md +0 -65
- package/dist/help/json/docs/patterns.md +0 -76
- package/dist/help/json/docs/prefs.md +0 -40
- package/dist/help/json/docs/qr.md +0 -37
- package/dist/help/json/docs/quick-map.md +0 -30
- package/dist/help/json/docs/refactor.batch.md +0 -72
- package/dist/help/json/docs/rename.md +0 -47
- package/dist/help/json/docs/reveal.md +0 -30
- package/dist/help/json/docs/selectors.md +0 -23
- package/dist/help/json/docs/session.md +0 -77
- package/dist/help/json/docs/view.md +0 -30
- package/dist/help/json/full.md +0 -1085
- package/dist/help/json/snippets/agents.md +0 -14
- package/dist/help/json/topics/basics.md +0 -13
- package/dist/help/json/topics/config-setup.aliases.md +0 -54
- package/dist/help/json/topics/config-setup.excludes.md +0 -43
- package/dist/help/json/topics/config-setup.import-normalize.md +0 -84
- package/dist/help/json/topics/config-setup.import-rules.md +0 -94
- package/dist/help/json/topics/config-setup.tsconfigs.md +0 -31
- package/dist/help/json/topics/dsl.md +0 -23
- package/dist/help/json/topics/first-setup.md +0 -290
- package/dist/help/json/topics/help-format.md +0 -7
- package/dist/help/json/topics/help-protocol.md +0 -24
- package/dist/help/json/topics/imports.normalize.md +0 -45
- package/dist/help/json/topics/inspect.code.md +0 -39
- package/dist/help/json/topics/inspect.cycles.md +0 -36
- package/dist/help/json/topics/inspect.deps.md +0 -44
- package/dist/help/json/topics/inspect.duplicates.md +0 -37
- package/dist/help/json/topics/inspect.exports.md +0 -38
- package/dist/help/json/topics/inspect.file.md +0 -36
- package/dist/help/json/topics/inspect.graph.md +0 -137
- package/dist/help/json/topics/inspect.imports.md +0 -13
- package/dist/help/json/topics/inspect.md +0 -86
- package/dist/help/json/topics/inspect.members.md +0 -30
- package/dist/help/json/topics/inspect.tree.md +0 -22
- package/dist/help/json/topics/inspect.usages.md +0 -59
- package/dist/help/json/topics/modulePlan.md +0 -60
- package/dist/help/json/topics/move.md +0 -46
- package/dist/help/json/topics/mutation.md +0 -63
- package/dist/help/json/topics/patterns.md +0 -74
- package/dist/help/json/topics/prefs.md +0 -38
- package/dist/help/json/topics/qr.md +0 -35
- package/dist/help/json/topics/quick-map.md +0 -28
- package/dist/help/json/topics/refactor.batch.md +0 -61
- package/dist/help/json/topics/rename.md +0 -42
- package/dist/help/json/topics/reveal.md +0 -28
- package/dist/help/json/topics/selectors.md +0 -21
- package/dist/help/json/topics/session.md +0 -59
- package/dist/help/json/topics/view.md +0 -28
- package/dist/help/topics/mutation.md +0 -48
- package/dist/help/topics/refactor.batch.md +0 -33
- package/dist/ide-launch/common.cjs +0 -162
- package/dist/managed-host/extension-vsix-resolver.js +0 -1
- package/dist/managed-host/manage-serve-web-host.cjs +0 -141
- package/dist/managed-host/serve-web-autostart.js +0 -1
- package/dist/managed-host/serve-web-host.cjs +0 -1904
- package/dist/runtime/managed-runtime-provisioning.js +0 -1
- package/dist/shared/diagnostic-catalog.js +0 -1
- package/dist/shared/diagnostics.js +0 -1
- package/dist/shared/operations.js +0 -1
- package/dist/shared/protocol.js +0 -1
- package/dist/shared/routes.js +0 -1
- package/extension/vscode-refactor-bridge-extension.vsix +0 -0
- package/runtimes/launcher/linux-x64/aib +0 -0
- package/runtimes/launcher/win-x64/aib.exe +0 -0
|
@@ -0,0 +1,1138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runImportsRebase = runImportsRebase;
|
|
40
|
+
const crypto = __importStar(require("node:crypto"));
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
44
|
+
const import_rules_1 = require("../config/import-rules");
|
|
45
|
+
const path_aliases_1 = require("../config/path-aliases");
|
|
46
|
+
const workspace_root_1 = require("../config/workspace-root");
|
|
47
|
+
const agent_text_1 = require("../shared/agent-text");
|
|
48
|
+
const errors_1 = require("../shared/errors");
|
|
49
|
+
const targeted_import_canonicalizer_1 = require("../mutation/targeted-import-canonicalizer");
|
|
50
|
+
const workspace_cache_1 = require("./workspace-cache");
|
|
51
|
+
const SOURCE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
52
|
+
const BARREL_INDEX_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
53
|
+
const EXCLUDED_DIRS = new Set(["node_modules", ".git", "dist", "out", "build", ".tmp"]);
|
|
54
|
+
function runImportsRebase(cwd, restArgs, payload) {
|
|
55
|
+
const action = readAction(restArgs[0]);
|
|
56
|
+
if (action === "apply") {
|
|
57
|
+
const planId = restArgs[1];
|
|
58
|
+
if (!planId || planId.startsWith("--")) {
|
|
59
|
+
throw new errors_1.CliError("IMPORT_REBASE_PLAN_REQUIRED", "imports rebase apply expects a preview id.");
|
|
60
|
+
}
|
|
61
|
+
return applyImportRebasePlan(cwd, planId);
|
|
62
|
+
}
|
|
63
|
+
const request = normalizeImportRebaseRequest(payload, action);
|
|
64
|
+
const response = runImportRebaseRequest(cwd, request);
|
|
65
|
+
return (0, agent_text_1.attachAgentText)(response, formatImportRebaseText(response));
|
|
66
|
+
}
|
|
67
|
+
function runImportRebaseRequest(cwd, request) {
|
|
68
|
+
const barrel = resolveBarrel(cwd, request.barrel, request.displayBarrel);
|
|
69
|
+
const files = request.files.length > 0
|
|
70
|
+
? request.files.map((file) => resolveInputPath(cwd, file)).filter((file) => isSourceFile(file))
|
|
71
|
+
: collectSourceFiles(resolveInputPath(cwd, request.scope ?? ""), cwd, request.pathExclude);
|
|
72
|
+
const programContext = createImportRebaseProgram(cwd, [barrel.file, ...files]);
|
|
73
|
+
const barrelGraphFiles = collectBarrelGraphFiles(cwd, barrel.file, programContext);
|
|
74
|
+
const exports = collectBarrelExports(cwd, barrel.file, request.symbols, programContext);
|
|
75
|
+
const plan = buildImportRebasePlan(cwd, request, barrel, exports, files, barrelGraphFiles, programContext);
|
|
76
|
+
if (request.operation === "imports.useBarrel" && plan.exports.length === 0) {
|
|
77
|
+
throw new errors_1.CliError("IMPORT_REBASE_BARREL_EXPORTS_NOT_FOUND", "Barrel has no usable named exports for this request.", {
|
|
78
|
+
barrel: toDisplayPath(cwd, barrel.file),
|
|
79
|
+
...(request.symbols.length > 0 ? { symbols: request.symbols } : {})
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (request.operation === "imports.useDirect" && plan.exports.length === 0) {
|
|
83
|
+
throw new errors_1.CliError("IMPORT_REBASE_DIRECT_EXPORTS_NOT_FOUND", "Barrel has no usable source exports for this request.", {
|
|
84
|
+
barrel: toDisplayPath(cwd, barrel.file),
|
|
85
|
+
...(request.symbols.length > 0 ? { symbols: request.symbols } : {})
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (request.operation === "imports.useBarrel" || request.operation === "imports.useDirect") {
|
|
89
|
+
const missingSymbols = request.symbols.filter((symbol) => !plan.exports.some((item) => item.name === symbol));
|
|
90
|
+
for (const symbol of missingSymbols) {
|
|
91
|
+
plan.skipped.push({ selector: symbol, reason: "not exported by barrel" });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (request.action === "execute") {
|
|
95
|
+
applyImportRebaseEdits(cwd, plan.edits);
|
|
96
|
+
}
|
|
97
|
+
const response = buildImportRebaseResponse(cwd, request, plan);
|
|
98
|
+
if (request.action === "preview" && plan.edits.length > 0) {
|
|
99
|
+
const planId = buildImportRebasePlanId(cwd, plan);
|
|
100
|
+
writeImportRebasePlan(cwd, {
|
|
101
|
+
planId,
|
|
102
|
+
createdAt: new Date().toISOString(),
|
|
103
|
+
cwd,
|
|
104
|
+
request,
|
|
105
|
+
barrel,
|
|
106
|
+
exports: plan.exports,
|
|
107
|
+
barrelGraphFiles: plan.barrelGraphFiles,
|
|
108
|
+
files: hashPlanFiles(cwd, plan),
|
|
109
|
+
edits: plan.edits,
|
|
110
|
+
skipped: plan.skipped,
|
|
111
|
+
scannedFiles: plan.scannedFiles
|
|
112
|
+
});
|
|
113
|
+
response.planId = planId;
|
|
114
|
+
response.next = `aib mutate apply ${planId}`;
|
|
115
|
+
}
|
|
116
|
+
return response;
|
|
117
|
+
}
|
|
118
|
+
function applyImportRebasePlan(cwd, planId) {
|
|
119
|
+
const record = readImportRebasePlan(cwd, planId);
|
|
120
|
+
const staleFiles = Object.entries(record.files)
|
|
121
|
+
.filter(([file, hash]) => {
|
|
122
|
+
const fullPath = path.resolve(cwd, file);
|
|
123
|
+
return !fs.existsSync(fullPath) || sha256(fs.readFileSync(fullPath)) !== hash;
|
|
124
|
+
})
|
|
125
|
+
.map(([file]) => file);
|
|
126
|
+
if (staleFiles.length > 0) {
|
|
127
|
+
throw new errors_1.CliError("IMPORT_REBASE_PLAN_STALE", `imports rebase plan is stale: ${planId}`, {
|
|
128
|
+
planId,
|
|
129
|
+
staleFiles: staleFiles.slice(0, 20),
|
|
130
|
+
...(staleFiles.length > 20 ? { hidden: `+ ${staleFiles.length - 20} more stale files` } : {})
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
applyImportRebaseEdits(cwd, record.edits);
|
|
134
|
+
const response = buildImportRebaseResponse(cwd, { ...record.request, action: "apply" }, {
|
|
135
|
+
barrel: record.barrel,
|
|
136
|
+
exports: record.exports,
|
|
137
|
+
barrelGraphFiles: record.barrelGraphFiles,
|
|
138
|
+
edits: record.edits,
|
|
139
|
+
skipped: record.skipped,
|
|
140
|
+
scannedFiles: record.scannedFiles
|
|
141
|
+
});
|
|
142
|
+
response.planId = planId;
|
|
143
|
+
return (0, agent_text_1.attachAgentText)(response, formatImportRebaseText(response));
|
|
144
|
+
}
|
|
145
|
+
function buildImportRebasePlan(cwd, request, barrel, exports, files, barrelGraphFiles, programContext) {
|
|
146
|
+
const barrelGraphKeys = new Set(barrelGraphFiles.map((file) => path.resolve(file)));
|
|
147
|
+
const byName = groupExportsByName(exports);
|
|
148
|
+
const sourceToExports = new Map();
|
|
149
|
+
for (const item of exports) {
|
|
150
|
+
if (item.importKind !== "named") {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const byImportedName = sourceToExports.get(path.resolve(item.sourceFile)) ?? new Map();
|
|
154
|
+
byImportedName.set(item.importedName, item);
|
|
155
|
+
sourceToExports.set(path.resolve(item.sourceFile), byImportedName);
|
|
156
|
+
}
|
|
157
|
+
const edits = [];
|
|
158
|
+
const skipped = [];
|
|
159
|
+
for (const file of files) {
|
|
160
|
+
if (request.operation === "imports.useBarrel" && barrelGraphKeys.has(path.resolve(file))) {
|
|
161
|
+
skipped.push({
|
|
162
|
+
file: toDisplayPath(cwd, file),
|
|
163
|
+
reason: path.resolve(file) === path.resolve(barrel.file)
|
|
164
|
+
? "barrel file skipped"
|
|
165
|
+
: "inside barrel export graph"
|
|
166
|
+
});
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const fileEdits = collectFileRebaseEdits(cwd, file, request, barrel, byName, sourceToExports, skipped, programContext);
|
|
170
|
+
edits.push(...fileEdits);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
barrel,
|
|
174
|
+
exports,
|
|
175
|
+
barrelGraphFiles: barrelGraphFiles.map((file) => toDisplayPath(cwd, file)),
|
|
176
|
+
edits,
|
|
177
|
+
skipped,
|
|
178
|
+
scannedFiles: files.map((file) => toDisplayPath(cwd, file))
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function collectFileRebaseEdits(cwd, file, request, barrel, byName, sourceToExports, skipped, programContext) {
|
|
182
|
+
const text = fs.readFileSync(file, "utf8");
|
|
183
|
+
const parsed = createSourceFile(file, text);
|
|
184
|
+
const edits = [];
|
|
185
|
+
for (const statement of parsed.statements) {
|
|
186
|
+
if (!typescript_1.default.isImportDeclaration(statement) || !typescript_1.default.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const importClause = statement.importClause;
|
|
190
|
+
const specifier = statement.moduleSpecifier.text;
|
|
191
|
+
if (!importClause) {
|
|
192
|
+
if (importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext)) {
|
|
193
|
+
skipped.push({ file: toDisplayPath(cwd, file), specifier, reason: "side-effect import unsupported" });
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (importClause.name && !importClause.namedBindings) {
|
|
198
|
+
if (importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext)) {
|
|
199
|
+
skipped.push({ file: toDisplayPath(cwd, file), specifier, reason: "default import unsupported" });
|
|
200
|
+
}
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (importClause.name && importClause.namedBindings) {
|
|
204
|
+
if (importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext)) {
|
|
205
|
+
skipped.push({ file: toDisplayPath(cwd, file), specifier, reason: "default import unsupported" });
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const bindings = importClause.namedBindings;
|
|
210
|
+
if (!bindings || typescript_1.default.isNamespaceImport(bindings)) {
|
|
211
|
+
if (importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext)) {
|
|
212
|
+
skipped.push({ file: toDisplayPath(cwd, file), specifier, reason: "namespace import unsupported" });
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (hasAmbiguousTargetImportComments(text, parsed, statement) && importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext)) {
|
|
217
|
+
skipped.push({ file: toDisplayPath(cwd, file), specifier, reason: "import comments require preserving this declaration" });
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (request.operation === "imports.useBarrel") {
|
|
221
|
+
edits.push(...collectUseBarrelImportEdits(cwd, file, text, statement, bindings, specifier, barrel, sourceToExports, request, skipped, programContext));
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
edits.push(...collectUseDirectImportEdits(cwd, file, text, statement, bindings, specifier, barrel, byName, request, skipped, programContext));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return edits;
|
|
228
|
+
}
|
|
229
|
+
function collectUseBarrelImportEdits(cwd, file, text, statement, bindings, specifier, barrel, sourceToExports, request, skipped, programContext) {
|
|
230
|
+
const resolved = resolveSpecifier(cwd, file, specifier, programContext);
|
|
231
|
+
if (!resolved) {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const exportsByImportedName = sourceToExports.get(path.resolve(resolved));
|
|
235
|
+
if (!exportsByImportedName || path.resolve(resolved) === path.resolve(barrel.file)) {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
const eligible = bindings.elements
|
|
239
|
+
.map((element) => {
|
|
240
|
+
const importedName = element.propertyName?.text ?? element.name.text;
|
|
241
|
+
const barrelExport = exportsByImportedName.get(importedName);
|
|
242
|
+
return barrelExport ? { element, barrelExport } : null;
|
|
243
|
+
})
|
|
244
|
+
.filter((item) => Boolean(item));
|
|
245
|
+
if (eligible.length === 0) {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
const eligibleElements = new Set(eligible.map((item) => item.element));
|
|
249
|
+
const ineligible = bindings.elements.filter((element) => !eligibleElements.has(element));
|
|
250
|
+
const targetSpecifier = barrel.importSpecifierHint ?? (0, targeted_import_canonicalizer_1.chooseTargetedImportSpecifier)({
|
|
251
|
+
cwd,
|
|
252
|
+
fromFile: file,
|
|
253
|
+
targetFile: barrel.file,
|
|
254
|
+
allowIndexCollapse: true,
|
|
255
|
+
importRules: programContext.importRules,
|
|
256
|
+
tsConfigCache: programContext.tsConfigCache
|
|
257
|
+
});
|
|
258
|
+
const replacement = buildReplacementImportTextWithPreparedElements(text, statement, importClauseIsTypeOnly(statement), eligible.map((item) => ({
|
|
259
|
+
selector: item.barrelExport.name,
|
|
260
|
+
text: formatBarrelImportSpecifier(item.element, item.barrelExport)
|
|
261
|
+
})), ineligible, targetSpecifier, specifier);
|
|
262
|
+
return [{
|
|
263
|
+
file: toDisplayPath(cwd, file),
|
|
264
|
+
from: specifier,
|
|
265
|
+
to: targetSpecifier,
|
|
266
|
+
symbols: eligible.map((item) => item.barrelExport.name),
|
|
267
|
+
matchSymbols: eligible.map((item) => item.element.propertyName?.text ?? item.element.name.text),
|
|
268
|
+
declarationText: replacement
|
|
269
|
+
}];
|
|
270
|
+
}
|
|
271
|
+
function collectUseDirectImportEdits(cwd, file, text, statement, bindings, specifier, barrel, byName, request, skipped, programContext) {
|
|
272
|
+
const resolved = resolveSpecifier(cwd, file, specifier, programContext);
|
|
273
|
+
if (!resolved || path.resolve(resolved) !== path.resolve(barrel.file)) {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
const byTarget = new Map();
|
|
277
|
+
const remaining = [];
|
|
278
|
+
for (const element of bindings.elements) {
|
|
279
|
+
const name = element.propertyName?.text ?? element.name.text;
|
|
280
|
+
if (!symbolAllowed(request, name)) {
|
|
281
|
+
remaining.push(element);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const candidates = byName.get(name) ?? [];
|
|
285
|
+
if (candidates.length === 0) {
|
|
286
|
+
skipped.push({ file: toDisplayPath(cwd, file), selector: name, specifier, reason: "not exported by barrel" });
|
|
287
|
+
remaining.push(element);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const directCandidates = uniqueBy(candidates.filter((item) => path.resolve(item.sourceFile) !== path.resolve(barrel.file)), (item) => path.resolve(item.sourceFile));
|
|
291
|
+
if (directCandidates.length !== 1) {
|
|
292
|
+
skipped.push({
|
|
293
|
+
file: toDisplayPath(cwd, file),
|
|
294
|
+
selector: name,
|
|
295
|
+
specifier,
|
|
296
|
+
reason: directCandidates.length > 1 ? "ambiguous barrel source" : "direct source unavailable",
|
|
297
|
+
...(directCandidates.length > 1 ? { candidates: directCandidates.map((candidate) => toDisplayPath(cwd, candidate.sourceFile)) } : {})
|
|
298
|
+
});
|
|
299
|
+
remaining.push(element);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const targetFile = directCandidates[0].sourceFile;
|
|
303
|
+
const directExport = directCandidates[0];
|
|
304
|
+
if (directExport.importKind === "default") {
|
|
305
|
+
skipped.push({ file: toDisplayPath(cwd, file), selector: name, specifier, reason: "default re-export unsupported" });
|
|
306
|
+
remaining.push(element);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
byTarget.set(targetFile, [...(byTarget.get(targetFile) ?? []), {
|
|
310
|
+
selector: name,
|
|
311
|
+
text: formatDirectImportSpecifier(element, directExport)
|
|
312
|
+
}]);
|
|
313
|
+
}
|
|
314
|
+
if (byTarget.size === 0) {
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
const imports = Array.from(byTarget.entries()).map(([targetFile, elements]) => ({
|
|
318
|
+
targetFile,
|
|
319
|
+
elements,
|
|
320
|
+
specifier: (0, targeted_import_canonicalizer_1.chooseTargetedImportSpecifier)({
|
|
321
|
+
cwd,
|
|
322
|
+
fromFile: file,
|
|
323
|
+
targetFile,
|
|
324
|
+
allowIndexCollapse: false,
|
|
325
|
+
importRules: programContext.importRules,
|
|
326
|
+
tsConfigCache: programContext.tsConfigCache
|
|
327
|
+
})
|
|
328
|
+
}));
|
|
329
|
+
const parts = [];
|
|
330
|
+
if (remaining.length > 0) {
|
|
331
|
+
parts.push(formatImportDeclaration(text, statement, importClauseIsTypeOnly(statement), remaining, specifier));
|
|
332
|
+
}
|
|
333
|
+
for (const item of imports) {
|
|
334
|
+
parts.push(formatDirectImportDeclaration(text, statement, importClauseIsTypeOnly(statement), item.elements, item.specifier));
|
|
335
|
+
}
|
|
336
|
+
return [{
|
|
337
|
+
file: toDisplayPath(cwd, file),
|
|
338
|
+
from: specifier,
|
|
339
|
+
to: imports.map((item) => item.specifier).join(", "),
|
|
340
|
+
symbols: imports.flatMap((item) => item.elements.map((element) => element.selector)),
|
|
341
|
+
declarationText: parts.join("\n")
|
|
342
|
+
}];
|
|
343
|
+
}
|
|
344
|
+
function buildReplacementImportText(fullText, statement, typeOnly, eligible, ineligible, targetSpecifier, originalSpecifier) {
|
|
345
|
+
const parts = [];
|
|
346
|
+
if (ineligible.length > 0) {
|
|
347
|
+
parts.push(formatImportDeclaration(fullText, statement, typeOnly, ineligible, originalSpecifier));
|
|
348
|
+
}
|
|
349
|
+
if (eligible.length > 0) {
|
|
350
|
+
parts.push(formatImportDeclaration(fullText, statement, typeOnly, eligible, targetSpecifier));
|
|
351
|
+
}
|
|
352
|
+
return parts.join(detectNewline(fullText));
|
|
353
|
+
}
|
|
354
|
+
function buildReplacementImportTextWithPreparedElements(fullText, statement, typeOnly, eligible, ineligible, targetSpecifier, originalSpecifier) {
|
|
355
|
+
const parts = [];
|
|
356
|
+
if (ineligible.length > 0) {
|
|
357
|
+
parts.push(formatImportDeclaration(fullText, statement, typeOnly, ineligible, originalSpecifier));
|
|
358
|
+
}
|
|
359
|
+
if (eligible.length > 0) {
|
|
360
|
+
parts.push(formatDirectImportDeclaration(fullText, statement, typeOnly, eligible, targetSpecifier));
|
|
361
|
+
}
|
|
362
|
+
return parts.join(detectNewline(fullText));
|
|
363
|
+
}
|
|
364
|
+
function formatImportDeclaration(fullText, statement, typeOnly, elements, specifier) {
|
|
365
|
+
const sourceFile = statement.getSourceFile();
|
|
366
|
+
return (0, targeted_import_canonicalizer_1.renderTargetedNamedImportLike)({
|
|
367
|
+
sourceText: fullText,
|
|
368
|
+
sourceFile,
|
|
369
|
+
statement,
|
|
370
|
+
clauseTypeOnly: typeOnly,
|
|
371
|
+
specifier,
|
|
372
|
+
elements: elements.map((element) => ({
|
|
373
|
+
text: element.getText(sourceFile).replace(/^type\s+/, ""),
|
|
374
|
+
isTypeOnly: typeOnly || element.isTypeOnly
|
|
375
|
+
}))
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
function formatDirectImportDeclaration(fullText, statement, typeOnly, elements, specifier) {
|
|
379
|
+
return (0, targeted_import_canonicalizer_1.renderTargetedNamedImportLike)({
|
|
380
|
+
sourceText: fullText,
|
|
381
|
+
sourceFile: statement.getSourceFile(),
|
|
382
|
+
statement,
|
|
383
|
+
clauseTypeOnly: typeOnly,
|
|
384
|
+
specifier,
|
|
385
|
+
elements: elements.map((element) => ({
|
|
386
|
+
text: element.text.replace(/^type\s+/, ""),
|
|
387
|
+
isTypeOnly: typeOnly || /^type\s+/.test(element.text)
|
|
388
|
+
}))
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function formatDirectImportSpecifier(element, barrelExport) {
|
|
392
|
+
const localName = element.name.text;
|
|
393
|
+
const exportedName = barrelExport.name;
|
|
394
|
+
const importedName = barrelExport.importedName;
|
|
395
|
+
const prefix = element.isTypeOnly ? "type " : "";
|
|
396
|
+
if (importedName === exportedName) {
|
|
397
|
+
return element.getText();
|
|
398
|
+
}
|
|
399
|
+
return `${prefix}${importedName}${localName === importedName ? "" : ` as ${localName}`}`;
|
|
400
|
+
}
|
|
401
|
+
function formatBarrelImportSpecifier(element, barrelExport) {
|
|
402
|
+
const localName = element.name.text;
|
|
403
|
+
const directImportedName = element.propertyName?.text ?? element.name.text;
|
|
404
|
+
const exportedName = barrelExport.name;
|
|
405
|
+
const prefix = element.isTypeOnly ? "type " : "";
|
|
406
|
+
if (exportedName === directImportedName) {
|
|
407
|
+
return element.getText();
|
|
408
|
+
}
|
|
409
|
+
return `${prefix}${exportedName}${localName === exportedName ? "" : ` as ${localName}`}`;
|
|
410
|
+
}
|
|
411
|
+
function importMayBeRelevant(cwd, file, specifier, request, barrel, sourceToExports, programContext) {
|
|
412
|
+
const resolved = resolveSpecifier(cwd, file, specifier, programContext);
|
|
413
|
+
if (!resolved) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
if (request.operation === "imports.useDirect") {
|
|
417
|
+
return path.resolve(resolved) === path.resolve(barrel.file);
|
|
418
|
+
}
|
|
419
|
+
return sourceToExports.has(path.resolve(resolved));
|
|
420
|
+
}
|
|
421
|
+
function detectNewline(text) {
|
|
422
|
+
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
423
|
+
}
|
|
424
|
+
function hasAmbiguousTargetImportComments(sourceText, sourceFile, statement) {
|
|
425
|
+
if (/\/\/|\/\*/.test(statement.getText(sourceFile))) {
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
const lineStart = sourceText.lastIndexOf("\n", Math.max(0, statement.getStart(sourceFile) - 1)) + 1;
|
|
429
|
+
if (sourceText.slice(lineStart, statement.getStart(sourceFile)).trim().length > 0) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
const lineEnd = sourceText.indexOf("\n", statement.end);
|
|
433
|
+
return /\/\/|\/\*/.test(sourceText.slice(statement.end, lineEnd < 0 ? sourceText.length : lineEnd));
|
|
434
|
+
}
|
|
435
|
+
function applyImportRebaseEdits(cwd, edits) {
|
|
436
|
+
const byFile = new Map();
|
|
437
|
+
for (const edit of edits) {
|
|
438
|
+
byFile.set(edit.file, [...(byFile.get(edit.file) ?? []), edit]);
|
|
439
|
+
}
|
|
440
|
+
for (const [relativeFile, fileEdits] of byFile.entries()) {
|
|
441
|
+
const fullPath = path.resolve(cwd, relativeFile);
|
|
442
|
+
let text = fs.readFileSync(fullPath, "utf8");
|
|
443
|
+
const parsed = createSourceFile(fullPath, text);
|
|
444
|
+
const replacements = fileEdits.map((edit) => findImportDeclarationReplacement(parsed, edit.from, edit.matchSymbols ?? edit.symbols, edit.declarationText)).filter((item) => Boolean(item));
|
|
445
|
+
for (const replacement of replacements.sort((left, right) => right.start - left.start)) {
|
|
446
|
+
text = `${text.slice(0, replacement.start)}${replacement.text}${text.slice(replacement.end)}`;
|
|
447
|
+
}
|
|
448
|
+
text = (0, targeted_import_canonicalizer_1.canonicalizeTargetedNamedImports)(text, fullPath).text;
|
|
449
|
+
fs.writeFileSync(fullPath, text, "utf8");
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function findImportDeclarationReplacement(parsed, from, symbols, text) {
|
|
453
|
+
for (const statement of parsed.statements) {
|
|
454
|
+
if (!typescript_1.default.isImportDeclaration(statement) || !typescript_1.default.isStringLiteralLike(statement.moduleSpecifier) || statement.moduleSpecifier.text !== from) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
const elements = statement.importClause?.namedBindings && typescript_1.default.isNamedImports(statement.importClause.namedBindings)
|
|
458
|
+
? statement.importClause.namedBindings.elements.map((element) => element.propertyName?.text ?? element.name.text)
|
|
459
|
+
: [];
|
|
460
|
+
if (symbols.every((symbol) => elements.includes(symbol))) {
|
|
461
|
+
return { start: statement.getStart(parsed), end: statement.end, text };
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return null;
|
|
465
|
+
}
|
|
466
|
+
function buildImportRebaseResponse(cwd, request, plan) {
|
|
467
|
+
const filesChanged = new Set(plan.edits.map((edit) => edit.file)).size;
|
|
468
|
+
const response = {
|
|
469
|
+
ok: true,
|
|
470
|
+
operation: request.operation,
|
|
471
|
+
mode: request.action,
|
|
472
|
+
barrel: toDisplayPath(cwd, plan.barrel.file),
|
|
473
|
+
requestedBarrel: request.displayBarrel ?? request.barrel,
|
|
474
|
+
filesScanned: plan.scannedFiles.length,
|
|
475
|
+
filesChanged,
|
|
476
|
+
edits: plan.edits.length,
|
|
477
|
+
symbolsUpdated: plan.edits.reduce((count, edit) => count + edit.symbols.length, 0),
|
|
478
|
+
exportsConsidered: plan.exports.length,
|
|
479
|
+
barrelGraphFiles: plan.barrelGraphFiles,
|
|
480
|
+
...(request.scope ? { scope: request.scope } : {}),
|
|
481
|
+
...(request.files.length > 0 ? { files: request.files } : {}),
|
|
482
|
+
...(request.pathExclude.length > 0 ? { pathExclude: request.pathExclude } : {}),
|
|
483
|
+
...(request.symbols.length > 0 ? { symbols: request.symbols } : {}),
|
|
484
|
+
exports: plan.exports.map((item) => ({
|
|
485
|
+
name: item.name,
|
|
486
|
+
importedName: item.importedName,
|
|
487
|
+
sourceFile: toDisplayPath(cwd, item.sourceFile),
|
|
488
|
+
kind: item.kind,
|
|
489
|
+
importKind: item.importKind
|
|
490
|
+
})),
|
|
491
|
+
skipped: plan.skipped,
|
|
492
|
+
importEdits: plan.edits.map((edit) => ({
|
|
493
|
+
file: edit.file,
|
|
494
|
+
from: edit.from,
|
|
495
|
+
to: edit.to,
|
|
496
|
+
symbols: edit.symbols,
|
|
497
|
+
...(edit.matchSymbols ? { matchSymbols: edit.matchSymbols } : {})
|
|
498
|
+
})),
|
|
499
|
+
samples: plan.edits.slice(0, request.showAll ? plan.edits.length : 12).map((edit) => `${edit.file}: ${edit.from} -> ${edit.to} (${edit.symbols.join(", ")})`),
|
|
500
|
+
...(!request.showAll && plan.edits.length > 12 ? { hidden: `+ ${plan.edits.length - 12} more edits` } : {}),
|
|
501
|
+
filesWritten: request.action === "preview" ? [] : Array.from(new Set(plan.edits.map((edit) => edit.file))),
|
|
502
|
+
filesTouched: Array.from(new Set(plan.edits.map((edit) => edit.file))),
|
|
503
|
+
next: request.action === "preview"
|
|
504
|
+
? plan.edits.length > 0
|
|
505
|
+
? "Apply this mutate preview if the import rebase matches intent."
|
|
506
|
+
: plan.skipped.length > 0
|
|
507
|
+
? "Review skipped imports; adjust scope/barrel/symbols and rerun if needed."
|
|
508
|
+
: "No action needed unless the scope/barrel/symbols are wrong."
|
|
509
|
+
: "Run typecheck or targeted validation for the affected project."
|
|
510
|
+
};
|
|
511
|
+
return response;
|
|
512
|
+
}
|
|
513
|
+
function formatImportRebaseText(response) {
|
|
514
|
+
const mode = readString(response.mode) ?? "execute";
|
|
515
|
+
const operation = readString(response.operation) ?? "imports.rebase";
|
|
516
|
+
const planId = readString(response.planId);
|
|
517
|
+
const filesChanged = readNumber(response.filesChanged) ?? 0;
|
|
518
|
+
const edits = readNumber(response.edits) ?? 0;
|
|
519
|
+
const symbolsUpdated = readNumber(response.symbolsUpdated) ?? 0;
|
|
520
|
+
const skipped = readObjectArray(response.skipped).length;
|
|
521
|
+
const barrel = readString(response.barrel);
|
|
522
|
+
const lines = [];
|
|
523
|
+
lines.push(mode === "preview" && planId ? `${operation}.preview ${planId}` : mode === "apply" ? `${operation}.apply` : `${operation}.execute`);
|
|
524
|
+
const action = mode === "preview" ? "planned" : "updated";
|
|
525
|
+
lines.push(edits === 0 && filesChanged === 0
|
|
526
|
+
? "no import boundary changes"
|
|
527
|
+
: `${action}: ${symbolsUpdated} ${symbolsUpdated === 1 ? "symbol" : "symbols"} in ${edits} ${edits === 1 ? "import" : "imports"}, ${filesChanged} ${filesChanged === 1 ? "file" : "files"}`);
|
|
528
|
+
if (barrel) {
|
|
529
|
+
lines.push(`barrel: ${barrel}`);
|
|
530
|
+
}
|
|
531
|
+
const exportsConsidered = readNumber(response.exportsConsidered);
|
|
532
|
+
if (exportsConsidered !== null) {
|
|
533
|
+
lines.push(`exports: ${exportsConsidered} considered`);
|
|
534
|
+
}
|
|
535
|
+
if (skipped > 0) {
|
|
536
|
+
appendImportRebaseSkippedSummary(lines, readObjectArray(response.skipped));
|
|
537
|
+
}
|
|
538
|
+
const samples = readStringArray(response.samples);
|
|
539
|
+
if (samples.length > 0) {
|
|
540
|
+
lines.push("samples:");
|
|
541
|
+
for (const sample of samples.slice(0, 8)) {
|
|
542
|
+
lines.push(sample);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const hidden = readString(response.hidden);
|
|
546
|
+
if (hidden) {
|
|
547
|
+
lines.push(hidden);
|
|
548
|
+
}
|
|
549
|
+
const filesWritten = readStringArray(response.filesWritten);
|
|
550
|
+
if (filesWritten.length > 0) {
|
|
551
|
+
lines.push("filesWritten:");
|
|
552
|
+
for (const file of filesWritten.slice(0, 12)) {
|
|
553
|
+
lines.push(file);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const next = readString(response.next);
|
|
557
|
+
if (next) {
|
|
558
|
+
lines.push(`next: ${next}`);
|
|
559
|
+
}
|
|
560
|
+
return lines.join("\n");
|
|
561
|
+
}
|
|
562
|
+
function resolveBarrel(cwd, rawInput, displayInput) {
|
|
563
|
+
const hintInput = displayInput ?? rawInput;
|
|
564
|
+
const importSpecifierHint = hintInput.startsWith("@") ? normalizeAliasImportHint(hintInput) : null;
|
|
565
|
+
const resolved = resolveInputPath(cwd, rawInput);
|
|
566
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
|
567
|
+
const candidates = BARREL_INDEX_EXTENSIONS
|
|
568
|
+
.map((ext) => path.join(resolved, `index${ext}`))
|
|
569
|
+
.filter((candidate) => fs.existsSync(candidate) && fs.statSync(candidate).isFile());
|
|
570
|
+
if (candidates.length !== 1) {
|
|
571
|
+
throw new errors_1.CliError("IMPORT_REBASE_BARREL_AMBIGUOUS", candidates.length === 0 ? "Barrel directory has no index barrel." : "Barrel directory is ambiguous.", {
|
|
572
|
+
barrel: rawInput,
|
|
573
|
+
candidates: candidates.map((candidate) => toDisplayPath(cwd, candidate)),
|
|
574
|
+
next: "Pass the exact barrel file path."
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
const file = candidates[0];
|
|
578
|
+
return { input: rawInput, file, importSpecifierHint: importSpecifierHint ?? aliasHintForResolvedFile(cwd, file), candidates: candidates.map((candidate) => toDisplayPath(cwd, candidate)) };
|
|
579
|
+
}
|
|
580
|
+
const file = resolveImportBase(resolved);
|
|
581
|
+
if (!file) {
|
|
582
|
+
throw new errors_1.CliError("IMPORT_REBASE_BARREL_NOT_FOUND", `Barrel file not found: ${rawInput}`, {
|
|
583
|
+
barrel: rawInput,
|
|
584
|
+
resolved
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
return { input: rawInput, file, importSpecifierHint: importSpecifierHint ?? aliasHintForResolvedFile(cwd, file), candidates: [toDisplayPath(cwd, file)] };
|
|
588
|
+
}
|
|
589
|
+
function collectBarrelExports(cwd, barrelFile, symbols, programContext) {
|
|
590
|
+
const allowed = new Set(symbols);
|
|
591
|
+
const all = collectProgramBarrelExports(cwd, barrelFile, programContext);
|
|
592
|
+
return all.filter((item) => allowed.size === 0 || allowed.has(item.name));
|
|
593
|
+
}
|
|
594
|
+
function appendImportRebaseSkippedSummary(lines, skipped) {
|
|
595
|
+
lines.push(`skipped: ${skipped.length}`);
|
|
596
|
+
const barrelGraph = skipped.filter((item) => {
|
|
597
|
+
const reason = readString(item.reason);
|
|
598
|
+
return reason === "barrel file skipped" || reason === "inside barrel export graph";
|
|
599
|
+
});
|
|
600
|
+
if (barrelGraph.length > 0) {
|
|
601
|
+
const files = barrelGraph
|
|
602
|
+
.map((item) => readString(item.file))
|
|
603
|
+
.filter((file) => file !== null);
|
|
604
|
+
lines.push(`barrel graph consumers: ${barrelGraph.length} ${barrelGraph.length === 1 ? "file" : "files"}${files.length > 0 ? ` under ${formatCommonPathGlob(files)}` : ""}`);
|
|
605
|
+
}
|
|
606
|
+
const other = skipped.filter((item) => !barrelGraph.includes(item));
|
|
607
|
+
for (const item of other.slice(0, 8)) {
|
|
608
|
+
const selector = readString(item.selector);
|
|
609
|
+
const file = readString(item.file);
|
|
610
|
+
const reason = readString(item.reason) ?? "skipped";
|
|
611
|
+
lines.push(selector ? `${selector}: ${reason}${file ? ` in ${file}` : ""}` : `${file ?? "item"}: ${reason}`);
|
|
612
|
+
}
|
|
613
|
+
if (other.length > 8) {
|
|
614
|
+
lines.push(`+ ${other.length - 8} more skipped`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
function formatCommonPathGlob(files) {
|
|
618
|
+
if (files.length === 0) {
|
|
619
|
+
return "**";
|
|
620
|
+
}
|
|
621
|
+
const parts = files.map((file) => file.replace(/\\/g, "/").split("/"));
|
|
622
|
+
const common = [];
|
|
623
|
+
for (let index = 0;; index += 1) {
|
|
624
|
+
const value = parts[0]?.[index];
|
|
625
|
+
if (!value || parts.some((part) => part[index] !== value)) {
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
common.push(value);
|
|
629
|
+
}
|
|
630
|
+
if (common.length === 0) {
|
|
631
|
+
return "**";
|
|
632
|
+
}
|
|
633
|
+
const last = common[common.length - 1] ?? "";
|
|
634
|
+
const hasExtension = /\.[^/.]+$/.test(last);
|
|
635
|
+
return `${(hasExtension ? common.slice(0, -1) : common).join("/") || "."}/**`;
|
|
636
|
+
}
|
|
637
|
+
function collectProgramBarrelExports(cwd, barrelFile, context) {
|
|
638
|
+
const sourceFile = context.program.getSourceFile(path.resolve(barrelFile));
|
|
639
|
+
const moduleSymbol = sourceFile ? context.checker.getSymbolAtLocation(sourceFile) : undefined;
|
|
640
|
+
if (!sourceFile || !moduleSymbol) {
|
|
641
|
+
return [];
|
|
642
|
+
}
|
|
643
|
+
const exports = [];
|
|
644
|
+
for (const exportSymbol of context.checker.getExportsOfModule(moduleSymbol)) {
|
|
645
|
+
const name = exportSymbol.getName();
|
|
646
|
+
if (name === "default") {
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
const targetSymbol = isAliasSymbol(exportSymbol)
|
|
650
|
+
? context.checker.getAliasedSymbol(exportSymbol)
|
|
651
|
+
: exportSymbol;
|
|
652
|
+
const declaration = pickSymbolDeclaration(targetSymbol) ?? pickSymbolDeclaration(exportSymbol);
|
|
653
|
+
if (!declaration) {
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
const importedName = readImportedNameForExportSymbol(targetSymbol, declaration);
|
|
657
|
+
const source = declaration.getSourceFile();
|
|
658
|
+
exports.push({
|
|
659
|
+
name,
|
|
660
|
+
importedName,
|
|
661
|
+
sourceFile: path.resolve(source.fileName),
|
|
662
|
+
kind: readExportKind(sourceFile, source),
|
|
663
|
+
importKind: isDefaultExportSymbol(targetSymbol, declaration) ? "default" : "named",
|
|
664
|
+
exportText: name
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
return uniqueBy(exports, (item) => `${item.name}:${item.importedName}:${path.resolve(item.sourceFile)}`);
|
|
668
|
+
}
|
|
669
|
+
function readExportKind(barrelSourceFile, sourceFile) {
|
|
670
|
+
return path.resolve(barrelSourceFile.fileName) === path.resolve(sourceFile.fileName) ? "local" : "named";
|
|
671
|
+
}
|
|
672
|
+
function isAliasSymbol(symbol) {
|
|
673
|
+
return (symbol.flags & typescript_1.default.SymbolFlags.Alias) !== 0;
|
|
674
|
+
}
|
|
675
|
+
function pickSymbolDeclaration(symbol) {
|
|
676
|
+
return symbol.valueDeclaration ?? symbol.declarations?.[0] ?? null;
|
|
677
|
+
}
|
|
678
|
+
function readImportedNameForExportSymbol(symbol, declaration) {
|
|
679
|
+
if (isDefaultExportSymbol(symbol, declaration)) {
|
|
680
|
+
return "default";
|
|
681
|
+
}
|
|
682
|
+
const name = symbol.getName();
|
|
683
|
+
if (name && name !== "__function" && name !== "__class") {
|
|
684
|
+
return name;
|
|
685
|
+
}
|
|
686
|
+
const named = declaration.name;
|
|
687
|
+
return named && typescript_1.default.isIdentifier(named) ? named.text : name;
|
|
688
|
+
}
|
|
689
|
+
function isDefaultExportSymbol(symbol, declaration) {
|
|
690
|
+
if (symbol.getName() === "default") {
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
if (typescript_1.default.canHaveModifiers(declaration) && typescript_1.default.getModifiers(declaration)?.some((modifier) => modifier.kind === typescript_1.default.SyntaxKind.DefaultKeyword)) {
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
function collectBarrelGraphFiles(cwd, barrelFile, programContext) {
|
|
699
|
+
return Array.from(collectBarrelGraphFileSet(cwd, barrelFile, new Set(), programContext)).sort();
|
|
700
|
+
}
|
|
701
|
+
function collectBarrelGraphFileSet(cwd, sourceFile, seen, programContext) {
|
|
702
|
+
const normalized = path.resolve(sourceFile);
|
|
703
|
+
if (seen.has(normalized) || !fs.existsSync(normalized)) {
|
|
704
|
+
return seen;
|
|
705
|
+
}
|
|
706
|
+
seen.add(normalized);
|
|
707
|
+
const text = fs.readFileSync(normalized, "utf8");
|
|
708
|
+
const parsed = createSourceFile(normalized, text);
|
|
709
|
+
const localExportNames = collectLocalExportNames(parsed);
|
|
710
|
+
for (const statement of parsed.statements) {
|
|
711
|
+
if (typescript_1.default.isExportDeclaration(statement)) {
|
|
712
|
+
const targetFile = statement.moduleSpecifier && typescript_1.default.isStringLiteralLike(statement.moduleSpecifier)
|
|
713
|
+
? resolveSpecifier(cwd, normalized, statement.moduleSpecifier.text, programContext)
|
|
714
|
+
: null;
|
|
715
|
+
if (targetFile) {
|
|
716
|
+
collectBarrelGraphFileSet(cwd, targetFile, seen, programContext);
|
|
717
|
+
}
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
if (localExportNames.size > 0 && typescript_1.default.isImportDeclaration(statement)) {
|
|
721
|
+
const importedBindings = collectImportBindingNames(statement);
|
|
722
|
+
if (importedBindings.some((name) => localExportNames.has(name))) {
|
|
723
|
+
const targetFile = statement.moduleSpecifier && typescript_1.default.isStringLiteralLike(statement.moduleSpecifier)
|
|
724
|
+
? resolveSpecifier(cwd, normalized, statement.moduleSpecifier.text, programContext)
|
|
725
|
+
: null;
|
|
726
|
+
if (targetFile) {
|
|
727
|
+
collectBarrelGraphFileSet(cwd, targetFile, seen, programContext);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
return seen;
|
|
733
|
+
}
|
|
734
|
+
function collectLocalExportNames(sourceFile) {
|
|
735
|
+
const names = new Set();
|
|
736
|
+
for (const statement of sourceFile.statements) {
|
|
737
|
+
if (!typescript_1.default.isExportDeclaration(statement) || statement.moduleSpecifier || !statement.exportClause) {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (typescript_1.default.isNamedExports(statement.exportClause)) {
|
|
741
|
+
for (const element of statement.exportClause.elements) {
|
|
742
|
+
names.add((element.propertyName ?? element.name).text);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return names;
|
|
747
|
+
}
|
|
748
|
+
function collectImportBindingNames(statement) {
|
|
749
|
+
const bindings = statement.importClause;
|
|
750
|
+
if (!bindings) {
|
|
751
|
+
return [];
|
|
752
|
+
}
|
|
753
|
+
const names = [];
|
|
754
|
+
if (bindings.name) {
|
|
755
|
+
names.push(bindings.name.text);
|
|
756
|
+
}
|
|
757
|
+
const namedBindings = bindings.namedBindings;
|
|
758
|
+
if (namedBindings && typescript_1.default.isNamespaceImport(namedBindings)) {
|
|
759
|
+
names.push(namedBindings.name.text);
|
|
760
|
+
}
|
|
761
|
+
if (namedBindings && typescript_1.default.isNamedImports(namedBindings)) {
|
|
762
|
+
for (const element of namedBindings.elements) {
|
|
763
|
+
names.push(element.name.text);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return names;
|
|
767
|
+
}
|
|
768
|
+
function normalizeImportRebaseRequest(payload, action) {
|
|
769
|
+
if (!isJsonObject(payload)) {
|
|
770
|
+
throw new errors_1.CliError("IMPORT_REBASE_PAYLOAD_REQUIRED", "imports.useBarrel/useDirect expects an object payload.");
|
|
771
|
+
}
|
|
772
|
+
const operation = readString(payload.operation);
|
|
773
|
+
if (operation !== "imports.useBarrel" && operation !== "imports.useDirect") {
|
|
774
|
+
throw new errors_1.CliError("IMPORT_REBASE_OPERATION_UNSUPPORTED", "imports rebase expects operation imports.useBarrel or imports.useDirect.");
|
|
775
|
+
}
|
|
776
|
+
const barrel = readString(payload.barrel) ?? readString(payload.target) ?? readString(payload.path);
|
|
777
|
+
const displayBarrel = readString(payload.displayBarrel);
|
|
778
|
+
if (!barrel) {
|
|
779
|
+
throw new errors_1.CliError("IMPORT_REBASE_BARREL_REQUIRED", `${operation} expects a barrel path.`);
|
|
780
|
+
}
|
|
781
|
+
const scope = readString(payload.scope);
|
|
782
|
+
const files = readStringArray(payload.files);
|
|
783
|
+
if (!scope && files.length === 0) {
|
|
784
|
+
throw new errors_1.CliError("IMPORT_REBASE_SCOPE_REQUIRED", `${operation} expects @scope or @files.`);
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
operation,
|
|
788
|
+
barrel,
|
|
789
|
+
...(displayBarrel ? { displayBarrel } : {}),
|
|
790
|
+
...(scope ? { scope } : {}),
|
|
791
|
+
files,
|
|
792
|
+
pathExclude: uniqueStrings([...readStringArray(payload.pathExclude), ...readStringArray(payload.exclude), ...readStringArray(payload.excludes)]),
|
|
793
|
+
symbols: readStringArray(payload.symbols),
|
|
794
|
+
showAll: payload.all === true || payload.details === true || payload.details === "all",
|
|
795
|
+
action
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
function readAction(value) {
|
|
799
|
+
if (value === "apply" || value === "execute" || value === "preview") {
|
|
800
|
+
return value;
|
|
801
|
+
}
|
|
802
|
+
return "preview";
|
|
803
|
+
}
|
|
804
|
+
function resolveInputPath(cwd, input) {
|
|
805
|
+
const expanded = (0, path_aliases_1.expandPathAliasValue)(cwd, input, (0, path_aliases_1.readConfigPathAliases)(cwd));
|
|
806
|
+
if (path.isAbsolute(expanded)) {
|
|
807
|
+
return path.normalize(expanded);
|
|
808
|
+
}
|
|
809
|
+
const workspace = (0, workspace_root_1.resolveWorkspaceRoot)(cwd);
|
|
810
|
+
return path.resolve(workspace?.root ?? cwd, expanded);
|
|
811
|
+
}
|
|
812
|
+
function createImportRebaseProgram(cwd, focusFiles) {
|
|
813
|
+
const tsconfig = findNearestTsconfig(cwd, focusFiles[0] ?? cwd);
|
|
814
|
+
const parsed = tsconfig ? readParsedTsconfig(tsconfig) : null;
|
|
815
|
+
const options = {
|
|
816
|
+
...(parsed?.options ?? {}),
|
|
817
|
+
allowJs: true,
|
|
818
|
+
checkJs: false,
|
|
819
|
+
noEmit: true,
|
|
820
|
+
skipLibCheck: true,
|
|
821
|
+
moduleResolution: parsed?.options.moduleResolution ?? typescript_1.default.ModuleResolutionKind.Node10
|
|
822
|
+
};
|
|
823
|
+
const rootNames = uniqueStrings([
|
|
824
|
+
...focusFiles.map((file) => path.resolve(file)).filter((file) => fs.existsSync(file))
|
|
825
|
+
]);
|
|
826
|
+
const program = typescript_1.default.createProgram(rootNames, options);
|
|
827
|
+
return {
|
|
828
|
+
program,
|
|
829
|
+
checker: program.getTypeChecker(),
|
|
830
|
+
options,
|
|
831
|
+
importRules: (0, import_rules_1.readConfigImportRules)(cwd),
|
|
832
|
+
tsConfigCache: new Map()
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
function findNearestTsconfig(cwd, fromFile) {
|
|
836
|
+
let current = fs.existsSync(fromFile) && fs.statSync(fromFile).isFile()
|
|
837
|
+
? path.dirname(path.resolve(fromFile))
|
|
838
|
+
: path.resolve(fromFile);
|
|
839
|
+
const root = path.resolve(cwd);
|
|
840
|
+
while (current.startsWith(root)) {
|
|
841
|
+
const candidate = path.join(current, "tsconfig.json");
|
|
842
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
843
|
+
return candidate;
|
|
844
|
+
}
|
|
845
|
+
const parent = path.dirname(current);
|
|
846
|
+
if (parent === current) {
|
|
847
|
+
break;
|
|
848
|
+
}
|
|
849
|
+
current = parent;
|
|
850
|
+
}
|
|
851
|
+
const rootConfig = path.join(root, "tsconfig.json");
|
|
852
|
+
return fs.existsSync(rootConfig) ? rootConfig : null;
|
|
853
|
+
}
|
|
854
|
+
function readParsedTsconfig(tsconfig) {
|
|
855
|
+
const config = typescript_1.default.readConfigFile(tsconfig, typescript_1.default.sys.readFile);
|
|
856
|
+
if (config.error) {
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
return typescript_1.default.parseJsonConfigFileContent(config.config, typescript_1.default.sys, path.dirname(tsconfig), {
|
|
860
|
+
allowJs: true,
|
|
861
|
+
checkJs: false,
|
|
862
|
+
noEmit: true
|
|
863
|
+
}, tsconfig);
|
|
864
|
+
}
|
|
865
|
+
function normalizeAliasImportHint(input) {
|
|
866
|
+
return input
|
|
867
|
+
.replace(/\\/g, "/")
|
|
868
|
+
.replace(/\.(tsx?|jsx?|mjs|cjs|cts|mts)$/i, "")
|
|
869
|
+
.replace(/\/index$/i, "");
|
|
870
|
+
}
|
|
871
|
+
function aliasHintForResolvedFile(cwd, file) {
|
|
872
|
+
const workspace = (0, workspace_root_1.resolveWorkspaceRoot)(cwd);
|
|
873
|
+
const baseDir = workspace?.root ?? cwd;
|
|
874
|
+
const aliases = (0, path_aliases_1.readConfigPathAliases)(cwd);
|
|
875
|
+
const fileNoExt = withoutSourceExtension(path.resolve(file));
|
|
876
|
+
const candidates = Object.entries(aliases).flatMap(([alias, target]) => {
|
|
877
|
+
const targetNoExt = withoutSourceExtension(path.resolve(baseDir, target));
|
|
878
|
+
if (fileNoExt === targetNoExt) {
|
|
879
|
+
return [`@${alias}`];
|
|
880
|
+
}
|
|
881
|
+
if (fileNoExt === path.join(targetNoExt, "index")) {
|
|
882
|
+
return [`@${alias}`];
|
|
883
|
+
}
|
|
884
|
+
if (fileNoExt.startsWith(`${targetNoExt}${path.sep}`)) {
|
|
885
|
+
const suffix = path.relative(targetNoExt, fileNoExt).replace(/\\/g, "/");
|
|
886
|
+
return [`@${alias}/${suffix.replace(/\/index$/i, "")}`];
|
|
887
|
+
}
|
|
888
|
+
return [];
|
|
889
|
+
});
|
|
890
|
+
return candidates.sort((left, right) => left.length - right.length || left.localeCompare(right))[0] ?? null;
|
|
891
|
+
}
|
|
892
|
+
function collectSourceFiles(scope, cwd, exclude) {
|
|
893
|
+
if (!fs.existsSync(scope)) {
|
|
894
|
+
throw new errors_1.CliError("IMPORT_REBASE_SCOPE_NOT_FOUND", `Scope does not exist: ${scope}`);
|
|
895
|
+
}
|
|
896
|
+
if (isExcludedPath(cwd, scope, exclude)) {
|
|
897
|
+
return [];
|
|
898
|
+
}
|
|
899
|
+
const stat = fs.statSync(scope);
|
|
900
|
+
if (stat.isFile()) {
|
|
901
|
+
return isSourceFile(scope) ? [scope] : [];
|
|
902
|
+
}
|
|
903
|
+
if (!stat.isDirectory()) {
|
|
904
|
+
return [];
|
|
905
|
+
}
|
|
906
|
+
const files = [];
|
|
907
|
+
for (const entry of fs.readdirSync(scope, { withFileTypes: true })) {
|
|
908
|
+
const child = path.join(scope, entry.name);
|
|
909
|
+
if (entry.isDirectory()) {
|
|
910
|
+
if (!EXCLUDED_DIRS.has(entry.name) && !isExcludedPath(cwd, child, exclude)) {
|
|
911
|
+
files.push(...collectSourceFiles(child, cwd, exclude));
|
|
912
|
+
}
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (entry.isFile() && isSourceFile(child) && !isExcludedPath(cwd, child, exclude)) {
|
|
916
|
+
files.push(child);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
return files.sort();
|
|
920
|
+
}
|
|
921
|
+
function resolveSpecifier(cwd, file, specifier, programContext) {
|
|
922
|
+
if (programContext) {
|
|
923
|
+
const resolved = typescript_1.default.resolveModuleName(specifier, path.resolve(file), programContext.options, typescript_1.default.sys).resolvedModule?.resolvedFileName;
|
|
924
|
+
if (resolved) {
|
|
925
|
+
const file = resolveImportBase(resolved);
|
|
926
|
+
if (file) {
|
|
927
|
+
return file;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
if (!specifier.startsWith(".")) {
|
|
932
|
+
if (specifier.startsWith("@")) {
|
|
933
|
+
try {
|
|
934
|
+
return resolveImportBase((0, path_aliases_1.expandPathAliasValue)(cwd, specifier, (0, path_aliases_1.readConfigPathAliases)(cwd)));
|
|
935
|
+
}
|
|
936
|
+
catch {
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
return resolveImportBase(path.resolve(path.dirname(file), specifier));
|
|
943
|
+
}
|
|
944
|
+
function resolveImportBase(base) {
|
|
945
|
+
const candidates = new Set();
|
|
946
|
+
candidates.add(base);
|
|
947
|
+
const ext = path.extname(base);
|
|
948
|
+
if (ext && [".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
949
|
+
const withoutExt = base.slice(0, -ext.length);
|
|
950
|
+
for (const sourceExt of SOURCE_EXTENSIONS) {
|
|
951
|
+
candidates.add(`${withoutExt}${sourceExt}`);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
if (!ext) {
|
|
955
|
+
for (const candidateExt of SOURCE_EXTENSIONS) {
|
|
956
|
+
candidates.add(`${base}${candidateExt}`);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
for (const candidateExt of SOURCE_EXTENSIONS) {
|
|
960
|
+
candidates.add(path.join(base, `index${candidateExt}`));
|
|
961
|
+
}
|
|
962
|
+
for (const candidate of candidates) {
|
|
963
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile() && isSourceFile(candidate)) {
|
|
964
|
+
return path.resolve(candidate);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
function createSourceFile(file, text) {
|
|
970
|
+
return typescript_1.default.createSourceFile(file, text, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(file));
|
|
971
|
+
}
|
|
972
|
+
function scriptKindForFile(file) {
|
|
973
|
+
if (file.endsWith(".tsx"))
|
|
974
|
+
return typescript_1.default.ScriptKind.TSX;
|
|
975
|
+
if (file.endsWith(".jsx"))
|
|
976
|
+
return typescript_1.default.ScriptKind.JSX;
|
|
977
|
+
if (file.endsWith(".js") || file.endsWith(".mjs") || file.endsWith(".cjs"))
|
|
978
|
+
return typescript_1.default.ScriptKind.JS;
|
|
979
|
+
return typescript_1.default.ScriptKind.TS;
|
|
980
|
+
}
|
|
981
|
+
function importClauseIsTypeOnly(statement) {
|
|
982
|
+
return statement.importClause?.isTypeOnly === true;
|
|
983
|
+
}
|
|
984
|
+
function symbolAllowed(request, name) {
|
|
985
|
+
return request.symbols.length === 0 || request.symbols.includes(name);
|
|
986
|
+
}
|
|
987
|
+
function groupExportsByName(exports) {
|
|
988
|
+
const map = new Map();
|
|
989
|
+
for (const item of exports) {
|
|
990
|
+
map.set(item.name, [...(map.get(item.name) ?? []), item]);
|
|
991
|
+
}
|
|
992
|
+
return map;
|
|
993
|
+
}
|
|
994
|
+
function isSourceFile(file) {
|
|
995
|
+
return SOURCE_EXTENSIONS.includes(path.extname(file)) && !file.endsWith(".d.ts");
|
|
996
|
+
}
|
|
997
|
+
function withoutSourceExtension(file) {
|
|
998
|
+
const ext = path.extname(file);
|
|
999
|
+
return SOURCE_EXTENSIONS.includes(ext) ? file.slice(0, -ext.length) : file;
|
|
1000
|
+
}
|
|
1001
|
+
function isExcludedPath(cwd, candidate, exclude) {
|
|
1002
|
+
if (exclude.length === 0) {
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
const relative = toDisplayPath(cwd, path.resolve(candidate));
|
|
1006
|
+
return exclude.some((pattern) => matchesExcludePattern(cwd, relative, pattern));
|
|
1007
|
+
}
|
|
1008
|
+
function matchesExcludePattern(cwd, relativePath, pattern) {
|
|
1009
|
+
const normalizedPattern = toDisplayPath(cwd, path.isAbsolute(pattern) ? pattern : path.resolve(cwd, pattern));
|
|
1010
|
+
if (!containsGlob(pattern)) {
|
|
1011
|
+
return relativePath === normalizedPattern || relativePath.startsWith(`${normalizedPattern}/`);
|
|
1012
|
+
}
|
|
1013
|
+
return globToRegExp(pattern.replace(/\\/g, "/")).test(relativePath);
|
|
1014
|
+
}
|
|
1015
|
+
function containsGlob(value) {
|
|
1016
|
+
return /[*?]/.test(value);
|
|
1017
|
+
}
|
|
1018
|
+
function globToRegExp(pattern) {
|
|
1019
|
+
let source = "";
|
|
1020
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
1021
|
+
const char = pattern[index];
|
|
1022
|
+
if (char === "*") {
|
|
1023
|
+
if (pattern[index + 1] === "*") {
|
|
1024
|
+
source += ".*";
|
|
1025
|
+
index += 1;
|
|
1026
|
+
}
|
|
1027
|
+
else {
|
|
1028
|
+
source += "[^/]*";
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
else if (char === "?") {
|
|
1032
|
+
source += "[^/]";
|
|
1033
|
+
}
|
|
1034
|
+
else {
|
|
1035
|
+
source += escapeRegExp(char ?? "");
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
return new RegExp(`^${source}$`);
|
|
1039
|
+
}
|
|
1040
|
+
function buildImportRebasePlanId(cwd, plan) {
|
|
1041
|
+
return `imports_rebase_${sha256(stableStringify({ cwd, plan })).slice(0, 8)}`;
|
|
1042
|
+
}
|
|
1043
|
+
function writeImportRebasePlan(cwd, record) {
|
|
1044
|
+
const filePath = importRebasePlanPath(cwd, record.planId);
|
|
1045
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
1046
|
+
fs.writeFileSync(filePath, `${JSON.stringify(record, null, 2)}\n`, "utf8");
|
|
1047
|
+
}
|
|
1048
|
+
function readImportRebasePlan(cwd, planId) {
|
|
1049
|
+
const filePath = importRebasePlanPath(cwd, planId);
|
|
1050
|
+
if (!fs.existsSync(filePath)) {
|
|
1051
|
+
throw new errors_1.CliError("IMPORT_REBASE_PLAN_NOT_FOUND", `imports rebase plan not found: ${planId}`, { planId, expectedPath: filePath });
|
|
1052
|
+
}
|
|
1053
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
1054
|
+
}
|
|
1055
|
+
function importRebasePlanPath(cwd, planId) {
|
|
1056
|
+
return (0, workspace_cache_1.workspaceCachePath)(cwd, "imports-rebase", `${planId.replace(/[^a-z0-9_-]+/gi, "-")}.json`);
|
|
1057
|
+
}
|
|
1058
|
+
function hashPlanFiles(cwd, plan) {
|
|
1059
|
+
const hashes = {};
|
|
1060
|
+
const files = new Set();
|
|
1061
|
+
files.add(toDisplayPath(cwd, plan.barrel.file));
|
|
1062
|
+
for (const item of plan.exports) {
|
|
1063
|
+
files.add(toDisplayPath(cwd, item.sourceFile));
|
|
1064
|
+
}
|
|
1065
|
+
for (const file of plan.barrelGraphFiles) {
|
|
1066
|
+
files.add(toDisplayPath(cwd, path.resolve(cwd, file)));
|
|
1067
|
+
}
|
|
1068
|
+
for (const edit of plan.edits) {
|
|
1069
|
+
files.add(edit.file);
|
|
1070
|
+
}
|
|
1071
|
+
for (const file of files) {
|
|
1072
|
+
const fullPath = path.resolve(cwd, file);
|
|
1073
|
+
if (fs.existsSync(fullPath)) {
|
|
1074
|
+
hashes[file] = sha256(fs.readFileSync(fullPath));
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return hashes;
|
|
1078
|
+
}
|
|
1079
|
+
function sha256(value) {
|
|
1080
|
+
return crypto.createHash("sha256").update(value).digest("hex");
|
|
1081
|
+
}
|
|
1082
|
+
function stableStringify(value) {
|
|
1083
|
+
if (value === null || typeof value !== "object") {
|
|
1084
|
+
return JSON.stringify(value);
|
|
1085
|
+
}
|
|
1086
|
+
if (Array.isArray(value)) {
|
|
1087
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
1088
|
+
}
|
|
1089
|
+
return `{${Object.entries(value)
|
|
1090
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
1091
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
|
|
1092
|
+
.join(",")}}`;
|
|
1093
|
+
}
|
|
1094
|
+
function uniqueBy(items, key) {
|
|
1095
|
+
const seen = new Set();
|
|
1096
|
+
const unique = [];
|
|
1097
|
+
for (const item of items) {
|
|
1098
|
+
const value = key(item);
|
|
1099
|
+
if (!seen.has(value)) {
|
|
1100
|
+
seen.add(value);
|
|
1101
|
+
unique.push(item);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return unique;
|
|
1105
|
+
}
|
|
1106
|
+
function readString(value) {
|
|
1107
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
|
|
1108
|
+
}
|
|
1109
|
+
function readNumber(value) {
|
|
1110
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1111
|
+
}
|
|
1112
|
+
function readStringArray(value) {
|
|
1113
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1114
|
+
return [value.trim()];
|
|
1115
|
+
}
|
|
1116
|
+
if (!Array.isArray(value)) {
|
|
1117
|
+
return [];
|
|
1118
|
+
}
|
|
1119
|
+
return value
|
|
1120
|
+
.filter((item) => typeof item === "string")
|
|
1121
|
+
.map((item) => item.trim())
|
|
1122
|
+
.filter((item) => item.length > 0);
|
|
1123
|
+
}
|
|
1124
|
+
function readObjectArray(value) {
|
|
1125
|
+
return Array.isArray(value) ? value.filter(isJsonObject) : [];
|
|
1126
|
+
}
|
|
1127
|
+
function uniqueStrings(items) {
|
|
1128
|
+
return Array.from(new Set(items));
|
|
1129
|
+
}
|
|
1130
|
+
function isJsonObject(value) {
|
|
1131
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1132
|
+
}
|
|
1133
|
+
function toDisplayPath(cwd, file) {
|
|
1134
|
+
return path.relative(cwd, file).replace(/\\/g, "/");
|
|
1135
|
+
}
|
|
1136
|
+
function escapeRegExp(value) {
|
|
1137
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1138
|
+
}
|