weavatrix 0.3.13 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/README.md +231 -199
- package/bin/native/darwin-arm64/weavatrix +0 -0
- package/bin/native/darwin-x64/weavatrix +0 -0
- package/bin/native/linux-arm64/weavatrix +0 -0
- package/bin/native/linux-x64/weavatrix +0 -0
- package/bin/native/win32-arm64/weavatrix.exe +0 -0
- package/bin/native/win32-x64/weavatrix.exe +0 -0
- package/bin/resolve-binary.mjs +73 -0
- package/bin/run-native.mjs +26 -0
- package/bin/weavatrix-mcp.mjs +7 -6
- package/bin/weavatrix.mjs +5 -0
- package/package.json +8 -65
- package/skill/SKILL.md +62 -374
- package/skill/agents/openai.yaml +4 -0
- package/skill/references/tool-routing.md +45 -0
- package/SECURITY.md +0 -101
- package/docs/adr/0001-v0.3-offline-online-split.md +0 -60
- package/docs/agent-task-benchmark.md +0 -58
- package/docs/releases/v0.2.19.md +0 -33
- package/docs/releases/v0.3.0.md +0 -43
- package/docs/releases/v0.3.1.md +0 -30
- package/docs/releases/v0.3.10.md +0 -76
- package/docs/releases/v0.3.11.md +0 -55
- package/docs/releases/v0.3.12.md +0 -44
- package/docs/releases/v0.3.13.md +0 -34
- package/docs/releases/v0.3.2.md +0 -15
- package/docs/releases/v0.3.3.md +0 -25
- package/docs/releases/v0.3.4.md +0 -40
- package/docs/releases/v0.3.5.md +0 -50
- package/docs/releases/v0.3.6.md +0 -44
- package/docs/releases/v0.3.7.md +0 -37
- package/docs/releases/v0.3.8.md +0 -21
- package/docs/releases/v0.3.9.md +0 -36
- package/scripts/run-agent-task-benchmark.mjs +0 -118
- package/src/analysis/allowed-test-runner.js +0 -70
- package/src/analysis/architecture/contract-graph.js +0 -119
- package/src/analysis/architecture/contract-schema.js +0 -110
- package/src/analysis/architecture/contract-storage.js +0 -35
- package/src/analysis/architecture/contract-verification.js +0 -168
- package/src/analysis/architecture-contract.js +0 -16
- package/src/analysis/audit-debt.js +0 -94
- package/src/analysis/audit-extensions.js +0 -60
- package/src/analysis/cargo-dependency-evidence.js +0 -108
- package/src/analysis/cargo-manifests.js +0 -81
- package/src/analysis/change-classification/diff-parser.js +0 -103
- package/src/analysis/change-classification/options.js +0 -40
- package/src/analysis/change-classification/symbol-classifier.js +0 -177
- package/src/analysis/change-classification.js +0 -188
- package/src/analysis/coverage-reports.js +0 -235
- package/src/analysis/cycle-route.js +0 -14
- package/src/analysis/data-flow-evidence.js +0 -114
- package/src/analysis/dead-check.js +0 -300
- package/src/analysis/dead-code-review/candidates.js +0 -194
- package/src/analysis/dead-code-review/policy.js +0 -23
- package/src/analysis/dead-code-review.js +0 -119
- package/src/analysis/dep-check-ecosystems.js +0 -205
- package/src/analysis/dep-check.js +0 -290
- package/src/analysis/dep-rules.js +0 -10
- package/src/analysis/dependency/conventions.js +0 -16
- package/src/analysis/dependency/scoped-dependencies.js +0 -51
- package/src/analysis/dependency/source-references.js +0 -21
- package/src/analysis/duplicate-groups.js +0 -104
- package/src/analysis/duplicates-worker.js +0 -11
- package/src/analysis/duplicates.compute.js +0 -269
- package/src/analysis/duplicates.js +0 -15
- package/src/analysis/duplicates.run.js +0 -52
- package/src/analysis/duplicates.tokenize.js +0 -199
- package/src/analysis/endpoints/common.js +0 -62
- package/src/analysis/endpoints/extract.js +0 -107
- package/src/analysis/endpoints/inventory.js +0 -84
- package/src/analysis/endpoints/mounts.js +0 -129
- package/src/analysis/endpoints-java.js +0 -260
- package/src/analysis/endpoints-rust.js +0 -124
- package/src/analysis/endpoints.js +0 -3
- package/src/analysis/findings.js +0 -70
- package/src/analysis/git-history/analytics.js +0 -177
- package/src/analysis/git-history/collector.js +0 -67
- package/src/analysis/git-history/options.js +0 -66
- package/src/analysis/git-history.js +0 -143
- package/src/analysis/git-ref-graph.js +0 -76
- package/src/analysis/go-dependency-evidence.js +0 -62
- package/src/analysis/graph-analysis.aggregate.js +0 -295
- package/src/analysis/graph-analysis.edges.js +0 -24
- package/src/analysis/graph-analysis.js +0 -7
- package/src/analysis/graph-analysis.refs.js +0 -154
- package/src/analysis/graph-analysis.summaries.js +0 -65
- package/src/analysis/health-capabilities.js +0 -83
- package/src/analysis/hot-path-review.js +0 -266
- package/src/analysis/http-contract-wrappers.js +0 -241
- package/src/analysis/http-contracts/analysis.js +0 -179
- package/src/analysis/http-contracts/client-call-detection.js +0 -82
- package/src/analysis/http-contracts/client-call-parser.js +0 -273
- package/src/analysis/http-contracts/graph-context.js +0 -143
- package/src/analysis/http-contracts/matching.js +0 -61
- package/src/analysis/http-contracts/shared.js +0 -85
- package/src/analysis/http-contracts.js +0 -6
- package/src/analysis/internal-audit/dependency-health.js +0 -113
- package/src/analysis/internal-audit/python-manifests.js +0 -78
- package/src/analysis/internal-audit/repo-files.js +0 -50
- package/src/analysis/internal-audit/supply-chain.js +0 -149
- package/src/analysis/internal-audit.collect.js +0 -213
- package/src/analysis/internal-audit.js +0 -9
- package/src/analysis/internal-audit.reach.js +0 -173
- package/src/analysis/internal-audit.run.js +0 -256
- package/src/analysis/java-source.js +0 -36
- package/src/analysis/jvm-artifact-index.js +0 -87
- package/src/analysis/jvm-dependency-evidence.js +0 -138
- package/src/analysis/jvm-manifests.js +0 -114
- package/src/analysis/manifests.js +0 -123
- package/src/analysis/package-reachability.js +0 -39
- package/src/analysis/source-complexity.ast.js +0 -97
- package/src/analysis/source-complexity.constants.js +0 -55
- package/src/analysis/source-complexity.js +0 -14
- package/src/analysis/source-complexity.report.js +0 -81
- package/src/analysis/source-complexity.walk.js +0 -228
- package/src/analysis/source-correctness/retry-patterns.js +0 -93
- package/src/analysis/source-correctness.js +0 -222
- package/src/analysis/static-test-reachability.js +0 -150
- package/src/analysis/structure/dependency-graph.js +0 -151
- package/src/analysis/structure/findings.js +0 -162
- package/src/analysis/task-retrieval.js +0 -107
- package/src/analysis/transport-contracts.js +0 -224
- package/src/analysis/transport-runtime-evidence.js +0 -155
- package/src/analysis-kit.mjs +0 -17
- package/src/bounds.js +0 -4
- package/src/build-graph.js +0 -209
- package/src/child-env.js +0 -7
- package/src/config.js +0 -5
- package/src/extension/local-services.mjs +0 -75
- package/src/git-exec.js +0 -67
- package/src/graph/build-worker.js +0 -49
- package/src/graph/builder/go-receiver-resolution.js +0 -112
- package/src/graph/builder/js/dynamic-import.js +0 -26
- package/src/graph/builder/js/queries.js +0 -48
- package/src/graph/builder/lang-csharp.js +0 -40
- package/src/graph/builder/lang-css.js +0 -29
- package/src/graph/builder/lang-go.js +0 -140
- package/src/graph/builder/lang-html.js +0 -29
- package/src/graph/builder/lang-java-calls.js +0 -142
- package/src/graph/builder/lang-java.js +0 -215
- package/src/graph/builder/lang-js.js +0 -291
- package/src/graph/builder/lang-python.js +0 -235
- package/src/graph/builder/lang-rust-calls.js +0 -63
- package/src/graph/builder/lang-rust.js +0 -299
- package/src/graph/builder/lang-solidity.js +0 -126
- package/src/graph/builder/lang-sql.js +0 -263
- package/src/graph/builder/pass2-resolution.js +0 -81
- package/src/graph/builder/spec-pkg.js +0 -87
- package/src/graph/community.js +0 -27
- package/src/graph/edge-provenance.js +0 -31
- package/src/graph/file-lock.js +0 -69
- package/src/graph/freshness-probe.js +0 -142
- package/src/graph/graph-filter.js +0 -63
- package/src/graph/incremental-refresh.js +0 -235
- package/src/graph/internal-builder.barrels.js +0 -235
- package/src/graph/internal-builder.build.js +0 -300
- package/src/graph/internal-builder.java.js +0 -33
- package/src/graph/internal-builder.js +0 -12
- package/src/graph/internal-builder.langs.js +0 -157
- package/src/graph/internal-builder.pass2.js +0 -163
- package/src/graph/internal-builder.resolvers.js +0 -286
- package/src/graph/layout.js +0 -51
- package/src/graph/node-id.js +0 -7
- package/src/graph/parser-artifact-boundary.js +0 -55
- package/src/graph/relations.js +0 -4
- package/src/graph/repo-registry.js +0 -124
- package/src/graph/resolvers/rust.js +0 -117
- package/src/infra/infra-items.js +0 -255
- package/src/infra/infra-registry.js +0 -184
- package/src/infra/infra.detect.js +0 -119
- package/src/infra/infra.js +0 -38
- package/src/infra/infra.match.js +0 -102
- package/src/infra/infra.scan.js +0 -93
- package/src/mcp/actions/graph-lifecycle.mjs +0 -148
- package/src/mcp/architecture-bootstrap.mjs +0 -168
- package/src/mcp/architecture-starter.mjs +0 -234
- package/src/mcp/catalog.mjs +0 -233
- package/src/mcp/company-contract-page.mjs +0 -142
- package/src/mcp/company-contract-reconcile.mjs +0 -87
- package/src/mcp/company-contract-verdict.mjs +0 -42
- package/src/mcp/evidence/bun-lock-graph.mjs +0 -209
- package/src/mcp/evidence/duplicate-member-order.mjs +0 -8
- package/src/mcp/evidence/package-graph-common.mjs +0 -115
- package/src/mcp/evidence/package-lock-graph.mjs +0 -92
- package/src/mcp/evidence-snapshot.architecture.mjs +0 -80
- package/src/mcp/evidence-snapshot.common.mjs +0 -158
- package/src/mcp/evidence-snapshot.duplicates.mjs +0 -213
- package/src/mcp/evidence-snapshot.health.mjs +0 -102
- package/src/mcp/evidence-snapshot.inventory.mjs +0 -148
- package/src/mcp/evidence-snapshot.mjs +0 -50
- package/src/mcp/evidence-snapshot.package-graph.mjs +0 -34
- package/src/mcp/evidence-snapshot.structure.mjs +0 -84
- package/src/mcp/extension-api.mjs +0 -77
- package/src/mcp/git-output.mjs +0 -7
- package/src/mcp/graph/context-core.mjs +0 -111
- package/src/mcp/graph/context-seeds.mjs +0 -207
- package/src/mcp/graph/context-state.mjs +0 -85
- package/src/mcp/graph/reverse-reach.mjs +0 -42
- package/src/mcp/graph/tools-core.mjs +0 -143
- package/src/mcp/graph/tools-query.mjs +0 -276
- package/src/mcp/graph-context.mjs +0 -5
- package/src/mcp/graph-diff.mjs +0 -218
- package/src/mcp/health/audit-format.mjs +0 -199
- package/src/mcp/health/audit.mjs +0 -174
- package/src/mcp/health/dead-code.mjs +0 -110
- package/src/mcp/health/duplicates.mjs +0 -85
- package/src/mcp/health/endpoints.mjs +0 -71
- package/src/mcp/health/structure.mjs +0 -219
- package/src/mcp/runtime-version.mjs +0 -31
- package/src/mcp/server/auto-refresh.mjs +0 -66
- package/src/mcp/server/runtime-config.mjs +0 -43
- package/src/mcp/server/shutdown.mjs +0 -40
- package/src/mcp/staleness-notice.mjs +0 -20
- package/src/mcp/sync/evidence-architecture.mjs +0 -54
- package/src/mcp/sync/evidence-common.mjs +0 -88
- package/src/mcp/sync/evidence-duplicates.mjs +0 -97
- package/src/mcp/sync/evidence-health.mjs +0 -56
- package/src/mcp/sync/evidence-packages.mjs +0 -95
- package/src/mcp/sync/payload-common.mjs +0 -97
- package/src/mcp/sync/payload-v2.mjs +0 -54
- package/src/mcp/sync/payload-v3.mjs +0 -79
- package/src/mcp/sync-evidence.mjs +0 -23
- package/src/mcp/sync-payload.mjs +0 -70
- package/src/mcp/tool-result.mjs +0 -54
- package/src/mcp/tools-actions.mjs +0 -11
- package/src/mcp/tools-architecture.mjs +0 -177
- package/src/mcp/tools-company.mjs +0 -251
- package/src/mcp/tools-context.mjs +0 -222
- package/src/mcp/tools-endpoints.mjs +0 -207
- package/src/mcp/tools-graph-hubs.mjs +0 -78
- package/src/mcp/tools-graph.mjs +0 -17
- package/src/mcp/tools-health.mjs +0 -24
- package/src/mcp/tools-history.mjs +0 -28
- package/src/mcp/tools-impact-change.mjs +0 -220
- package/src/mcp/tools-impact-precision.mjs +0 -89
- package/src/mcp/tools-impact.mjs +0 -169
- package/src/mcp/tools-source.mjs +0 -238
- package/src/mcp/tools-verified-change.mjs +0 -200
- package/src/mcp-rg.mjs +0 -50
- package/src/mcp-runtime.mjs +0 -2
- package/src/mcp-server.mjs +0 -298
- package/src/mcp-source-tools.mjs +0 -163
- package/src/path-classification.js +0 -220
- package/src/path-ignore.js +0 -69
- package/src/precision/lsp-client/constants.js +0 -12
- package/src/precision/lsp-client/environment.js +0 -20
- package/src/precision/lsp-client/errors.js +0 -15
- package/src/precision/lsp-client/lifecycle.js +0 -114
- package/src/precision/lsp-client/message-parser.js +0 -81
- package/src/precision/lsp-client/protocol.js +0 -212
- package/src/precision/lsp-client/registry.js +0 -59
- package/src/precision/lsp-client/repo-uri.js +0 -60
- package/src/precision/lsp-client/stdio-client.js +0 -140
- package/src/precision/lsp-client.js +0 -10
- package/src/precision/lsp-overlay/budget-policy.js +0 -78
- package/src/precision/lsp-overlay/build.js +0 -261
- package/src/precision/lsp-overlay/contract.js +0 -61
- package/src/precision/lsp-overlay/reference-results.js +0 -108
- package/src/precision/lsp-overlay/semantic-inputs.js +0 -62
- package/src/precision/lsp-overlay/source-session.js +0 -142
- package/src/precision/lsp-overlay/store.js +0 -150
- package/src/precision/lsp-overlay/target-index.js +0 -152
- package/src/precision/lsp-overlay/target-query.js +0 -55
- package/src/precision/lsp-overlay.js +0 -11
- package/src/precision/symbol-query.js +0 -224
- package/src/precision/typescript-lsp-provider.js +0 -12
- package/src/precision/typescript-provider/client.js +0 -89
- package/src/precision/typescript-provider/discovery.js +0 -124
- package/src/precision/typescript-provider/isolated-runtime.js +0 -39
- package/src/precision/typescript-provider/project-host.js +0 -254
- package/src/precision/typescript-provider/project-safety.js +0 -166
- package/src/precision/typescript-provider/reference-usage.js +0 -53
- package/src/process.js +0 -95
- package/src/repo-path.js +0 -53
- package/src/scan/discover.inventory.js +0 -78
- package/src/scan/discover.js +0 -5
- package/src/scan/discover.list.js +0 -79
- package/src/scan/discover.stack.js +0 -227
- package/src/scan/search.core.js +0 -24
- package/src/scan/search.git.js +0 -102
- package/src/scan/search.js +0 -9
- package/src/scan/search.node.js +0 -83
- package/src/scan/search.preview.js +0 -49
- package/src/scan/search.rg.js +0 -145
- package/src/security/advisory-store.js +0 -172
- package/src/security/installed-jvm-rust.js +0 -46
- package/src/security/installed.js +0 -280
- package/src/security/malware-file-heuristics.js +0 -121
- package/src/security/malware-heuristics.exclusions.js +0 -134
- package/src/security/malware-heuristics.js +0 -15
- package/src/security/malware-heuristics.roots.js +0 -145
- package/src/security/malware-heuristics.scan.js +0 -89
- package/src/security/malware-heuristics.sweep.js +0 -122
- package/src/security/malware-scoring.js +0 -105
- package/src/security/match.js +0 -85
- package/src/security/registry-sig.classify.js +0 -137
- package/src/security/registry-sig.js +0 -18
- package/src/security/registry-sig.rules.js +0 -192
- package/src/security/rust-advisory-report.js +0 -60
- package/src/security/typosquat.js +0 -81
- package/src/util.js +0 -40
- package/src/version.js +0 -7
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// Global local registry for repository graphs. Absolute paths never leave the machine; composing
|
|
2
|
-
// extensions may use the opaque UUID. Identity is anchored in each canonical graph folder so simultaneous MCP
|
|
3
|
-
// processes cannot mint different IDs for the same repository.
|
|
4
|
-
import {randomUUID} from 'node:crypto'
|
|
5
|
-
import {existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync} from 'node:fs'
|
|
6
|
-
import {basename, join, relative, resolve} from 'node:path'
|
|
7
|
-
import process from 'node:process'
|
|
8
|
-
import {graphStorageKey} from './layout.js'
|
|
9
|
-
import {atomicWriteFileSync, withFileLockSync} from './file-lock.js'
|
|
10
|
-
|
|
11
|
-
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
12
|
-
const MARKER = '.repository-id'
|
|
13
|
-
|
|
14
|
-
const normalized = (value) => {
|
|
15
|
-
const path = String(value || '').replace(/\\/g, '/').replace(/\/+$/, '')
|
|
16
|
-
return process.platform === 'win32' ? path.toLowerCase() : path
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const realOrResolved = (value) => {
|
|
20
|
-
try { return realpathSync.native(value) } catch { return resolve(value) }
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const canonicalGraphDir = (repoPath, graphHome) => join(resolve(graphHome), graphStorageKey(repoPath))
|
|
24
|
-
const markerPath = (graphDir) => join(graphDir, MARKER)
|
|
25
|
-
|
|
26
|
-
export function registryPath(graphHome) { return join(graphHome, 'repositories.json') }
|
|
27
|
-
|
|
28
|
-
export function readRepositoryRegistry(graphHome) {
|
|
29
|
-
try {
|
|
30
|
-
const parsed = JSON.parse(readFileSync(registryPath(graphHome), 'utf8'))
|
|
31
|
-
return parsed?.repositoryRegistryV === 1 && Array.isArray(parsed.repositories)
|
|
32
|
-
? parsed.repositories.filter((item) => item && typeof item === 'object')
|
|
33
|
-
: []
|
|
34
|
-
} catch { return [] }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function writeRegistry(graphHome, repositories) {
|
|
38
|
-
atomicWriteFileSync(registryPath(graphHome), JSON.stringify({repositoryRegistryV: 1, repositories}, null, 2), 'utf8')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function readMarker(graphDir) {
|
|
42
|
-
try {
|
|
43
|
-
const id = readFileSync(markerPath(graphDir), 'utf8').trim()
|
|
44
|
-
return UUID.test(id) ? id : null
|
|
45
|
-
} catch { return null }
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function createOrReadMarker(graphDir, preferredId) {
|
|
49
|
-
mkdirSync(graphDir, {recursive: true})
|
|
50
|
-
const path = markerPath(graphDir)
|
|
51
|
-
const existing = readMarker(graphDir)
|
|
52
|
-
if (existing) return existing
|
|
53
|
-
if (existsSync(path)) throw new Error(`invalid repository identity marker: ${path}`)
|
|
54
|
-
const candidate = UUID.test(String(preferredId || '')) ? preferredId : randomUUID()
|
|
55
|
-
try { writeFileSync(path, `${candidate}\n`, {encoding: 'utf8', flag: 'wx'}) }
|
|
56
|
-
catch (error) {
|
|
57
|
-
if (error?.code !== 'EEXIST') throw error
|
|
58
|
-
const raced = readMarker(graphDir)
|
|
59
|
-
if (!raced) throw new Error(`invalid repository identity marker after concurrent registration: ${path}`)
|
|
60
|
-
return raced
|
|
61
|
-
}
|
|
62
|
-
return candidate
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function registerRepository({repoPath, graphDir, graphHome}) {
|
|
66
|
-
mkdirSync(graphHome, {recursive: true})
|
|
67
|
-
const real = realOrResolved(repoPath)
|
|
68
|
-
const canonical = canonicalGraphDir(real, graphHome)
|
|
69
|
-
if (normalized(realOrResolved(graphDir)) !== normalized(realOrResolved(canonical))) {
|
|
70
|
-
throw new Error(`repository graphs must be registered from the canonical graph directory: ${canonical}`)
|
|
71
|
-
}
|
|
72
|
-
return withFileLockSync(join(graphHome, '.repositories.lock'), () => {
|
|
73
|
-
const key = normalized(real)
|
|
74
|
-
const repositories = readRepositoryRegistry(graphHome)
|
|
75
|
-
let record = repositories.find((item) => normalized(item.repoPath) === key)
|
|
76
|
-
const now = new Date().toISOString()
|
|
77
|
-
const repositoryId = createOrReadMarker(canonical, record?.repositoryId)
|
|
78
|
-
if (!record) {
|
|
79
|
-
record = {repositoryId, repoPath: real, label: basename(real) || 'repo', graphDir: canonical, firstSeenAt: now, lastSeenAt: now}
|
|
80
|
-
repositories.push(record)
|
|
81
|
-
} else {
|
|
82
|
-
record.repositoryId = repositoryId
|
|
83
|
-
record.repoPath = real
|
|
84
|
-
record.graphDir = canonical
|
|
85
|
-
record.label = basename(real) || record.label || 'repo'
|
|
86
|
-
record.lastSeenAt = now
|
|
87
|
-
}
|
|
88
|
-
const deduped = repositories.filter((item, index, all) =>
|
|
89
|
-
normalized(item.repoPath) !== key || all.findIndex((candidate) => normalized(candidate.repoPath) === key) === index)
|
|
90
|
-
deduped.sort((a, b) => String(a.label).localeCompare(String(b.label)) || String(a.repositoryId).localeCompare(String(b.repositoryId)))
|
|
91
|
-
writeRegistry(graphHome, deduped)
|
|
92
|
-
return {...record}
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function repositoryRecord(repoPath, graphHome) {
|
|
97
|
-
const real = realOrResolved(repoPath)
|
|
98
|
-
const key = normalized(real)
|
|
99
|
-
return liveRepositoryRecords(graphHome).find((item) => normalized(item.repoPath) === key) || null
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function validLiveRecord(item, graphHome) {
|
|
103
|
-
if (!UUID.test(String(item?.repositoryId || '')) || typeof item?.repoPath !== 'string' || typeof item?.graphDir !== 'string') return null
|
|
104
|
-
let repoReal
|
|
105
|
-
let graphHomeReal
|
|
106
|
-
let graphReal
|
|
107
|
-
try {
|
|
108
|
-
repoReal = realpathSync.native(item.repoPath)
|
|
109
|
-
graphHomeReal = realpathSync.native(graphHome)
|
|
110
|
-
graphReal = realpathSync.native(item.graphDir)
|
|
111
|
-
if (!statSync(repoReal).isDirectory() || !existsSync(join(repoReal, '.git'))) return null
|
|
112
|
-
if (!statSync(graphReal).isDirectory() || !statSync(join(graphReal, 'graph.json')).isFile()) return null
|
|
113
|
-
} catch { return null }
|
|
114
|
-
if (normalized(graphReal) !== normalized(realOrResolved(canonicalGraphDir(repoReal, graphHomeReal)))) return null
|
|
115
|
-
const rel = relative(graphHomeReal, graphReal)
|
|
116
|
-
if (!rel || rel.startsWith('..') || resolve(graphHomeReal, rel) !== resolve(graphReal)) return null
|
|
117
|
-
if (readMarker(graphReal) !== item.repositoryId) return null
|
|
118
|
-
return {...item, repoPath: repoReal, graphDir: graphReal}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function liveRepositoryRecords(graphHome) {
|
|
122
|
-
if (!existsSync(graphHome)) return []
|
|
123
|
-
return readRepositoryRegistry(graphHome).map((item) => validLiveRecord(item, graphHome)).filter(Boolean)
|
|
124
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import {join} from 'node:path'
|
|
2
|
-
|
|
3
|
-
const cleanRustRel = (path) => String(path || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/+/g, '/').replace(/\/$/, '').replace(/^\.$/, '')
|
|
4
|
-
const rustDir = (path) => {
|
|
5
|
-
const clean = cleanRustRel(path)
|
|
6
|
-
const index = clean.lastIndexOf('/')
|
|
7
|
-
return index < 0 ? '' : clean.slice(0, index)
|
|
8
|
-
}
|
|
9
|
-
const rustBase = (path) => {
|
|
10
|
-
const clean = cleanRustRel(path)
|
|
11
|
-
const index = clean.lastIndexOf('/')
|
|
12
|
-
return index < 0 ? clean : clean.slice(index + 1)
|
|
13
|
-
}
|
|
14
|
-
const rustJoin = (...parts) => cleanRustRel(join(...parts.filter((part) => part != null && part !== '')))
|
|
15
|
-
|
|
16
|
-
export function createRustResolvers(fileSet) {
|
|
17
|
-
const rustFiles = new Set([...fileSet].filter((file) => file.endsWith('.rs')))
|
|
18
|
-
const rustRoots = new Map()
|
|
19
|
-
for (const file of rustFiles) {
|
|
20
|
-
const base = rustBase(file)
|
|
21
|
-
if (base !== 'lib.rs' && base !== 'main.rs') continue
|
|
22
|
-
const dir = rustDir(file)
|
|
23
|
-
let root = rustRoots.get(dir)
|
|
24
|
-
if (!root) rustRoots.set(dir, (root = {base: dir, lib: null, main: null}))
|
|
25
|
-
root[base === 'lib.rs' ? 'lib' : 'main'] = file
|
|
26
|
-
}
|
|
27
|
-
const rustRootList = [...rustRoots.values()].sort((a, b) => b.base.length - a.base.length)
|
|
28
|
-
|
|
29
|
-
const rustContext = (fromRel) => {
|
|
30
|
-
const clean = cleanRustRel(fromRel)
|
|
31
|
-
const base = rustBase(clean)
|
|
32
|
-
const dir = rustDir(clean)
|
|
33
|
-
if (base === 'lib.rs' || base === 'main.rs') return {base: dir, rootFile: clean}
|
|
34
|
-
if (/^(?:bin|examples|tests|benches)$/.test(rustBase(dir))) return {base: dir, rootFile: clean}
|
|
35
|
-
for (const root of rustRootList) {
|
|
36
|
-
if (!root.base || clean.startsWith(root.base + '/')) return {base: root.base, rootFile: root.lib || root.main}
|
|
37
|
-
}
|
|
38
|
-
return {base: dir, rootFile: clean}
|
|
39
|
-
}
|
|
40
|
-
const rustModuleBase = (fromRel) => {
|
|
41
|
-
const context = rustContext(fromRel)
|
|
42
|
-
if (context.rootFile === cleanRustRel(fromRel)) return rustDir(fromRel)
|
|
43
|
-
const name = rustBase(fromRel)
|
|
44
|
-
if (name === 'lib.rs' || name === 'main.rs' || name === 'mod.rs') return rustDir(fromRel)
|
|
45
|
-
return rustJoin(rustDir(fromRel), name.replace(/\.rs$/, ''))
|
|
46
|
-
}
|
|
47
|
-
const rustInlineBase = (fromRel, inlineModules = []) => {
|
|
48
|
-
let base = rustModuleBase(fromRel)
|
|
49
|
-
for (let index = 0; index < inlineModules.length; index++) {
|
|
50
|
-
const module = inlineModules[index] || {}
|
|
51
|
-
if (module.path) {
|
|
52
|
-
const parent = index === 0 ? rustDir(fromRel) : base
|
|
53
|
-
base = rustJoin(parent, module.path)
|
|
54
|
-
} else base = rustJoin(base, module.name)
|
|
55
|
-
}
|
|
56
|
-
return base
|
|
57
|
-
}
|
|
58
|
-
const rustModuleFile = (moduleBase, context) => {
|
|
59
|
-
const clean = cleanRustRel(moduleBase)
|
|
60
|
-
if (clean === cleanRustRel(context.base) && context.rootFile && rustFiles.has(context.rootFile)) return context.rootFile
|
|
61
|
-
const flat = clean + '.rs'
|
|
62
|
-
if (rustFiles.has(flat)) return flat
|
|
63
|
-
const legacy = rustJoin(clean, 'mod.rs')
|
|
64
|
-
return rustFiles.has(legacy) ? legacy : null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const resolveRustMod = (fromRel, name, {inlineModules = [], explicitPath = ''} = {}) => {
|
|
68
|
-
const clean = cleanRustRel(fromRel)
|
|
69
|
-
if (explicitPath) {
|
|
70
|
-
const parent = inlineModules.length ? rustInlineBase(clean, inlineModules) : rustDir(clean)
|
|
71
|
-
const target = rustJoin(parent, explicitPath)
|
|
72
|
-
return rustFiles.has(target) ? target : null
|
|
73
|
-
}
|
|
74
|
-
const targetBase = rustJoin(rustInlineBase(clean, inlineModules), String(name || '').replace(/^r#/, ''))
|
|
75
|
-
return rustModuleFile(targetBase, rustContext(clean))
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const resolveRustPath = (fromRel, rawSegments, {inlineModules = [], unqualified = true} = {}) => {
|
|
79
|
-
const clean = cleanRustRel(fromRel)
|
|
80
|
-
const segments = (Array.isArray(rawSegments) ? rawSegments : String(rawSegments || '').split('::'))
|
|
81
|
-
.map((segment) => String(segment).trim().replace(/^r#/, '')).filter(Boolean)
|
|
82
|
-
if (!segments.length) return null
|
|
83
|
-
const context = rustContext(clean)
|
|
84
|
-
const current = rustInlineBase(clean, inlineModules)
|
|
85
|
-
const rest = [...segments]
|
|
86
|
-
const starts = []
|
|
87
|
-
let anchored = false
|
|
88
|
-
if (rest[0] === 'crate') { anchored = true; rest.shift(); starts.push(context.base) }
|
|
89
|
-
else if (rest[0] === 'self') { anchored = true; rest.shift(); starts.push(current) }
|
|
90
|
-
else if (rest[0] === 'super') {
|
|
91
|
-
anchored = true
|
|
92
|
-
let base = current
|
|
93
|
-
while (rest[0] === 'super') { rest.shift(); base = rustDir(base) }
|
|
94
|
-
if (context.base && base !== context.base && !base.startsWith(context.base + '/')) return null
|
|
95
|
-
starts.push(base)
|
|
96
|
-
} else if (unqualified) {
|
|
97
|
-
starts.push(context.base)
|
|
98
|
-
if (current !== context.base) starts.push(current)
|
|
99
|
-
} else return null
|
|
100
|
-
|
|
101
|
-
for (const start of starts) {
|
|
102
|
-
const minimum = anchored ? 0 : 1
|
|
103
|
-
for (let used = rest.length; used >= minimum; used--) {
|
|
104
|
-
const target = rustModuleFile(rustJoin(start, ...rest.slice(0, used)), context)
|
|
105
|
-
if (target) return {
|
|
106
|
-
targetFile: target,
|
|
107
|
-
consumed: segments.length - rest.length + used,
|
|
108
|
-
remaining: rest.slice(used),
|
|
109
|
-
anchored,
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return null
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return {resolveRustMod, resolveRustPath}
|
|
117
|
-
}
|
package/src/infra/infra-items.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
// infra-items.js — extract concrete infra items (DB tables, cache keysets, queue topics, cloud files, SQL
|
|
2
|
-
// tables, env-declared endpoints) from source text for the detected services. Split out of infra.js; it owns
|
|
3
|
-
// the shared leaf helpers (lc/safeRead/size caps) as the lower module — infra.js imports them back.
|
|
4
|
-
import { safeRead, MAX_FILE_BYTES } from "../util.js";
|
|
5
|
-
|
|
6
|
-
const IMPORT_SCAN_MAX_FILES = 2000; // cap the synchronous import-scan pass (connector attribution only) so the
|
|
7
|
-
const lc = (s) => String(s || "").toLowerCase();
|
|
8
|
-
|
|
9
|
-
export { safeRead };
|
|
10
|
-
|
|
11
|
-
const ITEM_META = {
|
|
12
|
-
db: { label: "TABLES", unit: "rows" },
|
|
13
|
-
ts: { label: "SERIES", unit: "pts" },
|
|
14
|
-
cache: { label: "KEYSETS", unit: "keys" },
|
|
15
|
-
queue: { label: "TOPICS", unit: "msg/s" },
|
|
16
|
-
cloud: { label: "FILES", unit: "KB" },
|
|
17
|
-
fs: { label: "FILES", unit: "KB" },
|
|
18
|
-
logs: { label: "STREAMS", unit: "l/s" },
|
|
19
|
-
api: { label: "ENDPOINTS", unit: "req/s" },
|
|
20
|
-
};
|
|
21
|
-
const ITEM_VALUE = { db: 42, ts: 120, cache: 700, queue: 22, cloud: 120, fs: 80, logs: 55, api: 24 };
|
|
22
|
-
const SQL_RESERVED = new Set([
|
|
23
|
-
"select", "from", "where", "join", "left", "right", "inner", "outer", "full", "cross",
|
|
24
|
-
"on", "and", "or", "by", "group", "order", "limit", "offset", "as", "with", "values",
|
|
25
|
-
"set", "returning", "true", "false", "null", "undefined", "if", "case", "when", "then",
|
|
26
|
-
"else", "end", "having", "over", "partition", "distinct", "the", "is",
|
|
27
|
-
"count", "sum", "avg", "min", "max", "uniq", "array", "date", "datetime", "string", "number",
|
|
28
|
-
]);
|
|
29
|
-
|
|
30
|
-
export function itemMetaFor(service) {
|
|
31
|
-
if (service.id === "mongodb") return { label: "COLLECTIONS", unit: "docs" };
|
|
32
|
-
if (service.id === "dynamodb") return { label: "TABLES", unit: "items" };
|
|
33
|
-
if (service.id === "elasticsearch" || service.id === "solr" || service.id === "meilisearch" || service.id === "typesense") {
|
|
34
|
-
return { label: "INDEXES", unit: "docs" };
|
|
35
|
-
}
|
|
36
|
-
return ITEM_META[service.kind] || { label: "ITEMS", unit: "" };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function cleanInfraItemName(raw) {
|
|
40
|
-
const name = String(raw || "").trim().replace(/^(?:["'`]|\[)+|(?:["'`]|])+$/g, "").replace(/[;,]+$/g, "").trim();
|
|
41
|
-
if (!name || name.length < 2 || name.length > 64) return "";
|
|
42
|
-
if (name.includes("://") || name.includes("${") || name.includes("#{")) return "";
|
|
43
|
-
if (/[\s(){}+$]/.test(name)) return "";
|
|
44
|
-
if (!/^[A-Za-z0-9_./:\-*]+$/.test(name)) return "";
|
|
45
|
-
if (/^\d+$/.test(name) || SQL_RESERVED.has(name.toLowerCase())) return "";
|
|
46
|
-
return name;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function addInfraItem(map, raw, weight = 1, sourcePath = "", op = "") {
|
|
50
|
-
const name = cleanInfraItemName(raw);
|
|
51
|
-
if (!name) return;
|
|
52
|
-
const cur = map.get(name) || { name, refs: 0, files: new Set(), ops: new Set() };
|
|
53
|
-
cur.refs += Math.max(1, weight);
|
|
54
|
-
if (sourcePath) cur.files.add(sourcePath);
|
|
55
|
-
if (op) cur.ops.add(op);
|
|
56
|
-
map.set(name, cur);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// One regex-walk adder factory shared by the two matchers below — the only difference is how a
|
|
60
|
-
// captured group becomes items (a single name vs a string-array body).
|
|
61
|
-
const matchAdder = (add) => (map, text, re, group = 1, weight = 1, sourcePath = "", op = "") => {
|
|
62
|
-
for (const m of text.matchAll(re)) add(map, m[group], weight, sourcePath, op);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
function addStringArrayItems(map, raw, weight = 1, sourcePath = "", op = "") {
|
|
66
|
-
const body = String(raw || "");
|
|
67
|
-
for (const m of body.matchAll(/["'`]([^"'`]+)["'`]/g)) addInfraItem(map, m[1], weight, sourcePath, op);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const addMatches = matchAdder(addInfraItem);
|
|
71
|
-
const addStructArrayMatches = matchAdder(addStringArrayItems);
|
|
72
|
-
|
|
73
|
-
function addSqlTableMatches(map, text, re, cteAliases, group = 1, weight = 1, sourcePath = "", op = "") {
|
|
74
|
-
for (const m of String(text || "").matchAll(re)) {
|
|
75
|
-
const name = String(m[group] || "");
|
|
76
|
-
if (cteAliases.has(name.toLowerCase())) continue;
|
|
77
|
-
addInfraItem(map, name, weight, sourcePath, op);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function looksLikeSqlSnippet(raw) {
|
|
82
|
-
const text = String(raw || "").replace(/\$\{[\s\S]*?\}/g, " ");
|
|
83
|
-
if (!/[A-Za-z]/.test(text)) return false;
|
|
84
|
-
const statementStart = "(?:^|[\\r\\n;])\\s*";
|
|
85
|
-
return (
|
|
86
|
-
new RegExp(`${statementStart}(?:select|with)\\b[\\s\\S]{0,600}\\bfrom\\b`, "i").test(text) ||
|
|
87
|
-
new RegExp(`${statementStart}(?:insert\\s+into|delete\\s+from|alter\\s+table|create\\s+(?:or\\s+replace\\s+)?table|truncate\\s+table|update\\s+["'\`\\[]?[A-Za-z_][\\w$]*(?:\\.[A-Za-z_][\\w$]*)?["'\`\\]]?\\s+set)\\b`, "i").test(text)
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function stringLiteralBody(match) {
|
|
92
|
-
for (let i = 1; i < match.length; i++) if (match[i] != null) return match[i];
|
|
93
|
-
return "";
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function extractSqlSnippets(text) {
|
|
97
|
-
const out = [];
|
|
98
|
-
const src = String(text || "");
|
|
99
|
-
const add = (body) => {
|
|
100
|
-
const snippet = String(body || "");
|
|
101
|
-
if (looksLikeSqlSnippet(snippet)) out.push(snippet);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
for (const match of src.matchAll(/"""([\s\S]*?)"""|'''([\s\S]*?)'''/g)) add(stringLiteralBody(match));
|
|
105
|
-
for (const match of src.matchAll(/`([\s\S]*?)`|"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'/g)) add(stringLiteralBody(match));
|
|
106
|
-
return out.join("\n");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function sqlCteAliases(text) {
|
|
110
|
-
const out = new Set();
|
|
111
|
-
for (const match of String(text || "").matchAll(/(?:\bwith|,)\s+([A-Za-z_][\w$]*)\s+as\s*\(/gi)) {
|
|
112
|
-
out.add(String(match[1] || "").toLowerCase());
|
|
113
|
-
}
|
|
114
|
-
return out;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function hasServiceHint(service, text) {
|
|
118
|
-
const lower = lc(text);
|
|
119
|
-
const tokens = [service.id, service.name, ...(service.imports || []), ...(service.deps || [])]
|
|
120
|
-
.map((x) => lc(x))
|
|
121
|
-
.filter((x) => x && x.length > 2);
|
|
122
|
-
return tokens.some((token) => lower.includes(token));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function finalizeInfraItems(map, kind) {
|
|
126
|
-
const base = ITEM_VALUE[kind] || 40;
|
|
127
|
-
return [...map.values()]
|
|
128
|
-
.sort((a, b) => b.refs - a.refs || a.name.localeCompare(b.name))
|
|
129
|
-
.slice(0, 24)
|
|
130
|
-
.map((item) => ({
|
|
131
|
-
name: item.name,
|
|
132
|
-
val: Math.round(Math.max(4, base * (1 + Math.log2(item.refs + 1) * 0.55))),
|
|
133
|
-
health: Math.max(0.42, Math.min(0.96, 0.94 - Math.log2(item.refs + 1) * 0.08)),
|
|
134
|
-
refs: item.refs,
|
|
135
|
-
fileCount: item.files ? item.files.size : 0,
|
|
136
|
-
files: item.files ? [...item.files].sort().slice(0, 12) : [],
|
|
137
|
-
ops: item.ops ? [...item.ops].sort().slice(0, 12) : [],
|
|
138
|
-
}));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function extractInfraItemsForService(service, text, out, sourcePath = "") {
|
|
142
|
-
const id = service.id;
|
|
143
|
-
const kind = service.kind;
|
|
144
|
-
const hit = (re, group = 1, weight = 1, op = "") => addMatches(out, text, re, group, weight, sourcePath, op);
|
|
145
|
-
const hitSql = (target, re, cteAliases, group = 1, weight = 1, op = "") => addSqlTableMatches(out, target, re, cteAliases, group, weight, sourcePath, op);
|
|
146
|
-
const hitArrays = (re, group = 1, weight = 1, op = "") => addStructArrayMatches(out, text, re, group, weight, sourcePath, op);
|
|
147
|
-
// Go/CLI services often carry their topics/keyspaces as FLAG DEFAULTS, not literals at the call
|
|
148
|
-
// site (bgp-speaker: flag.String("bgp_update_kafka_topic", "bgp_updates", …), flag.String(
|
|
149
|
-
// "redis_key_base", "bgp:mitigators", …)) — the flag NAME says what the default VALUE is.
|
|
150
|
-
const hitFlagDefaults = (nameRe, weight = 2, op = "configured") => {
|
|
151
|
-
for (const m of text.matchAll(/\b(?:flag|pflag)\.String(?:Var)?\s*\(\s*(?:&[\w.]+\s*,\s*)?"([^"]+)"\s*,\s*"([^"]+)"/g)) {
|
|
152
|
-
if (nameRe.test(m[1])) addInfraItem(out, m[2], weight, sourcePath, op);
|
|
153
|
-
}
|
|
154
|
-
for (const m of text.matchAll(/\badd_argument\s*\(\s*["']--?([^"']+)["'][^)]{0,200}?\bdefault\s*=\s*["']([^"']+)["']/g)) {
|
|
155
|
-
if (nameRe.test(m[1])) addInfraItem(out, m[2], weight, sourcePath, op);
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
if (id === "mongodb") {
|
|
160
|
-
hit(/\.collection\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi, 1, 2);
|
|
161
|
-
hit(/\.Collection\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/g, 1, 2);
|
|
162
|
-
hit(/\bgetCollection\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi, 1, 2);
|
|
163
|
-
hit(/\bcollection\s*:\s*["'`]([^"'`]+)["'`]/gi);
|
|
164
|
-
hit(/\b(?:mongoose\.)?model\s*\(\s*["'`]([^"'`]+)["'`]/gi);
|
|
165
|
-
hit(/\bdb\s*\[\s*["'`]([^"'`]+)["'`]\s*\]/gi);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (id === "dynamodb") {
|
|
170
|
-
hit(/\bTableName\s*:\s*["'`]([^"'`]+)["'`]/g, 1, 2);
|
|
171
|
-
hit(/\btableName\s*[:=]\s*["'`]([^"'`]+)["'`]/g, 1, 2);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (id === "elasticsearch" || id === "solr" || id === "meilisearch" || id === "typesense") {
|
|
175
|
-
hit(/\bindex(?:Name)?\s*[:=]\s*["'`]([^"'`]+)["'`]/gi, 1, 2);
|
|
176
|
-
hit(/\.index\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi, 1, 2);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (kind === "db" || kind === "ts") {
|
|
180
|
-
const sqlText = extractSqlSnippets(text);
|
|
181
|
-
if (sqlText) {
|
|
182
|
-
const cteAliases = sqlCteAliases(sqlText);
|
|
183
|
-
hitSql(sqlText, /\b(?:insert\s+into|delete\s+from|alter\s+table|create\s+(?:or\s+replace\s+)?table|truncate\s+table)\s+(?:["'`]|\[)?([A-Za-z_][\w$]*(?:\.[A-Za-z_][\w$]*)?)(?:["'`]|])?/gi, cteAliases, 1, 2);
|
|
184
|
-
hitSql(sqlText, /\b(?:from|join|into|update|table)\s+(?:["'`]|\[)?([A-Za-z_][\w$]*(?:\.[A-Za-z_][\w$]*)?)(?:["'`]|])?/gi, cteAliases);
|
|
185
|
-
}
|
|
186
|
-
if (id !== "clickhouse" && hasServiceHint(service, text)) {
|
|
187
|
-
hit(/\b(?:table|tableName|measurement|bucket)\s*[:=]\s*["'`]([^"'`]+)["'`]/gi);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (kind === "cache") {
|
|
192
|
-
hit(/\b(?:get|getBuffer|getdel|exists|ttl|pttl)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 1, "read");
|
|
193
|
-
hit(/\b(?:set|setex|psetex|setnx|incr|decr|expire|persist)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 2, "write");
|
|
194
|
-
hit(/\b(?:del|delete|unlink|expireat|pexpireat)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 2, "delete");
|
|
195
|
-
hit(/\b(?:hget|hmget|hgetall|hexists)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 1, "hash read");
|
|
196
|
-
hit(/\b(?:hset|hmset|hdel)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 2, "hash write");
|
|
197
|
-
hit(/\b(?:lpush|rpush|lpop|rpop|sadd|srem|zadd|zrem)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 2, "collection");
|
|
198
|
-
hit(/\b(?:xadd|xread|xreadgroup|xgroup)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 2, "stream");
|
|
199
|
-
hit(/\b(?:publish|subscribe|psubscribe)\s*\(\s*(?:ctx\s*,\s*)?["'`]([^"'`]+)["'`]/gi, 1, 1, "pub/sub");
|
|
200
|
-
hit(/\b(?:cacheKey|redisKey|valkeyKey|redisPrefix|valkeyPrefix|keyPrefix|lockKey|rateLimitKey|sessionKey)\s*[:=]\s*["'`]([^"'`]+)["'`]/gi, 1, 2, "key pattern");
|
|
201
|
-
hitArrays(/\b(?:Streams|streams)\s*:\s*\[\]string\s*\{([^}]+)\}/g, 1, 2, "stream");
|
|
202
|
-
hitFlagDefaults(/key|keyspace|prefix/i, 2, "key pattern");
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (kind === "queue") {
|
|
206
|
-
hit(/\b(?:topic|topics|queue|subject|stream|channel|Topic|Queue|Subject|Stream|Channel)\s*[:=]\s*["'`]([^"'`]+)["'`]/g, 1, 2, "configured");
|
|
207
|
-
hit(/\b(?:publish|produce|send|sendMessage|writeMessage|writeMessages|emit)\s*\(\s*["'`]([^"'`]+)["'`]/gi, 1, 2, "produce");
|
|
208
|
-
hit(/\b(?:subscribe|consume|consumer|listen|readMessage|readMessages)\s*\(\s*["'`]([^"'`]+)["'`]/gi, 1, 1, "consume");
|
|
209
|
-
hit(/\b(?:producer\.send|sendBatch)\s*\(\s*\{[\s\S]{0,500}?\btopic\s*:\s*["'`]([^"'`]+)["'`]/gi, 1, 2, "produce");
|
|
210
|
-
hit(/\bconsumer\.subscribe\s*\(\s*\{[\s\S]{0,320}?\btopic\s*:\s*["'`]([^"'`]+)["'`]/gi, 1, 2, "consume");
|
|
211
|
-
hit(/\b(?:KafkaConsumer|NewConsumer|NewReader|NewWriter|NewTopic)\s*\(\s*["'`]([^"'`]+)["'`]/g, 1, 2, "configured");
|
|
212
|
-
hit(/@KafkaListener\s*\([^)]*\btopics?\s*=\s*["'`]([^"'`]+)["'`]/g, 1, 2, "consume");
|
|
213
|
-
hit(/\bkafkaTemplate\.send\s*\(\s*["'`]([^"'`]+)["'`]/g, 1, 2, "produce");
|
|
214
|
-
hitArrays(/\b(?:topics|Topics|GroupTopics|SubscribeTopics|streams|Streams)\s*[:=]\s*(?:\[\]string)?\s*\{([^}]+)\}/g, 1, 2, "configured");
|
|
215
|
-
hitArrays(/\b(?:subscribe|Consume|SubscribeTopics)\s*\(\s*(?:ctx\s*,\s*)?\[\]string\s*\{([^}]+)\}/g, 1, 2, "consume");
|
|
216
|
-
hitFlagDefaults(/topic|queue|subject|stream|channel/i, 2, "configured");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (kind === "cloud" || kind === "fs") {
|
|
220
|
-
hit(/\b(?:bucket|bucketName|container|containerName)\s*[:=]\s*["'`]([^"'`]+)["'`]/gi, 1, 2);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export function collectInfraItems(scan, entries, filesByService) {
|
|
225
|
-
const result = new Map();
|
|
226
|
-
const allFiles = (scan.codeFiles || []).slice(0, IMPORT_SCAN_MAX_FILES);
|
|
227
|
-
const textCache = new Map();
|
|
228
|
-
const readText = (f) => {
|
|
229
|
-
if (!f || !f.full) return "";
|
|
230
|
-
if (!textCache.has(f.full)) textCache.set(f.full, safeRead(f.full));
|
|
231
|
-
return textCache.get(f.full);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
for (const { service } of entries) {
|
|
235
|
-
const meta = itemMetaFor(service);
|
|
236
|
-
const wanted = filesByService.get(service.id);
|
|
237
|
-
const preferred = wanted && wanted.size ? allFiles.filter((f) => wanted.has(f.path)) : [];
|
|
238
|
-
const candidateFiles = preferred.length ? [...preferred, ...allFiles.filter((f) => !wanted.has(f.path))] : allFiles;
|
|
239
|
-
const itemMap = new Map();
|
|
240
|
-
for (const f of candidateFiles) {
|
|
241
|
-
const text = readText(f);
|
|
242
|
-
if (!text) continue;
|
|
243
|
-
extractInfraItemsForService(service, text, itemMap, f.path);
|
|
244
|
-
}
|
|
245
|
-
result.set(service.id, {
|
|
246
|
-
itemLabel: meta.label,
|
|
247
|
-
unit: meta.unit,
|
|
248
|
-
items: finalizeInfraItems(itemMap, service.kind),
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
return result;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
export { MAX_FILE_BYTES, IMPORT_SCAN_MAX_FILES, lc };
|