gitnexus 1.6.11-rc.8 → 1.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -26
- package/dist/_shared/graph/types.d.ts +81 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +2 -0
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/languages.d.ts +2 -1
- package/dist/_shared/languages.d.ts.map +1 -1
- package/dist/_shared/languages.js +1 -0
- package/dist/_shared/languages.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +4 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/finalize-algorithm.js +1 -0
- package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.d.ts +3 -0
- package/dist/_shared/scope-resolution/language-classification.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/language-classification.js +4 -0
- package/dist/_shared/scope-resolution/language-classification.js.map +1 -1
- package/dist/_shared/scope-resolution/reference-site.d.ts +10 -0
- package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
- package/dist/_shared/scope-resolution/types.d.ts +15 -0
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +4 -0
- package/dist/cli/ai-context.js +90 -14
- package/dist/cli/analyze-config.js +14 -0
- package/dist/cli/analyze-options.d.ts +14 -0
- package/dist/cli/analyze-watch.d.ts +20 -0
- package/dist/cli/analyze-watch.js +434 -0
- package/dist/cli/analyze.js +27 -9
- package/dist/cli/auto-sync.d.ts +1 -0
- package/dist/cli/auto-sync.js +107 -0
- package/dist/cli/command-banner.d.ts +15 -0
- package/dist/cli/command-banner.js +42 -0
- package/dist/cli/detect-changes-format.js +21 -0
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.js +14 -0
- package/dist/cli/group.js +7 -1
- package/dist/cli/help-i18n.js +4 -0
- package/dist/cli/i18n/en.d.ts +18 -3
- package/dist/cli/i18n/en.js +18 -3
- package/dist/cli/i18n/resources.d.ts +33 -3
- package/dist/cli/i18n/zh-CN.d.ts +15 -0
- package/dist/cli/i18n/zh-CN.js +18 -3
- package/dist/cli/index.js +34 -7
- package/dist/cli/mcp.d.ts +15 -0
- package/dist/cli/mcp.js +44 -0
- package/dist/cli/optional-grammars.d.ts +3 -2
- package/dist/cli/optional-grammars.js +19 -3
- package/dist/cli/setup.js +41 -15
- package/dist/cli/update-notice.d.ts +34 -0
- package/dist/cli/update-notice.js +91 -0
- package/dist/cli/update.d.ts +21 -0
- package/dist/cli/update.js +93 -0
- package/dist/cli/watch.d.ts +1 -20
- package/dist/cli/watch.js +5 -371
- package/dist/core/analysis-feature-registry.d.ts +2 -0
- package/dist/core/analysis-feature-registry.js +15 -0
- package/dist/core/analyzer-identity.js +21 -3
- package/dist/core/auto-sync/analysis-worker-launch.d.ts +30 -0
- package/dist/core/auto-sync/analysis-worker-launch.js +166 -0
- package/dist/core/auto-sync/config.d.ts +33 -0
- package/dist/core/auto-sync/config.js +320 -0
- package/dist/core/auto-sync/index.d.ts +6 -0
- package/dist/core/auto-sync/index.js +6 -0
- package/dist/core/auto-sync/path-security.d.ts +9 -0
- package/dist/core/auto-sync/path-security.js +251 -0
- package/dist/core/auto-sync/repo.d.ts +1 -0
- package/dist/core/auto-sync/repo.js +6 -0
- package/dist/core/auto-sync/runner.d.ts +44 -0
- package/dist/core/auto-sync/runner.js +428 -0
- package/dist/core/auto-sync/starter.d.ts +50 -0
- package/dist/core/auto-sync/starter.js +497 -0
- package/dist/core/auto-sync/state.d.ts +37 -0
- package/dist/core/auto-sync/state.js +119 -0
- package/dist/core/group/config-parser.js +8 -1
- package/dist/core/group/cross-impact.d.ts +3 -0
- package/dist/core/group/cross-impact.js +36 -4
- package/dist/core/group/extractors/http-patterns/java.js +22 -8
- package/dist/core/group/extractors/http-patterns/kotlin.js +86 -31
- package/dist/core/group/extractors/http-patterns/node.js +145 -8
- package/dist/core/group/extractors/http-patterns/python.js +11 -7
- package/dist/core/group/extractors/http-route-extractor.js +63 -17
- package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
- package/dist/core/group/group-lock.js +5 -6
- package/dist/core/group/normalization.d.ts +38 -1
- package/dist/core/group/normalization.js +59 -3
- package/dist/core/group/service.d.ts +11 -0
- package/dist/core/group/service.js +13 -1
- package/dist/core/group/storage.js +2 -2
- package/dist/core/group/sync.d.ts +24 -1
- package/dist/core/group/sync.js +46 -8
- package/dist/core/group/types.d.ts +13 -0
- package/dist/core/incremental/derived-writeback.d.ts +36 -0
- package/dist/core/incremental/derived-writeback.js +68 -0
- package/dist/core/incremental/spring-config-drift.d.ts +12 -0
- package/dist/core/incremental/spring-config-drift.js +46 -0
- package/dist/core/incremental/subgraph-extract.d.ts +7 -4
- package/dist/core/incremental/subgraph-extract.js +30 -5
- package/dist/core/ingestion/asyncapi/document.d.ts +226 -0
- package/dist/core/ingestion/asyncapi/document.js +758 -0
- package/dist/core/ingestion/asyncapi/protocol.d.ts +79 -0
- package/dist/core/ingestion/asyncapi/protocol.js +203 -0
- package/dist/core/ingestion/call-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/call-extractors/configs/zig.js +4 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +100 -0
- package/dist/core/ingestion/call-extractors/zig-static-gating.js +319 -0
- package/dist/core/ingestion/call-processor.js +3 -1
- package/dist/core/ingestion/class-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/class-extractors/configs/zig.js +32 -0
- package/dist/core/ingestion/class-extractors/generic.js +4 -1
- package/dist/core/ingestion/class-types.d.ts +6 -2
- package/dist/core/ingestion/destination-key.d.ts +59 -0
- package/dist/core/ingestion/destination-key.js +61 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +6 -2
- package/dist/core/ingestion/entry-point-scoring.js +8 -44
- package/dist/core/ingestion/export-detection.d.ts +37 -0
- package/dist/core/ingestion/export-detection.js +60 -0
- package/dist/core/ingestion/field-extractors/configs/zig.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/zig.js +49 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +1 -1
- package/dist/core/ingestion/field-extractors/generic.js +12 -1
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
- package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +5 -0
- package/dist/core/ingestion/frameworks/spring/analysis-features.js +9 -0
- package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +8 -1
- package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
- package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
- package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
- package/dist/core/ingestion/frameworks/spring/destinations.d.ts +539 -0
- package/dist/core/ingestion/frameworks/spring/destinations.js +840 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
- package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
- package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
- package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.d.ts +7 -0
- package/dist/core/ingestion/frameworks/spring/vendor-prefixes.js +22 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.d.ts +13 -0
- package/dist/core/ingestion/import-resolvers/configs/zig.js +26 -0
- package/dist/core/ingestion/import-resolvers/zig.d.ts +34 -0
- package/dist/core/ingestion/import-resolvers/zig.js +193 -0
- package/dist/core/ingestion/language-config.d.ts +177 -0
- package/dist/core/ingestion/language-config.js +719 -0
- package/dist/core/ingestion/language-provider.d.ts +178 -1
- package/dist/core/ingestion/language-provider.js +22 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
- package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
- package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
- package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -0
- package/dist/core/ingestion/languages/index.d.ts +1 -0
- package/dist/core/ingestion/languages/index.js +2 -0
- package/dist/core/ingestion/languages/java/analysis-features.d.ts +1 -1
- package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
- package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
- package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
- package/dist/core/ingestion/languages/java/captures.js +22 -1
- package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
- package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
- package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
- package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
- package/dist/core/ingestion/languages/java/spring-di.js +44 -2
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
- package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
- package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
- package/dist/core/ingestion/languages/java.js +18 -8
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
- package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
- package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
- package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
- package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
- package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
- package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
- package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
- package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
- package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
- package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
- package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
- package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
- package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
- package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
- package/dist/core/ingestion/languages/kotlin.js +24 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/rust/query.js +8 -8
- package/dist/core/ingestion/languages/zig/captures.d.ts +260 -0
- package/dist/core/ingestion/languages/zig/captures.js +2070 -0
- package/dist/core/ingestion/languages/zig/index.d.ts +4 -0
- package/dist/core/ingestion/languages/zig/index.js +4 -0
- package/dist/core/ingestion/languages/zig/interpret.d.ts +36 -0
- package/dist/core/ingestion/languages/zig/interpret.js +176 -0
- package/dist/core/ingestion/languages/zig/query.d.ts +3 -0
- package/dist/core/ingestion/languages/zig/query.js +426 -0
- package/dist/core/ingestion/languages/zig/range-binding.d.ts +37 -0
- package/dist/core/ingestion/languages/zig/range-binding.js +373 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.d.ts +12 -0
- package/dist/core/ingestion/languages/zig/scope-resolver.js +58 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.d.ts +25 -0
- package/dist/core/ingestion/languages/zig/simple-hooks.js +143 -0
- package/dist/core/ingestion/languages/zig.d.ts +32 -0
- package/dist/core/ingestion/languages/zig.js +130 -0
- package/dist/core/ingestion/method-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/method-extractors/configs/zig.js +120 -0
- package/dist/core/ingestion/method-extractors/generic.js +16 -4
- package/dist/core/ingestion/method-types.d.ts +10 -4
- package/dist/core/ingestion/model/field-registry.d.ts +3 -3
- package/dist/core/ingestion/model/field-registry.js +11 -7
- package/dist/core/ingestion/model/method-registry.d.ts +3 -3
- package/dist/core/ingestion/model/method-registry.js +13 -8
- package/dist/core/ingestion/model/registration-table.js +3 -0
- package/dist/core/ingestion/model/type-registry.js +8 -4
- package/dist/core/ingestion/pipeline-phases/di.js +47 -14
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +7 -1
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +79 -91
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
- package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
- package/dist/core/ingestion/pipeline-phases/routes.js +27 -18
- package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
- package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
- package/dist/core/ingestion/pipeline-phases/scan.js +82 -1
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.d.ts +123 -0
- package/dist/core/ingestion/pipeline-phases/spring-destinations.js +688 -0
- package/dist/core/ingestion/pipeline.d.ts +30 -1
- package/dist/core/ingestion/pipeline.js +52 -14
- package/dist/core/ingestion/resolve-references.js +5 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
- package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
- package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
- package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +12 -18
- package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +214 -33
- package/dist/core/ingestion/route-extractors/kotlin-spring.d.ts +13 -0
- package/dist/core/ingestion/route-extractors/kotlin-spring.js +259 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.d.ts +6 -0
- package/dist/core/ingestion/route-extractors/python-decorator-handler.js +16 -0
- package/dist/core/ingestion/route-extractors/spring-shared.d.ts +30 -1
- package/dist/core/ingestion/route-extractors/spring-shared.js +77 -9
- package/dist/core/ingestion/route-extractors/spring.js +9 -5
- package/dist/core/ingestion/scope-extractor.js +8 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +62 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +2 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +11 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +23 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +24 -3
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
- package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +11 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +29 -3
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +8 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +35 -9
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -4
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +277 -9
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +7 -3
- package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +43 -9
- package/dist/core/ingestion/scope-resolution/scope/walkers.js +71 -10
- package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -0
- package/dist/core/ingestion/tree-sitter-queries.js +161 -0
- package/dist/core/ingestion/type-extractors/zig.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/zig.js +17 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +40 -1
- package/dist/core/ingestion/utils/ast-helpers.js +124 -6
- package/dist/core/ingestion/utils/callable-flow-captures.d.ts +9 -0
- package/dist/core/ingestion/utils/callable-flow-captures.js +75 -14
- package/dist/core/ingestion/utils/test-file-path.d.ts +28 -0
- package/dist/core/ingestion/utils/test-file-path.js +87 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.d.ts +2 -0
- package/dist/core/ingestion/variable-extractors/configs/zig.js +71 -0
- package/dist/core/ingestion/workers/parse-worker.js +85 -14
- package/dist/core/install-context.d.ts +4 -0
- package/dist/core/install-context.js +152 -0
- package/dist/core/lbug/csv-generator.d.ts +10 -1
- package/dist/core/lbug/csv-generator.js +92 -22
- package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
- package/dist/core/lbug/graph-emit-sink.js +4 -2
- package/dist/core/lbug/lbug-adapter.d.ts +100 -5
- package/dist/core/lbug/lbug-adapter.js +236 -24
- package/dist/core/lbug/schema.d.ts +6 -5
- package/dist/core/lbug/schema.js +84 -22
- package/dist/core/net/url-guard.d.ts +6 -0
- package/dist/core/net/url-guard.js +147 -0
- package/dist/core/package-version.d.ts +5 -0
- package/dist/core/package-version.js +10 -0
- package/dist/core/run-analyze.d.ts +21 -4
- package/dist/core/run-analyze.js +426 -117
- package/dist/core/search/fts-indexes.d.ts +19 -1
- package/dist/core/search/fts-indexes.js +28 -1
- package/dist/core/tree-sitter/parser-loader.js +16 -0
- package/dist/core/update-cache.d.ts +39 -0
- package/dist/core/update-cache.js +141 -0
- package/dist/core/update-check.d.ts +31 -0
- package/dist/core/update-check.js +274 -0
- package/dist/mcp/local/local-backend.d.ts +27 -13
- package/dist/mcp/local/local-backend.js +148 -60
- package/dist/mcp/repository-policy.d.ts +5 -1
- package/dist/mcp/repository-policy.js +48 -4
- package/dist/mcp/resources.js +10 -1
- package/dist/mcp/server.js +8 -9
- package/dist/mcp/tools.js +32 -22
- package/dist/server/analyze-launch.d.ts +2 -0
- package/dist/server/analyze-launch.js +2 -0
- package/dist/server/analyze-worker-protocol.d.ts +6 -1
- package/dist/server/analyze-worker.d.ts +1 -0
- package/dist/server/analyze-worker.js +38 -20
- package/dist/server/api.d.ts +5 -1
- package/dist/server/api.js +105 -88
- package/dist/server/git-clone.d.ts +40 -16
- package/dist/server/git-clone.js +253 -199
- package/dist/server/grep-params.d.ts +18 -0
- package/dist/server/grep-params.js +83 -0
- package/dist/server/grep-scan.d.ts +23 -0
- package/dist/server/grep-scan.js +107 -0
- package/dist/server/grep-worker.d.ts +1 -0
- package/dist/server/grep-worker.js +12 -0
- package/dist/server/mcp-http.d.ts +8 -0
- package/dist/server/mcp-http.js +16 -1
- package/dist/server/update-controller.d.ts +29 -0
- package/dist/server/update-controller.js +82 -0
- package/dist/storage/file-lock.d.ts +15 -0
- package/dist/storage/file-lock.js +155 -0
- package/dist/storage/fs-atomic.d.ts +24 -0
- package/dist/storage/fs-atomic.js +86 -2
- package/dist/storage/global-dir.d.ts +2 -0
- package/dist/storage/global-dir.js +6 -0
- package/dist/storage/parse-cache.d.ts +45 -7
- package/dist/storage/parse-cache.js +189 -42
- package/dist/storage/parsedfile-store.d.ts +41 -60
- package/dist/storage/parsedfile-store.js +247 -171
- package/dist/storage/repo-manager.d.ts +10 -4
- package/dist/storage/repo-manager.js +35 -25
- package/dist/storage/repo-meta.d.ts +34 -0
- package/dist/storage/v8-sidecar.d.ts +48 -0
- package/dist/storage/v8-sidecar.js +347 -0
- package/dist/types/pipeline.d.ts +14 -0
- package/dist/utils/process-identity.d.ts +2 -0
- package/dist/utils/process-identity.js +35 -0
- package/package.json +10 -4
- package/scripts/assert-web-assets.mjs +35 -0
- package/scripts/build-web.js +72 -0
- package/scripts/build.js +31 -28
- package/scripts/cross-platform-tests.ts +5 -0
- package/skills/gitnexus-cli.md +5 -1
- package/web/assets/ProcessFlowModal-DAeX2BHW.js +24 -0
- package/web/assets/{abnfDiagram-QNN2D4NM-Cq2djWWe.js → abnfDiagram-PAR5IXJI-J3OdeHLl.js} +1 -1
- package/web/assets/{agent-BWAXPjC5.js → agent-BMRqXorA.js} +6 -4
- package/web/assets/architecture-7GRP2DOG-M7G3SWCO-G3sWyX6M.js +1 -0
- package/web/assets/architectureDiagram-2PNWDENW-ysKcRlGT.js +36 -0
- package/web/assets/blockDiagram-PUWGUBOA-oLXTa1lY.js +129 -0
- package/web/assets/c4Diagram-3NLNHZP5-D3iu4eC0.js +38 -0
- package/web/assets/{chunk-2SREHG4O-Dip42xOq.js → chunk-2NMSUPJH-B24w-wng.js} +1 -1
- package/web/assets/{chunk-VJFVEZTB-CX66F2ep.js → chunk-32MCUW2P-ByUyt0Sa.js} +3 -3
- package/web/assets/{chunk-4RFN2BYJ-DHHWuC-n.js → chunk-3NPNU5GP-DocZ07Sg.js} +1 -1
- package/web/assets/{chunk-XNMVGMAZ-Cg_LnPtj.js → chunk-3SMGFRGC-CAu4JRLv.js} +1 -1
- package/web/assets/{chunk-W44A43WB-BN8EQc_u.js → chunk-4CAJECRU-DRYMwG9z.js} +1 -1
- package/web/assets/chunk-4OADUZ5Q-CxrSvOwZ.js +10 -0
- package/web/assets/{chunk-DMV4VAQV-Bn6WXDSX.js → chunk-5IQCK5RY-CCMhl4so.js} +2 -2
- package/web/assets/{chunk-RRFMTAIC-CMN0wcYA.js → chunk-5MVFYWFU-Db9KvrYO.js} +1 -1
- package/web/assets/chunk-CLS4B6BI-Uvx5QNsu.js +168 -0
- package/web/assets/chunk-DZP67EKU-B3Mt380j.js +70 -0
- package/web/assets/{chunk-6L755F7B-CMhLBxi2.js → chunk-EICP7K5X-CqwE9hui.js} +1 -1
- package/web/assets/{chunk-BI6VK774-D0oaWk8V.js → chunk-GDY2UAB4-CtQQR0a8.js} +1 -1
- package/web/assets/chunk-H7VHZCWX-CE1nAmt6.js +1 -0
- package/web/assets/chunk-IJBDOHL6-BUKtY6oF.js +1 -0
- package/web/assets/{chunk-OIYT25JQ-CQ6KOZGX.js → chunk-JFFVMJIA-0fJenqia.js} +1 -1
- package/web/assets/{chunk-HNC4WDU7-DoU3KnA7.js → chunk-JZGDI5JK-BeTMSSkJ.js} +1 -1
- package/web/assets/{chunk-EQFTRU2I-1ix7TzW9.js → chunk-KD6SPIPN-Qp1Pflah.js} +1 -1
- package/web/assets/chunk-NF366YI6-CpSpya3n.js +231 -0
- package/web/assets/chunk-NUDPKBEF-CU1-BQIW.js +34 -0
- package/web/assets/{chunk-SATU7PGQ-B1zhgOvc.js → chunk-OJINMHTS-zOCQe4eI.js} +1 -1
- package/web/assets/{chunk-E5QJAATJ-dh-5CtIV.js → chunk-Q6NGPIAH-yyBomb63.js} +1 -1
- package/web/assets/chunk-QJSWEUOL-D_rf9gPD.js +128 -0
- package/web/assets/chunk-R7JDMUKV-CRoqKpD6.js +1 -0
- package/web/assets/{chunk-VE5CLXGZ-C1vB7wpY.js → chunk-RCXAM2GK-CUqrWQDV.js} +1 -1
- package/web/assets/{chunk-66DQ2XMT-CM0xjFAN.js → chunk-RT4MAWR3-zXy9-Lvt.js} +1 -1
- package/web/assets/{chunk-TZUXEDM2-B7p9AcTw.js → chunk-SFMINX4W-J2UrvMpD.js} +1 -1
- package/web/assets/{chunk-LORZLZWG-B57uGw2N.js → chunk-SLDQ463B-CHY6e_bQ.js} +2 -2
- package/web/assets/{chunk-FWYVLQTC-BgDItRzJ.js → chunk-TCEHX7R3-CXPDEVbm.js} +1 -1
- package/web/assets/{chunk-224SPVON-B8gxtXpy.js → chunk-VQC2EELJ-Dc8fIy4R.js} +1 -1
- package/web/assets/chunk-VRZKL3EH-DB3KixTQ.js +1 -0
- package/web/assets/{chunk-A7VWPJGB-B4O3oQdQ.js → chunk-VTHDQ7BV-b7FsPQZO.js} +1 -1
- package/web/assets/chunk-VY2OSTJR-Dkgc3Brg.js +2 -0
- package/web/assets/chunk-WUBWJARI-7FwILJ3k.js +2 -0
- package/web/assets/{chunk-D6VWDJW2-BxcBdZ9c.js → chunk-YBMQ5JGJ-BSnyWZmd.js} +1 -1
- package/web/assets/chunk-YDMLL4PJ-IHhMngTz.js +2 -0
- package/web/assets/chunk-Z6V44ARX-BjCEsF0Q.js +62 -0
- package/web/assets/chunk-ZJJ7VQJP-Dz089b-K.js +321 -0
- package/web/assets/chunk-ZNLK7HRR-B0iFpmW4.js +1 -0
- package/web/assets/chunk-ZQN7UHIL-Cy7KAjQt.js +1 -0
- package/web/assets/{chunk-L5GCOVLC-CE2w8Nm_.js → chunk-ZS6VBONO-DBjJO0w9.js} +2 -2
- package/web/assets/{chunk-NV3KIAZN-5yvcpMiu.js → chunk-ZUNWM646-DNRJyNPe.js} +1 -1
- package/web/assets/classDiagram-FGAMPOII-C5Ibyode.js +1 -0
- package/web/assets/classDiagram-v2-AI5RJEK4-C5Ibyode.js +1 -0
- package/web/assets/{cose-bilkent-RZA4XIPR-BHpK4Crp.js → cose-bilkent-Q72C2OJ3-DMeFXnK8.js} +1 -1
- package/web/assets/cynefin-OW5HDTMX-6OCTWOGG-vlqakYcO.js +1 -0
- package/web/assets/{cynefinDiagram-TR7LZUCG-C3Iar9lZ.js → cynefinDiagram-2OOWUY4M-BY6DZkTt.js} +1 -1
- package/web/assets/dagre-MPVFI544-DWO70fy_.js +4 -0
- package/web/assets/diagram-AE4NWXFW-f7JRVRUL.js +24 -0
- package/web/assets/{diagram-L7DVE3PN-GIRyVUtt.js → diagram-BUJID5UG-BXZv1rCS.js} +2 -2
- package/web/assets/{diagram-JCD7PQ7C-DC5-9FRr.js → diagram-C44CZ5NI-CRNfvjCq.js} +1 -1
- package/web/assets/diagram-EYOLEXXS-DZOjKQVE.js +30 -0
- package/web/assets/diagram-P7B6PWOJ-D3SQmw3_.js +3 -0
- package/web/assets/{ebnfDiagram-DRHRQJWO-D8_CI4ZF.js → ebnfDiagram-FTPZ3PV6-jKWpIDN2.js} +1 -1
- package/web/assets/erDiagram-H3ERR26V-BqJntEuJ.js +99 -0
- package/web/assets/eventmodeling-NTZA5JFV-WKSWQHFS-Bq4FqtBL.js +1 -0
- package/web/assets/flowDiagram-YHGXBVSY-Dnlk2bEu.js +1 -0
- package/web/assets/ganttDiagram-RWFTB7ED-Bl6Y1K5T.js +292 -0
- package/web/assets/gitGraph-4MIJSDKK-JH2HKYUO-B3yc4GkH.js +1 -0
- package/web/assets/gitGraphDiagram-MAR6GKOP-CkNvsrdw.js +106 -0
- package/web/assets/{index-CJDpyH-n.css → index-C2_aej58.css} +1 -1
- package/web/assets/{index-DDRie6_8.js → index-Dj3vQOHK.js} +51 -51
- package/web/assets/info-A6RAGUB7-3TX3OFWW-BM3N5_Dv.js +1 -0
- package/web/assets/infoDiagram-LV547AFH-COkFutAf.js +2 -0
- package/web/assets/{ishikawaDiagram-4JDSWWDM-DmqWtjkl.js → ishikawaDiagram-PUJQGNDS-Bb8FylSR.js} +2 -2
- package/web/assets/{journeyDiagram-QUS3FAKT-XAzVzrQW.js → journeyDiagram-EW5QJT4W-BzoHUBhM.js} +4 -4
- package/web/assets/{kanban-definition-D4L7SQKK-YurRnmYn.js → kanban-definition-JSQERAZB-Uy2Pi0yQ.js} +4 -4
- package/web/assets/katex-CZ4GXH2S-C0Fcou7U.js +257 -0
- package/web/assets/{mindmap-definition-66QP5TD6-ChrWWnil.js → mindmap-definition-VBJCLQLM-B-CnOnt_.js} +3 -3
- package/web/assets/packet-AYTQ26CC-MKII6P3Y-Bd52ZE3V.js +1 -0
- package/web/assets/{pegDiagram-YKIO5C6U-QGeQLEq2.js → pegDiagram-7WILOQTJ-D9sneKXg.js} +1 -1
- package/web/assets/pie-WAS4IAKB-6B4OPMJ5-DW5Xy69Z.js +1 -0
- package/web/assets/pieDiagram-EFA7CBSB-Dx2NQofL.js +39 -0
- package/web/assets/{quadrantDiagram-VO5QLCXA-B7098wSc.js → quadrantDiagram-WARVYA7P-DPKL9_0A.js} +3 -3
- package/web/assets/radar-RG4KPBEZ-UPTR3XUL-CkzibT2h.js +1 -0
- package/web/assets/railroad-74A4TZTK-MEFUPFMS-D9zF-mDN.js +1 -0
- package/web/assets/railroad-abnf-HS5TGJTU-R5YG2S5D-ruacjUbX.js +1 -0
- package/web/assets/railroad-ebnf-LZEXJU2U-G5QEX2L6-S1zc5OiO.js +1 -0
- package/web/assets/railroad-peg-WCYAUIDC-H5I2ZRY2-Cbcr0XzY.js +1 -0
- package/web/assets/{railroadDiagram-M77LTMSB-AXu4vxk_.js → railroadDiagram-5NIQVNLQ-DsweTo14.js} +1 -1
- package/web/assets/{requirementDiagram-RASO5HTO-B-l8InpK.js → requirementDiagram-SXREGOKZ-CXwdNSVR.js} +4 -4
- package/web/assets/{sankeyDiagram-F32LOJ6L-Kd7zjJgX.js → sankeyDiagram-VV74M2VP-CA6jtP9P.js} +3 -3
- package/web/assets/{sequenceDiagram-URATNSBD-BlcdY9DS.js → sequenceDiagram-52ZFIFDL-k_5rEbzm.js} +15 -15
- package/web/assets/src-Df5C1Nz4.js +1 -0
- package/web/assets/stateDiagram-3QAKPIVI-BejHTf31.js +1 -0
- package/web/assets/stateDiagram-v2-HN2P4RDZ-BrfoRuOc.js +1 -0
- package/web/assets/swimlanes-QLVP42QD-CQSVO5D6.js +1 -0
- package/web/assets/swimlanesDiagram-JKPDBFCN-DrWB9kcD.js +8 -0
- package/web/assets/{timeline-definition-WJXWRH4I-DUfp1R3E.js → timeline-definition-GS45XAXW-C0Ks8rPP.js} +4 -4
- package/web/assets/treeView-Q6P3EWNA-ZRJGANNQ-DmKOCo6L.js +1 -0
- package/web/assets/treemap-WGGIJYW6-K64VN5AS-DO3xY92U.js +1 -0
- package/web/assets/{vennDiagram-K3VCMQLI-Bj-FN-XS.js → vennDiagram-QIQU2ZRJ-rgPiS837.js} +3 -3
- package/web/assets/wardley-WFR3VGLG-D67OWCCH-DiDPBNft.js +1 -0
- package/web/assets/wardleyDiagram-U6YNM66N-DRVr7SPi.js +78 -0
- package/web/assets/{xychartDiagram-5VRUVLCW-CK_rbSWE.js → xychartDiagram-XJAZEDNM-COtlZzYb.js} +3 -3
- package/web/index.html +19 -17
- package/web/assets/ProcessFlowModal-Badh2Pbg.js +0 -24
- package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +0 -1
- package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +0 -36
- package/web/assets/blockDiagram-54WLDVWM-Dg_hrRWE.js +0 -132
- package/web/assets/c4Diagram-X2LASM7V-CnhoT4aV.js +0 -10
- package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +0 -127
- package/web/assets/chunk-5VCL7Z4A-CQ-2dYWj.js +0 -1
- package/web/assets/chunk-6BELYETK-ChsYtfHW.js +0 -1
- package/web/assets/chunk-7CWYLC5S-DRgGkkpF.js +0 -2
- package/web/assets/chunk-7FYTHRHK-CsmYIswB.js +0 -32
- package/web/assets/chunk-KRXBNO2N-C-UNuKKf.js +0 -1
- package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +0 -321
- package/web/assets/chunk-LIEV3EAG-pyKGssV3.js +0 -1
- package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +0 -62
- package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +0 -10
- package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +0 -156
- package/web/assets/chunk-SZD42YQK-ijyKKVr1.js +0 -70
- package/web/assets/chunk-TFPGFQPA-Dj6a-0pC.js +0 -231
- package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +0 -2
- package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +0 -1
- package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +0 -1
- package/web/assets/chunk-WJBAP47W-BckNkuEN.js +0 -1
- package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +0 -1
- package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +0 -1
- package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +0 -1
- package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +0 -4
- package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +0 -30
- package/web/assets/diagram-KFBZAVDW-Dfmf_4ti.js +0 -3
- package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +0 -24
- package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +0 -85
- package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +0 -1
- package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +0 -1
- package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +0 -292
- package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +0 -1
- package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +0 -106
- package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +0 -1
- package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +0 -2
- package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +0 -257
- package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +0 -1
- package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +0 -1
- package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +0 -39
- package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +0 -1
- package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +0 -1
- package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +0 -1
- package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +0 -1
- package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +0 -1
- package/web/assets/src-C5sx_gMp.js +0 -1
- package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +0 -1
- package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +0 -1
- package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +0 -2
- package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +0 -8
- package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +0 -1
- package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +0 -1
- package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +0 -1
- package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +0 -78
- /package/web/assets/{sizeCapture-5GORAGP4-BEqQzsxs.js → sizeCapture-FGA5AGYP-BEqQzsxs.js} +0 -0
|
@@ -59,6 +59,12 @@ export declare const SUPPORTED_FTS_STEMMERS: ReadonlySet<string>;
|
|
|
59
59
|
export interface CreateSearchFTSIndexesOptions {
|
|
60
60
|
onIndexStart?: (table: string, indexName: string) => void;
|
|
61
61
|
onIndexReady?: (table: string, indexName: string) => void;
|
|
62
|
+
/**
|
|
63
|
+
* When set, only these node-table names are dropped/rebuilt (#3016).
|
|
64
|
+
* Omit to rebuild every configured FTS index (full analyze / deleted-file
|
|
65
|
+
* incremental / `--repair-fts`).
|
|
66
|
+
*/
|
|
67
|
+
tables?: ReadonlySet<string>;
|
|
62
68
|
}
|
|
63
69
|
/**
|
|
64
70
|
* Resolve + validate `GITNEXUS_FTS_STEMMER` once, up front at analyze startup,
|
|
@@ -98,7 +104,19 @@ export declare function getSearchFTSStemmer(): string;
|
|
|
98
104
|
* contract, and the same one-shared-`SHOW_INDEXES`-read purpose, as the gates in
|
|
99
105
|
* `lbug-adapter.ts`. Omit it to have the sweep read the catalog itself.
|
|
100
106
|
*/
|
|
101
|
-
export declare function dropSearchFTSIndexes(indexRows?: IndexCatalogSnapshot): Promise<void>;
|
|
107
|
+
export declare function dropSearchFTSIndexes(indexRows?: IndexCatalogSnapshot, tables?: ReadonlySet<string>): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* The configured FTS tables whose index the catalog proves is ABSENT right now.
|
|
110
|
+
*
|
|
111
|
+
* `undefined` means the catalog could not be read, which proves nothing — the
|
|
112
|
+
* same fail-closed reading the sweep above applies. Callers narrowing a rebuild
|
|
113
|
+
* to a subset of tables (#3016) must union this in, or must not narrow at all
|
|
114
|
+
* when it is `undefined`: a run that rebuilds only the tables it wrote leaves
|
|
115
|
+
* keyword search permanently degraded on every table whose index went missing
|
|
116
|
+
* earlier (a prior escalation drops all of them, and only the next full rebuild
|
|
117
|
+
* would ever put them back).
|
|
118
|
+
*/
|
|
119
|
+
export declare function missingSearchFTSIndexTables(indexRows?: IndexCatalogSnapshot): Promise<Set<string> | undefined>;
|
|
102
120
|
/** One configured index that could not be (re)built, and why. */
|
|
103
121
|
export interface FtsIndexBuildFailure {
|
|
104
122
|
table: string;
|
|
@@ -172,7 +172,7 @@ export function getSearchFTSStemmer() {
|
|
|
172
172
|
* contract, and the same one-shared-`SHOW_INDEXES`-read purpose, as the gates in
|
|
173
173
|
* `lbug-adapter.ts`. Omit it to have the sweep read the catalog itself.
|
|
174
174
|
*/
|
|
175
|
-
export async function dropSearchFTSIndexes(indexRows) {
|
|
175
|
+
export async function dropSearchFTSIndexes(indexRows, tables) {
|
|
176
176
|
// One catalog read for the whole sweep, decided PER CONFIGURED INDEX on
|
|
177
177
|
// IDENTITY (#2841 cleanup review). `undefined` = the catalog could not be
|
|
178
178
|
// read, which proves nothing — attempt every drop rather than skip a real one,
|
|
@@ -193,6 +193,8 @@ export async function dropSearchFTSIndexes(indexRows) {
|
|
|
193
193
|
// whether the sweep ran or not.
|
|
194
194
|
const rows = await resolveGateRows(indexRows);
|
|
195
195
|
for (const { table, indexName } of FTS_INDEXES) {
|
|
196
|
+
if (tables && !tables.has(table))
|
|
197
|
+
continue;
|
|
196
198
|
// Skip only what the catalog POSITIVELY proves absent. Without this, a
|
|
197
199
|
// machine whose FTS extension cannot load, analyzing a DB that never carried
|
|
198
200
|
// an FTS index, pays one failed `CALL DROP_FTS_INDEX` per configured table on
|
|
@@ -209,6 +211,29 @@ export async function dropSearchFTSIndexes(indexRows) {
|
|
|
209
211
|
await dropFTSIndex(table, indexName);
|
|
210
212
|
}
|
|
211
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* The configured FTS tables whose index the catalog proves is ABSENT right now.
|
|
216
|
+
*
|
|
217
|
+
* `undefined` means the catalog could not be read, which proves nothing — the
|
|
218
|
+
* same fail-closed reading the sweep above applies. Callers narrowing a rebuild
|
|
219
|
+
* to a subset of tables (#3016) must union this in, or must not narrow at all
|
|
220
|
+
* when it is `undefined`: a run that rebuilds only the tables it wrote leaves
|
|
221
|
+
* keyword search permanently degraded on every table whose index went missing
|
|
222
|
+
* earlier (a prior escalation drops all of them, and only the next full rebuild
|
|
223
|
+
* would ever put them back).
|
|
224
|
+
*/
|
|
225
|
+
export async function missingSearchFTSIndexTables(indexRows) {
|
|
226
|
+
const rows = await resolveGateRows(indexRows);
|
|
227
|
+
if (rows === undefined)
|
|
228
|
+
return undefined;
|
|
229
|
+
const missing = new Set();
|
|
230
|
+
for (const { table, indexName } of FTS_INDEXES) {
|
|
231
|
+
const present = rows.some((row) => indexRowTable(row) === table && indexRowName(row) === indexName);
|
|
232
|
+
if (!present)
|
|
233
|
+
missing.add(table);
|
|
234
|
+
}
|
|
235
|
+
return missing;
|
|
236
|
+
}
|
|
212
237
|
/**
|
|
213
238
|
* Build every configured FTS index, and keep going when one of them fails
|
|
214
239
|
* (#2889).
|
|
@@ -232,6 +257,8 @@ export async function createSearchFTSIndexes(options) {
|
|
|
232
257
|
const stemmer = getSearchFTSStemmer();
|
|
233
258
|
const failures = [];
|
|
234
259
|
for (const { table, indexName, properties } of FTS_INDEXES) {
|
|
260
|
+
if (options?.tables && !options.tables.has(table))
|
|
261
|
+
continue;
|
|
235
262
|
options?.onIndexStart?.(table, indexName);
|
|
236
263
|
// Drop first so the live `properties` always win. `createFTSIndex` is
|
|
237
264
|
// idempotent-by-name (skips when the index already exists), so without the
|
|
@@ -112,6 +112,22 @@ const SOURCES = {
|
|
|
112
112
|
'Likely cause: no prebuilt `.node` for this platform/architecture. ' +
|
|
113
113
|
`See ${ISSUES_URL}/2107.`,
|
|
114
114
|
},
|
|
115
|
+
// Zig grammar declares peerOptional `tree-sitter@^0.22.1` but its native
|
|
116
|
+
// binding is ABI-compatible with the bundled `tree-sitter@0.21.x` runtime
|
|
117
|
+
// (verified by load-time smoke test). The peer-dep mismatch is suppressed
|
|
118
|
+
// via the `overrides` block in package.json. Listed as `optional: true`
|
|
119
|
+
// because the package is in `optionalDependencies` — users on platforms
|
|
120
|
+
// without a prebuild may not have it — and `userSkippable` because it is
|
|
121
|
+
// a genuinely-optional grammar: `GITNEXUS_SKIP_OPTIONAL_GRAMMARS` must be
|
|
122
|
+
// able to disable it at analyze time like swift/dart/kotlin.
|
|
123
|
+
[SupportedLanguages.Zig]: {
|
|
124
|
+
load: () => _require('@tree-sitter-grammars/tree-sitter-zig'),
|
|
125
|
+
optional: true,
|
|
126
|
+
userSkippable: true,
|
|
127
|
+
unavailableNote: 'Zig parsing disabled: `@tree-sitter-grammars/tree-sitter-zig` is an ' +
|
|
128
|
+
'optionalDependency and is not installed (or its native binding failed ' +
|
|
129
|
+
'to load on this platform).',
|
|
130
|
+
},
|
|
115
131
|
};
|
|
116
132
|
export const listGrammarSources = () => Object.entries(SOURCES).map(([key, source]) => ({
|
|
117
133
|
key,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const UPDATE_CACHE_TTL_MS: number;
|
|
2
|
+
export declare const STRICT_UPDATE_VERSION: RegExp;
|
|
3
|
+
export declare const DEFAULT_UPDATE_REGISTRY = "https://registry.npmjs.org";
|
|
4
|
+
export interface UpdateCacheEntry {
|
|
5
|
+
lastCheckAt: string;
|
|
6
|
+
registry: string;
|
|
7
|
+
latestVersion?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ValidatedUpdateCache {
|
|
10
|
+
lastCheckAt: number;
|
|
11
|
+
latestVersion?: string;
|
|
12
|
+
stale: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Broad truthy parsing shared by the update-notifier guards. */
|
|
15
|
+
export declare function isTruthyEnv(value: string | undefined): boolean;
|
|
16
|
+
/** The update notifier is disabled by either opt-out env or a CI environment. */
|
|
17
|
+
export declare function updateNotifierOptedOut(env: NodeJS.ProcessEnv): boolean;
|
|
18
|
+
/** Freshness gate for the 24h TTL; future-dated timestamps are stale. */
|
|
19
|
+
export declare function isUpdateCacheFresh(lastCheckAt: string, now: number): boolean;
|
|
20
|
+
/** Strict x.y.z numeric comparison. Invalid or prerelease versions are silent. */
|
|
21
|
+
export declare function isNewerVersion(installedVersion: string, latestVersion: string): boolean;
|
|
22
|
+
export declare function normalizedUpdateRegistry(env?: NodeJS.ProcessEnv): {
|
|
23
|
+
identity: string;
|
|
24
|
+
packageUrl: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function updateCheckCachePath(env?: NodeJS.ProcessEnv): string;
|
|
27
|
+
export declare function updateCheckLockPath(env?: NodeJS.ProcessEnv): string;
|
|
28
|
+
/**
|
|
29
|
+
* Best-effort synchronous probe: is a refresh plausibly in flight? Used to
|
|
30
|
+
* coalesce detached refresh spawns. A dead same-host owner returns false so
|
|
31
|
+
* the spawned child can reclaim the stale lock; a foreign-host owner returns
|
|
32
|
+
* false and lets the child's full lock logic decide.
|
|
33
|
+
*/
|
|
34
|
+
export declare function updateRefreshInProgress(env?: NodeJS.ProcessEnv): boolean;
|
|
35
|
+
export declare function parseUpdateCache(raw: string, registry: string): UpdateCacheEntry | null;
|
|
36
|
+
export declare function readValidatedUpdateCacheSync(options?: {
|
|
37
|
+
env?: NodeJS.ProcessEnv;
|
|
38
|
+
now?: number;
|
|
39
|
+
}): ValidatedUpdateCache | null;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getGlobalDir } from '../storage/global-dir.js';
|
|
5
|
+
import { isProcessAlive, readProcessStartTime } from '../utils/process-identity.js';
|
|
6
|
+
export const UPDATE_CACHE_TTL_MS = 24 * 60 * 60 * 1_000;
|
|
7
|
+
export const STRICT_UPDATE_VERSION = /^\d+\.\d+\.\d+$/;
|
|
8
|
+
export const DEFAULT_UPDATE_REGISTRY = 'https://registry.npmjs.org';
|
|
9
|
+
/** Broad truthy parsing shared by the update-notifier guards. */
|
|
10
|
+
export function isTruthyEnv(value) {
|
|
11
|
+
if (!value)
|
|
12
|
+
return false;
|
|
13
|
+
return !['', '0', 'false', 'no', 'off'].includes(value.toLowerCase());
|
|
14
|
+
}
|
|
15
|
+
/** The update notifier is disabled by either opt-out env or a CI environment. */
|
|
16
|
+
export function updateNotifierOptedOut(env) {
|
|
17
|
+
return (isTruthyEnv(env.GITNEXUS_NO_UPDATE_NOTIFIER) ||
|
|
18
|
+
isTruthyEnv(env.NO_UPDATE_NOTIFIER) ||
|
|
19
|
+
isTruthyEnv(env.CI));
|
|
20
|
+
}
|
|
21
|
+
/** Freshness gate for the 24h TTL; future-dated timestamps are stale. */
|
|
22
|
+
export function isUpdateCacheFresh(lastCheckAt, now) {
|
|
23
|
+
const checkedAt = Date.parse(lastCheckAt);
|
|
24
|
+
return checkedAt <= now && now - checkedAt < UPDATE_CACHE_TTL_MS;
|
|
25
|
+
}
|
|
26
|
+
/** Strict x.y.z numeric comparison. Invalid or prerelease versions are silent. */
|
|
27
|
+
export function isNewerVersion(installedVersion, latestVersion) {
|
|
28
|
+
if (!STRICT_UPDATE_VERSION.test(installedVersion) || !STRICT_UPDATE_VERSION.test(latestVersion)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const installed = installedVersion.split('.').map(BigInt);
|
|
32
|
+
const latest = latestVersion.split('.').map(BigInt);
|
|
33
|
+
for (let index = 0; index < 3; index += 1) {
|
|
34
|
+
if (latest[index] !== installed[index])
|
|
35
|
+
return latest[index] > installed[index];
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
let registryMemo;
|
|
40
|
+
export function normalizedUpdateRegistry(env = process.env) {
|
|
41
|
+
const key = env.npm_config_registry ?? '';
|
|
42
|
+
if (registryMemo?.key === key)
|
|
43
|
+
return registryMemo.value;
|
|
44
|
+
const value = buildUpdateRegistry(key);
|
|
45
|
+
registryMemo = { key, value };
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function buildUpdateRegistry(rawRegistry) {
|
|
49
|
+
const parsed = new URL(rawRegistry || DEFAULT_UPDATE_REGISTRY);
|
|
50
|
+
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
|
|
51
|
+
throw new Error('Unsupported npm registry protocol');
|
|
52
|
+
}
|
|
53
|
+
if (parsed.search || parsed.hash) {
|
|
54
|
+
throw new Error('Registry URL cannot contain query or fragment');
|
|
55
|
+
}
|
|
56
|
+
parsed.username = '';
|
|
57
|
+
parsed.password = '';
|
|
58
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, '') || '/';
|
|
59
|
+
const pathname = parsed.pathname === '/' ? '' : parsed.pathname;
|
|
60
|
+
const identity = `${parsed.protocol}//${parsed.host}${pathname}`;
|
|
61
|
+
// `/<pkg>/latest` is the small dist-tag document. The full packument at
|
|
62
|
+
// `/<pkg>` is multi-megabyte on this package and cannot fit the fetch cap.
|
|
63
|
+
const packagePath = `${pathname}/gitnexus/latest`.replace(/\/{2,}/g, '/');
|
|
64
|
+
return { identity, packageUrl: `${parsed.protocol}//${parsed.host}${packagePath}` };
|
|
65
|
+
}
|
|
66
|
+
export function updateCheckCachePath(env = process.env) {
|
|
67
|
+
return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.json');
|
|
68
|
+
}
|
|
69
|
+
export function updateCheckLockPath(env = process.env) {
|
|
70
|
+
return path.join(env.GITNEXUS_HOME || getGlobalDir(), 'update-check.lock');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Best-effort synchronous probe: is a refresh plausibly in flight? Used to
|
|
74
|
+
* coalesce detached refresh spawns. A dead same-host owner returns false so
|
|
75
|
+
* the spawned child can reclaim the stale lock; a foreign-host owner returns
|
|
76
|
+
* false and lets the child's full lock logic decide.
|
|
77
|
+
*/
|
|
78
|
+
export function updateRefreshInProgress(env = process.env) {
|
|
79
|
+
try {
|
|
80
|
+
const owner = JSON.parse(fs.readFileSync(updateCheckLockPath(env), 'utf8'));
|
|
81
|
+
if (typeof owner.pid !== 'number' || owner.pid <= 0)
|
|
82
|
+
return false;
|
|
83
|
+
if (owner.hostname !== os.hostname())
|
|
84
|
+
return false;
|
|
85
|
+
if (!isProcessAlive(owner.pid))
|
|
86
|
+
return false;
|
|
87
|
+
// Same rule as acquireFileLock: a live PID with a different start time is
|
|
88
|
+
// reuse, not the lock owner. Unreadable start time stays conservative
|
|
89
|
+
// (treat as in progress) so we don't spawn a racing child.
|
|
90
|
+
if (typeof owner.processStartTime === 'string' && owner.processStartTime) {
|
|
91
|
+
const currentStartTime = readProcessStartTime(owner.pid);
|
|
92
|
+
if (currentStartTime && currentStartTime !== owner.processStartTime)
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function parseUpdateCache(raw, registry) {
|
|
102
|
+
try {
|
|
103
|
+
const parsed = JSON.parse(raw);
|
|
104
|
+
if (typeof parsed.lastCheckAt !== 'string' ||
|
|
105
|
+
!Number.isFinite(Date.parse(parsed.lastCheckAt)) ||
|
|
106
|
+
parsed.registry !== registry ||
|
|
107
|
+
(parsed.latestVersion !== undefined &&
|
|
108
|
+
(typeof parsed.latestVersion !== 'string' ||
|
|
109
|
+
!STRICT_UPDATE_VERSION.test(parsed.latestVersion)))) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
lastCheckAt: parsed.lastCheckAt,
|
|
114
|
+
registry: parsed.registry,
|
|
115
|
+
...(parsed.latestVersion === undefined ? {} : { latestVersion: parsed.latestVersion }),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function readValidatedUpdateCacheSync(options = {}) {
|
|
123
|
+
try {
|
|
124
|
+
const env = options.env ?? process.env;
|
|
125
|
+
const registry = normalizedUpdateRegistry(env);
|
|
126
|
+
const raw = fs.readFileSync(updateCheckCachePath(env), 'utf8');
|
|
127
|
+
const entry = parseUpdateCache(raw, registry.identity);
|
|
128
|
+
if (!entry)
|
|
129
|
+
return null;
|
|
130
|
+
const lastCheckAt = Date.parse(entry.lastCheckAt);
|
|
131
|
+
const now = options.now ?? Date.now();
|
|
132
|
+
return {
|
|
133
|
+
lastCheckAt,
|
|
134
|
+
...(entry.latestVersion === undefined ? {} : { latestVersion: entry.latestVersion }),
|
|
135
|
+
stale: !isUpdateCacheFresh(entry.lastCheckAt, now),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface UpdateState {
|
|
2
|
+
updateAvailable: boolean;
|
|
3
|
+
latestVersion?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface UpdateCheckOptions {
|
|
6
|
+
/** Test/adapter override; omitted means classify process.argv[1]. */
|
|
7
|
+
eligible?: boolean;
|
|
8
|
+
/** Test override; omitted means this package's installed version. */
|
|
9
|
+
installedVersion?: string;
|
|
10
|
+
/** Test override in epoch milliseconds. */
|
|
11
|
+
now?: number;
|
|
12
|
+
/** Cache-only consumers can suppress stale-while-revalidate. */
|
|
13
|
+
refreshIfStale?: boolean;
|
|
14
|
+
/** Explicit `gitnexus update`: check even when CI/opt-out env is set. */
|
|
15
|
+
ignoreOptOut?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateRefreshSchedulerOptions extends Omit<UpdateCheckOptions, 'now' | 'refreshIfStale'> {
|
|
18
|
+
now?: () => number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Read update state cache-first. Every invalid/missing/stale cache starts one
|
|
22
|
+
* catch-isolated refresh unless the caller explicitly requests cache-only.
|
|
23
|
+
*/
|
|
24
|
+
export declare function evaluate(options?: UpdateCheckOptions): Promise<UpdateState | null>;
|
|
25
|
+
/** Run one locked, fail-open registry refresh. */
|
|
26
|
+
export declare function refresh(options?: UpdateCheckOptions): Promise<UpdateState | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Start an immediate evaluation and repeat on the cache TTL cadence. Timers
|
|
29
|
+
* never keep the process alive; refresh() supplies process-wide single-flight.
|
|
30
|
+
*/
|
|
31
|
+
export declare function armUpdateRefreshScheduler(onState: (state: UpdateState | null) => void, options?: UpdateRefreshSchedulerOptions): () => void;
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { getGlobalDir } from '../storage/global-dir.js';
|
|
3
|
+
import { writeFileAtomic } from '../storage/fs-atomic.js';
|
|
4
|
+
import { acquireFileLock, FileLockBusyError } from '../storage/file-lock.js';
|
|
5
|
+
import { validateGitUrl } from './net/url-guard.js';
|
|
6
|
+
import { updateEligibleInstall } from './install-context.js';
|
|
7
|
+
import { createLogger } from './logger.js';
|
|
8
|
+
import { packageVersion } from './package-version.js';
|
|
9
|
+
import { isNewerVersion, isUpdateCacheFresh, normalizedUpdateRegistry, parseUpdateCache, STRICT_UPDATE_VERSION, UPDATE_CACHE_TTL_MS, updateCheckCachePath, updateCheckLockPath, updateNotifierOptedOut, } from './update-cache.js';
|
|
10
|
+
const FETCH_TIMEOUT_MS = 3_000;
|
|
11
|
+
const MAX_RESPONSE_BYTES = 64 * 1024;
|
|
12
|
+
const MAX_REDIRECTS = 5;
|
|
13
|
+
/** Backoff when refresh cannot publish (lock-busy or still-stale cache). */
|
|
14
|
+
const LOCK_BUSY_RETRY_MIN_MS = 30_000;
|
|
15
|
+
const LOCK_BUSY_RETRY_JITTER_MS = 30_000;
|
|
16
|
+
const updateLogger = createLogger('update-check');
|
|
17
|
+
function defaultInstalledVersion() {
|
|
18
|
+
return packageVersion();
|
|
19
|
+
}
|
|
20
|
+
function nextSchedulerDelay(entry, now) {
|
|
21
|
+
if (entry && isUpdateCacheFresh(entry.lastCheckAt, now)) {
|
|
22
|
+
return Math.max(1, Date.parse(entry.lastCheckAt) + UPDATE_CACHE_TTL_MS - now);
|
|
23
|
+
}
|
|
24
|
+
// Missing, future-dated, or still stale after a lock-busy skip: back off
|
|
25
|
+
// from now instead of deriving 1ms from a past-due timestamp.
|
|
26
|
+
return LOCK_BUSY_RETRY_MIN_MS + Math.floor(Math.random() * LOCK_BUSY_RETRY_JITTER_MS);
|
|
27
|
+
}
|
|
28
|
+
function isOptedOut() {
|
|
29
|
+
return updateNotifierOptedOut(process.env);
|
|
30
|
+
}
|
|
31
|
+
async function isEligible(override) {
|
|
32
|
+
return override ?? (await updateEligibleInstall());
|
|
33
|
+
}
|
|
34
|
+
function cacheFile() {
|
|
35
|
+
return updateCheckCachePath();
|
|
36
|
+
}
|
|
37
|
+
function lockFile() {
|
|
38
|
+
return updateCheckLockPath();
|
|
39
|
+
}
|
|
40
|
+
function normalizedRegistry() {
|
|
41
|
+
const registry = normalizedUpdateRegistry();
|
|
42
|
+
validateGitUrl(registry.packageUrl);
|
|
43
|
+
return registry;
|
|
44
|
+
}
|
|
45
|
+
async function readCache(registry) {
|
|
46
|
+
try {
|
|
47
|
+
return parseUpdateCache(await fs.readFile(cacheFile(), 'utf8'), registry);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function stateFrom(entry, installedVersion) {
|
|
54
|
+
return {
|
|
55
|
+
updateAvailable: entry.latestVersion !== undefined && isNewerVersion(installedVersion, entry.latestVersion),
|
|
56
|
+
...(entry.latestVersion === undefined ? {} : { latestVersion: entry.latestVersion }),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function installedVersionOf(options) {
|
|
60
|
+
return options.installedVersion ?? defaultInstalledVersion();
|
|
61
|
+
}
|
|
62
|
+
async function isNotifierActive(options = {}) {
|
|
63
|
+
return (options.ignoreOptOut === true || !isOptedOut()) && (await isEligible(options.eligible));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read update state cache-first. Every invalid/missing/stale cache starts one
|
|
67
|
+
* catch-isolated refresh unless the caller explicitly requests cache-only.
|
|
68
|
+
*/
|
|
69
|
+
export async function evaluate(options = {}) {
|
|
70
|
+
try {
|
|
71
|
+
if (!(await isNotifierActive(options)))
|
|
72
|
+
return null;
|
|
73
|
+
const registry = normalizedRegistry();
|
|
74
|
+
const now = options.now ?? Date.now();
|
|
75
|
+
const entry = await readCache(registry.identity);
|
|
76
|
+
if ((!entry || !isUpdateCacheFresh(entry.lastCheckAt, now)) &&
|
|
77
|
+
options.refreshIfStale !== false) {
|
|
78
|
+
void refresh(options).catch(() => { });
|
|
79
|
+
}
|
|
80
|
+
if (!entry)
|
|
81
|
+
return null;
|
|
82
|
+
return stateFrom(entry, installedVersionOf(options));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function readResponseBody(response) {
|
|
89
|
+
const advertised = Number(response.headers.get('content-length'));
|
|
90
|
+
if (Number.isFinite(advertised) && advertised > MAX_RESPONSE_BYTES) {
|
|
91
|
+
await response.body?.cancel().catch(() => { });
|
|
92
|
+
throw new Error('Registry response too large');
|
|
93
|
+
}
|
|
94
|
+
if (!response.body)
|
|
95
|
+
return '';
|
|
96
|
+
const reader = response.body.getReader();
|
|
97
|
+
const chunks = [];
|
|
98
|
+
let bytes = 0;
|
|
99
|
+
try {
|
|
100
|
+
for (;;) {
|
|
101
|
+
const { done, value } = await reader.read();
|
|
102
|
+
if (done)
|
|
103
|
+
break;
|
|
104
|
+
bytes += value.byteLength;
|
|
105
|
+
if (bytes > MAX_RESPONSE_BYTES)
|
|
106
|
+
throw new Error('Registry response too large');
|
|
107
|
+
chunks.push(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
if (bytes > MAX_RESPONSE_BYTES)
|
|
112
|
+
await reader.cancel().catch(() => { });
|
|
113
|
+
reader.releaseLock();
|
|
114
|
+
}
|
|
115
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
116
|
+
}
|
|
117
|
+
function sanitizedHttpUrl(input, base) {
|
|
118
|
+
const parsed = new URL(input, base);
|
|
119
|
+
parsed.username = '';
|
|
120
|
+
parsed.password = '';
|
|
121
|
+
validateGitUrl(parsed.toString());
|
|
122
|
+
return parsed;
|
|
123
|
+
}
|
|
124
|
+
async function fetchLatest(packageUrl) {
|
|
125
|
+
let url = sanitizedHttpUrl(packageUrl);
|
|
126
|
+
for (let redirects = 0;; redirects += 1) {
|
|
127
|
+
const response = await fetch(url.toString(), {
|
|
128
|
+
method: 'GET',
|
|
129
|
+
redirect: 'manual',
|
|
130
|
+
headers: { accept: 'application/json' },
|
|
131
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
132
|
+
});
|
|
133
|
+
if (response.status >= 300 && response.status < 400) {
|
|
134
|
+
if (redirects >= MAX_REDIRECTS)
|
|
135
|
+
throw new Error('Too many registry redirects');
|
|
136
|
+
const location = response.headers.get('location');
|
|
137
|
+
await response.body?.cancel().catch(() => { });
|
|
138
|
+
if (!location)
|
|
139
|
+
throw new Error('Registry redirect missing location');
|
|
140
|
+
url = sanitizedHttpUrl(location, url.toString());
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
await response.body?.cancel().catch(() => { });
|
|
145
|
+
throw new Error(`Registry returned ${response.status}`);
|
|
146
|
+
}
|
|
147
|
+
const parsed = JSON.parse(await readResponseBody(response));
|
|
148
|
+
const latest = (typeof parsed.version === 'string' ? parsed.version : undefined) ??
|
|
149
|
+
(typeof parsed['dist-tags']?.latest === 'string' ? parsed['dist-tags'].latest : undefined);
|
|
150
|
+
if (typeof latest !== 'string' || !STRICT_UPDATE_VERSION.test(latest)) {
|
|
151
|
+
throw new Error('Registry latest version is invalid');
|
|
152
|
+
}
|
|
153
|
+
return latest;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function publishMonotonically(entry, attemptStartedAt) {
|
|
157
|
+
const current = await readCache(entry.registry);
|
|
158
|
+
const currentAt = current ? Date.parse(current.lastCheckAt) : Number.NaN;
|
|
159
|
+
// A later in-the-past write wins. Future-dated entries (wall-clock) are
|
|
160
|
+
// clock-skew poison and must stay replaceable so a later holder can repair them.
|
|
161
|
+
if (Number.isFinite(currentAt) && currentAt <= Date.now() && currentAt > attemptStartedAt) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
await fs.mkdir(getGlobalDir(), { recursive: true });
|
|
165
|
+
await writeFileAtomic(cacheFile(), `${JSON.stringify(entry)}\n`, 1);
|
|
166
|
+
}
|
|
167
|
+
let refreshInFlight = null;
|
|
168
|
+
/** Run one locked, fail-open registry refresh. */
|
|
169
|
+
export function refresh(options = {}) {
|
|
170
|
+
if (refreshInFlight)
|
|
171
|
+
return refreshInFlight;
|
|
172
|
+
const run = async () => {
|
|
173
|
+
let release;
|
|
174
|
+
try {
|
|
175
|
+
if (!(await isNotifierActive(options)))
|
|
176
|
+
return null;
|
|
177
|
+
const registry = normalizedRegistry();
|
|
178
|
+
const attemptStartedAt = options.now ?? Date.now();
|
|
179
|
+
try {
|
|
180
|
+
release = await acquireFileLock(lockFile(), { retries: 0 });
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error instanceof FileLockBusyError)
|
|
184
|
+
return null;
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
let fetched;
|
|
188
|
+
try {
|
|
189
|
+
fetched = await fetchLatest(registry.packageUrl);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Negative entries enforce the same TTL on offline/authenticated-only
|
|
193
|
+
// registries as successful checks. A known same-identity latestVersion
|
|
194
|
+
// must survive a later failed refresh so notices do not go silent
|
|
195
|
+
// for a day; only a first-ever miss stays version-less.
|
|
196
|
+
}
|
|
197
|
+
const latestVersion = fetched ?? (await readCache(registry.identity))?.latestVersion;
|
|
198
|
+
const entry = {
|
|
199
|
+
lastCheckAt: new Date(attemptStartedAt).toISOString(),
|
|
200
|
+
registry: registry.identity,
|
|
201
|
+
...(latestVersion === undefined ? {} : { latestVersion }),
|
|
202
|
+
};
|
|
203
|
+
await publishMonotonically(entry, attemptStartedAt);
|
|
204
|
+
// Live fetch failed: keep the on-disk pin for notices, but do not
|
|
205
|
+
// return it as a confirmed refresh so `gitnexus update` cannot install
|
|
206
|
+
// from an unconfirmed cache.
|
|
207
|
+
if (fetched === undefined)
|
|
208
|
+
return null;
|
|
209
|
+
return stateFrom(entry, installedVersionOf(options));
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
updateLogger.debug({ code: error.code }, 'Update check failed open');
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
if (release)
|
|
217
|
+
await release().catch(() => { });
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
refreshInFlight = run().finally(() => {
|
|
221
|
+
refreshInFlight = null;
|
|
222
|
+
});
|
|
223
|
+
return refreshInFlight;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Start an immediate evaluation and repeat on the cache TTL cadence. Timers
|
|
227
|
+
* never keep the process alive; refresh() supplies process-wide single-flight.
|
|
228
|
+
*/
|
|
229
|
+
export function armUpdateRefreshScheduler(onState, options = {}) {
|
|
230
|
+
let stopped = false;
|
|
231
|
+
let timer;
|
|
232
|
+
const cycle = async () => {
|
|
233
|
+
if (stopped)
|
|
234
|
+
return;
|
|
235
|
+
const now = options.now?.() ?? Date.now();
|
|
236
|
+
let entry = null;
|
|
237
|
+
try {
|
|
238
|
+
const registry = normalizedRegistry();
|
|
239
|
+
entry = await readCache(registry.identity);
|
|
240
|
+
if (!entry || !isUpdateCacheFresh(entry.lastCheckAt, now)) {
|
|
241
|
+
await refresh({ ...options, now });
|
|
242
|
+
entry = await readCache(registry.identity);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// The public scheduler shares the service's fail-open contract.
|
|
247
|
+
}
|
|
248
|
+
// Derive state from the entry already read above; a full evaluate() here
|
|
249
|
+
// would re-run guards and re-read the cache on every tick.
|
|
250
|
+
let state = null;
|
|
251
|
+
try {
|
|
252
|
+
state =
|
|
253
|
+
!entry || !(await isNotifierActive(options))
|
|
254
|
+
? null
|
|
255
|
+
: stateFrom(entry, installedVersionOf(options));
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
state = null;
|
|
259
|
+
}
|
|
260
|
+
if (!stopped)
|
|
261
|
+
onState(state);
|
|
262
|
+
if (!stopped) {
|
|
263
|
+
timer = setTimeout(() => void cycle(), nextSchedulerDelay(entry, now));
|
|
264
|
+
timer.unref();
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
timer = setTimeout(() => void cycle(), 0);
|
|
268
|
+
timer.unref();
|
|
269
|
+
return () => {
|
|
270
|
+
stopped = true;
|
|
271
|
+
if (timer)
|
|
272
|
+
clearTimeout(timer);
|
|
273
|
+
};
|
|
274
|
+
}
|
|
@@ -5,14 +5,12 @@
|
|
|
5
5
|
* Supports multiple indexed repositories via a global registry.
|
|
6
6
|
* LadybugDB connections are opened lazily per repo on first query.
|
|
7
7
|
*/
|
|
8
|
+
import { isTestFilePath } from '../../core/ingestion/utils/test-file-path.js';
|
|
8
9
|
import { type RegistryEntry, type BranchSummary } from '../../storage/repo-manager.js';
|
|
9
10
|
import { GroupService } from '../../core/group/service.js';
|
|
10
11
|
import { type StalenessInfo } from '../../core/git-staleness.js';
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
* Matches common test file patterns across all supported languages.
|
|
14
|
-
*/
|
|
15
|
-
export declare function isTestFilePath(filePath: string | null | undefined): boolean;
|
|
12
|
+
/** Shared predicate; re-exported so MCP importers keep the old public name. */
|
|
13
|
+
export { isTestFilePath };
|
|
16
14
|
/** Valid LadybugDB node labels for safe Cypher query construction */
|
|
17
15
|
export declare const VALID_NODE_LABELS: Set<string>;
|
|
18
16
|
/** Valid relation types for impact analysis filtering */
|
|
@@ -371,10 +369,26 @@ export declare class LocalBackend {
|
|
|
371
369
|
* - If only 1 repo, use it
|
|
372
370
|
* - If 0 or multiple without param, throw with helpful message
|
|
373
371
|
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
372
|
+
* Re-reads the registry before an omitted implicit target or after an
|
|
373
|
+
* explicit miss, so long-running servers see newly indexed repositories.
|
|
376
374
|
*/
|
|
377
375
|
resolveRepo(repoParam?: string, branch?: string): Promise<RepoHandle>;
|
|
376
|
+
/**
|
|
377
|
+
* Internal resolver variant for CLI/MCP tool routing and discovery.
|
|
378
|
+
* - If repoParam is given, match by name or path
|
|
379
|
+
* - If only 1 repo, use it
|
|
380
|
+
* - If multiple repos exist and repoParam is omitted, callers may opt in to
|
|
381
|
+
* the registered repo containing process.cwd()
|
|
382
|
+
* - If 0 repos exist, or cwd cannot disambiguate multiple repos, throw
|
|
383
|
+
*
|
|
384
|
+
* Omitted-repo resolution re-reads the registry before accepting any
|
|
385
|
+
* implicit target, including a cached singleton. A caller that just obtained
|
|
386
|
+
* a fresh registry snapshot may disable that refresh explicitly.
|
|
387
|
+
*/
|
|
388
|
+
selectToolRepository(repoParam?: string, branch?: string, options?: {
|
|
389
|
+
allowCwdDefault?: boolean;
|
|
390
|
+
refreshRegistry?: boolean;
|
|
391
|
+
}): Promise<RepoHandle>;
|
|
378
392
|
/**
|
|
379
393
|
* Re-point a resolved repo handle at a specific branch index (#2106).
|
|
380
394
|
*
|
|
@@ -409,12 +423,13 @@ export declare class LocalBackend {
|
|
|
409
423
|
*/
|
|
410
424
|
private resolveRepoFromCache;
|
|
411
425
|
/**
|
|
412
|
-
*
|
|
426
|
+
* Match process.cwd() against indexed repositories.
|
|
413
427
|
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
428
|
+
* Explicit duplicate aliases use exact Git-root matching only. Omitted
|
|
429
|
+
* read-only calls opt into deepest containing-path selection. In that mode a
|
|
430
|
+
* candidate must not sit above cwd's Git root, so an unindexed nested checkout
|
|
431
|
+
* cannot fall through to an indexed ancestor. The `.git` ancestor fallback
|
|
432
|
+
* preserves that boundary when the git executable is unavailable.
|
|
418
433
|
*/
|
|
419
434
|
private pickRepoHandleForCwd;
|
|
420
435
|
private handleToRegistryEntry;
|
|
@@ -842,4 +857,3 @@ export declare class LocalBackend {
|
|
|
842
857
|
queryProcessDetail(name: string, repoName?: string): Promise<any>;
|
|
843
858
|
disconnect(): Promise<void>;
|
|
844
859
|
}
|
|
845
|
-
export {};
|