gitnexus 1.6.6-rc.24 → 1.6.6-rc.26
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.
|
@@ -35,7 +35,9 @@ export interface EvalServerOptions {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Validate the --host value. Accepts IPv4, IPv6, or "localhost".
|
|
38
|
-
* Returns the
|
|
38
|
+
* Returns the host string unchanged, or null if invalid.
|
|
39
|
+
* "localhost" is passed through so the OS resolves it to the correct loopback
|
|
40
|
+
* address (127.0.0.1 or ::1) at bind time rather than forcing IPv4.
|
|
39
41
|
*/
|
|
40
42
|
export declare function validateHost(raw: string): string | null;
|
|
41
43
|
export declare function formatQueryResult(result: any): string;
|
package/dist/cli/eval-server.js
CHANGED
|
@@ -36,11 +36,13 @@ import { logger } from '../core/logger.js';
|
|
|
36
36
|
import { cliInfo, cliWarn, cliError } from './cli-message.js';
|
|
37
37
|
/**
|
|
38
38
|
* Validate the --host value. Accepts IPv4, IPv6, or "localhost".
|
|
39
|
-
* Returns the
|
|
39
|
+
* Returns the host string unchanged, or null if invalid.
|
|
40
|
+
* "localhost" is passed through so the OS resolves it to the correct loopback
|
|
41
|
+
* address (127.0.0.1 or ::1) at bind time rather than forcing IPv4.
|
|
40
42
|
*/
|
|
41
43
|
export function validateHost(raw) {
|
|
42
44
|
if (raw === 'localhost')
|
|
43
|
-
return
|
|
45
|
+
return raw;
|
|
44
46
|
if (isIPv4(raw) || isIPv6(raw))
|
|
45
47
|
return raw;
|
|
46
48
|
return null;
|
|
@@ -395,11 +397,13 @@ export async function evalServerCommand(options) {
|
|
|
395
397
|
` 2. Use a different port: gitnexus eval-server --port 4849\n`, { code: err.code, port, host });
|
|
396
398
|
}
|
|
397
399
|
else if (err.code === 'EADDRNOTAVAIL') {
|
|
398
|
-
|
|
400
|
+
// "localhost" may resolve to ::1 on IPv6-only systems; treat it as
|
|
401
|
+
// potentially IPv6 so the user gets the right diagnostic hint.
|
|
402
|
+
const isIPv6Host = isIPv6(host) || host === 'localhost';
|
|
399
403
|
cliError(`\nGitNexus eval-server failed to start:\n` +
|
|
400
404
|
` Address ${host} is not available on this machine.\n\n` +
|
|
401
405
|
(isIPv6Host
|
|
402
|
-
? `
|
|
406
|
+
? ` Address ${host} resolved but is not reachable — IPv6 may be disabled, or the loopback interface may be unavailable.\n` +
|
|
403
407
|
` Docker containers and many CI environments disable IPv6 by default.\n\n`
|
|
404
408
|
: ` The --host value must be an IP assigned to a local network interface.\n` +
|
|
405
409
|
` Run \`ip addr\` (Linux) or \`ipconfig\` (Windows) to list available addresses.\n\n`) +
|
|
@@ -426,10 +430,19 @@ export async function evalServerCommand(options) {
|
|
|
426
430
|
// Plain-text banner for the human watching stderr; structured record
|
|
427
431
|
// for log aggregation (split into two so the user sees a real banner
|
|
428
432
|
// not `{"level":30,"msg":"...","port":4747,"endpoints":[...]}`).
|
|
429
|
-
// Use server.address()
|
|
433
|
+
// Use server.address() so the banner and READY signal reflect what the OS
|
|
434
|
+
// actually bound to, not the input host string. This matters when "localhost"
|
|
435
|
+
// is passed: the OS may resolve it to ::1 on some systems.
|
|
430
436
|
const addr = server.address();
|
|
431
|
-
|
|
432
|
-
|
|
437
|
+
// server.listen callback only fires after a successful TCP bind, so
|
|
438
|
+
// server.address() is guaranteed to return an AddressInfo object here.
|
|
439
|
+
if (typeof addr !== 'object' || addr === null) {
|
|
440
|
+
cliError(`\nGitNexus eval-server: unexpected server.address() value after bind: ${JSON.stringify(addr)}\n`);
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
const boundPort = addr.port;
|
|
444
|
+
const boundAddress = addr.address;
|
|
445
|
+
const displayHost = boundAddress.includes(':') ? `[${boundAddress}]` : boundAddress;
|
|
433
446
|
const bannerLines = [
|
|
434
447
|
`GitNexus eval-server: listening on http://${displayHost}:${boundPort}`,
|
|
435
448
|
` POST /tool/query — search execution flows`,
|
|
@@ -457,8 +470,7 @@ export async function evalServerCommand(options) {
|
|
|
457
470
|
});
|
|
458
471
|
try {
|
|
459
472
|
// Use fd 1 directly — LadybugDB captures process.stdout (#324)
|
|
460
|
-
|
|
461
|
-
writeSync(1, `GITNEXUS_EVAL_SERVER_READY:${readyHost}:${boundPort}\n`);
|
|
473
|
+
writeSync(1, `GITNEXUS_EVAL_SERVER_READY:${displayHost}:${boundPort}\n`);
|
|
462
474
|
}
|
|
463
475
|
catch {
|
|
464
476
|
// stdout may not be available (e.g., broken pipe)
|
|
@@ -15,12 +15,14 @@ import { getPluginForFile, HTTP_SCAN_GLOB } from './http-patterns/index.js';
|
|
|
15
15
|
* the preferred path because the graph has richer symbol metadata
|
|
16
16
|
* (real uids, class/method structure, etc.).
|
|
17
17
|
*
|
|
18
|
-
* 2. **Source-scan
|
|
19
|
-
* the per-language plugin registry in `./http-patterns/`. Used
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* 2. **Source-scan supplement (Strategy B)** — parse files directly with
|
|
19
|
+
* the per-language plugin registry in `./http-patterns/`. Used to
|
|
20
|
+
* fill gaps when graph extraction only covers part of a polyglot repo
|
|
21
|
+
* (e.g. Java graph routes plus Go source-scan routes). Graph entries
|
|
22
|
+
* remain authoritative for duplicate contract IDs because they carry
|
|
23
|
+
* richer symbol metadata. Each plugin owns its tree-sitter grammar
|
|
24
|
+
* and query sources — this orchestrator imports NO grammars or query
|
|
25
|
+
* strings.
|
|
24
26
|
*
|
|
25
27
|
* Adding a new language for Strategy B is a one-file edit in
|
|
26
28
|
* `http-patterns/index.ts`: register a new `HttpLanguagePlugin` and
|
|
@@ -175,13 +177,11 @@ export class HttpRouteExtractor {
|
|
|
175
177
|
return scannedFiles;
|
|
176
178
|
};
|
|
177
179
|
const graphProviders = dbExecutor != null ? await this.extractProvidersGraph(dbExecutor, getDetections) : [];
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
// Source scan always runs to capture routes in languages/files not covered
|
|
181
|
+
// by graph edges; the glob and per-file parse results are cached above.
|
|
182
|
+
const providers = this.mergeGraphAndSourceContracts(graphProviders, this.extractProvidersSourceScan(await getScannedFiles(), getDetections));
|
|
181
183
|
const graphConsumers = dbExecutor != null ? await this.extractConsumersGraph(dbExecutor, getDetections) : [];
|
|
182
|
-
const consumers = graphConsumers.
|
|
183
|
-
? graphConsumers
|
|
184
|
-
: this.extractConsumersSourceScan(await getScannedFiles(), getDetections);
|
|
184
|
+
const consumers = this.mergeGraphAndSourceContracts(graphConsumers, this.extractConsumersSourceScan(await getScannedFiles(), getDetections));
|
|
185
185
|
return [...providers, ...consumers];
|
|
186
186
|
}
|
|
187
187
|
async scanFiles(repoPath) {
|
|
@@ -427,4 +427,15 @@ export class HttpRouteExtractor {
|
|
|
427
427
|
}
|
|
428
428
|
return out;
|
|
429
429
|
}
|
|
430
|
+
mergeGraphAndSourceContracts(graphContracts, sourceContracts) {
|
|
431
|
+
const seenContractIds = new Set(graphContracts.map((c) => c.contractId));
|
|
432
|
+
const out = [...graphContracts];
|
|
433
|
+
for (const contract of sourceContracts) {
|
|
434
|
+
if (seenContractIds.has(contract.contractId))
|
|
435
|
+
continue;
|
|
436
|
+
seenContractIds.add(contract.contractId);
|
|
437
|
+
out.push(contract);
|
|
438
|
+
}
|
|
439
|
+
return out;
|
|
440
|
+
}
|
|
430
441
|
}
|
package/package.json
CHANGED