cgraphx 2.0.2 → 2.0.3
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/dist/core/code/engine/cli/analyze-config.js +320 -0
- package/dist/core/code/engine/cli/analyze.js +1086 -0
- package/dist/core/code/engine/cli/cli-message.js +83 -0
- package/dist/core/code/engine/cli/detect-changes-format.js +58 -0
- package/dist/core/code/engine/cli/embedding-dims.js +43 -0
- package/dist/core/code/engine/cli/format-elapsed.js +12 -0
- package/dist/core/code/engine/cli/help-i18n.js +144 -0
- package/dist/core/code/engine/cli/i18n/en.js +110 -0
- package/dist/core/code/engine/cli/i18n/index.js +47 -0
- package/dist/core/code/engine/cli/i18n/resources.js +9 -0
- package/dist/core/code/engine/cli/i18n/zh-CN.js +110 -0
- package/dist/core/code/engine/cli/lazy-action.js +67 -0
- package/dist/core/code/engine/cli/optional-grammars.js +136 -0
- package/dist/core/code/engine/cli/resolve-invocation.js +76 -0
- package/dist/core/code/engine/cli/status.js +156 -0
- package/dist/core/code/engine/cli/tool.js +384 -0
- package/dist/core/code/engine/config/ignore-service.js +511 -0
- package/dist/core/code/engine/config/supported-languages.js +17 -0
- package/dist/core/code/engine/core/analysis-features.js +64 -0
- package/dist/core/code/engine/core/analyzer-identity.js +2171 -0
- package/dist/core/code/engine/core/git-staleness.js +180 -0
- package/dist/core/code/engine/core/graph/graph.js +180 -0
- package/dist/core/code/engine/core/graph/import-cycles.js +106 -0
- package/dist/core/code/engine/core/graph/types.js +2 -0
- package/dist/core/code/engine/core/index-freshness.js +12 -0
- package/dist/core/code/engine/core/ingestion/binding-accumulator.js +341 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/c-cpp.js +168 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/csharp.js +9 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/dart.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/go.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/jvm.js +54 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/php.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/python.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/ruby.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/rust.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/swift.js +8 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/configs/typescript-javascript.js +11 -0
- package/dist/core/code/engine/core/ingestion/call-extractors/generic.js +62 -0
- package/dist/core/code/engine/core/ingestion/call-processor.js +503 -0
- package/dist/core/code/engine/core/ingestion/call-routing.js +98 -0
- package/dist/core/code/engine/core/ingestion/call-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/cfg/callee-cell-format.js +45 -0
- package/dist/core/code/engine/core/ingestion/cfg/cfg-builder.js +202 -0
- package/dist/core/code/engine/core/ingestion/cfg/collect.js +81 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-dependence.js +185 -0
- package/dist/core/code/engine/core/ingestion/cfg/control-flow-context.js +130 -0
- package/dist/core/code/engine/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/code/engine/core/ingestion/cfg/post-dominators.js +182 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-def-reason-codec.js +139 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs-graph.js +322 -0
- package/dist/core/code/engine/core/ingestion/cfg/reaching-defs.js +792 -0
- package/dist/core/code/engine/core/ingestion/cfg/synthetic-escape.js +305 -0
- package/dist/core/code/engine/core/ingestion/cfg/traversal-result.js +6 -0
- package/dist/core/code/engine/core/ingestion/cfg/types.js +14 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp-harvest.js +545 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/c-cpp.js +590 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/call-site-harvest.js +356 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp-harvest.js +593 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/csharp.js +871 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart-harvest.js +874 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/dart.js +840 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go-harvest.js +625 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/go.js +642 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java-harvest.js +517 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/java.js +816 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin-harvest.js +723 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/kotlin.js +813 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php-harvest.js +630 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/php.js +725 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python-harvest.js +776 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/python.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby-harvest.js +591 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/ruby.js +760 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust-harvest.js +877 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/rust.js +562 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/scope-tree-harvest.js +120 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift-harvest.js +683 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/swift.js +791 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript-harvest.js +1060 -0
- package/dist/core/code/engine/core/ingestion/cfg/visitors/typescript.js +587 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/c-cpp.js +77 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/csharp.js +24 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/dart.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/go.js +28 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/jvm.js +67 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/php.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/python.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/ruby.js +13 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/rust.js +10 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/swift.js +21 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/configs/typescript-javascript.js +31 -0
- package/dist/core/code/engine/core/ingestion/class-extractors/generic.js +144 -0
- package/dist/core/code/engine/core/ingestion/class-types.js +2 -0
- package/dist/core/code/engine/core/ingestion/cluster-enricher.js +174 -0
- package/dist/core/code/engine/core/ingestion/community-processor.js +604 -0
- package/dist/core/code/engine/core/ingestion/constants.js +26 -0
- package/dist/core/code/engine/core/ingestion/cpp-ue-preprocessor.js +263 -0
- package/dist/core/code/engine/core/ingestion/csharp-namespace-gate.js +133 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/index.js +38 -0
- package/dist/core/code/engine/core/ingestion/di-extractors/spring.js +310 -0
- package/dist/core/code/engine/core/ingestion/emit-references.js +244 -0
- package/dist/core/code/engine/core/ingestion/entry-point-scoring.js +201 -0
- package/dist/core/code/engine/core/ingestion/export-detection.js +244 -0
- package/dist/core/code/engine/core/ingestion/field-extractor.js +29 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/c-cpp.js +107 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/csharp.js +124 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/dart.js +99 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/go.js +102 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/helpers.js +198 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/jvm.js +172 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/python.js +94 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/ruby.js +79 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/swift.js +93 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/configs/typescript-javascript.js +59 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/generic.js +147 -0
- package/dist/core/code/engine/core/ingestion/field-extractors/typescript.js +266 -0
- package/dist/core/code/engine/core/ingestion/field-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/filesystem-walker.js +136 -0
- package/dist/core/code/engine/core/ingestion/finalize-orchestrator.js +159 -0
- package/dist/core/code/engine/core/ingestion/framework-detection.js +432 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/analysis-features.js +38 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/annotation-arguments.js +234 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop-candidates.js +88 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/aop.js +487 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/auto-configuration.js +21 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-candidates.js +189 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-catalog.js +32 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/bean-factories.js +73 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/conditionals.js +323 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/config-bindings.js +119 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/di-metadata.js +385 -0
- package/dist/core/code/engine/core/ingestion/frameworks/spring/resource-injection.js +96 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/c-cpp.js +17 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/csharp.js +46 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/dart.js +59 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/go.js +30 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/jvm.js +73 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/php.js +19 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/python.js +45 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/rust.js +58 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/swift.js +94 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/configs/typescript-javascript.js +26 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/csharp.js +128 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/go.js +50 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/jvm.js +112 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/php.js +80 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/python.js +75 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/resolver-factory.js +36 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/ruby.js +20 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/standard.js +180 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/types.js +7 -0
- package/dist/core/code/engine/core/ingestion/import-resolvers/utils.js +153 -0
- package/dist/core/code/engine/core/ingestion/import-target-adapter.js +99 -0
- package/dist/core/code/engine/core/ingestion/language-config.js +391 -0
- package/dist/core/code/engine/core/ingestion/language-provider.js +25 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity-metadata.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/c/arity.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/c/capture-side-channel.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/c/captures.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/c/header-scan.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-decomposer.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/c/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/c/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/c/interpret.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/c/merge-bindings.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/c/query.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/c/scope-resolver.js +112 -0
- package/dist/core/code/engine/core/ingestion/languages/c/simple-hooks.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/c/static-linkage.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/c-cpp.js +506 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/adl.js +804 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity-metadata.js +258 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/arity.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/capture-side-channel.js +89 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/captures.js +1975 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-extractor.js +311 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/constraint-filter.js +210 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/conversion-rank.js +163 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/file-local-linkage.js +327 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/header-scan.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-decomposer.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/import-target.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/index.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/inline-namespaces.js +379 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/interpret.js +239 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/member-lookup.js +470 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/merge-bindings.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/query.js +763 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/range-bindings.js +230 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/scope-resolver.js +354 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/simple-hooks.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/two-phase-lookup.js +348 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/type-classifier.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/cpp/user-defined-conversions.js +128 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/accessor-unwrap.js +67 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/arity.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/captures.js +557 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-decomposer.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/import-target.js +176 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/index.js +95 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/interpret.js +150 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/merge-bindings.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/namespace-siblings.js +708 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/qualified-type-names.js +62 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/query.js +578 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/receiver-binding.js +142 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/resolution-config.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/scope-resolver.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp/simple-hooks.js +81 -0
- package/dist/core/code/engine/core/ingestion/languages/csharp.js +204 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity-metadata.js +38 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/arity.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/built-ins.js +37 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/cache-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/captures.js +1096 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/expand-wildcards.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/extension-type-preprocess.js +33 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/import-target.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/index.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/interpret.js +101 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/merge-bindings.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/query.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/receiver-binding.js +90 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/scope-resolver.js +197 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/signature-bindings.js +54 -0
- package/dist/core/code/engine/core/ingestion/languages/dart/simple-hooks.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/dart.js +138 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity-metadata.js +71 -0
- package/dist/core/code/engine/core/ingestion/languages/go/arity.js +17 -0
- package/dist/core/code/engine/core/ingestion/languages/go/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/captures.js +492 -0
- package/dist/core/code/engine/core/ingestion/languages/go/expand-wildcards.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/go/generic-type-parameters.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-decomposer.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/go/import-target.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/go/index.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interface-impls.js +955 -0
- package/dist/core/code/engine/core/ingestion/languages/go/interpret.js +177 -0
- package/dist/core/code/engine/core/ingestion/languages/go/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/go/method-owners.js +131 -0
- package/dist/core/code/engine/core/ingestion/languages/go/namespace-mirror.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-clause.js +79 -0
- package/dist/core/code/engine/core/ingestion/languages/go/package-siblings.js +83 -0
- package/dist/core/code/engine/core/ingestion/languages/go/query.js +298 -0
- package/dist/core/code/engine/core/ingestion/languages/go/range-binding.js +127 -0
- package/dist/core/code/engine/core/ingestion/languages/go/receiver-binding.js +24 -0
- package/dist/core/code/engine/core/ingestion/languages/go/scope-resolver.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/go/simple-hooks.js +31 -0
- package/dist/core/code/engine/core/ingestion/languages/go/type-binding.js +279 -0
- package/dist/core/code/engine/core/ingestion/languages/go.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/index.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/java/analysis-features.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity-metadata.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/arity.js +27 -0
- package/dist/core/code/engine/core/ingestion/languages/java/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/java/capture-side-channel.js +123 -0
- package/dist/core/code/engine/core/ingestion/languages/java/captures.js +791 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-decomposer.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/java/import-target.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/java/index.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/interpret.js +146 -0
- package/dist/core/code/engine/core/ingestion/languages/java/merge-bindings.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/java/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/query.js +319 -0
- package/dist/core/code/engine/core/ingestion/languages/java/receiver-binding.js +98 -0
- package/dist/core/code/engine/core/ingestion/languages/java/scope-resolver.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/java/simple-hooks.js +39 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-aop.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-conditionals.js +52 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-config-bindings.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/java/spring-di.js +165 -0
- package/dist/core/code/engine/core/ingestion/languages/java.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/arity.js +15 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/captures.js +1122 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/import-target.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/index.js +109 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/interpret.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/query.js +659 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/scope-resolver.js +78 -0
- package/dist/core/code/engine/core/ingestion/languages/javascript/simple-hooks.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-facts.js +46 -0
- package/dist/core/code/engine/core/ingestion/languages/jvm/package-siblings.js +200 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity-metadata.js +23 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/arity.js +18 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/capture-side-channel.js +160 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/captures.js +1262 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/companion-scopes.js +72 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-decomposer.js +40 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/import-target.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/index.js +26 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/interpret.js +75 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/merge-bindings.js +28 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/owners.js +134 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-facts.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/package-siblings.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/query.js +243 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/receiver-binding.js +103 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/scope-resolver.js +207 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/simple-hooks.js +42 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-aop.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-bean-metadata.js +11 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-conditionals.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin/spring-di.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/kotlin.js +189 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity-metadata.js +66 -0
- package/dist/core/code/engine/core/ingestion/languages/php/arity.js +43 -0
- package/dist/core/code/engine/core/ingestion/languages/php/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/php/captures.js +1166 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-decomposer.js +238 -0
- package/dist/core/code/engine/core/ingestion/languages/php/import-target.js +213 -0
- package/dist/core/code/engine/core/ingestion/languages/php/index.js +85 -0
- package/dist/core/code/engine/core/ingestion/languages/php/interpret.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/php/merge-bindings.js +50 -0
- package/dist/core/code/engine/core/ingestion/languages/php/namespace-siblings.js +353 -0
- package/dist/core/code/engine/core/ingestion/languages/php/query.js +391 -0
- package/dist/core/code/engine/core/ingestion/languages/php/receiver-binding.js +135 -0
- package/dist/core/code/engine/core/ingestion/languages/php/scope-resolver.js +361 -0
- package/dist/core/code/engine/core/ingestion/languages/php/simple-hooks.js +116 -0
- package/dist/core/code/engine/core/ingestion/languages/php.js +302 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity-metadata.js +49 -0
- package/dist/core/code/engine/core/ingestion/languages/python/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/python/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/python/captures.js +299 -0
- package/dist/core/code/engine/core/ingestion/languages/python/depends-references.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-decomposer.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/python/import-target.js +440 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index-stats.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/python/index.js +96 -0
- package/dist/core/code/engine/core/ingestion/languages/python/interpret.js +430 -0
- package/dist/core/code/engine/core/ingestion/languages/python/merge-bindings.js +47 -0
- package/dist/core/code/engine/core/ingestion/languages/python/query.js +323 -0
- package/dist/core/code/engine/core/ingestion/languages/python/receiver-binding.js +310 -0
- package/dist/core/code/engine/core/ingestion/languages/python/scope-resolver.js +80 -0
- package/dist/core/code/engine/core/ingestion/languages/python/simple-hooks.js +53 -0
- package/dist/core/code/engine/core/ingestion/languages/python.js +140 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/arity.js +41 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/captures.js +864 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/import-target.js +88 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/interpret.js +115 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/query.js +349 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/receiver-binding.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/scope-resolver.js +263 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby/simple-hooks.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/ruby.js +215 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/arity.js +16 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/cache-stats.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/captures.js +304 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-decomposer.js +167 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/import-target.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/index.js +29 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/interpret.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/merge-bindings.js +21 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/method-owners.js +76 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/module-path.js +222 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/qualified-call.js +482 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/query.js +280 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/range-binding.js +687 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/receiver-binding.js +148 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/scope-resolver.js +151 -0
- package/dist/core/code/engine/core/ingestion/languages/rust/simple-hooks.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/rust.js +183 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity-metadata.js +44 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/arity.js +45 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/base-type.js +30 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/cache-stats.js +32 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/captures.js +594 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/conditional-directive-preprocess.js +256 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/implicit-imports.js +60 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-decomposer.js +87 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/import-target.js +84 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/index.js +56 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/interpret.js +93 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/merge-bindings.js +51 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/query.js +226 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/receiver-binding.js +169 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/scope-resolver.js +192 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/sibling-type-bindings.js +68 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/signature-bindings.js +69 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/simple-hooks.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-grouping.js +97 -0
- package/dist/core/code/engine/core/ingestion/languages/swift/target-siblings.js +74 -0
- package/dist/core/code/engine/core/ingestion/languages/swift.js +246 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity-metadata.js +106 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/arity.js +57 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/array-callback.js +58 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cache-stats.js +34 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/captures.js +956 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-export-assignment.js +535 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/cjs-module-exports.js +196 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-decomposer.js +374 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/import-target.js +65 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/index.js +108 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/interpret.js +344 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/merge-bindings.js +161 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/nuxt-auto-imports.js +325 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/query.js +1328 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/receiver-binding.js +201 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/scope-resolver.js +293 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript/simple-hooks.js +139 -0
- package/dist/core/code/engine/core/ingestion/languages/typescript.js +455 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/captures.js +70 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/import-target.js +61 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/index.js +55 -0
- package/dist/core/code/engine/core/ingestion/languages/vue/scope-resolver.js +295 -0
- package/dist/core/code/engine/core/ingestion/languages/vue.js +96 -0
- package/dist/core/code/engine/core/ingestion/local-symbol-pruner.js +68 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/c-cpp.js +387 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/csharp.js +290 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/dart.js +392 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/go.js +179 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/jvm.js +350 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/php.js +306 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/python.js +312 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/ruby.js +289 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/rust.js +198 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/swift.js +286 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/configs/typescript-javascript.js +341 -0
- package/dist/core/code/engine/core/ingestion/method-extractors/generic.js +209 -0
- package/dist/core/code/engine/core/ingestion/method-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/model/field-registry.js +41 -0
- package/dist/core/code/engine/core/ingestion/model/index.js +52 -0
- package/dist/core/code/engine/core/ingestion/model/method-registry.js +138 -0
- package/dist/core/code/engine/core/ingestion/model/owned-members-lookup.js +46 -0
- package/dist/core/code/engine/core/ingestion/model/registration-table.js +234 -0
- package/dist/core/code/engine/core/ingestion/model/resolve.js +183 -0
- package/dist/core/code/engine/core/ingestion/model/scope-resolution-indexes.js +43 -0
- package/dist/core/code/engine/core/ingestion/model/semantic-model.js +179 -0
- package/dist/core/code/engine/core/ingestion/model/symbol-table.js +216 -0
- package/dist/core/code/engine/core/ingestion/model/type-registry.js +84 -0
- package/dist/core/code/engine/core/ingestion/mro-processor.js +709 -0
- package/dist/core/code/engine/core/ingestion/parsing-processor.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/communities.js +69 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/cross-file.js +71 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/di.js +338 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/http-api-calls.js +312 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/index.js +54 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/mro.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/orm.js +78 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse-impl.js +1286 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/parse.js +41 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/processes.js +193 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/prune-local-symbols.js +29 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/registry.js +52 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/routes.js +409 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/rpc-edges.js +301 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/runner.js +207 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/scan.js +49 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-aop.js +442 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-auto-configuration.js +264 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/spring-config.js +440 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/structure.js +38 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/tools.js +89 -0
- package/dist/core/code/engine/core/ingestion/pipeline-phases/types.js +40 -0
- package/dist/core/code/engine/core/ingestion/pipeline.js +152 -0
- package/dist/core/code/engine/core/ingestion/process-processor.js +325 -0
- package/dist/core/code/engine/core/ingestion/resolve-references.js +205 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/constant-resolver.js +135 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django-root-discovery.js +221 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/django.js +428 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/expo.js +39 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/fastapi-router-bindings.js +264 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/laravel.js +501 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/middleware.js +175 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/nextjs.js +81 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/php.js +25 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/python-const-resolver.js +307 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/response-shapes.js +299 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/route-path.js +71 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring-shared.js +310 -0
- package/dist/core/code/engine/core/ingestion/route-extractors/spring.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor-bridge.js +60 -0
- package/dist/core/code/engine/core/ingestion/scope-extractor.js +1373 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/contract/scope-resolver.js +282 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +72 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/edges.js +194 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/ids.js +472 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +43 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +274 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +93 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/callable-value-flow.js +1240 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/compound-receiver.js +1174 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/free-call-fallback.js +873 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/imported-return-types.js +226 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/mro.js +107 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/overload-narrowing.js +441 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/property-dispatch.js +122 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +1720 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/phase.js +395 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +208 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/registry.js +49 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/run.js +632 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/pipeline/validate-bindings-immutability.js +112 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/resolution-outcome.js +41 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/namespace-targets.js +81 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/scope/walkers.js +1835 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/unresolved-receivers.js +242 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/utils/definition-id.js +22 -0
- package/dist/core/code/engine/core/ingestion/scope-resolution/workspace-index.js +151 -0
- package/dist/core/code/engine/core/ingestion/structure-processor.js +40 -0
- package/dist/core/code/engine/core/ingestion/tree-sitter-queries.js +2244 -0
- package/dist/core/code/engine/core/ingestion/ts-js-hoc-utils.js +115 -0
- package/dist/core/code/engine/core/ingestion/type-env.js +1136 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/c-cpp.js +555 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/csharp.js +570 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/dart.js +372 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/go.js +508 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/jvm.js +875 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/php.js +537 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/python.js +477 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/ruby.js +380 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/rust.js +502 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/shared.js +843 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/swift.js +490 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/types.js +2 -0
- package/dist/core/code/engine/core/ingestion/type-extractors/typescript.js +690 -0
- package/dist/core/code/engine/core/ingestion/utils/ast-helpers.js +1693 -0
- package/dist/core/code/engine/core/ingestion/utils/call-analysis.js +779 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-flow-captures.js +932 -0
- package/dist/core/code/engine/core/ingestion/utils/callable-labels.js +49 -0
- package/dist/core/code/engine/core/ingestion/utils/deferred-resolution-profile.js +151 -0
- package/dist/core/code/engine/core/ingestion/utils/effective-ram.js +67 -0
- package/dist/core/code/engine/core/ingestion/utils/env.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/event-loop.js +9 -0
- package/dist/core/code/engine/core/ingestion/utils/graph-sort.js +103 -0
- package/dist/core/code/engine/core/ingestion/utils/heap-probe.js +45 -0
- package/dist/core/code/engine/core/ingestion/utils/heritage-marker.js +47 -0
- package/dist/core/code/engine/core/ingestion/utils/line-base.js +24 -0
- package/dist/core/code/engine/core/ingestion/utils/max-file-size.js +59 -0
- package/dist/core/code/engine/core/ingestion/utils/method-props.js +198 -0
- package/dist/core/code/engine/core/ingestion/utils/qualified-name.js +73 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-captures.js +60 -0
- package/dist/core/code/engine/core/ingestion/utils/receiver-chain-codec.js +188 -0
- package/dist/core/code/engine/core/ingestion/utils/scope-tree-walk.js +36 -0
- package/dist/core/code/engine/core/ingestion/utils/symbol-labels.js +48 -0
- package/dist/core/code/engine/core/ingestion/utils/template-arguments.js +187 -0
- package/dist/core/code/engine/core/ingestion/utils/type-parameters.js +209 -0
- package/dist/core/code/engine/core/ingestion/utils/verbose.js +6 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/c-cpp.js +133 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/csharp.js +66 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/dart.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/go.js +153 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/jvm.js +145 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/php.js +61 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/python.js +104 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/ruby.js +55 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/rust.js +79 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/swift.js +91 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/configs/typescript-javascript.js +86 -0
- package/dist/core/code/engine/core/ingestion/variable-extractors/generic.js +111 -0
- package/dist/core/code/engine/core/ingestion/variable-types.js +3 -0
- package/dist/core/code/engine/core/ingestion/vue-sfc-extractor.js +544 -0
- package/dist/core/code/engine/core/ingestion/workers/callable-id.js +122 -0
- package/dist/core/code/engine/core/ingestion/workers/clone-safety.js +470 -0
- package/dist/core/code/engine/core/ingestion/workers/parse-worker.js +2456 -0
- package/dist/core/code/engine/core/ingestion/workers/post-result.js +90 -0
- package/dist/core/code/engine/core/ingestion/workers/quarantine.js +41 -0
- package/dist/core/code/engine/core/ingestion/workers/result-merge.js +59 -0
- package/dist/core/code/engine/core/ingestion/workers/worker-pool.js +1725 -0
- package/dist/core/code/engine/core/ingestion/workspace-config.js +139 -0
- package/dist/core/code/engine/core/lbug/conn-lock.js +72 -0
- package/dist/core/code/engine/core/lbug/csv-generator.js +710 -0
- package/dist/core/code/engine/core/lbug/cypher-escape.js +24 -0
- package/dist/core/code/engine/core/lbug/extension-load-error.js +339 -0
- package/dist/core/code/engine/core/lbug/extension-loader.js +261 -0
- package/dist/core/code/engine/core/lbug/graph-emit-sink.js +584 -0
- package/dist/core/code/engine/core/lbug/lbug-adapter.js +2703 -0
- package/dist/core/code/engine/core/lbug/lbug-config.js +1029 -0
- package/dist/core/code/engine/core/lbug/native-check.js +435 -0
- package/dist/core/code/engine/core/lbug/pool-adapter.js +973 -0
- package/dist/core/code/engine/core/lbug/query-params.js +25 -0
- package/dist/core/code/engine/core/lbug/query-result-utils.js +31 -0
- package/dist/core/code/engine/core/lbug/rel-pair-routing.js +373 -0
- package/dist/core/code/engine/core/lbug/schema.js +771 -0
- package/dist/core/code/engine/core/lbug/shutdown-helpers.js +40 -0
- package/dist/core/code/engine/core/lbug/sidecar-recovery.js +716 -0
- package/dist/core/code/engine/core/lbug/stdio-capture.js +49 -0
- package/dist/core/code/engine/core/lbug/sync-csv-writer.js +115 -0
- package/dist/core/code/engine/core/lbug/wal-checkpoint-driver.js +215 -0
- package/dist/core/code/engine/core/lbug/wal-driver-state.js +28 -0
- package/dist/core/code/engine/core/logger.js +339 -0
- package/dist/core/code/engine/core/platform/capabilities.js +91 -0
- package/dist/core/code/engine/core/run-analyze.js +1098 -0
- package/dist/core/code/engine/core/tree-sitter/parser-loader.js +281 -0
- package/dist/core/code/engine/core/tree-sitter/safe-parse.js +258 -0
- package/dist/core/code/engine/core/tree-sitter/vendored-grammars.js +64 -0
- package/dist/core/code/engine/lib/utils.js +121 -0
- package/dist/core/code/engine/mcp/core/lbug-adapter.js +27 -0
- package/dist/core/code/engine/mcp/local/aop-metadata.js +230 -0
- package/dist/core/code/engine/mcp/local/bean-metadata.js +49 -0
- package/dist/core/code/engine/mcp/local/limits.js +15 -0
- package/dist/core/code/engine/mcp/local/line-display.js +6 -0
- package/dist/core/code/engine/mcp/local/local-backend.js +4142 -0
- package/dist/core/code/engine/storage/branch-index.js +72 -0
- package/dist/core/code/engine/storage/file-hash.js +95 -0
- package/dist/core/code/engine/storage/fs-atomic.js +34 -0
- package/dist/core/code/engine/storage/git.js +555 -0
- package/dist/core/code/engine/storage/index-lock.js +664 -0
- package/dist/core/code/engine/storage/parse-cache.js +650 -0
- package/dist/core/code/engine/storage/parsedfile-store.js +620 -0
- package/dist/core/code/engine/storage/repo-manager.js +1061 -0
- package/dist/core/code/engine/storage/scope-index-store.js +247 -0
- package/dist/core/code/engine/types/pipeline.js +2 -0
- package/dist/core/code/scripts/install-duckdb-extension.mjs +125 -0
- package/dist/core/code/scripts/resolve-analyze-cmd.cjs +346 -0
- package/dist/core/code/shared/graph/types.js +8 -0
- package/dist/core/code/shared/index.js +105 -0
- package/dist/core/code/shared/integrations/circuit-breaker.js +242 -0
- package/dist/core/code/shared/integrations/resilient-fetch.js +224 -0
- package/dist/core/code/shared/integrations/retry.js +70 -0
- package/dist/core/code/shared/integrations/understand-quickly.js +145 -0
- package/dist/core/code/shared/language-detection.js +162 -0
- package/dist/core/code/shared/languages.js +27 -0
- package/dist/core/code/shared/lbug/schema-constants.js +98 -0
- package/dist/core/code/shared/mro-strategy.js +2 -0
- package/dist/core/code/shared/pipeline.js +5 -0
- package/dist/core/code/shared/scope-resolution/callable-flow-site.js +11 -0
- package/dist/core/code/shared/scope-resolution/def-index.js +53 -0
- package/dist/core/code/shared/scope-resolution/evidence-weights.js +87 -0
- package/dist/core/code/shared/scope-resolution/finalize-algorithm.js +807 -0
- package/dist/core/code/shared/scope-resolution/language-classification.js +46 -0
- package/dist/core/code/shared/scope-resolution/method-dispatch-index.js +100 -0
- package/dist/core/code/shared/scope-resolution/module-scope-index.js +59 -0
- package/dist/core/code/shared/scope-resolution/origin-priority.js +23 -0
- package/dist/core/code/shared/scope-resolution/parsed-file.js +54 -0
- package/dist/core/code/shared/scope-resolution/position-index.js +136 -0
- package/dist/core/code/shared/scope-resolution/qualified-name-index.js +77 -0
- package/dist/core/code/shared/scope-resolution/reference-site.js +24 -0
- package/dist/core/code/shared/scope-resolution/registries/class-registry.js +32 -0
- package/dist/core/code/shared/scope-resolution/registries/context.js +52 -0
- package/dist/core/code/shared/scope-resolution/registries/evidence.js +152 -0
- package/dist/core/code/shared/scope-resolution/registries/field-registry.js +33 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-core.js +392 -0
- package/dist/core/code/shared/scope-resolution/registries/lookup-qualified.js +58 -0
- package/dist/core/code/shared/scope-resolution/registries/macro-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/method-registry.js +34 -0
- package/dist/core/code/shared/scope-resolution/registries/tie-breaks.js +63 -0
- package/dist/core/code/shared/scope-resolution/resolve-type-ref.js +128 -0
- package/dist/core/code/shared/scope-resolution/scope-id.js +49 -0
- package/dist/core/code/shared/scope-resolution/scope-tree.js +225 -0
- package/dist/core/code/shared/scope-resolution/symbol-definition.js +12 -0
- package/dist/core/code/shared/scope-resolution/types.js +25 -0
- package/dist/core/code/shared/test-helpers.js +17 -0
- package/dist/core/code/vendor/leiden/index.cjs +355 -0
- package/dist/core/code/vendor/leiden/utils.cjs +419 -0
- package/dist/core/timeline/cli.d.ts.map +1 -1
- package/dist/core/timeline/cli.js +13 -6
- package/dist/core/timeline/cli.js.map +1 -1
- package/dist/core/timeline/debris.d.ts +20 -0
- package/dist/core/timeline/debris.d.ts.map +1 -0
- package/dist/core/timeline/debris.js +124 -0
- package/dist/core/timeline/debris.js.map +1 -0
- package/dist/core/timeline/hook-runner.d.ts.map +1 -1
- package/dist/core/timeline/hook-runner.js +3 -1
- package/dist/core/timeline/hook-runner.js.map +1 -1
- package/dist/core/timeline/hooks.d.ts.map +1 -1
- package/dist/core/timeline/hooks.js +13 -5
- package/dist/core/timeline/hooks.js.map +1 -1
- package/dist/core/timeline/installer.d.ts +2 -0
- package/dist/core/timeline/installer.d.ts.map +1 -1
- package/dist/core/timeline/installer.js +12 -0
- package/dist/core/timeline/installer.js.map +1 -1
- package/dist/core/timeline/project-root.d.ts +21 -0
- package/dist/core/timeline/project-root.d.ts.map +1 -0
- package/dist/core/timeline/project-root.js +83 -0
- package/dist/core/timeline/project-root.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1061 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Repository Manager
|
|
4
|
+
*
|
|
5
|
+
* Manages GitNexus index storage:
|
|
6
|
+
* - Per-repo metadata file (cgraph.json) under .cgraphx/code/, dual-written to a
|
|
7
|
+
* legacy meta.json mirror for backward compatibility (see MIGRATION.md)
|
|
8
|
+
* - .cgraphx/code/ directory for local metadata and caches (parse-cache, parsedfile-store)
|
|
9
|
+
*
|
|
10
|
+
* cgraph.json is simply a filename distinct from the generic meta.json — it
|
|
11
|
+
* has no bearing on git worktree behavior. .cgraphx/code/ remains fully git-ignored
|
|
12
|
+
* in every case; each worktree already has its own independent .cgraphx/code/ by
|
|
13
|
+
* construction (getStoragePath is per-checkout), regardless of which filename
|
|
14
|
+
* the metadata inside it uses.
|
|
15
|
+
*/
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.findSiblingClones = exports.saveCLIConfig = exports.loadCLIConfig = exports.getGlobalConfigPath = exports.listRegisteredRepos = exports.resolveRegistryEntry = exports.assertSafeStoragePath = exports.UnsafeStoragePathError = exports.assertAnalysisFinalized = exports.isRepoRegistered = exports.AnalysisNotFinalizedError = exports.RegistryAmbiguousTargetError = exports.RegistryNotFoundError = exports.adoptFlatBranchLabel = exports.removeBranchIndex = exports.unregisterRepo = exports.registerRepo = exports.RegistryNameCollisionError = exports.readRegistry = exports.resolveProjectRoot = exports.getGlobalDir = exports.ensureGitNexusIgnored = exports.findRepo = exports.reconcileMetadataFiles = exports.loadRepo = exports.hasIndex = exports.saveMeta = exports.loadMeta = exports.cleanupOldKuzuFiles = exports.hasKuzuIndex = exports.getStoragePaths = exports.getStoragePath = exports.INDEX_METADATA_FILE = exports.cloneDirBelongsToEntry = exports.registryPathEquals = exports.canonicalizePath = exports.resolveBranchPlacement = exports.branchSlug = void 0;
|
|
21
|
+
exports.isReadOnlyFilesystemError = isReadOnlyFilesystemError;
|
|
22
|
+
exports.isMissingFilesystemError = isMissingFilesystemError;
|
|
23
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
24
|
+
const fs_1 = require("fs");
|
|
25
|
+
const path_1 = __importDefault(require("path"));
|
|
26
|
+
const os_1 = __importDefault(require("os"));
|
|
27
|
+
const crypto_1 = require("crypto");
|
|
28
|
+
const git_js_1 = require("./git.js");
|
|
29
|
+
const utils_js_1 = require("../lib/utils.js");
|
|
30
|
+
const fs_atomic_js_1 = require("./fs-atomic.js");
|
|
31
|
+
const logger_js_1 = require("../core/logger.js");
|
|
32
|
+
const branch_index_js_1 = require("./branch-index.js");
|
|
33
|
+
Object.defineProperty(exports, "branchSlug", { enumerable: true, get: function () { return branch_index_js_1.branchSlug; } });
|
|
34
|
+
Object.defineProperty(exports, "resolveBranchPlacement", { enumerable: true, get: function () { return branch_index_js_1.resolveBranchPlacement; } });
|
|
35
|
+
/**
|
|
36
|
+
* Normalise a repo path for registry comparison across platforms
|
|
37
|
+
* (#664 review feedback from @evander-wang).
|
|
38
|
+
*
|
|
39
|
+
* Why this exists: `path.resolve` alone is NOT enough for
|
|
40
|
+
* cross-platform registry stability.
|
|
41
|
+
* - **macOS**: tmpdirs and `/var` are symlinks to `/private/var`.
|
|
42
|
+
* A child process that stored `/private/var/folders/.../repo` in
|
|
43
|
+
* the registry cannot later be matched by an outer caller that
|
|
44
|
+
* supplies the symlink form `/var/folders/.../repo`. `path.resolve`
|
|
45
|
+
* does not follow symlinks; `realpathSync.native` does.
|
|
46
|
+
* - **Windows**: GitHub runners surface tmpdirs in 8.3 short-name
|
|
47
|
+
* form (`RUNNERA~1\...`), but `process.cwd()` often returns the
|
|
48
|
+
* long form (`runneradmin\...`). `realpathSync.native` normalises
|
|
49
|
+
* both sides to the long-name canonical path.
|
|
50
|
+
* - **Windows, extended-length paths** (#2667): a caller can supply a
|
|
51
|
+
* `\\?\`-prefixed path — the usual MAX_PATH workaround — and
|
|
52
|
+
* `path.resolve` preserves the prefix, so the string compare below
|
|
53
|
+
* never matches the un-prefixed entry the registry stores. The
|
|
54
|
+
* realpath branch already dropped it (libuv strips the prefix inside
|
|
55
|
+
* `fs__realpath`), but the fallback branch did not, which is exactly
|
|
56
|
+
* the branch a missing path takes. `stripWindowsLongPathPrefix` is
|
|
57
|
+
* applied to both so the two branches agree.
|
|
58
|
+
*
|
|
59
|
+
* This normalisation is safe here precisely because the result is only ever
|
|
60
|
+
* compared, never opened: Node does NOT re-add `\\?\` for over-MAX_PATH
|
|
61
|
+
* paths, so an fs-facing path must keep whatever form the caller gave it.
|
|
62
|
+
* See the `registerRepo` comment on applying canonicalisation at COMPARE
|
|
63
|
+
* points only.
|
|
64
|
+
*
|
|
65
|
+
* Fallback behaviour: if the path does not exist on disk (e.g. a user
|
|
66
|
+
* passed `gitnexus remove some-alias` and the alias misses every
|
|
67
|
+
* registry entry, or the caller is resolving a path that was deleted
|
|
68
|
+
* after registration), we return `path.resolve(p)` rather than
|
|
69
|
+
* throwing. This preserves the idempotent-on-missing semantics of
|
|
70
|
+
* `resolveRegistryEntry` / `remove`.
|
|
71
|
+
*
|
|
72
|
+
* Backwards compatibility: this function is applied to BOTH the
|
|
73
|
+
* caller-supplied input AND each stored `entry.path` at compare time
|
|
74
|
+
* inside `resolveRegistryEntry`, so registries written by older
|
|
75
|
+
* versions still match correctly. Entries are NOT canonicalised at
|
|
76
|
+
* write time — `registerRepo` stores `path.resolve(repoPath)` — which
|
|
77
|
+
* is what makes the compare-only rule above hold.
|
|
78
|
+
*/
|
|
79
|
+
const canonicalizePath = (p) => {
|
|
80
|
+
const resolved = path_1.default.resolve(p);
|
|
81
|
+
try {
|
|
82
|
+
return (0, utils_js_1.stripWindowsLongPathPrefix)(fs_1.realpathSync.native(resolved));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return (0, utils_js_1.stripWindowsLongPathPrefix)(resolved);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.canonicalizePath = canonicalizePath;
|
|
89
|
+
/**
|
|
90
|
+
* Compare two already-canonicalised registry paths. Case-insensitive on Windows
|
|
91
|
+
* (its filesystem is), case-sensitive elsewhere. Both arguments must already be
|
|
92
|
+
* run through {@link canonicalizePath}; this is the single comparison the registry
|
|
93
|
+
* lookups/dedup/finalize checks all share so they answer identically.
|
|
94
|
+
*/
|
|
95
|
+
const registryPathEquals = (a, b) => process.platform === 'win32' ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
96
|
+
exports.registryPathEquals = registryPathEquals;
|
|
97
|
+
/**
|
|
98
|
+
* Does the clone dir derived from an entry's *name* actually belong to that
|
|
99
|
+
* entry? Registry names are not unique across storage locations: a cloned
|
|
100
|
+
* repo under `~/.cgraphx/code/repos/<name>` and a local repo registered under the
|
|
101
|
+
* same name share a `getCloneDir(entry.name)` result. The server's delete
|
|
102
|
+
* handler must therefore never remove the clone dir based on the name alone —
|
|
103
|
+
* only when the entry's own `path` resolves to that dir (mirroring its step-2b
|
|
104
|
+
* rule that cleanup is driven off `entry.path`, so a same-named sibling's
|
|
105
|
+
* clone is never removed). Both sides are canonicalised so symlinked or
|
|
106
|
+
* differently-spelled forms of the same dir still match.
|
|
107
|
+
*/
|
|
108
|
+
const cloneDirBelongsToEntry = (cloneDir, entryPath) => (0, exports.registryPathEquals)((0, exports.canonicalizePath)(cloneDir), (0, exports.canonicalizePath)(entryPath));
|
|
109
|
+
exports.cloneDirBelongsToEntry = cloneDirBelongsToEntry;
|
|
110
|
+
// Index directory: `<projectRoot>/.cgraphx/code` (cgraphx code 子系统,spec §4.4).
|
|
111
|
+
// Kept as two segments so path joins and the string-based git-exclude checks
|
|
112
|
+
// below share one source of truth.
|
|
113
|
+
const CGRAPHX_DIR = '.cgraphx';
|
|
114
|
+
const CGRAPHX_CODE_DIR_PARTS = [CGRAPHX_DIR, 'code'];
|
|
115
|
+
// git exclude entry covers the whole `.cgraphx/` tree (index + any sibling
|
|
116
|
+
// cgraphx state), not just the `code/` subdirectory.
|
|
117
|
+
const CGRAPHX_EXCLUDE_ENTRY = `${CGRAPHX_DIR}/`;
|
|
118
|
+
exports.INDEX_METADATA_FILE = 'cgraph.json';
|
|
119
|
+
// Dual-written mirror of INDEX_METADATA_FILE, kept for backward compatibility
|
|
120
|
+
// with consumers that only know the pre-rename filename (see MIGRATION.md).
|
|
121
|
+
const LEGACY_METADATA_FILE = 'meta.json';
|
|
122
|
+
// ─── Local Storage Helpers ─────────────────────────────────────────────
|
|
123
|
+
/**
|
|
124
|
+
* Get the .cgraphx/code storage path for a repository.
|
|
125
|
+
* Used for local metadata and caches that are not committed.
|
|
126
|
+
*/
|
|
127
|
+
const getStoragePath = (repoPath) => {
|
|
128
|
+
return path_1.default.join(path_1.default.resolve(repoPath), ...CGRAPHX_CODE_DIR_PARTS);
|
|
129
|
+
};
|
|
130
|
+
exports.getStoragePath = getStoragePath;
|
|
131
|
+
/**
|
|
132
|
+
* Get paths to key storage files.
|
|
133
|
+
*
|
|
134
|
+
* `storagePath` is ALWAYS the flat `<repo>/.cgraphx/code` — content-addressed
|
|
135
|
+
* caches (`parse-cache/`, `parsedfile-store/`) live there and are shared
|
|
136
|
+
* across branches (#2106 KTD7). When `branch` is provided, both `lbugPath`
|
|
137
|
+
* and `metaPath` are scoped under `branches/<slug>/`. For the flat call
|
|
138
|
+
* (no `branch`), `storagePath` and `lbugPath` remain byte-identical to the
|
|
139
|
+
* pre-multi-branch behavior (#2106); `metaPath`'s FILENAME changed from
|
|
140
|
+
* `meta.json` to `cgraph.json` (PR #2363) — `saveMeta` keeps a `meta.json`
|
|
141
|
+
* mirror in sync for consumers that still read the legacy name.
|
|
142
|
+
*
|
|
143
|
+
* Each branch slot has its own metadata file:
|
|
144
|
+
* - Primary/flat: <repo>/.cgraphx/code/cgraph.json
|
|
145
|
+
* - Feature branches: <repo>/.cgraphx/code/branches/<slug>/cgraph.json
|
|
146
|
+
*
|
|
147
|
+
* Callers should use `loadMeta(metaDir)` and `saveMeta(metaDir, meta)` where
|
|
148
|
+
* metaDir is the directory containing the metadata file — both handle the
|
|
149
|
+
* legacy mirror automatically.
|
|
150
|
+
*/
|
|
151
|
+
const getStoragePaths = (repoPath, branch) => {
|
|
152
|
+
const storagePath = (0, exports.getStoragePath)(repoPath);
|
|
153
|
+
const baseDir = branch ? path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR, (0, branch_index_js_1.branchSlug)(branch)) : storagePath;
|
|
154
|
+
return {
|
|
155
|
+
storagePath,
|
|
156
|
+
lbugPath: path_1.default.join(baseDir, 'lbug'),
|
|
157
|
+
metaPath: path_1.default.join(baseDir, exports.INDEX_METADATA_FILE), // Branch-specific metadata file
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
exports.getStoragePaths = getStoragePaths;
|
|
161
|
+
/**
|
|
162
|
+
* Check whether a KuzuDB index exists in the given storage path.
|
|
163
|
+
* Non-destructive — safe to call from status commands.
|
|
164
|
+
*/
|
|
165
|
+
const hasKuzuIndex = async (storagePath) => {
|
|
166
|
+
try {
|
|
167
|
+
await promises_1.default.stat(path_1.default.join(storagePath, 'kuzu'));
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
exports.hasKuzuIndex = hasKuzuIndex;
|
|
175
|
+
/**
|
|
176
|
+
* Clean up stale KuzuDB files after migration to LadybugDB.
|
|
177
|
+
*
|
|
178
|
+
* Returns:
|
|
179
|
+
* found — true if .cgraphx/code/kuzu existed and was deleted
|
|
180
|
+
* needsReindex — true if kuzu existed but lbug does not (re-analyze required)
|
|
181
|
+
*
|
|
182
|
+
* Callers own the user-facing messaging; this function only deletes files.
|
|
183
|
+
*/
|
|
184
|
+
const cleanupOldKuzuFiles = async (storagePath) => {
|
|
185
|
+
const oldPath = path_1.default.join(storagePath, 'kuzu');
|
|
186
|
+
const newPath = path_1.default.join(storagePath, 'lbug');
|
|
187
|
+
try {
|
|
188
|
+
await promises_1.default.stat(oldPath);
|
|
189
|
+
// Old kuzu file/dir exists — determine if lbug is already present
|
|
190
|
+
let needsReindex = false;
|
|
191
|
+
try {
|
|
192
|
+
await promises_1.default.stat(newPath);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
needsReindex = true;
|
|
196
|
+
}
|
|
197
|
+
// Delete kuzu database file and its sidecars (.wal, .lock)
|
|
198
|
+
for (const suffix of ['', '.wal', '.lock']) {
|
|
199
|
+
try {
|
|
200
|
+
await promises_1.default.unlink(oldPath + suffix);
|
|
201
|
+
}
|
|
202
|
+
catch { }
|
|
203
|
+
}
|
|
204
|
+
// Also handle the case where kuzu was stored as a directory
|
|
205
|
+
try {
|
|
206
|
+
await promises_1.default.rm(oldPath, { recursive: true, force: true });
|
|
207
|
+
}
|
|
208
|
+
catch { }
|
|
209
|
+
return { found: true, needsReindex };
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Old path doesn't exist — nothing to do
|
|
213
|
+
return { found: false, needsReindex: false };
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
exports.cleanupOldKuzuFiles = cleanupOldKuzuFiles;
|
|
217
|
+
/**
|
|
218
|
+
* Load metadata from the legacy `meta.json` mirror in the given directory.
|
|
219
|
+
* Returns null when the file is absent, unreadable, or unparseable — a
|
|
220
|
+
* corrupt legacy file is treated the same as a missing one (safe rebuild).
|
|
221
|
+
*/
|
|
222
|
+
const loadMetaLegacy = async (metaDir) => tryReadMetaFile(metaDir, LEGACY_METADATA_FILE);
|
|
223
|
+
/**
|
|
224
|
+
* Load metadata from a directory containing the metadata file (cgraph.json).
|
|
225
|
+
* For primary/flat: metaDir = <repo>/.cgraphx/code
|
|
226
|
+
* For feature branches: metaDir = <repo>/.cgraphx/code/branches/<slug>
|
|
227
|
+
*
|
|
228
|
+
* Falls back to the legacy `meta.json` mirror ONLY when `cgraph.json` is
|
|
229
|
+
* provably absent (ENOENT/ENOTDIR). Any other failure — a parse error, EACCES,
|
|
230
|
+
* EIO — returns null instead of silently resurrecting possibly-stale legacy
|
|
231
|
+
* content: a corrupt primary file must trigger the same safe full-rebuild path
|
|
232
|
+
* a missing index would (the fail-safe `saveMeta`'s docstring relies on), not
|
|
233
|
+
* an incremental run over a stale legacy baseline.
|
|
234
|
+
*/
|
|
235
|
+
const loadMeta = async (metaDir) => {
|
|
236
|
+
let raw;
|
|
237
|
+
try {
|
|
238
|
+
raw = await promises_1.default.readFile(path_1.default.join(metaDir, exports.INDEX_METADATA_FILE), 'utf-8');
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
// Provably absent → the legacy mirror is the source of truth (pre-rename
|
|
242
|
+
// repo, or a mirror-only state). Anything else → fail safe with null.
|
|
243
|
+
return isMissingFilesystemError(err) ? loadMetaLegacy(metaDir) : null;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
return JSON.parse(raw);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// Corrupt primary file — do NOT mask it with legacy content.
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
exports.loadMeta = loadMeta;
|
|
254
|
+
/**
|
|
255
|
+
* Atomically write `meta` to `<dir>/<filename>`. Tmp name includes a random
|
|
256
|
+
* suffix (not a fixed `.tmp`) so two concurrent writers targeting the same
|
|
257
|
+
* directory never collide on the same tmp path — mirrors the pattern in
|
|
258
|
+
* core/group/bridge-db.ts's `writeBridgeMeta` (`'wx'` + `0o600` closes the
|
|
259
|
+
* symlink-race/permissions holes CodeQL flags as `js/insecure-temporary-file`;
|
|
260
|
+
* `retryRename` absorbs a transient EBUSY/EPERM/EACCES on the rename itself).
|
|
261
|
+
*/
|
|
262
|
+
async function writeMetaFile(dir, filename, meta) {
|
|
263
|
+
const targetPath = path_1.default.join(dir, filename);
|
|
264
|
+
const tmpPath = `${targetPath}.tmp.${(0, crypto_1.randomBytes)(8).toString('hex')}`;
|
|
265
|
+
const handle = await promises_1.default.open(tmpPath, 'wx', 0o600);
|
|
266
|
+
try {
|
|
267
|
+
await handle.writeFile(JSON.stringify(meta, null, 2), 'utf-8');
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
await handle.close();
|
|
271
|
+
}
|
|
272
|
+
await (0, fs_atomic_js_1.retryRename)(tmpPath, targetPath);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Save metadata to the metadata file (cgraph.json) in the given directory,
|
|
276
|
+
* dual-writing the legacy `meta.json` mirror for backward compatibility.
|
|
277
|
+
*
|
|
278
|
+
* Atomic via tmp-file + rename (matches `saveParseCache`'s pattern). The
|
|
279
|
+
* `incrementalInProgress` dirty flag travels through this file — a crash
|
|
280
|
+
* mid-write would leave a corrupt `cgraph.json` that the next run's
|
|
281
|
+
* `loadMeta` would silently treat as "no prior index", losing the dirty
|
|
282
|
+
* flag and skipping the recovery full-rebuild. Write-and-rename rules
|
|
283
|
+
* that out: the rename is atomic on POSIX and on Windows (`fs.rename`
|
|
284
|
+
* on `node:fs/promises` uses `MoveFileEx(REPLACE_EXISTING)`), so either
|
|
285
|
+
* the old or the new file is observed at every moment.
|
|
286
|
+
*
|
|
287
|
+
* `cgraph.json` is the primary write and must succeed. `meta.json` is a
|
|
288
|
+
* best-effort mirror kept for consumers that only know the legacy filename
|
|
289
|
+
* (see MIGRATION.md) — its write failure is logged, not thrown, so a
|
|
290
|
+
* mirror-write hiccup never fails the caller's analyze run.
|
|
291
|
+
*/
|
|
292
|
+
const saveMeta = async (metaDir, meta) => {
|
|
293
|
+
await promises_1.default.mkdir(metaDir, { recursive: true });
|
|
294
|
+
await writeMetaFile(metaDir, exports.INDEX_METADATA_FILE, meta);
|
|
295
|
+
try {
|
|
296
|
+
await writeMetaFile(metaDir, LEGACY_METADATA_FILE, meta);
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
logger_js_1.logger.warn({ err, metaDir }, 'Failed to write legacy meta.json mirror (non-critical)');
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
exports.saveMeta = saveMeta;
|
|
303
|
+
/**
|
|
304
|
+
* Check if a path has a GitNexus index (metadata file or legacy location)
|
|
305
|
+
*/
|
|
306
|
+
const hasIndex = async (repoPath) => {
|
|
307
|
+
const paths = (0, exports.getStoragePaths)(repoPath);
|
|
308
|
+
// Check new metadata file first
|
|
309
|
+
try {
|
|
310
|
+
await promises_1.default.access(paths.metaPath);
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// Fall back to legacy location
|
|
315
|
+
try {
|
|
316
|
+
await promises_1.default.access(path_1.default.join(paths.storagePath, LEGACY_METADATA_FILE));
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
exports.hasIndex = hasIndex;
|
|
325
|
+
/**
|
|
326
|
+
* Load an indexed repo from a path (checks metadata file first, then legacy)
|
|
327
|
+
*/
|
|
328
|
+
const loadRepo = async (repoPath) => {
|
|
329
|
+
const paths = (0, exports.getStoragePaths)(repoPath);
|
|
330
|
+
const meta = await (0, exports.loadMeta)(paths.storagePath);
|
|
331
|
+
if (!meta)
|
|
332
|
+
return null;
|
|
333
|
+
return {
|
|
334
|
+
repoPath: path_1.default.resolve(repoPath),
|
|
335
|
+
...paths,
|
|
336
|
+
meta,
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
exports.loadRepo = loadRepo;
|
|
340
|
+
/**
|
|
341
|
+
* Best-effort read of one specific metadata filename — no fallback, null on
|
|
342
|
+
* any failure (absent, unreadable, or unparseable).
|
|
343
|
+
*/
|
|
344
|
+
const tryReadMetaFile = async (dir, filename) => {
|
|
345
|
+
try {
|
|
346
|
+
const raw = await promises_1.default.readFile(path_1.default.join(dir, filename), 'utf-8');
|
|
347
|
+
return JSON.parse(raw);
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
/** `indexedAt` as epoch millis; 0 when absent/unparseable (i.e. oldest). */
|
|
354
|
+
const metaTimestamp = (meta) => {
|
|
355
|
+
const t = Date.parse(meta.indexedAt ?? '');
|
|
356
|
+
return Number.isFinite(t) ? t : 0;
|
|
357
|
+
};
|
|
358
|
+
/**
|
|
359
|
+
* Reconcile `cgraph.json` and the legacy `meta.json` mirror in one
|
|
360
|
+
* directory: whichever parses and is fresher (by `indexedAt`) wins and is
|
|
361
|
+
* re-written to BOTH files via `saveMeta`. Never deletes anything.
|
|
362
|
+
* Returns true when a write occurred.
|
|
363
|
+
*/
|
|
364
|
+
const reconcileMetaDir = async (dir) => {
|
|
365
|
+
const primary = await tryReadMetaFile(dir, exports.INDEX_METADATA_FILE);
|
|
366
|
+
const legacy = await tryReadMetaFile(dir, LEGACY_METADATA_FILE);
|
|
367
|
+
if (!primary && !legacy) {
|
|
368
|
+
// Fresh directory (neither file) is a silent no-op; a file that exists
|
|
369
|
+
// but doesn't parse deserves a warning — loadMeta will treat it as "no
|
|
370
|
+
// prior index" and the next successful saveMeta self-heals it.
|
|
371
|
+
for (const filename of [exports.INDEX_METADATA_FILE, LEGACY_METADATA_FILE]) {
|
|
372
|
+
try {
|
|
373
|
+
await promises_1.default.access(path_1.default.join(dir, filename));
|
|
374
|
+
logger_js_1.logger.warn({ dir, filename }, 'Metadata file exists but is unreadable/corrupt; leaving as-is (next successful analyze rewrites it)');
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
// absent — expected for a fresh directory
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
if (primary && legacy) {
|
|
383
|
+
if (JSON.stringify(primary) === JSON.stringify(legacy))
|
|
384
|
+
return false; // converged
|
|
385
|
+
// Both parse but differ — the fresher one wins (an older binary may have
|
|
386
|
+
// re-analyzed and written only meta.json AFTER cgraph.json was created;
|
|
387
|
+
// blind-preferring the primary would permanently shadow that fresher
|
|
388
|
+
// state, silently certifying a stale index as up to date).
|
|
389
|
+
const winner = metaTimestamp(legacy) > metaTimestamp(primary) ? legacy : primary;
|
|
390
|
+
await (0, exports.saveMeta)(dir, winner);
|
|
391
|
+
logger_js_1.logger.info({ dir, winner: winner === legacy ? LEGACY_METADATA_FILE : exports.INDEX_METADATA_FILE }, 'Reconciled diverged metadata files (fresher indexedAt wins, written to both)');
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
// Exactly one parses — establish/repair the other so both stay in sync.
|
|
395
|
+
const survivor = (primary ?? legacy);
|
|
396
|
+
await (0, exports.saveMeta)(dir, survivor);
|
|
397
|
+
return true;
|
|
398
|
+
};
|
|
399
|
+
/**
|
|
400
|
+
* Reconcile the metadata files for a repo's flat slot and every
|
|
401
|
+
* `branches/<slug>/` slot. Runs once per `analyze` (see run-analyze.ts).
|
|
402
|
+
*
|
|
403
|
+
* This is a best-effort compatibility sync, NOT a one-way migration: the
|
|
404
|
+
* legacy `meta.json` mirror is kept in sync indefinitely (removal happens at
|
|
405
|
+
* a future major version — see MIGRATION.md), so older binaries, still-running
|
|
406
|
+
* MCP servers, and the shipped editor hooks keep working, and a rollback to a
|
|
407
|
+
* pre-rename version sees current metadata instead of "no prior index".
|
|
408
|
+
* Returns true when any file was written.
|
|
409
|
+
*/
|
|
410
|
+
const reconcileMetadataFiles = async (repoPath) => {
|
|
411
|
+
const storagePath = (0, exports.getStoragePath)(repoPath);
|
|
412
|
+
let changed = await reconcileMetaDir(storagePath);
|
|
413
|
+
const branchesDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR);
|
|
414
|
+
let branchDirs;
|
|
415
|
+
try {
|
|
416
|
+
branchDirs = await promises_1.default.readdir(branchesDir);
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
// branchesDir may not exist (not a multi-branch repo) — expected, silent.
|
|
420
|
+
return changed;
|
|
421
|
+
}
|
|
422
|
+
for (const branchDir of branchDirs) {
|
|
423
|
+
const branchPath = path_1.default.join(branchesDir, branchDir);
|
|
424
|
+
// Per-branch isolation: one bad branch dir (dangling symlink, EACCES)
|
|
425
|
+
// must not silently abort reconciliation for every branch after it —
|
|
426
|
+
// readdir order is stable, so an unguarded throw here would permanently
|
|
427
|
+
// starve the same trailing branches on every run.
|
|
428
|
+
try {
|
|
429
|
+
const stat = await promises_1.default.stat(branchPath);
|
|
430
|
+
if (!stat.isDirectory())
|
|
431
|
+
continue;
|
|
432
|
+
if (await reconcileMetaDir(branchPath))
|
|
433
|
+
changed = true;
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
logger_js_1.logger.warn({ branchDir, err }, 'Skipping branch directory during metadata reconciliation (non-critical)');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return changed;
|
|
440
|
+
};
|
|
441
|
+
exports.reconcileMetadataFiles = reconcileMetadataFiles;
|
|
442
|
+
/**
|
|
443
|
+
* Find the .cgraphx/code index by walking up from a starting path
|
|
444
|
+
*/
|
|
445
|
+
const findRepo = async (startPath) => {
|
|
446
|
+
let current = path_1.default.resolve(startPath);
|
|
447
|
+
const root = path_1.default.parse(current).root;
|
|
448
|
+
while (current !== root) {
|
|
449
|
+
const repo = await (0, exports.loadRepo)(current);
|
|
450
|
+
if (repo)
|
|
451
|
+
return repo;
|
|
452
|
+
current = path_1.default.dirname(current);
|
|
453
|
+
}
|
|
454
|
+
return null;
|
|
455
|
+
};
|
|
456
|
+
exports.findRepo = findRepo;
|
|
457
|
+
function isReadOnlyFilesystemError(err) {
|
|
458
|
+
const code = err?.code;
|
|
459
|
+
return code === 'EROFS' || code === 'EACCES' || code === 'EPERM';
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* True for errors that prove a path is absent (ENOENT/ENOTDIR) — as opposed
|
|
463
|
+
* to transient/permission failures (EIO/EACCES/EBUSY…) where the file may
|
|
464
|
+
* well still exist. Exported for consumers that need the same "provably
|
|
465
|
+
* missing vs not provably absent" distinction (e.g. collectBranchCacheKeys).
|
|
466
|
+
*/
|
|
467
|
+
function isMissingFilesystemError(err) {
|
|
468
|
+
const code = err?.code;
|
|
469
|
+
return code === 'ENOENT' || code === 'ENOTDIR';
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Keep .cgraphx/code/ ignored. It contains local index state and caches.
|
|
473
|
+
*/
|
|
474
|
+
const ensureGitNexusIgnored = async (repoPath) => {
|
|
475
|
+
const gitignorePath = path_1.default.join((0, exports.getStoragePath)(repoPath), '.gitignore');
|
|
476
|
+
const desired = '*\n';
|
|
477
|
+
// Idempotent fast path: skip the write entirely when the file already has
|
|
478
|
+
// the expected content. Lets this run cleanly on read-only mounts (e.g.
|
|
479
|
+
// the documented Docker workflow with WORKSPACE_DIR bound :ro) when an
|
|
480
|
+
// earlier `analyze` already created the file. See issue #1549.
|
|
481
|
+
try {
|
|
482
|
+
if ((await promises_1.default.readFile(gitignorePath, 'utf-8')) === desired) {
|
|
483
|
+
await ensureGitInfoExclude(repoPath);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
catch (err) {
|
|
488
|
+
if (err?.code !== 'ENOENT')
|
|
489
|
+
throw err;
|
|
490
|
+
}
|
|
491
|
+
try {
|
|
492
|
+
await promises_1.default.mkdir(path_1.default.dirname(gitignorePath), { recursive: true });
|
|
493
|
+
await promises_1.default.writeFile(gitignorePath, desired, 'utf-8');
|
|
494
|
+
}
|
|
495
|
+
catch (err) {
|
|
496
|
+
if (isReadOnlyFilesystemError(err)) {
|
|
497
|
+
logger_js_1.logger.warn({ path: gitignorePath, code: err.code }, 'GitNexus storage filesystem is not writable; skipping .cgraphx/code/.gitignore. Cache files may appear as untracked in this repo locally.');
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
throw err;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
await ensureGitInfoExclude(repoPath);
|
|
504
|
+
};
|
|
505
|
+
exports.ensureGitNexusIgnored = ensureGitNexusIgnored;
|
|
506
|
+
const ensureGitInfoExclude = async (repoPath) => {
|
|
507
|
+
const gitDirPath = path_1.default.join(path_1.default.resolve(repoPath), '.git');
|
|
508
|
+
const excludePath = path_1.default.join(gitDirPath, 'info', 'exclude');
|
|
509
|
+
try {
|
|
510
|
+
const gitDir = await promises_1.default.stat(gitDirPath);
|
|
511
|
+
if (!gitDir.isDirectory())
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
catch {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
let content = '';
|
|
518
|
+
try {
|
|
519
|
+
content = await promises_1.default.readFile(excludePath, 'utf-8');
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
if (err?.code !== 'ENOENT')
|
|
523
|
+
throw err;
|
|
524
|
+
}
|
|
525
|
+
const excludes = content
|
|
526
|
+
.split(/\r?\n/)
|
|
527
|
+
.map((line) => line.trim())
|
|
528
|
+
.filter((line) => line && !line.startsWith('#'));
|
|
529
|
+
if (excludes.includes(CGRAPHX_DIR) || excludes.includes(CGRAPHX_EXCLUDE_ENTRY))
|
|
530
|
+
return;
|
|
531
|
+
const separator = content.length === 0 || content.endsWith('\n') ? '' : '\n';
|
|
532
|
+
try {
|
|
533
|
+
await promises_1.default.mkdir(path_1.default.dirname(excludePath), { recursive: true });
|
|
534
|
+
await promises_1.default.writeFile(excludePath, `${content}${separator}${CGRAPHX_EXCLUDE_ENTRY}\n`, 'utf-8');
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
if (isReadOnlyFilesystemError(err)) {
|
|
538
|
+
logger_js_1.logger.warn({ path: excludePath, code: err.code }, 'GitNexus storage filesystem is not writable; skipping .git/info/exclude update. .cgraphx/ cache directory may appear as untracked in `git status` locally.');
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
throw err;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
// ─── Global Directory (~/.cgraphx/code/) ───────────────────────────────
|
|
546
|
+
/**
|
|
547
|
+
* Get the path to the global GitNexus directory (used for CLI config only).
|
|
548
|
+
*/
|
|
549
|
+
const getGlobalDir = () => {
|
|
550
|
+
return process.env.CGRAPH_HOME || path_1.default.join(os_1.default.homedir(), '.cgraphx', 'code');
|
|
551
|
+
};
|
|
552
|
+
exports.getGlobalDir = getGlobalDir;
|
|
553
|
+
// ─── Project-root discovery (cwd-based; global registry removed) ────────
|
|
554
|
+
//
|
|
555
|
+
// The global registry was removed per spec §8 ("无全局状态"): index data lives
|
|
556
|
+
// ONLY in `<projectRoot>/.cgraphx/code/`, and the CLI operates on "当前目录或显式
|
|
557
|
+
// 路径的项目根索引". These functions replace the old registry I/O with cwd-
|
|
558
|
+
// based discovery so every former registry consumer (LocalBackend.refreshRepos,
|
|
559
|
+
// git-staleness.checkCwdMatch, findSiblingClones) resolves the same single
|
|
560
|
+
// project-root index without any `~/.cgraphx/code/registry.json`.
|
|
561
|
+
/**
|
|
562
|
+
* Best-effort `process.cwd()` that never throws — some sandboxed runtimes
|
|
563
|
+
* (deleted cwd, container teardown) make `process.cwd()` throw EBADF/ENOENT.
|
|
564
|
+
* Falling back to the current module directory keeps discovery alive instead
|
|
565
|
+
* of crashing the CLI entrypoint.
|
|
566
|
+
*/
|
|
567
|
+
const safeCwd = () => {
|
|
568
|
+
try {
|
|
569
|
+
return process.cwd();
|
|
570
|
+
}
|
|
571
|
+
catch {
|
|
572
|
+
return __dirname;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
/**
|
|
576
|
+
* Resolve the project root whose `.cgraphx/code/` index the CLI should operate on
|
|
577
|
+
* (spec §8). Discovery precedence:
|
|
578
|
+
*
|
|
579
|
+
* 1. `opts.explicitPath` — a caller-provided `--path` project root.
|
|
580
|
+
* 2. `CGRAPH_REPO` env var — an ambient override for scripted/CI contexts.
|
|
581
|
+
* 3. upward walk from `opts.startCwd` (default `process.cwd()`) for the
|
|
582
|
+
* nearest ancestor (or self) directory containing a readable `.cgraphx/code/`
|
|
583
|
+
* index metadata file.
|
|
584
|
+
*
|
|
585
|
+
* Returns the discovered {@link IndexedRepo} (meta + paths), or `null` when no
|
|
586
|
+
* index is found — callers surface a "run `cgraph analyze`" error in that case.
|
|
587
|
+
*
|
|
588
|
+
* Reuses {@link findRepo} / {@link loadRepo} so the walk, the cgraph.json↔
|
|
589
|
+
* meta.json fallback, and the storage-path derivation stay identical to the
|
|
590
|
+
* `status` / `analyze` commands.
|
|
591
|
+
*/
|
|
592
|
+
const resolveProjectRoot = async (opts) => {
|
|
593
|
+
const explicit = opts?.explicitPath ?? process.env.CGRAPH_REPO;
|
|
594
|
+
const start = opts?.startCwd ?? (explicit ? path_1.default.resolve(explicit) : safeCwd());
|
|
595
|
+
return (0, exports.findRepo)(start);
|
|
596
|
+
};
|
|
597
|
+
exports.resolveProjectRoot = resolveProjectRoot;
|
|
598
|
+
/**
|
|
599
|
+
* Scan the `branches/<slug>/` sub-indexes of a project root and return their
|
|
600
|
+
* summaries (#2106). Non-primary branch indexes live under
|
|
601
|
+
* `<storagePath>/branches/<slug>/cgraph.json`; each readable meta becomes one
|
|
602
|
+
* {@link BranchSummary}. Absent dir, unreadable entries, or a fresh repo yield
|
|
603
|
+
* `[]`. Used by discovery so `--branch` scoping in LocalBackend still resolves
|
|
604
|
+
* pinned sub-indexes without a global registry.
|
|
605
|
+
*/
|
|
606
|
+
const readBranchSummaries = async (repoPath) => {
|
|
607
|
+
const { storagePath } = (0, exports.getStoragePaths)(repoPath);
|
|
608
|
+
const branchesDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR);
|
|
609
|
+
let entries;
|
|
610
|
+
try {
|
|
611
|
+
entries = await promises_1.default.readdir(branchesDir);
|
|
612
|
+
}
|
|
613
|
+
catch {
|
|
614
|
+
return []; // no branches dir → single-branch/legacy repo, expected.
|
|
615
|
+
}
|
|
616
|
+
const summaries = [];
|
|
617
|
+
for (const slug of entries) {
|
|
618
|
+
const slugDir = path_1.default.join(branchesDir, slug);
|
|
619
|
+
try {
|
|
620
|
+
const stat = await promises_1.default.stat(slugDir);
|
|
621
|
+
if (!stat.isDirectory())
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
continue; // dangling symlink / EACCES — skip one branch, not the whole scan.
|
|
626
|
+
}
|
|
627
|
+
const meta = await (0, exports.loadMeta)(slugDir);
|
|
628
|
+
if (meta?.branch) {
|
|
629
|
+
summaries.push({
|
|
630
|
+
branch: meta.branch,
|
|
631
|
+
indexedAt: meta.indexedAt ?? '',
|
|
632
|
+
lastCommit: meta.lastCommit ?? '',
|
|
633
|
+
stats: meta.stats,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return summaries;
|
|
638
|
+
};
|
|
639
|
+
/**
|
|
640
|
+
* Convert a discovered {@link IndexedRepo} into the {@link RegistryEntry} shape
|
|
641
|
+
* that former registry consumers (LocalBackend, git-staleness) expect. The
|
|
642
|
+
* `name` is derived the same way {@link registerRepo} derives it (explicit
|
|
643
|
+
* alias → inferred git remote name → basename), so the displayed label matches
|
|
644
|
+
* what `cgraph analyze` would report.
|
|
645
|
+
*/
|
|
646
|
+
const indexedRepoToRegistryEntry = async (repo) => ({
|
|
647
|
+
name: (0, git_js_1.getInferredRepoName)(repo.repoPath) ?? path_1.default.basename(repo.repoPath),
|
|
648
|
+
path: repo.repoPath,
|
|
649
|
+
storagePath: repo.storagePath,
|
|
650
|
+
indexedAt: repo.meta.indexedAt ?? '',
|
|
651
|
+
lastCommit: repo.meta.lastCommit ?? '',
|
|
652
|
+
remoteUrl: repo.meta.remoteUrl,
|
|
653
|
+
stats: repo.meta.stats,
|
|
654
|
+
branch: repo.meta.branch,
|
|
655
|
+
branches: await readBranchSummaries(repo.repoPath),
|
|
656
|
+
});
|
|
657
|
+
/**
|
|
658
|
+
* Read the set of indexed repos discoverable from the given context. With the
|
|
659
|
+
* global registry removed (spec §8), this is cwd-based discovery that returns
|
|
660
|
+
* at most ONE entry — the project root whose `.cgraphx/code/` index is nearest the
|
|
661
|
+
* starting directory (or the explicit `--path` / `CGRAPH_REPO` override).
|
|
662
|
+
*
|
|
663
|
+
* Formerly read `~/.cgraphx/code/registry.json`; now delegates to
|
|
664
|
+
* {@link resolveProjectRoot}. Accepts optional discovery context so callers
|
|
665
|
+
* like `checkCwdMatch(cwd)` can pin the start directory instead of implicitly
|
|
666
|
+
* using `process.cwd()`.
|
|
667
|
+
*/
|
|
668
|
+
const readRegistry = async (opts) => {
|
|
669
|
+
const repo = await (0, exports.resolveProjectRoot)(opts);
|
|
670
|
+
return repo ? [await indexedRepoToRegistryEntry(repo)] : [];
|
|
671
|
+
};
|
|
672
|
+
exports.readRegistry = readRegistry;
|
|
673
|
+
/**
|
|
674
|
+
* Thrown by {@link registerRepo} when a requested name is already in
|
|
675
|
+
* use by a DIFFERENT path. The CLI layer surfaces this as an actionable
|
|
676
|
+
* error instead of relying on `.message` string-matching.
|
|
677
|
+
*
|
|
678
|
+
* The colliding alias is exposed as `err.registryName` (not `err.name`).
|
|
679
|
+
* `err.name` keeps its inherited `Error.prototype.name` semantics (the
|
|
680
|
+
* class name) so downstream code can do the usual `err.name ===
|
|
681
|
+
* 'RegistryNameCollisionError'` checks; use the `kind` discriminant or
|
|
682
|
+
* `instanceof RegistryNameCollisionError` for type-safe narrowing.
|
|
683
|
+
*/
|
|
684
|
+
class RegistryNameCollisionError extends Error {
|
|
685
|
+
registryName;
|
|
686
|
+
existingPath;
|
|
687
|
+
requestedPath;
|
|
688
|
+
kind = 'RegistryNameCollisionError';
|
|
689
|
+
constructor(registryName, existingPath, requestedPath) {
|
|
690
|
+
super(`Registry name "${registryName}" is already used by "${existingPath}".\n` +
|
|
691
|
+
`Pass --name <alias> to register "${requestedPath}" under a different name, ` +
|
|
692
|
+
`or --allow-duplicate-name to allow both paths under the same name (leaves -r <name> ambiguous for these two).`);
|
|
693
|
+
this.registryName = registryName;
|
|
694
|
+
this.existingPath = existingPath;
|
|
695
|
+
this.requestedPath = requestedPath;
|
|
696
|
+
this.name = 'RegistryNameCollisionError';
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
exports.RegistryNameCollisionError = RegistryNameCollisionError;
|
|
700
|
+
/**
|
|
701
|
+
* Register a repo. With the global registry removed (spec §8), this is a
|
|
702
|
+
* minimal stub: it derives and returns a project name from the repo path
|
|
703
|
+
* or the provided `opts.name`, performing no disk I/O. Called after
|
|
704
|
+
* `cgraph analyze` completes.
|
|
705
|
+
*
|
|
706
|
+
* Name resolution precedence:
|
|
707
|
+
* 1. explicit `opts.name` (from `analyze --name <alias>`)
|
|
708
|
+
* 2. `git config --get remote.origin.url` repo name
|
|
709
|
+
* 3. `path.basename(repoPath)` (the original default)
|
|
710
|
+
*/
|
|
711
|
+
const registerRepo = async (repoPath, _meta, opts) => {
|
|
712
|
+
if (opts?.name)
|
|
713
|
+
return opts.name;
|
|
714
|
+
const resolved = path_1.default.resolve(repoPath);
|
|
715
|
+
return (0, git_js_1.getInferredRepoName)(resolved) ?? path_1.default.basename((0, git_js_1.resolveRepoIdentityRoot)(resolved));
|
|
716
|
+
};
|
|
717
|
+
exports.registerRepo = registerRepo;
|
|
718
|
+
/**
|
|
719
|
+
* No-op unregister — the global registry no longer exists.
|
|
720
|
+
*/
|
|
721
|
+
const unregisterRepo = async (_repoPath) => { };
|
|
722
|
+
exports.unregisterRepo = unregisterRepo;
|
|
723
|
+
/**
|
|
724
|
+
* No-op branch-index removal — the global registry no longer exists.
|
|
725
|
+
* Returns `false` (no matching entry found) unconditionally.
|
|
726
|
+
*/
|
|
727
|
+
const removeBranchIndex = async (_repoPath, _branch) => false;
|
|
728
|
+
exports.removeBranchIndex = removeBranchIndex;
|
|
729
|
+
/**
|
|
730
|
+
* Remove a shadowed `branches/<slug>/` sub-index directory when the flat slot
|
|
731
|
+
* adopts this run's branch label (#2354).
|
|
732
|
+
*
|
|
733
|
+
* The flat index follows the checked-out working tree, so when a plain analyze
|
|
734
|
+
* lands on a branch that also has a pinned `branches/<slug>/` sub-index, that
|
|
735
|
+
* sub-index becomes permanently shadowed — explicit `--branch` runs re-resolve
|
|
736
|
+
* to the flat slot and query-side branch scoping serves the flat handle first.
|
|
737
|
+
* This deletes the shadowed directory to avoid stranding un-cleanable disk
|
|
738
|
+
* bloat. The registry-summary bookkeeping half was removed along with the
|
|
739
|
+
* global registry (spec §8).
|
|
740
|
+
*/
|
|
741
|
+
const adoptFlatBranchLabel = async (repoPath, branch) => {
|
|
742
|
+
const resolved = path_1.default.resolve(repoPath);
|
|
743
|
+
const { storagePath } = (0, exports.getStoragePaths)(resolved);
|
|
744
|
+
// Remove a shadowed sub-index directory, mirroring `clean --branch`'s
|
|
745
|
+
// containment guard: the target MUST live under .cgraphx/code/branches/.
|
|
746
|
+
const branchDir = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR, (0, branch_index_js_1.branchSlug)(branch));
|
|
747
|
+
const branchesRoot = path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR) + path_1.default.sep;
|
|
748
|
+
if (!branchDir.startsWith(branchesRoot))
|
|
749
|
+
return;
|
|
750
|
+
let rmError;
|
|
751
|
+
await promises_1.default.rm(branchDir, { recursive: true, force: true }).catch((err) => {
|
|
752
|
+
rmError = err;
|
|
753
|
+
});
|
|
754
|
+
let dirGone = false;
|
|
755
|
+
if (!rmError) {
|
|
756
|
+
dirGone = true;
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
// On failure, probe the disk and treat only provably-absent errno as gone
|
|
760
|
+
// — EACCES/EIO are "not provably absent" (same polarity as the old
|
|
761
|
+
// listRegisteredRepos validate path).
|
|
762
|
+
const probeCode = await promises_1.default.access(branchDir).then(() => null, (e) => e?.code ?? 'UNKNOWN');
|
|
763
|
+
dirGone = probeCode === 'ENOENT' || probeCode === 'ENOTDIR';
|
|
764
|
+
}
|
|
765
|
+
if (dirGone) {
|
|
766
|
+
// Non-recursive by design: only removes the parent when no other pinned
|
|
767
|
+
// sub-index remains, so an empty branches/ dir doesn't read as "pinned".
|
|
768
|
+
await promises_1.default.rmdir(path_1.default.join(storagePath, branch_index_js_1.BRANCHES_DIR)).catch(() => { });
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
logger_js_1.logger.warn({ path: branchDir, code: rmError?.code }, 'Could not remove the shadowed branch sub-index.');
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
exports.adoptFlatBranchLabel = adoptFlatBranchLabel;
|
|
775
|
+
/**
|
|
776
|
+
* Thrown by {@link resolveRegistryEntry} when no registered repo matches
|
|
777
|
+
* the caller's target string (by alias, basename, remote-inferred name,
|
|
778
|
+
* or resolved path). CLI callers that want idempotent "remove" semantics
|
|
779
|
+
* should catch this and exit 0 with a warning; non-idempotent callers
|
|
780
|
+
* (e.g. MCP tools) can surface the error directly.
|
|
781
|
+
*/
|
|
782
|
+
class RegistryNotFoundError extends Error {
|
|
783
|
+
target;
|
|
784
|
+
availableNames;
|
|
785
|
+
kind = 'RegistryNotFoundError';
|
|
786
|
+
constructor(target, availableNames) {
|
|
787
|
+
const hint = availableNames.length > 0
|
|
788
|
+
? ` Available: ${availableNames.join(', ')}.`
|
|
789
|
+
: ' No repositories are currently registered.';
|
|
790
|
+
super(`No registered repo matches "${target}".${hint}`);
|
|
791
|
+
this.target = target;
|
|
792
|
+
this.availableNames = availableNames;
|
|
793
|
+
this.name = 'RegistryNotFoundError';
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
exports.RegistryNotFoundError = RegistryNotFoundError;
|
|
797
|
+
/**
|
|
798
|
+
* Thrown by {@link resolveRegistryEntry} when the target string matches
|
|
799
|
+
* the `name` of two or more entries — only possible when the user
|
|
800
|
+
* previously registered duplicates via `analyze --name X
|
|
801
|
+
* --allow-duplicate-name` (#829). The error carries enough information
|
|
802
|
+
* for the caller to render an actionable disambiguation hint without
|
|
803
|
+
* string-matching on `.message`.
|
|
804
|
+
*
|
|
805
|
+
* `kind` is a string literal discriminant (same pattern as
|
|
806
|
+
* {@link RegistryNameCollisionError}) so callers can narrow via
|
|
807
|
+
* `err.kind === 'RegistryAmbiguousTargetError'` without importing the
|
|
808
|
+
* class.
|
|
809
|
+
*/
|
|
810
|
+
class RegistryAmbiguousTargetError extends Error {
|
|
811
|
+
target;
|
|
812
|
+
matches;
|
|
813
|
+
kind = 'RegistryAmbiguousTargetError';
|
|
814
|
+
constructor(target, matches) {
|
|
815
|
+
const listing = matches.map((m) => ` - ${m.name} (${m.path})`).join('\n');
|
|
816
|
+
super(`Multiple registered repos match "${target}":\n${listing}\n` +
|
|
817
|
+
`Pass the absolute path instead to disambiguate.`);
|
|
818
|
+
this.target = target;
|
|
819
|
+
this.matches = matches;
|
|
820
|
+
this.name = 'RegistryAmbiguousTargetError';
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
exports.RegistryAmbiguousTargetError = RegistryAmbiguousTargetError;
|
|
824
|
+
/**
|
|
825
|
+
* Thrown by {@link assertAnalysisFinalized} when a successful `analyze` run
|
|
826
|
+
* did not actually persist the index metadata file (#1169).
|
|
827
|
+
*
|
|
828
|
+
* Why this exists: on Windows, `cgraph analyze` has been observed to exit
|
|
829
|
+
* cleanly (code 0) with `lbug.wal` written but no metadata file, leaving the
|
|
830
|
+
* repo invisible to `cgraph list`/`status`. This invariant fails loudly so
|
|
831
|
+
* the silent-finalize bug surfaces with a non-zero exit code regardless of
|
|
832
|
+
* the upstream root cause.
|
|
833
|
+
*/
|
|
834
|
+
class AnalysisNotFinalizedError extends Error {
|
|
835
|
+
repoPath;
|
|
836
|
+
storagePath;
|
|
837
|
+
kind = 'AnalysisNotFinalizedError';
|
|
838
|
+
constructor(repoPath, storagePath) {
|
|
839
|
+
super(`Analysis did not finalize for ${repoPath}: ` +
|
|
840
|
+
`${exports.INDEX_METADATA_FILE} was not written to ${path_1.default.join(storagePath, exports.INDEX_METADATA_FILE)}. ` +
|
|
841
|
+
`The on-disk index is incomplete. ` +
|
|
842
|
+
`Re-run "cgraph analyze" — if the problem persists, inspect ` +
|
|
843
|
+
`${storagePath} for a stale lbug.wal that signals an aborted write.`);
|
|
844
|
+
this.repoPath = repoPath;
|
|
845
|
+
this.storagePath = storagePath;
|
|
846
|
+
this.name = 'AnalysisNotFinalizedError';
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
exports.AnalysisNotFinalizedError = AnalysisNotFinalizedError;
|
|
850
|
+
/**
|
|
851
|
+
* Always returns false — the global registry no longer exists, so no repo is
|
|
852
|
+
* ever "registered" in that sense.
|
|
853
|
+
*/
|
|
854
|
+
const isRepoRegistered = async (_repoPath) => false;
|
|
855
|
+
exports.isRepoRegistered = isRepoRegistered;
|
|
856
|
+
/**
|
|
857
|
+
* Verify that a successful `analyze` call actually produced the index
|
|
858
|
+
* metadata file on disk:
|
|
859
|
+
* - `cgraph.json` must exist at `<repoPath>/.cgraphx/code/cgraph.json`.
|
|
860
|
+
*
|
|
861
|
+
* Throws {@link AnalysisNotFinalizedError} on failure. Pure read — does not
|
|
862
|
+
* mutate disk state.
|
|
863
|
+
*
|
|
864
|
+
* Callers must skip this assertion on the `alreadyUpToDate` early-return
|
|
865
|
+
* path, where the rebuild was deliberately not run.
|
|
866
|
+
*/
|
|
867
|
+
const assertAnalysisFinalized = async (repoPath) => {
|
|
868
|
+
const resolved = path_1.default.resolve(repoPath);
|
|
869
|
+
const { storagePath, metaPath } = (0, exports.getStoragePaths)(resolved);
|
|
870
|
+
try {
|
|
871
|
+
await promises_1.default.access(metaPath);
|
|
872
|
+
}
|
|
873
|
+
catch {
|
|
874
|
+
throw new AnalysisNotFinalizedError(resolved, storagePath);
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
exports.assertAnalysisFinalized = assertAnalysisFinalized;
|
|
878
|
+
/**
|
|
879
|
+
* Thrown by {@link assertSafeStoragePath} when an entry's `storagePath` does
|
|
880
|
+
* NOT point at the expected `<entry.path>/.cgraphx/code` subfolder. CLI destructive
|
|
881
|
+
* commands (`remove`, `clean --all`) should catch this and exit non-zero
|
|
882
|
+
* without deleting anything — proceeding would mean `fs.rm(recursive: true)`
|
|
883
|
+
* on whatever odd path the entry is pointing at.
|
|
884
|
+
*/
|
|
885
|
+
class UnsafeStoragePathError extends Error {
|
|
886
|
+
entry;
|
|
887
|
+
expectedStoragePath;
|
|
888
|
+
actualStoragePath;
|
|
889
|
+
kind = 'UnsafeStoragePathError';
|
|
890
|
+
constructor(entry, expectedStoragePath, actualStoragePath) {
|
|
891
|
+
super(`Refusing to remove storage path for safety: expected ` +
|
|
892
|
+
`"${expectedStoragePath}" under the repo's .cgraphx/code subfolder, ` +
|
|
893
|
+
`but the entry has "${actualStoragePath}".`);
|
|
894
|
+
this.entry = entry;
|
|
895
|
+
this.expectedStoragePath = expectedStoragePath;
|
|
896
|
+
this.actualStoragePath = actualStoragePath;
|
|
897
|
+
this.name = 'UnsafeStoragePathError';
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
exports.UnsafeStoragePathError = UnsafeStoragePathError;
|
|
901
|
+
/**
|
|
902
|
+
* Guard rail for destructive CLI paths: verify that an entry's `storagePath`
|
|
903
|
+
* is the canonical `<repo>/.cgraphx/code` subfolder of its `path`. If not, throw
|
|
904
|
+
* {@link UnsafeStoragePathError} so the caller exits without touching disk.
|
|
905
|
+
*
|
|
906
|
+
* Pure string check — does NOT require the paths to exist on disk.
|
|
907
|
+
* Windows: case-insensitive; POSIX: case-sensitive.
|
|
908
|
+
*/
|
|
909
|
+
const assertSafeStoragePath = (entry) => {
|
|
910
|
+
const expected = path_1.default.join(path_1.default.resolve(entry.path), ...CGRAPHX_CODE_DIR_PARTS);
|
|
911
|
+
const actual = path_1.default.resolve(entry.storagePath);
|
|
912
|
+
const matches = process.platform === 'win32'
|
|
913
|
+
? expected.toLowerCase() === actual.toLowerCase()
|
|
914
|
+
: expected === actual;
|
|
915
|
+
if (!matches) {
|
|
916
|
+
throw new UnsafeStoragePathError(entry, expected, actual);
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
exports.assertSafeStoragePath = assertSafeStoragePath;
|
|
920
|
+
/**
|
|
921
|
+
* Resolve a user-supplied target string (from `gitnexus remove <target>`
|
|
922
|
+
* or equivalent MCP tool argument) to a single registry entry.
|
|
923
|
+
*
|
|
924
|
+
* Match precedence (first hit wins, subsequent tiers are only tried if
|
|
925
|
+
* the prior tier produces zero matches):
|
|
926
|
+
* 1. Exact resolved-path match (Windows: case-insensitive).
|
|
927
|
+
* Paths are unique by registry construction, so a path match can
|
|
928
|
+
* never be ambiguous.
|
|
929
|
+
* 2. Exact `name` match (case-insensitive). If ≥ 2 entries share the
|
|
930
|
+
* name — only possible via `--allow-duplicate-name` (#829) —
|
|
931
|
+
* throws {@link RegistryAmbiguousTargetError}.
|
|
932
|
+
*
|
|
933
|
+
* No fuzzy / partial matching — unambiguous, scriptable behaviour is
|
|
934
|
+
* more important than convenience for destructive commands.
|
|
935
|
+
*
|
|
936
|
+
* Throws {@link RegistryNotFoundError} if no entry matches.
|
|
937
|
+
*
|
|
938
|
+
* `entries` is passed in (rather than re-read) so callers that already
|
|
939
|
+
* hold the registry snapshot (e.g. to print a "before" state) can avoid
|
|
940
|
+
* a second disk read, and so tests can inject fixtures without touching
|
|
941
|
+
* `CGRAPH_HOME`.
|
|
942
|
+
*/
|
|
943
|
+
const resolveRegistryEntry = (entries, target) => {
|
|
944
|
+
// Tier 1: path match. Canonicalise BOTH sides so symlink and
|
|
945
|
+
// Windows-8.3 quirks don't cause a false miss — e.g. the caller
|
|
946
|
+
// passes `/var/folders/.../repo` while the registry has
|
|
947
|
+
// `/private/var/folders/.../repo` (both resolve to the same
|
|
948
|
+
// `realpath.native`). See `canonicalizePath` for the rationale.
|
|
949
|
+
//
|
|
950
|
+
// Canonicalising the STORED entry (not just the input) is what gives
|
|
951
|
+
// us backward-compat for registries written by versions that only
|
|
952
|
+
// ran `path.resolve` — both get canonicalised here at compare time.
|
|
953
|
+
const canonicalTarget = (0, exports.canonicalizePath)(target);
|
|
954
|
+
const pathMatch = entries.find((e) => {
|
|
955
|
+
const a = (0, exports.canonicalizePath)(e.path);
|
|
956
|
+
const b = canonicalTarget;
|
|
957
|
+
return (0, exports.registryPathEquals)(a, b);
|
|
958
|
+
});
|
|
959
|
+
if (pathMatch)
|
|
960
|
+
return pathMatch;
|
|
961
|
+
// Tier 2: name match. Case-insensitive on all platforms — registry
|
|
962
|
+
// name collisions are already filtered case-insensitively in
|
|
963
|
+
// `registerRepo`, so "APP" vs "app" are considered the same key.
|
|
964
|
+
const targetLower = target.toLowerCase();
|
|
965
|
+
const nameMatches = entries.filter((e) => e.name.toLowerCase() === targetLower);
|
|
966
|
+
if (nameMatches.length === 1)
|
|
967
|
+
return nameMatches[0];
|
|
968
|
+
if (nameMatches.length > 1) {
|
|
969
|
+
throw new RegistryAmbiguousTargetError(target, nameMatches);
|
|
970
|
+
}
|
|
971
|
+
// Tier 3: miss. Build the available-names hint ONCE; resolveRepo-style
|
|
972
|
+
// disambiguated labels (`app (/path)`) are applied when the same name
|
|
973
|
+
// appears in multiple entries so the user sees the same hint shape as
|
|
974
|
+
// `-r <name>` errors.
|
|
975
|
+
const nameCounts = new Map();
|
|
976
|
+
for (const e of entries) {
|
|
977
|
+
const key = e.name.toLowerCase();
|
|
978
|
+
nameCounts.set(key, (nameCounts.get(key) ?? 0) + 1);
|
|
979
|
+
}
|
|
980
|
+
const availableNames = entries.map((e) => (nameCounts.get(e.name.toLowerCase()) ?? 0) > 1 ? `${e.name} (${e.path})` : e.name);
|
|
981
|
+
throw new RegistryNotFoundError(target, availableNames);
|
|
982
|
+
};
|
|
983
|
+
exports.resolveRegistryEntry = resolveRegistryEntry;
|
|
984
|
+
/**
|
|
985
|
+
* List the indexed repos available to CLI tool operations. With the global
|
|
986
|
+
* registry removed (spec §8), this is cwd-based discovery ({@link readRegistry})
|
|
987
|
+
* returning at most ONE entry — the project root whose `.cgraphx/code/` index is
|
|
988
|
+
* nearest `startCwd` (or the `explicitPath` / `CGRAPH_REPO` override).
|
|
989
|
+
*
|
|
990
|
+
* The legacy `validate` flag is now implicit: discovery reads the index meta,
|
|
991
|
+
* so an absent or unreadable `.cgraphx/code/` naturally yields `[]` (the "no index"
|
|
992
|
+
* path) — there is no separate on-disk validation step to skip.
|
|
993
|
+
*/
|
|
994
|
+
const listRegisteredRepos = async (opts) => (0, exports.readRegistry)(opts);
|
|
995
|
+
exports.listRegisteredRepos = listRegisteredRepos;
|
|
996
|
+
/**
|
|
997
|
+
* Get the path to the global CLI config file
|
|
998
|
+
*/
|
|
999
|
+
const getGlobalConfigPath = () => {
|
|
1000
|
+
return path_1.default.join((0, exports.getGlobalDir)(), 'config.json');
|
|
1001
|
+
};
|
|
1002
|
+
exports.getGlobalConfigPath = getGlobalConfigPath;
|
|
1003
|
+
/**
|
|
1004
|
+
* Load CLI config from ~/.cgraphx/code/config.json
|
|
1005
|
+
*/
|
|
1006
|
+
const loadCLIConfig = async () => {
|
|
1007
|
+
try {
|
|
1008
|
+
const raw = await promises_1.default.readFile((0, exports.getGlobalConfigPath)(), 'utf-8');
|
|
1009
|
+
return JSON.parse(raw);
|
|
1010
|
+
}
|
|
1011
|
+
catch {
|
|
1012
|
+
return {};
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
exports.loadCLIConfig = loadCLIConfig;
|
|
1016
|
+
/**
|
|
1017
|
+
* Save CLI config to ~/.cgraphx/code/config.json
|
|
1018
|
+
*/
|
|
1019
|
+
const saveCLIConfig = async (config) => {
|
|
1020
|
+
const dir = (0, exports.getGlobalDir)();
|
|
1021
|
+
await promises_1.default.mkdir(dir, { recursive: true });
|
|
1022
|
+
const configPath = (0, exports.getGlobalConfigPath)();
|
|
1023
|
+
await promises_1.default.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
1024
|
+
// Restrict file permissions on Unix (config may contain API keys)
|
|
1025
|
+
if (process.platform !== 'win32') {
|
|
1026
|
+
try {
|
|
1027
|
+
await promises_1.default.chmod(configPath, 0o600);
|
|
1028
|
+
}
|
|
1029
|
+
catch {
|
|
1030
|
+
/* best-effort */
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
exports.saveCLIConfig = saveCLIConfig;
|
|
1035
|
+
// ─── Sibling-clone detection ─────────────────────────────────────────────
|
|
1036
|
+
//
|
|
1037
|
+
// A "sibling clone" is a different on-disk path that points at the same
|
|
1038
|
+
// logical repository (same `origin` remote URL) as an indexed project root.
|
|
1039
|
+
// With the global registry removed (spec §8), detection is limited to the
|
|
1040
|
+
// one project root discoverable from the caller's context ({@link readRegistry}
|
|
1041
|
+
// → cwd / `--path` / `CGRAPH_REPO`): it can surface a sibling only when the
|
|
1042
|
+
// discovered index's `remoteUrl` matches and its path differs from the
|
|
1043
|
+
// caller's `selfPath`. Cross-clone discovery that walks every registered path
|
|
1044
|
+
// is gone with the registry; the realistic shape this still catches is a
|
|
1045
|
+
// query whose cwd resolves to one clone while the indexed root lives at
|
|
1046
|
+
// another path sharing the same origin.
|
|
1047
|
+
/**
|
|
1048
|
+
* Find a discovered project root whose `remoteUrl` matches the given one,
|
|
1049
|
+
* excluding `selfPath` (case-insensitive on Windows). Entries without a
|
|
1050
|
+
* `remoteUrl` are ignored — we cannot prove sibling-ness without a fingerprint.
|
|
1051
|
+
*/
|
|
1052
|
+
const findSiblingClones = async (remoteUrl, selfPath) => {
|
|
1053
|
+
if (!remoteUrl)
|
|
1054
|
+
return [];
|
|
1055
|
+
const entries = await (0, exports.readRegistry)();
|
|
1056
|
+
const isWin = process.platform === 'win32';
|
|
1057
|
+
const norm = (p) => (isWin ? path_1.default.resolve(p).toLowerCase() : path_1.default.resolve(p));
|
|
1058
|
+
const self = norm(selfPath);
|
|
1059
|
+
return entries.filter((e) => e.remoteUrl === remoteUrl && norm(e.path) !== self);
|
|
1060
|
+
};
|
|
1061
|
+
exports.findSiblingClones = findSiblingClones;
|