githits 0.2.3 → 0.3.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/GEMINI.md +4 -6
- package/README.md +31 -17
- package/commands/help.md +4 -4
- package/dist/cli.js +668 -186
- package/dist/index.js +1 -1
- package/dist/shared/chunk-1gqfte6e.js +11 -0
- package/dist/shared/{chunk-a9js75mw.js → chunk-5mk9k2gv.js} +1269 -626
- package/dist/shared/{chunk-js72s35a.js → chunk-gxya097b.js} +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +4 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/help.md +4 -4
- package/plugins/claude/skills/search/SKILL.md +2 -2
- package/skills/search/SKILL.md +2 -2
- package/dist/shared/chunk-9zze00cp.js +0 -11
|
@@ -1,7 +1,93 @@
|
|
|
1
1
|
import {
|
|
2
2
|
version
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-gxya097b.js";
|
|
4
4
|
|
|
5
|
+
// src/services/app-config-paths.ts
|
|
6
|
+
var APP_DIR = "githits";
|
|
7
|
+
function getAppConfigDir(fs) {
|
|
8
|
+
const home = fs.getHomeDir();
|
|
9
|
+
switch (process.platform) {
|
|
10
|
+
case "win32":
|
|
11
|
+
return fs.joinPath(process.env.APPDATA ?? fs.joinPath(home, "AppData", "Roaming"), APP_DIR);
|
|
12
|
+
case "darwin":
|
|
13
|
+
return fs.joinPath(home, "Library", "Application Support", APP_DIR);
|
|
14
|
+
default:
|
|
15
|
+
return fs.joinPath(process.env.XDG_CONFIG_HOME ?? fs.joinPath(home, ".config"), APP_DIR);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function getAuthConfigPath(fs) {
|
|
19
|
+
return fs.joinPath(getAppConfigDir(fs), "config.toml");
|
|
20
|
+
}
|
|
21
|
+
function getAuthFileStorageDir(fs) {
|
|
22
|
+
return fs.joinPath(getAppConfigDir(fs), "auth");
|
|
23
|
+
}
|
|
24
|
+
function getLegacyAuthStorageDir(fs) {
|
|
25
|
+
return fs.joinPath(fs.getHomeDir(), ".githits");
|
|
26
|
+
}
|
|
27
|
+
// src/services/auth-config.ts
|
|
28
|
+
import { parse as parseToml } from "smol-toml";
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
var AUTH_STORAGE_MODES = ["keychain", "file"];
|
|
31
|
+
var AUTH_STORAGE_MODE_VALUES = new Set(AUTH_STORAGE_MODES);
|
|
32
|
+
var CONFIG_SCHEMA = z.object({
|
|
33
|
+
auth: z.object({
|
|
34
|
+
storage: z.string().optional()
|
|
35
|
+
}).optional()
|
|
36
|
+
}).passthrough();
|
|
37
|
+
|
|
38
|
+
class AuthConfigError extends Error {
|
|
39
|
+
constructor(message) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = "AuthConfigError";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function parseAuthStorageMode(value) {
|
|
45
|
+
const normalized = value.trim().toLowerCase();
|
|
46
|
+
if (AUTH_STORAGE_MODE_VALUES.has(normalized)) {
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
throw new AuthConfigError(`Invalid auth storage mode "${value}". Use "keychain" or "file". File mode stores OAuth credentials unencrypted on disk.`);
|
|
50
|
+
}
|
|
51
|
+
async function loadAuthConfig(fs) {
|
|
52
|
+
const configPath = getAuthConfigPath(fs);
|
|
53
|
+
const envMode = process.env.GITHITS_AUTH_STORAGE;
|
|
54
|
+
if (envMode !== undefined && envMode.trim() !== "") {
|
|
55
|
+
try {
|
|
56
|
+
return { storage: parseAuthStorageMode(envMode), configPath };
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (error instanceof AuthConfigError) {
|
|
59
|
+
throw new AuthConfigError(`Invalid GITHITS_AUTH_STORAGE: ${error.message}`);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!await fs.exists(configPath)) {
|
|
65
|
+
return { storage: "keychain", configPath };
|
|
66
|
+
}
|
|
67
|
+
let rawConfig;
|
|
68
|
+
try {
|
|
69
|
+
rawConfig = parseToml(await fs.readFile(configPath));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
throw new AuthConfigError(`Cannot parse GitHits config at ${configPath}: ${message}`);
|
|
73
|
+
}
|
|
74
|
+
const parsed = CONFIG_SCHEMA.safeParse(rawConfig);
|
|
75
|
+
if (!parsed.success) {
|
|
76
|
+
throw new AuthConfigError(`Invalid GitHits config at ${configPath}: ${z.prettifyError(parsed.error)}`);
|
|
77
|
+
}
|
|
78
|
+
const configuredMode = parsed.data.auth?.storage;
|
|
79
|
+
if (configuredMode === undefined || configuredMode.trim() === "") {
|
|
80
|
+
return { storage: "keychain", configPath };
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
return { storage: parseAuthStorageMode(configuredMode), configPath };
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (error instanceof AuthConfigError) {
|
|
86
|
+
throw new AuthConfigError(`Invalid GitHits config at ${configPath}: ${error.message}`);
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
5
91
|
// src/services/auth-service.ts
|
|
6
92
|
import { createServer } from "node:http";
|
|
7
93
|
|
|
@@ -310,11 +396,9 @@ function escapeHtml(text) {
|
|
|
310
396
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
311
397
|
}
|
|
312
398
|
// src/services/auth-storage.ts
|
|
313
|
-
var CONFIG_DIR = ".githits";
|
|
314
399
|
var AUTH_FILE = "auth.json";
|
|
315
400
|
var CLIENT_FILE = "client.json";
|
|
316
401
|
var DIR_MODE = 448;
|
|
317
|
-
var FILE_MODE = 384;
|
|
318
402
|
|
|
319
403
|
class AuthStorageImpl {
|
|
320
404
|
fs;
|
|
@@ -323,7 +407,7 @@ class AuthStorageImpl {
|
|
|
323
407
|
clientPath;
|
|
324
408
|
constructor(fs, configDir) {
|
|
325
409
|
this.fs = fs;
|
|
326
|
-
this.configDir = configDir ??
|
|
410
|
+
this.configDir = configDir ?? getAuthFileStorageDir(fs);
|
|
327
411
|
this.authPath = fs.joinPath(this.configDir, AUTH_FILE);
|
|
328
412
|
this.clientPath = fs.joinPath(this.configDir, CLIENT_FILE);
|
|
329
413
|
}
|
|
@@ -343,7 +427,7 @@ class AuthStorageImpl {
|
|
|
343
427
|
};
|
|
344
428
|
stored.tokens[normalizeBaseUrl(baseUrl)] = data;
|
|
345
429
|
await this.fs.ensureDir(this.configDir, DIR_MODE);
|
|
346
|
-
await this.fs.
|
|
430
|
+
await this.fs.atomicWriteFile(this.authPath, JSON.stringify(stored, null, 2));
|
|
347
431
|
}
|
|
348
432
|
async clearTokens(baseUrl) {
|
|
349
433
|
const stored = await this.loadAuthFile();
|
|
@@ -353,7 +437,7 @@ class AuthStorageImpl {
|
|
|
353
437
|
if (Object.keys(stored.tokens).length === 0) {
|
|
354
438
|
await this.fs.deleteFile(this.authPath);
|
|
355
439
|
} else {
|
|
356
|
-
await this.fs.
|
|
440
|
+
await this.fs.atomicWriteFile(this.authPath, JSON.stringify(stored, null, 2));
|
|
357
441
|
}
|
|
358
442
|
}
|
|
359
443
|
async loadClient(baseUrl) {
|
|
@@ -370,7 +454,7 @@ class AuthStorageImpl {
|
|
|
370
454
|
if (Object.keys(stored.clients).length === 0) {
|
|
371
455
|
await this.fs.deleteFile(this.clientPath);
|
|
372
456
|
} else {
|
|
373
|
-
await this.fs.
|
|
457
|
+
await this.fs.atomicWriteFile(this.clientPath, JSON.stringify(stored, null, 2));
|
|
374
458
|
}
|
|
375
459
|
}
|
|
376
460
|
async saveClient(baseUrl, data) {
|
|
@@ -380,7 +464,7 @@ class AuthStorageImpl {
|
|
|
380
464
|
};
|
|
381
465
|
stored.clients[normalizeBaseUrl(baseUrl)] = data;
|
|
382
466
|
await this.fs.ensureDir(this.configDir, DIR_MODE);
|
|
383
|
-
await this.fs.
|
|
467
|
+
await this.fs.atomicWriteFile(this.clientPath, JSON.stringify(stored, null, 2));
|
|
384
468
|
}
|
|
385
469
|
async loadAuthFile() {
|
|
386
470
|
if (!await this.fs.exists(this.authPath))
|
|
@@ -531,54 +615,34 @@ class ChunkingKeyringService {
|
|
|
531
615
|
}
|
|
532
616
|
}
|
|
533
617
|
}
|
|
534
|
-
// src/services/
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
function extractFeatureFlags(payload) {
|
|
547
|
-
if (isStringArray(payload.feature_flags)) {
|
|
548
|
-
return payload.feature_flags;
|
|
549
|
-
}
|
|
550
|
-
if (payload.claims && isStringArray(payload.claims.feature_flags)) {
|
|
551
|
-
return payload.claims.feature_flags;
|
|
618
|
+
// src/services/client-update-required-error.ts
|
|
619
|
+
var CLIENT_UPDATE_REQUIRED_REASON = "Backend protocol changed";
|
|
620
|
+
|
|
621
|
+
class ClientUpdateRequiredError extends Error {
|
|
622
|
+
reason;
|
|
623
|
+
currentVersion;
|
|
624
|
+
constructor(message = `Update required: ${CLIENT_UPDATE_REQUIRED_REASON}`, reason = CLIENT_UPDATE_REQUIRED_REASON, currentVersion = version) {
|
|
625
|
+
super(message);
|
|
626
|
+
this.reason = reason;
|
|
627
|
+
this.currentVersion = currentVersion;
|
|
628
|
+
this.name = "ClientUpdateRequiredError";
|
|
552
629
|
}
|
|
553
|
-
return null;
|
|
554
630
|
}
|
|
555
|
-
function
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const
|
|
560
|
-
if (
|
|
561
|
-
return
|
|
562
|
-
try {
|
|
563
|
-
const decoded = Buffer.from(toBase64(parts[1] ?? ""), "base64").toString("utf8");
|
|
564
|
-
const parsed = JSON.parse(decoded);
|
|
565
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
566
|
-
return null;
|
|
567
|
-
}
|
|
568
|
-
return parsed;
|
|
569
|
-
} catch {
|
|
570
|
-
return null;
|
|
631
|
+
function isClientUpdateRequiredGraphQLError(input) {
|
|
632
|
+
if (input.code === "CLIENT_UPDATE_REQUIRED") {
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
const message = input.message;
|
|
636
|
+
if (!isGraphQLSchemaMismatchMessage(message)) {
|
|
637
|
+
return false;
|
|
571
638
|
}
|
|
639
|
+
return !input.code || input.code === "GRAPHQL_VALIDATION_FAILED" || input.code === "BAD_USER_INPUT";
|
|
572
640
|
}
|
|
573
|
-
function
|
|
574
|
-
|
|
575
|
-
const padding = normalized.length % 4;
|
|
576
|
-
if (padding === 0)
|
|
577
|
-
return normalized;
|
|
578
|
-
return normalized.padEnd(normalized.length + (4 - padding), "=");
|
|
641
|
+
function isGraphQLSchemaMismatchMessage(message) {
|
|
642
|
+
return /Cannot query field|Field .* does not exist|Unknown argument|Unknown type|Unknown field/i.test(message);
|
|
579
643
|
}
|
|
580
644
|
// src/services/code-navigation-service.ts
|
|
581
|
-
import { z } from "zod";
|
|
645
|
+
import { z as z2 } from "zod";
|
|
582
646
|
|
|
583
647
|
// src/shared/debug-log.ts
|
|
584
648
|
function debugLog(area, payload) {
|
|
@@ -903,17 +967,6 @@ async function withTelemetrySpan(name, operation, attributes) {
|
|
|
903
967
|
throw error;
|
|
904
968
|
}
|
|
905
969
|
}
|
|
906
|
-
function withTelemetrySpanSync(name, operation, attributes) {
|
|
907
|
-
const handle = telemetryCollector.startSpan(name, attributes);
|
|
908
|
-
try {
|
|
909
|
-
const result = operation();
|
|
910
|
-
telemetryCollector.endSpan(handle);
|
|
911
|
-
return result;
|
|
912
|
-
} catch (error) {
|
|
913
|
-
telemetryCollector.endSpan(handle, { error: true });
|
|
914
|
-
throw error;
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
970
|
function startTelemetrySpan(name, attributes) {
|
|
918
971
|
return telemetryCollector.startSpan(name, attributes);
|
|
919
972
|
}
|
|
@@ -1420,80 +1473,80 @@ function asRecord(value) {
|
|
|
1420
1473
|
}
|
|
1421
1474
|
return;
|
|
1422
1475
|
}
|
|
1423
|
-
var availableVersionSchema =
|
|
1424
|
-
version:
|
|
1425
|
-
ref:
|
|
1476
|
+
var availableVersionSchema = z2.object({
|
|
1477
|
+
version: z2.string().nullable().optional(),
|
|
1478
|
+
ref: z2.string()
|
|
1426
1479
|
});
|
|
1427
|
-
var unifiedSearchSourceSchema =
|
|
1428
|
-
var unifiedSearchResultTypeSchema =
|
|
1480
|
+
var unifiedSearchSourceSchema = z2.enum(["AUTO", "DOCS", "CODE", "SYMBOL"]);
|
|
1481
|
+
var unifiedSearchResultTypeSchema = z2.enum([
|
|
1429
1482
|
"DOCUMENTATION_PAGE",
|
|
1430
1483
|
"REPOSITORY_SYMBOL",
|
|
1431
1484
|
"REPOSITORY_CODE",
|
|
1432
1485
|
"REPOSITORY_DOC"
|
|
1433
1486
|
]);
|
|
1434
|
-
var unifiedSearchLocatorSchema =
|
|
1435
|
-
registry:
|
|
1436
|
-
packageName:
|
|
1437
|
-
version:
|
|
1438
|
-
pageId:
|
|
1439
|
-
sourceKind:
|
|
1440
|
-
sourceUrl:
|
|
1441
|
-
repoUrl:
|
|
1442
|
-
gitRef:
|
|
1443
|
-
requestedRef:
|
|
1444
|
-
filePath:
|
|
1445
|
-
startLine:
|
|
1446
|
-
endLine:
|
|
1447
|
-
fileContentHash:
|
|
1448
|
-
symbolRef:
|
|
1449
|
-
qualifiedPath:
|
|
1450
|
-
kind:
|
|
1451
|
-
category:
|
|
1452
|
-
language:
|
|
1487
|
+
var unifiedSearchLocatorSchema = z2.object({
|
|
1488
|
+
registry: z2.string().nullable().optional(),
|
|
1489
|
+
packageName: z2.string().nullable().optional(),
|
|
1490
|
+
version: z2.string().nullable().optional(),
|
|
1491
|
+
pageId: z2.string().nullable().optional(),
|
|
1492
|
+
sourceKind: z2.string().nullable().optional(),
|
|
1493
|
+
sourceUrl: z2.string().nullable().optional(),
|
|
1494
|
+
repoUrl: z2.string().nullable().optional(),
|
|
1495
|
+
gitRef: z2.string().nullable().optional(),
|
|
1496
|
+
requestedRef: z2.string().nullable().optional(),
|
|
1497
|
+
filePath: z2.string().nullable().optional(),
|
|
1498
|
+
startLine: z2.number().int().nullable().optional(),
|
|
1499
|
+
endLine: z2.number().int().nullable().optional(),
|
|
1500
|
+
fileContentHash: z2.string().nullable().optional(),
|
|
1501
|
+
symbolRef: z2.string().nullable().optional(),
|
|
1502
|
+
qualifiedPath: z2.string().nullable().optional(),
|
|
1503
|
+
kind: z2.string().nullable().optional(),
|
|
1504
|
+
category: z2.string().nullable().optional(),
|
|
1505
|
+
language: z2.string().nullable().optional()
|
|
1453
1506
|
});
|
|
1454
|
-
var unifiedSearchHitSchema =
|
|
1455
|
-
id:
|
|
1507
|
+
var unifiedSearchHitSchema = z2.object({
|
|
1508
|
+
id: z2.string(),
|
|
1456
1509
|
resultType: unifiedSearchResultTypeSchema,
|
|
1457
|
-
targetLabel:
|
|
1458
|
-
title:
|
|
1459
|
-
summary:
|
|
1460
|
-
score:
|
|
1461
|
-
highlights:
|
|
1462
|
-
title:
|
|
1463
|
-
summary:
|
|
1510
|
+
targetLabel: z2.string(),
|
|
1511
|
+
title: z2.string().nullable().optional(),
|
|
1512
|
+
summary: z2.string().nullable().optional(),
|
|
1513
|
+
score: z2.number().nullable().optional(),
|
|
1514
|
+
highlights: z2.object({
|
|
1515
|
+
title: z2.array(z2.tuple([z2.number().int(), z2.number().int()])).nullable().optional(),
|
|
1516
|
+
summary: z2.array(z2.tuple([z2.number().int(), z2.number().int()])).nullable().optional()
|
|
1464
1517
|
}).nullable().optional(),
|
|
1465
1518
|
locator: unifiedSearchLocatorSchema
|
|
1466
1519
|
});
|
|
1467
|
-
var unifiedSearchPageInfoSchema =
|
|
1468
|
-
offset:
|
|
1469
|
-
limit:
|
|
1470
|
-
returned:
|
|
1471
|
-
hasMore:
|
|
1520
|
+
var unifiedSearchPageInfoSchema = z2.object({
|
|
1521
|
+
offset: z2.number().int(),
|
|
1522
|
+
limit: z2.number().int(),
|
|
1523
|
+
returned: z2.number().int(),
|
|
1524
|
+
hasMore: z2.boolean()
|
|
1472
1525
|
});
|
|
1473
|
-
var unifiedSearchSourceStatusSchema =
|
|
1526
|
+
var unifiedSearchSourceStatusSchema = z2.object({
|
|
1474
1527
|
source: unifiedSearchSourceSchema,
|
|
1475
|
-
targetLabel:
|
|
1476
|
-
indexingStatus:
|
|
1477
|
-
codeIndexState:
|
|
1478
|
-
resultCount:
|
|
1479
|
-
appliedFilters:
|
|
1480
|
-
ignoredFilters:
|
|
1481
|
-
incompatibleFilters:
|
|
1482
|
-
appliedQueryFeatures:
|
|
1483
|
-
ignoredQueryFeatures:
|
|
1484
|
-
incompatibleQueryFeatures:
|
|
1485
|
-
note:
|
|
1528
|
+
targetLabel: z2.string(),
|
|
1529
|
+
indexingStatus: z2.string().nullable().optional(),
|
|
1530
|
+
codeIndexState: z2.string().nullable().optional(),
|
|
1531
|
+
resultCount: z2.number().int().nullable().optional(),
|
|
1532
|
+
appliedFilters: z2.array(z2.string()),
|
|
1533
|
+
ignoredFilters: z2.array(z2.string()),
|
|
1534
|
+
incompatibleFilters: z2.array(z2.string()),
|
|
1535
|
+
appliedQueryFeatures: z2.array(z2.string()),
|
|
1536
|
+
ignoredQueryFeatures: z2.array(z2.string()),
|
|
1537
|
+
incompatibleQueryFeatures: z2.array(z2.string()),
|
|
1538
|
+
note: z2.string().nullable().optional()
|
|
1486
1539
|
});
|
|
1487
|
-
var unifiedSearchResultSchema =
|
|
1488
|
-
query:
|
|
1489
|
-
queryWarnings:
|
|
1490
|
-
sources:
|
|
1491
|
-
results:
|
|
1540
|
+
var unifiedSearchResultSchema = z2.object({
|
|
1541
|
+
query: z2.string(),
|
|
1542
|
+
queryWarnings: z2.array(z2.string()),
|
|
1543
|
+
sources: z2.array(unifiedSearchSourceSchema),
|
|
1544
|
+
results: z2.array(unifiedSearchHitSchema),
|
|
1492
1545
|
page: unifiedSearchPageInfoSchema,
|
|
1493
|
-
partialResults:
|
|
1494
|
-
sourceStatus:
|
|
1546
|
+
partialResults: z2.boolean(),
|
|
1547
|
+
sourceStatus: z2.array(unifiedSearchSourceStatusSchema)
|
|
1495
1548
|
});
|
|
1496
|
-
var unifiedSearchSessionStatusSchema =
|
|
1549
|
+
var unifiedSearchSessionStatusSchema = z2.enum([
|
|
1497
1550
|
"PENDING",
|
|
1498
1551
|
"INDEXING",
|
|
1499
1552
|
"SEARCHING",
|
|
@@ -1501,60 +1554,60 @@ var unifiedSearchSessionStatusSchema = z.enum([
|
|
|
1501
1554
|
"TIMEOUT",
|
|
1502
1555
|
"FAILED"
|
|
1503
1556
|
]);
|
|
1504
|
-
var unifiedSearchProgressSchema =
|
|
1505
|
-
searchRef:
|
|
1557
|
+
var unifiedSearchProgressSchema = z2.object({
|
|
1558
|
+
searchRef: z2.string(),
|
|
1506
1559
|
status: unifiedSearchSessionStatusSchema,
|
|
1507
|
-
targetsTotal:
|
|
1508
|
-
targetsReady:
|
|
1509
|
-
elapsedMs:
|
|
1510
|
-
query:
|
|
1511
|
-
queryWarnings:
|
|
1512
|
-
sources:
|
|
1513
|
-
expiresAt:
|
|
1560
|
+
targetsTotal: z2.number().int(),
|
|
1561
|
+
targetsReady: z2.number().int(),
|
|
1562
|
+
elapsedMs: z2.number().int(),
|
|
1563
|
+
query: z2.string(),
|
|
1564
|
+
queryWarnings: z2.array(z2.string()),
|
|
1565
|
+
sources: z2.array(unifiedSearchSourceSchema),
|
|
1566
|
+
expiresAt: z2.string().nullable().optional(),
|
|
1514
1567
|
results: unifiedSearchResultSchema.nullable().optional()
|
|
1515
1568
|
});
|
|
1516
|
-
var asyncUnifiedSearchResultSchema =
|
|
1517
|
-
completed:
|
|
1518
|
-
searchRef:
|
|
1569
|
+
var asyncUnifiedSearchResultSchema = z2.object({
|
|
1570
|
+
completed: z2.boolean(),
|
|
1571
|
+
searchRef: z2.string().nullable().optional(),
|
|
1519
1572
|
result: unifiedSearchResultSchema.nullable().optional(),
|
|
1520
1573
|
progress: unifiedSearchProgressSchema.nullable().optional()
|
|
1521
1574
|
});
|
|
1522
|
-
var graphQLErrorSchema =
|
|
1523
|
-
message:
|
|
1524
|
-
extensions:
|
|
1575
|
+
var graphQLErrorSchema = z2.object({
|
|
1576
|
+
message: z2.string(),
|
|
1577
|
+
extensions: z2.record(z2.string(), z2.unknown()).optional()
|
|
1525
1578
|
});
|
|
1526
|
-
var navigationResolutionSchema =
|
|
1527
|
-
requestedVersion:
|
|
1528
|
-
requestedRef:
|
|
1529
|
-
resolvedRef:
|
|
1530
|
-
commitSha:
|
|
1579
|
+
var navigationResolutionSchema = z2.object({
|
|
1580
|
+
requestedVersion: z2.string().nullable().optional(),
|
|
1581
|
+
requestedRef: z2.string().nullable().optional(),
|
|
1582
|
+
resolvedRef: z2.string().nullable().optional(),
|
|
1583
|
+
commitSha: z2.string().nullable().optional()
|
|
1531
1584
|
}).nullable().optional();
|
|
1532
|
-
var navigationDiagnosticsSchema =
|
|
1533
|
-
hint:
|
|
1585
|
+
var navigationDiagnosticsSchema = z2.object({
|
|
1586
|
+
hint: z2.string().nullable().optional()
|
|
1534
1587
|
}).nullable().optional();
|
|
1535
|
-
var repoFileEntrySchema =
|
|
1536
|
-
path:
|
|
1537
|
-
name:
|
|
1538
|
-
language:
|
|
1539
|
-
fileType:
|
|
1540
|
-
byteSize:
|
|
1588
|
+
var repoFileEntrySchema = z2.object({
|
|
1589
|
+
path: z2.string(),
|
|
1590
|
+
name: z2.string().nullable().optional(),
|
|
1591
|
+
language: z2.string().nullable().optional(),
|
|
1592
|
+
fileType: z2.string().nullable().optional(),
|
|
1593
|
+
byteSize: z2.number().int().nullable().optional()
|
|
1541
1594
|
});
|
|
1542
|
-
var listRepoFilesResponseSchema =
|
|
1543
|
-
files:
|
|
1544
|
-
total:
|
|
1545
|
-
hasMore:
|
|
1546
|
-
indexedVersion:
|
|
1595
|
+
var listRepoFilesResponseSchema = z2.object({
|
|
1596
|
+
files: z2.array(repoFileEntrySchema),
|
|
1597
|
+
total: z2.number().int(),
|
|
1598
|
+
hasMore: z2.boolean(),
|
|
1599
|
+
indexedVersion: z2.string().nullable().optional(),
|
|
1547
1600
|
resolution: navigationResolutionSchema,
|
|
1548
1601
|
diagnostics: navigationDiagnosticsSchema,
|
|
1549
|
-
codeIndexState:
|
|
1550
|
-
indexingRef:
|
|
1551
|
-
availableVersions:
|
|
1602
|
+
codeIndexState: z2.string(),
|
|
1603
|
+
indexingRef: z2.string().nullable().optional(),
|
|
1604
|
+
availableVersions: z2.array(availableVersionSchema).nullable().optional()
|
|
1552
1605
|
});
|
|
1553
|
-
var listRepoFilesGraphQLResponseSchema =
|
|
1554
|
-
data:
|
|
1606
|
+
var listRepoFilesGraphQLResponseSchema = z2.object({
|
|
1607
|
+
data: z2.object({
|
|
1555
1608
|
listRepoFiles: listRepoFilesResponseSchema.nullable().optional()
|
|
1556
1609
|
}).nullable().optional(),
|
|
1557
|
-
errors:
|
|
1610
|
+
errors: z2.array(graphQLErrorSchema).optional()
|
|
1558
1611
|
});
|
|
1559
1612
|
var LIST_REPO_FILES_QUERY = `
|
|
1560
1613
|
query ListRepoFiles(
|
|
@@ -1604,24 +1657,24 @@ query ListRepoFiles(
|
|
|
1604
1657
|
}
|
|
1605
1658
|
}
|
|
1606
1659
|
}`;
|
|
1607
|
-
var codeContextResponseSchema =
|
|
1608
|
-
content:
|
|
1609
|
-
filePath:
|
|
1610
|
-
language:
|
|
1611
|
-
totalLines:
|
|
1612
|
-
startLine:
|
|
1613
|
-
endLine:
|
|
1614
|
-
repoUrl:
|
|
1615
|
-
gitRef:
|
|
1616
|
-
isBinary:
|
|
1617
|
-
codeIndexState:
|
|
1618
|
-
indexingRef:
|
|
1660
|
+
var codeContextResponseSchema = z2.object({
|
|
1661
|
+
content: z2.string().nullable().optional(),
|
|
1662
|
+
filePath: z2.string().nullable().optional(),
|
|
1663
|
+
language: z2.string().nullable().optional(),
|
|
1664
|
+
totalLines: z2.number().int().nullable().optional(),
|
|
1665
|
+
startLine: z2.number().int().nullable().optional(),
|
|
1666
|
+
endLine: z2.number().int().nullable().optional(),
|
|
1667
|
+
repoUrl: z2.string().nullable().optional(),
|
|
1668
|
+
gitRef: z2.string().nullable().optional(),
|
|
1669
|
+
isBinary: z2.boolean().nullable().optional(),
|
|
1670
|
+
codeIndexState: z2.string(),
|
|
1671
|
+
indexingRef: z2.string().nullable().optional()
|
|
1619
1672
|
});
|
|
1620
|
-
var fetchCodeContextGraphQLResponseSchema =
|
|
1621
|
-
data:
|
|
1673
|
+
var fetchCodeContextGraphQLResponseSchema = z2.object({
|
|
1674
|
+
data: z2.object({
|
|
1622
1675
|
fetchCodeContext: codeContextResponseSchema.nullable().optional()
|
|
1623
1676
|
}).nullable().optional(),
|
|
1624
|
-
errors:
|
|
1677
|
+
errors: z2.array(graphQLErrorSchema).optional()
|
|
1625
1678
|
});
|
|
1626
1679
|
var FETCH_CODE_CONTEXT_QUERY = `
|
|
1627
1680
|
query FetchCodeContext(
|
|
@@ -1659,63 +1712,63 @@ query FetchCodeContext(
|
|
|
1659
1712
|
indexingRef
|
|
1660
1713
|
}
|
|
1661
1714
|
}`;
|
|
1662
|
-
var grepRepoMatchSchema =
|
|
1663
|
-
filePath:
|
|
1664
|
-
line:
|
|
1665
|
-
matchStartByte:
|
|
1666
|
-
matchEndByte:
|
|
1667
|
-
lineContent:
|
|
1668
|
-
contextBefore:
|
|
1669
|
-
contextAfter:
|
|
1670
|
-
fileContentHash:
|
|
1671
|
-
fileIntent:
|
|
1672
|
-
symbolRowId:
|
|
1673
|
-
symbol:
|
|
1674
|
-
symbolRef:
|
|
1675
|
-
name:
|
|
1676
|
-
qualifiedPath:
|
|
1677
|
-
kind:
|
|
1678
|
-
category:
|
|
1679
|
-
arity:
|
|
1680
|
-
isPublic:
|
|
1681
|
-
filePath:
|
|
1682
|
-
startLine:
|
|
1683
|
-
endLine:
|
|
1684
|
-
code:
|
|
1685
|
-
callerCount:
|
|
1686
|
-
contentHash:
|
|
1687
|
-
parentSymbolRef:
|
|
1688
|
-
parentPath:
|
|
1715
|
+
var grepRepoMatchSchema = z2.object({
|
|
1716
|
+
filePath: z2.string(),
|
|
1717
|
+
line: z2.number().int(),
|
|
1718
|
+
matchStartByte: z2.number().int(),
|
|
1719
|
+
matchEndByte: z2.number().int(),
|
|
1720
|
+
lineContent: z2.string(),
|
|
1721
|
+
contextBefore: z2.array(z2.string()).nullable().optional(),
|
|
1722
|
+
contextAfter: z2.array(z2.string()).nullable().optional(),
|
|
1723
|
+
fileContentHash: z2.string().nullable().optional(),
|
|
1724
|
+
fileIntent: z2.string().nullable().optional(),
|
|
1725
|
+
symbolRowId: z2.string().nullable().optional(),
|
|
1726
|
+
symbol: z2.object({
|
|
1727
|
+
symbolRef: z2.string().optional(),
|
|
1728
|
+
name: z2.string().optional(),
|
|
1729
|
+
qualifiedPath: z2.string().nullable().optional(),
|
|
1730
|
+
kind: z2.string().nullable().optional(),
|
|
1731
|
+
category: z2.string().nullable().optional(),
|
|
1732
|
+
arity: z2.number().int().nullable().optional(),
|
|
1733
|
+
isPublic: z2.boolean().nullable().optional(),
|
|
1734
|
+
filePath: z2.string().nullable().optional(),
|
|
1735
|
+
startLine: z2.number().int().nullable().optional(),
|
|
1736
|
+
endLine: z2.number().int().nullable().optional(),
|
|
1737
|
+
code: z2.string().nullable().optional(),
|
|
1738
|
+
callerCount: z2.number().int().nullable().optional(),
|
|
1739
|
+
contentHash: z2.string().nullable().optional(),
|
|
1740
|
+
parentSymbolRef: z2.string().nullable().optional(),
|
|
1741
|
+
parentPath: z2.string().nullable().optional()
|
|
1689
1742
|
}).nullable().optional()
|
|
1690
1743
|
});
|
|
1691
|
-
var grepRepoResponseSchema =
|
|
1692
|
-
matches:
|
|
1693
|
-
nextCursor:
|
|
1694
|
-
hasMore:
|
|
1695
|
-
truncatedReason:
|
|
1744
|
+
var grepRepoResponseSchema = z2.object({
|
|
1745
|
+
matches: z2.array(grepRepoMatchSchema),
|
|
1746
|
+
nextCursor: z2.string().nullable().optional(),
|
|
1747
|
+
hasMore: z2.boolean(),
|
|
1748
|
+
truncatedReason: z2.enum([
|
|
1696
1749
|
"NONE",
|
|
1697
1750
|
"MAX_MATCHES",
|
|
1698
1751
|
"MAX_MATCHES_PER_FILE",
|
|
1699
1752
|
"DEADLINE"
|
|
1700
1753
|
]),
|
|
1701
|
-
routeTaken:
|
|
1702
|
-
filesScanned:
|
|
1703
|
-
filesInScope:
|
|
1704
|
-
binaryFilesSkipped:
|
|
1705
|
-
filesTooLargeSkipped:
|
|
1706
|
-
totalMatches:
|
|
1707
|
-
uniqueFilesMatched:
|
|
1708
|
-
indexedVersion:
|
|
1754
|
+
routeTaken: z2.enum(["SINGLE_FILE", "CONTENT_INDEX"]).nullable().optional(),
|
|
1755
|
+
filesScanned: z2.number().int(),
|
|
1756
|
+
filesInScope: z2.number().int(),
|
|
1757
|
+
binaryFilesSkipped: z2.number().int(),
|
|
1758
|
+
filesTooLargeSkipped: z2.number().int(),
|
|
1759
|
+
totalMatches: z2.number().int(),
|
|
1760
|
+
uniqueFilesMatched: z2.number().int(),
|
|
1761
|
+
indexedVersion: z2.string().nullable().optional(),
|
|
1709
1762
|
resolution: navigationResolutionSchema,
|
|
1710
|
-
codeIndexState:
|
|
1711
|
-
indexingRef:
|
|
1712
|
-
availableVersions:
|
|
1763
|
+
codeIndexState: z2.string(),
|
|
1764
|
+
indexingRef: z2.string().nullable().optional(),
|
|
1765
|
+
availableVersions: z2.array(availableVersionSchema).nullable().optional()
|
|
1713
1766
|
});
|
|
1714
|
-
var grepRepoGraphQLResponseSchema =
|
|
1715
|
-
data:
|
|
1767
|
+
var grepRepoGraphQLResponseSchema = z2.object({
|
|
1768
|
+
data: z2.object({
|
|
1716
1769
|
grepRepo: grepRepoResponseSchema.nullable().optional()
|
|
1717
1770
|
}).nullable().optional(),
|
|
1718
|
-
errors:
|
|
1771
|
+
errors: z2.array(graphQLErrorSchema).optional()
|
|
1719
1772
|
});
|
|
1720
1773
|
var GREP_REPO_SYMBOL_SELECTIONS = {
|
|
1721
1774
|
symbol_ref: "symbolRef",
|
|
@@ -1824,17 +1877,17 @@ query GrepRepo(
|
|
|
1824
1877
|
}
|
|
1825
1878
|
}`;
|
|
1826
1879
|
}
|
|
1827
|
-
var unifiedSearchGraphQLResponseSchema =
|
|
1828
|
-
data:
|
|
1880
|
+
var unifiedSearchGraphQLResponseSchema = z2.object({
|
|
1881
|
+
data: z2.object({
|
|
1829
1882
|
search: asyncUnifiedSearchResultSchema.nullable().optional()
|
|
1830
1883
|
}).nullable().optional(),
|
|
1831
|
-
errors:
|
|
1884
|
+
errors: z2.array(graphQLErrorSchema).optional()
|
|
1832
1885
|
});
|
|
1833
|
-
var unifiedSearchStatusGraphQLResponseSchema =
|
|
1834
|
-
data:
|
|
1886
|
+
var unifiedSearchStatusGraphQLResponseSchema = z2.object({
|
|
1887
|
+
data: z2.object({
|
|
1835
1888
|
discoverySearchProgress: unifiedSearchProgressSchema.nullable().optional()
|
|
1836
1889
|
}).nullable().optional(),
|
|
1837
|
-
errors:
|
|
1890
|
+
errors: z2.array(graphQLErrorSchema).optional()
|
|
1838
1891
|
});
|
|
1839
1892
|
|
|
1840
1893
|
class CodeNavigationServiceImpl {
|
|
@@ -1987,6 +2040,9 @@ class CodeNavigationServiceImpl {
|
|
|
1987
2040
|
const code = typeof extensions?.code === "string" ? extensions.code : undefined;
|
|
1988
2041
|
const retryable = typeof extensions?.retryable === "boolean" ? extensions.retryable : undefined;
|
|
1989
2042
|
const indexingRef = getGraphQLIndexingRef(errors);
|
|
2043
|
+
if (isClientUpdateRequiredGraphQLError({ message, code })) {
|
|
2044
|
+
return new ClientUpdateRequiredError;
|
|
2045
|
+
}
|
|
1990
2046
|
switch (code) {
|
|
1991
2047
|
case "PACKAGE_INDEXING":
|
|
1992
2048
|
return new CodeNavigationIndexingError(this.createIndexingMessage(indexingRef), indexingRef, parseAvailableVersions(extensions));
|
|
@@ -2481,19 +2537,11 @@ function getCodeNavigationUrl() {
|
|
|
2481
2537
|
if (explicitUrl) {
|
|
2482
2538
|
return explicitUrl;
|
|
2483
2539
|
}
|
|
2484
|
-
|
|
2485
|
-
return usingDefaultEnvironment ? DEFAULT_CODE_NAV_URL : undefined;
|
|
2540
|
+
return DEFAULT_CODE_NAV_URL;
|
|
2486
2541
|
}
|
|
2487
2542
|
function getEnvApiToken() {
|
|
2488
2543
|
return process.env.GITHITS_API_TOKEN;
|
|
2489
2544
|
}
|
|
2490
|
-
function isCodeNavigationCliOverrideEnabled() {
|
|
2491
|
-
const raw = process.env.GITHITS_CODE_NAVIGATION;
|
|
2492
|
-
if (!raw)
|
|
2493
|
-
return false;
|
|
2494
|
-
const normalized = raw.toLowerCase();
|
|
2495
|
-
return normalized !== "0" && normalized !== "false" && normalized !== "";
|
|
2496
|
-
}
|
|
2497
2545
|
// src/services/exec-service.ts
|
|
2498
2546
|
import { spawn } from "node:child_process";
|
|
2499
2547
|
|
|
@@ -2523,6 +2571,7 @@ class ExecServiceImpl {
|
|
|
2523
2571
|
}
|
|
2524
2572
|
}
|
|
2525
2573
|
// src/services/filesystem-service.ts
|
|
2574
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2526
2575
|
import {
|
|
2527
2576
|
mkdir,
|
|
2528
2577
|
readdir,
|
|
@@ -2586,7 +2635,7 @@ class FileSystemServiceImpl {
|
|
|
2586
2635
|
}
|
|
2587
2636
|
}
|
|
2588
2637
|
async atomicWriteFile(path, contents) {
|
|
2589
|
-
const tmpPath = `${path}.${process.pid}.${
|
|
2638
|
+
const tmpPath = `${path}.${process.pid}.${randomUUID2()}.tmp`;
|
|
2590
2639
|
let mode = 384;
|
|
2591
2640
|
try {
|
|
2592
2641
|
const existing = await stat(path);
|
|
@@ -2718,149 +2767,345 @@ class KeyringServiceImpl {
|
|
|
2718
2767
|
}
|
|
2719
2768
|
}
|
|
2720
2769
|
}
|
|
2770
|
+
// src/services/mode-aware-file-auth-storage.ts
|
|
2771
|
+
class AuthStoragePolicyError extends Error {
|
|
2772
|
+
constructor(message) {
|
|
2773
|
+
super(message);
|
|
2774
|
+
this.name = "AuthStoragePolicyError";
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
function createFileAuthStorageGuidance(configPath) {
|
|
2778
|
+
return `OAuth credentials were not saved to plaintext file storage.
|
|
2779
|
+
|
|
2780
|
+
Options:
|
|
2781
|
+
1. Unlock or fix your system keychain.
|
|
2782
|
+
2. Use GITHITS_API_TOKEN for CI/automation.
|
|
2783
|
+
3. If you accept storing OAuth credentials unencrypted on disk, set:
|
|
2784
|
+
|
|
2785
|
+
[auth]
|
|
2786
|
+
storage = "file"
|
|
2787
|
+
|
|
2788
|
+
in ${configPath}, or run with GITHITS_AUTH_STORAGE=file.
|
|
2789
|
+
|
|
2790
|
+
Warning: file storage is plaintext. Use it only on machines where local file access is trusted.`;
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
class ModeAwareFileAuthStorage {
|
|
2794
|
+
storage;
|
|
2795
|
+
mode;
|
|
2796
|
+
configPath;
|
|
2797
|
+
constructor(storage, mode, configPath = "your GitHits config.toml") {
|
|
2798
|
+
this.storage = storage;
|
|
2799
|
+
this.mode = mode;
|
|
2800
|
+
this.configPath = configPath;
|
|
2801
|
+
}
|
|
2802
|
+
loadTokens(baseUrl2) {
|
|
2803
|
+
return this.storage.loadTokens(baseUrl2);
|
|
2804
|
+
}
|
|
2805
|
+
async saveTokens(baseUrl2, data) {
|
|
2806
|
+
this.assertFileMode();
|
|
2807
|
+
await this.storage.saveTokens(baseUrl2, data);
|
|
2808
|
+
}
|
|
2809
|
+
clearTokens(baseUrl2) {
|
|
2810
|
+
return this.storage.clearTokens(baseUrl2);
|
|
2811
|
+
}
|
|
2812
|
+
loadClient(baseUrl2) {
|
|
2813
|
+
return this.storage.loadClient(baseUrl2);
|
|
2814
|
+
}
|
|
2815
|
+
async saveClient(baseUrl2, data) {
|
|
2816
|
+
this.assertFileMode();
|
|
2817
|
+
await this.storage.saveClient(baseUrl2, data);
|
|
2818
|
+
}
|
|
2819
|
+
clearClient(baseUrl2) {
|
|
2820
|
+
return this.storage.clearClient(baseUrl2);
|
|
2821
|
+
}
|
|
2822
|
+
getStorageLocation() {
|
|
2823
|
+
return this.storage.getStorageLocation();
|
|
2824
|
+
}
|
|
2825
|
+
assertFileMode() {
|
|
2826
|
+
if (this.mode === "file")
|
|
2827
|
+
return;
|
|
2828
|
+
throw new AuthStoragePolicyError(createFileAuthStorageGuidance(this.configPath));
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2721
2832
|
// src/services/migrating-auth-storage.ts
|
|
2722
2833
|
class MigratingAuthStorage {
|
|
2723
2834
|
primary;
|
|
2835
|
+
file;
|
|
2724
2836
|
legacy;
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2837
|
+
mode;
|
|
2838
|
+
configPath;
|
|
2839
|
+
onWarning;
|
|
2840
|
+
warnedFileModeKeychainExport = false;
|
|
2841
|
+
warnedAmbiguousPlaintext = false;
|
|
2842
|
+
constructor(primary, file, legacy, mode, configPath = "your GitHits config.toml", onWarning = () => {}) {
|
|
2729
2843
|
this.primary = primary;
|
|
2844
|
+
this.file = file;
|
|
2730
2845
|
this.legacy = legacy;
|
|
2731
|
-
this.
|
|
2846
|
+
this.mode = mode;
|
|
2847
|
+
this.configPath = configPath;
|
|
2848
|
+
this.onWarning = onWarning;
|
|
2732
2849
|
}
|
|
2733
2850
|
async loadTokens(baseUrl2) {
|
|
2734
|
-
if (this.
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2851
|
+
if (this.mode === "file") {
|
|
2852
|
+
return this.loadTokensFileMode(baseUrl2);
|
|
2853
|
+
}
|
|
2854
|
+
return this.loadTokensKeychainMode(baseUrl2);
|
|
2855
|
+
}
|
|
2856
|
+
async saveTokens(baseUrl2, data) {
|
|
2857
|
+
if (this.mode === "file") {
|
|
2858
|
+
await this.file.saveTokens(baseUrl2, data);
|
|
2859
|
+
return;
|
|
2743
2860
|
}
|
|
2744
|
-
const legacyTokens = await this.legacy.loadTokens(baseUrl2);
|
|
2745
|
-
if (!legacyTokens)
|
|
2746
|
-
return null;
|
|
2747
|
-
if (!this.primaryAvailable)
|
|
2748
|
-
return legacyTokens;
|
|
2749
2861
|
try {
|
|
2750
|
-
await this.primary.saveTokens(baseUrl2,
|
|
2862
|
+
await this.primary.saveTokens(baseUrl2, data);
|
|
2751
2863
|
} catch (error) {
|
|
2752
|
-
|
|
2753
|
-
throw error;
|
|
2754
|
-
return legacyTokens;
|
|
2864
|
+
throw this.toPolicyError(error);
|
|
2755
2865
|
}
|
|
2756
|
-
try {
|
|
2757
|
-
await this.legacy.clearTokens(baseUrl2);
|
|
2758
|
-
} catch {}
|
|
2759
|
-
return legacyTokens;
|
|
2760
2866
|
}
|
|
2761
|
-
async
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
if (!this.handlePrimaryFailure(error))
|
|
2768
|
-
throw error;
|
|
2769
|
-
}
|
|
2867
|
+
async clearTokens(baseUrl2) {
|
|
2868
|
+
const primaryError = await this.clearBestEffort(() => this.primary.clearTokens(baseUrl2));
|
|
2869
|
+
await this.clearBestEffort(() => this.file.clearTokens(baseUrl2));
|
|
2870
|
+
await this.clearBestEffort(() => this.legacy.clearTokens(baseUrl2));
|
|
2871
|
+
if (primaryError && !(primaryError instanceof KeychainUnavailableError)) {
|
|
2872
|
+
throw primaryError;
|
|
2770
2873
|
}
|
|
2771
|
-
await this.legacy.saveTokens(baseUrl2, data);
|
|
2772
2874
|
}
|
|
2773
|
-
async
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2875
|
+
async loadClient(baseUrl2) {
|
|
2876
|
+
if (this.mode === "file") {
|
|
2877
|
+
return this.loadClientFileMode(baseUrl2);
|
|
2878
|
+
}
|
|
2879
|
+
return this.loadClientKeychainMode(baseUrl2);
|
|
2880
|
+
}
|
|
2881
|
+
async saveClient(baseUrl2, data) {
|
|
2882
|
+
if (this.mode === "file") {
|
|
2883
|
+
await this.file.saveClient(baseUrl2, data);
|
|
2884
|
+
return;
|
|
2783
2885
|
}
|
|
2784
2886
|
try {
|
|
2785
|
-
await this.
|
|
2786
|
-
} catch {
|
|
2787
|
-
|
|
2887
|
+
await this.primary.saveClient(baseUrl2, data);
|
|
2888
|
+
} catch (error) {
|
|
2889
|
+
throw this.toPolicyError(error);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
async clearClient(baseUrl2) {
|
|
2893
|
+
const primaryError = await this.clearBestEffort(() => this.primary.clearClient(baseUrl2));
|
|
2894
|
+
await this.clearBestEffort(() => this.file.clearClient(baseUrl2));
|
|
2895
|
+
await this.clearBestEffort(() => this.legacy.clearClient(baseUrl2));
|
|
2896
|
+
if (primaryError && !(primaryError instanceof KeychainUnavailableError)) {
|
|
2788
2897
|
throw primaryError;
|
|
2898
|
+
}
|
|
2789
2899
|
}
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2900
|
+
getStorageLocation() {
|
|
2901
|
+
return this.mode === "file" ? this.file.getStorageLocation() : this.primary.getStorageLocation();
|
|
2902
|
+
}
|
|
2903
|
+
async loadTokensKeychainMode(baseUrl2) {
|
|
2904
|
+
try {
|
|
2905
|
+
const primaryTokens = await this.primary.loadTokens(baseUrl2);
|
|
2906
|
+
if (primaryTokens)
|
|
2907
|
+
return primaryTokens;
|
|
2908
|
+
} catch (error) {
|
|
2909
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
2910
|
+
throw error;
|
|
2911
|
+
}
|
|
2912
|
+
const candidate = await this.selectPlaintextTokenCandidate(baseUrl2);
|
|
2913
|
+
if (!candidate)
|
|
2914
|
+
return null;
|
|
2915
|
+
try {
|
|
2916
|
+
await this.primary.saveTokens(baseUrl2, candidate.data);
|
|
2917
|
+
} catch (error) {
|
|
2918
|
+
if (error instanceof KeychainUnavailableError)
|
|
2919
|
+
return candidate.data;
|
|
2920
|
+
throw error;
|
|
2921
|
+
}
|
|
2922
|
+
await this.clearMigratedPlaintext(baseUrl2, "tokens", candidate.source, candidate.ambiguous);
|
|
2923
|
+
return candidate.data;
|
|
2924
|
+
}
|
|
2925
|
+
async loadTokensFileMode(baseUrl2) {
|
|
2926
|
+
const candidate = await this.selectPlaintextTokenCandidate(baseUrl2);
|
|
2927
|
+
if (candidate) {
|
|
2928
|
+
if (candidate.source === "legacy") {
|
|
2929
|
+
await this.file.saveTokens(baseUrl2, candidate.data);
|
|
2930
|
+
await this.clearBestEffort(() => this.legacy.clearTokens(baseUrl2));
|
|
2799
2931
|
}
|
|
2932
|
+
return candidate.data;
|
|
2800
2933
|
}
|
|
2801
|
-
|
|
2802
|
-
|
|
2934
|
+
let primaryTokens = null;
|
|
2935
|
+
try {
|
|
2936
|
+
primaryTokens = await this.primary.loadTokens(baseUrl2);
|
|
2937
|
+
} catch (error) {
|
|
2938
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
2939
|
+
throw error;
|
|
2940
|
+
}
|
|
2941
|
+
if (!primaryTokens)
|
|
2803
2942
|
return null;
|
|
2804
|
-
|
|
2805
|
-
|
|
2943
|
+
this.warnKeychainExport();
|
|
2944
|
+
await this.file.saveTokens(baseUrl2, primaryTokens);
|
|
2945
|
+
return primaryTokens;
|
|
2946
|
+
}
|
|
2947
|
+
async loadClientKeychainMode(baseUrl2) {
|
|
2806
2948
|
try {
|
|
2807
|
-
await this.primary.
|
|
2949
|
+
const primaryClient = await this.primary.loadClient(baseUrl2);
|
|
2950
|
+
if (primaryClient)
|
|
2951
|
+
return primaryClient;
|
|
2808
2952
|
} catch (error) {
|
|
2809
|
-
if (!
|
|
2953
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
2810
2954
|
throw error;
|
|
2811
|
-
return legacyClient;
|
|
2812
2955
|
}
|
|
2956
|
+
const candidate = await this.selectPlaintextClientCandidate(baseUrl2);
|
|
2957
|
+
if (!candidate)
|
|
2958
|
+
return null;
|
|
2813
2959
|
try {
|
|
2814
|
-
await this.
|
|
2815
|
-
} catch {
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
if (this.primaryAvailable) {
|
|
2820
|
-
try {
|
|
2821
|
-
await this.primary.saveClient(baseUrl2, data);
|
|
2822
|
-
return;
|
|
2823
|
-
} catch (error) {
|
|
2824
|
-
if (!this.handlePrimaryFailure(error))
|
|
2825
|
-
throw error;
|
|
2826
|
-
}
|
|
2960
|
+
await this.primary.saveClient(baseUrl2, candidate.data);
|
|
2961
|
+
} catch (error) {
|
|
2962
|
+
if (error instanceof KeychainUnavailableError)
|
|
2963
|
+
return candidate.data;
|
|
2964
|
+
throw error;
|
|
2827
2965
|
}
|
|
2828
|
-
await this.
|
|
2966
|
+
await this.clearMigratedPlaintext(baseUrl2, "client", candidate.source, candidate.ambiguous);
|
|
2967
|
+
return candidate.data;
|
|
2829
2968
|
}
|
|
2830
|
-
async
|
|
2831
|
-
|
|
2832
|
-
if (
|
|
2833
|
-
|
|
2834
|
-
await this.
|
|
2835
|
-
|
|
2836
|
-
if (!this.handlePrimaryFailure(error)) {
|
|
2837
|
-
primaryError = error;
|
|
2838
|
-
}
|
|
2969
|
+
async loadClientFileMode(baseUrl2) {
|
|
2970
|
+
const candidate = await this.selectPlaintextClientCandidate(baseUrl2);
|
|
2971
|
+
if (candidate) {
|
|
2972
|
+
if (candidate.source === "legacy") {
|
|
2973
|
+
await this.file.saveClient(baseUrl2, candidate.data);
|
|
2974
|
+
await this.clearBestEffort(() => this.legacy.clearClient(baseUrl2));
|
|
2839
2975
|
}
|
|
2976
|
+
return candidate.data;
|
|
2840
2977
|
}
|
|
2978
|
+
let primaryClient = null;
|
|
2841
2979
|
try {
|
|
2842
|
-
await this.
|
|
2843
|
-
} catch {
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2980
|
+
primaryClient = await this.primary.loadClient(baseUrl2);
|
|
2981
|
+
} catch (error) {
|
|
2982
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
2983
|
+
throw error;
|
|
2984
|
+
}
|
|
2985
|
+
if (!primaryClient)
|
|
2986
|
+
return null;
|
|
2987
|
+
this.warnKeychainExport();
|
|
2988
|
+
await this.file.saveClient(baseUrl2, primaryClient);
|
|
2989
|
+
return primaryClient;
|
|
2990
|
+
}
|
|
2991
|
+
async selectPlaintextTokenCandidate(baseUrl2) {
|
|
2992
|
+
const candidates = [];
|
|
2993
|
+
const fileTokens = await this.file.loadTokens(baseUrl2);
|
|
2994
|
+
if (fileTokens) {
|
|
2995
|
+
candidates.push({
|
|
2996
|
+
data: fileTokens,
|
|
2997
|
+
source: "file",
|
|
2998
|
+
timestamp: fileTokens.createdAt,
|
|
2999
|
+
ambiguous: false
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
const legacyTokens = await this.legacy.loadTokens(baseUrl2);
|
|
3003
|
+
if (legacyTokens) {
|
|
3004
|
+
candidates.push({
|
|
3005
|
+
data: legacyTokens,
|
|
3006
|
+
source: "legacy",
|
|
3007
|
+
timestamp: legacyTokens.createdAt,
|
|
3008
|
+
ambiguous: false
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
return this.selectNewestCandidate(candidates);
|
|
3012
|
+
}
|
|
3013
|
+
async selectPlaintextClientCandidate(baseUrl2) {
|
|
3014
|
+
const candidates = [];
|
|
3015
|
+
const fileClient = await this.file.loadClient(baseUrl2);
|
|
3016
|
+
if (fileClient) {
|
|
3017
|
+
candidates.push({
|
|
3018
|
+
data: fileClient,
|
|
3019
|
+
source: "file",
|
|
3020
|
+
timestamp: fileClient.registeredAt,
|
|
3021
|
+
ambiguous: false
|
|
3022
|
+
});
|
|
3023
|
+
}
|
|
3024
|
+
const legacyClient = await this.legacy.loadClient(baseUrl2);
|
|
3025
|
+
if (legacyClient) {
|
|
3026
|
+
candidates.push({
|
|
3027
|
+
data: legacyClient,
|
|
3028
|
+
source: "legacy",
|
|
3029
|
+
timestamp: legacyClient.registeredAt,
|
|
3030
|
+
ambiguous: false
|
|
3031
|
+
});
|
|
3032
|
+
}
|
|
3033
|
+
return this.selectNewestCandidate(candidates);
|
|
2849
3034
|
}
|
|
2850
|
-
|
|
2851
|
-
if (
|
|
2852
|
-
return
|
|
3035
|
+
selectNewestCandidate(candidates) {
|
|
3036
|
+
if (candidates.length === 0)
|
|
3037
|
+
return null;
|
|
3038
|
+
if (candidates.length === 1)
|
|
3039
|
+
return candidates[0] ?? null;
|
|
3040
|
+
const parsed = candidates.map((candidate) => ({
|
|
3041
|
+
candidate,
|
|
3042
|
+
timestampMs: Date.parse(candidate.timestamp)
|
|
3043
|
+
}));
|
|
3044
|
+
if (parsed.some((entry) => Number.isNaN(entry.timestampMs))) {
|
|
3045
|
+
this.warnAmbiguousPlaintext();
|
|
3046
|
+
const selected = candidates.find((candidate) => candidate.source === "file") ?? candidates[0] ?? null;
|
|
3047
|
+
if (selected)
|
|
3048
|
+
selected.ambiguous = true;
|
|
3049
|
+
return selected;
|
|
3050
|
+
}
|
|
3051
|
+
const sorted = [...parsed].sort((a, b) => b.timestampMs - a.timestampMs);
|
|
3052
|
+
const first = sorted[0];
|
|
3053
|
+
const second = sorted[1];
|
|
3054
|
+
if (!first)
|
|
3055
|
+
return candidates[0] ?? null;
|
|
3056
|
+
if (second && first.timestampMs === second.timestampMs) {
|
|
3057
|
+
this.warnAmbiguousPlaintext();
|
|
3058
|
+
const selected = candidates.find((candidate) => candidate.source === "file") ?? first.candidate;
|
|
3059
|
+
selected.ambiguous = true;
|
|
3060
|
+
return selected;
|
|
3061
|
+
}
|
|
3062
|
+
return first.candidate;
|
|
3063
|
+
}
|
|
3064
|
+
async clearMigratedPlaintext(baseUrl2, kind, source, ambiguous = false) {
|
|
3065
|
+
if (!ambiguous) {
|
|
3066
|
+
await this.clearPlaintextSource(this.file, baseUrl2, kind);
|
|
3067
|
+
await this.clearPlaintextSource(this.legacy, baseUrl2, kind);
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
if (source === "file") {
|
|
3071
|
+
await this.clearPlaintextSource(this.file, baseUrl2, kind);
|
|
3072
|
+
return;
|
|
2853
3073
|
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
this.warnedOnPrimaryFailure = true;
|
|
2857
|
-
this.onPrimaryUnavailable(error);
|
|
3074
|
+
if (source === "legacy") {
|
|
3075
|
+
await this.clearPlaintextSource(this.legacy, baseUrl2, kind);
|
|
2858
3076
|
}
|
|
2859
|
-
|
|
3077
|
+
}
|
|
3078
|
+
async clearPlaintextSource(storage, baseUrl2, kind) {
|
|
3079
|
+
await this.clearBestEffort(() => kind === "tokens" ? storage.clearTokens(baseUrl2) : storage.clearClient(baseUrl2));
|
|
3080
|
+
}
|
|
3081
|
+
async clearBestEffort(fn) {
|
|
3082
|
+
try {
|
|
3083
|
+
await fn();
|
|
3084
|
+
return;
|
|
3085
|
+
} catch (error) {
|
|
3086
|
+
return error;
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
toPolicyError(error) {
|
|
3090
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
3091
|
+
return error;
|
|
3092
|
+
return new AuthStoragePolicyError(`System keychain is unavailable. ${createFileAuthStorageGuidance(this.configPath)}`);
|
|
3093
|
+
}
|
|
3094
|
+
warnKeychainExport() {
|
|
3095
|
+
if (this.warnedFileModeKeychainExport)
|
|
3096
|
+
return;
|
|
3097
|
+
this.warnedFileModeKeychainExport = true;
|
|
3098
|
+
this.onWarning("Warning: auth.storage=file is exporting existing keychain credentials to plaintext file storage.");
|
|
3099
|
+
}
|
|
3100
|
+
warnAmbiguousPlaintext() {
|
|
3101
|
+
if (this.warnedAmbiguousPlaintext)
|
|
3102
|
+
return;
|
|
3103
|
+
this.warnedAmbiguousPlaintext = true;
|
|
3104
|
+
this.onWarning("Warning: multiple plaintext auth entries exist with ambiguous timestamps; using the new config auth path and leaving the other entry intact.");
|
|
2860
3105
|
}
|
|
2861
3106
|
}
|
|
2862
3107
|
// src/services/package-intelligence-service.ts
|
|
2863
|
-
import { z as
|
|
3108
|
+
import { z as z3 } from "zod";
|
|
2864
3109
|
|
|
2865
3110
|
// src/services/promote-version-not-found.ts
|
|
2866
3111
|
function promoteGenericVersionNotFound(error, params) {
|
|
@@ -2975,63 +3220,63 @@ class PackageIntelligenceChangelogSourceNotFoundError extends Error {
|
|
|
2975
3220
|
this.name = "PackageIntelligenceChangelogSourceNotFoundError";
|
|
2976
3221
|
}
|
|
2977
3222
|
}
|
|
2978
|
-
var githubRepositorySchema =
|
|
2979
|
-
stargazersCount:
|
|
2980
|
-
forksCount:
|
|
2981
|
-
openIssuesCount:
|
|
2982
|
-
archived:
|
|
2983
|
-
language:
|
|
2984
|
-
topics:
|
|
2985
|
-
pushedAt:
|
|
3223
|
+
var githubRepositorySchema = z3.object({
|
|
3224
|
+
stargazersCount: z3.number().int().nullable().optional(),
|
|
3225
|
+
forksCount: z3.number().int().nullable().optional(),
|
|
3226
|
+
openIssuesCount: z3.number().int().nullable().optional(),
|
|
3227
|
+
archived: z3.boolean().nullable().optional(),
|
|
3228
|
+
language: z3.string().nullable().optional(),
|
|
3229
|
+
topics: z3.array(z3.string()).nullable().optional(),
|
|
3230
|
+
pushedAt: z3.string().nullable().optional()
|
|
2986
3231
|
}).nullable().optional();
|
|
2987
|
-
var packageIdentitySchema =
|
|
2988
|
-
name:
|
|
2989
|
-
registry:
|
|
2990
|
-
description:
|
|
2991
|
-
latestVersion:
|
|
2992
|
-
latestVersionPublishedAt:
|
|
2993
|
-
homepage:
|
|
2994
|
-
repositoryUrl:
|
|
2995
|
-
license:
|
|
2996
|
-
downloadsLastMonth:
|
|
2997
|
-
downloadsTotal:
|
|
3232
|
+
var packageIdentitySchema = z3.object({
|
|
3233
|
+
name: z3.string().nullable().optional(),
|
|
3234
|
+
registry: z3.string().nullable().optional(),
|
|
3235
|
+
description: z3.string().nullable().optional(),
|
|
3236
|
+
latestVersion: z3.string().nullable().optional(),
|
|
3237
|
+
latestVersionPublishedAt: z3.string().nullable().optional(),
|
|
3238
|
+
homepage: z3.string().nullable().optional(),
|
|
3239
|
+
repositoryUrl: z3.string().nullable().optional(),
|
|
3240
|
+
license: z3.string().nullable().optional(),
|
|
3241
|
+
downloadsLastMonth: z3.number().int().nullable().optional(),
|
|
3242
|
+
downloadsTotal: z3.number().int().nullable().optional(),
|
|
2998
3243
|
githubRepository: githubRepositorySchema
|
|
2999
3244
|
});
|
|
3000
|
-
var vulnerabilityOverviewSchema =
|
|
3001
|
-
osvId:
|
|
3002
|
-
summary:
|
|
3003
|
-
severityScore:
|
|
3004
|
-
publishedAt:
|
|
3245
|
+
var vulnerabilityOverviewSchema = z3.object({
|
|
3246
|
+
osvId: z3.string().nullable().optional(),
|
|
3247
|
+
summary: z3.string().nullable().optional(),
|
|
3248
|
+
severityScore: z3.number().nullable().optional(),
|
|
3249
|
+
publishedAt: z3.string().nullable().optional()
|
|
3005
3250
|
});
|
|
3006
|
-
var packageSecurityOverviewSchema =
|
|
3007
|
-
vulnerabilityCount:
|
|
3008
|
-
hasCurrentVulnerabilities:
|
|
3009
|
-
recentVulnerabilities:
|
|
3251
|
+
var packageSecurityOverviewSchema = z3.object({
|
|
3252
|
+
vulnerabilityCount: z3.number().int().nullable().optional(),
|
|
3253
|
+
hasCurrentVulnerabilities: z3.boolean().nullable().optional(),
|
|
3254
|
+
recentVulnerabilities: z3.array(vulnerabilityOverviewSchema).nullable().optional()
|
|
3010
3255
|
}).nullable().optional();
|
|
3011
|
-
var quickstartInfoSchema =
|
|
3012
|
-
installCommand:
|
|
3013
|
-
usageExample:
|
|
3256
|
+
var quickstartInfoSchema = z3.object({
|
|
3257
|
+
installCommand: z3.string().nullable().optional(),
|
|
3258
|
+
usageExample: z3.string().nullable().optional()
|
|
3014
3259
|
}).nullable().optional();
|
|
3015
|
-
var changelogEntrySchema =
|
|
3016
|
-
version:
|
|
3017
|
-
publishedAt:
|
|
3018
|
-
body:
|
|
3260
|
+
var changelogEntrySchema = z3.object({
|
|
3261
|
+
version: z3.string().nullable().optional(),
|
|
3262
|
+
publishedAt: z3.string().nullable().optional(),
|
|
3263
|
+
body: z3.string().nullable().optional()
|
|
3019
3264
|
});
|
|
3020
|
-
var packageSummaryResponseSchema =
|
|
3265
|
+
var packageSummaryResponseSchema = z3.object({
|
|
3021
3266
|
package: packageIdentitySchema.nullable().optional(),
|
|
3022
3267
|
security: packageSecurityOverviewSchema,
|
|
3023
3268
|
quickstart: quickstartInfoSchema,
|
|
3024
|
-
latestChangelogs:
|
|
3269
|
+
latestChangelogs: z3.array(changelogEntrySchema).nullable().optional()
|
|
3025
3270
|
});
|
|
3026
|
-
var graphQLErrorSchema2 =
|
|
3027
|
-
message:
|
|
3028
|
-
extensions:
|
|
3271
|
+
var graphQLErrorSchema2 = z3.object({
|
|
3272
|
+
message: z3.string(),
|
|
3273
|
+
extensions: z3.record(z3.string(), z3.unknown()).optional()
|
|
3029
3274
|
});
|
|
3030
|
-
var graphQLResponseSchema =
|
|
3031
|
-
data:
|
|
3275
|
+
var graphQLResponseSchema = z3.object({
|
|
3276
|
+
data: z3.object({
|
|
3032
3277
|
packageSummary: packageSummaryResponseSchema.nullable().optional()
|
|
3033
3278
|
}).nullable().optional(),
|
|
3034
|
-
errors:
|
|
3279
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3035
3280
|
});
|
|
3036
3281
|
var PACKAGE_SUMMARY_QUERY = `
|
|
3037
3282
|
query PackageSummary($registry: Registry!, $name: String!) {
|
|
@@ -3078,39 +3323,55 @@ query PackageSummary($registry: Registry!, $name: String!) {
|
|
|
3078
3323
|
}
|
|
3079
3324
|
}
|
|
3080
3325
|
}`;
|
|
3081
|
-
var packageVersionIdentitySchema =
|
|
3082
|
-
name:
|
|
3083
|
-
registry:
|
|
3084
|
-
version:
|
|
3326
|
+
var packageVersionIdentitySchema = z3.object({
|
|
3327
|
+
name: z3.string().nullable().optional(),
|
|
3328
|
+
registry: z3.string().nullable().optional(),
|
|
3329
|
+
version: z3.string().nullable().optional()
|
|
3085
3330
|
});
|
|
3086
|
-
var vulnerabilityDetailSchema =
|
|
3087
|
-
osvId:
|
|
3088
|
-
summary:
|
|
3089
|
-
severityScore:
|
|
3090
|
-
severityType:
|
|
3091
|
-
affectedVersionRanges:
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3331
|
+
var vulnerabilityDetailSchema = z3.object({
|
|
3332
|
+
osvId: z3.string().nullable().optional(),
|
|
3333
|
+
summary: z3.string().nullable().optional(),
|
|
3334
|
+
severityScore: z3.number().nullable().optional(),
|
|
3335
|
+
severityType: z3.string().nullable().optional(),
|
|
3336
|
+
affectedVersionRanges: z3.array(z3.string()).nullable().optional(),
|
|
3337
|
+
affectedVersionRangesCount: z3.number().int(),
|
|
3338
|
+
affectedVersionRangesTruncated: z3.boolean(),
|
|
3339
|
+
fixedInVersions: z3.array(z3.string()).nullable().optional(),
|
|
3340
|
+
publishedAt: z3.string().nullable().optional(),
|
|
3341
|
+
modifiedAt: z3.string().nullable().optional(),
|
|
3342
|
+
withdrawnAt: z3.string().nullable().optional(),
|
|
3343
|
+
aliases: z3.array(z3.string()).nullable().optional(),
|
|
3344
|
+
isMalicious: z3.boolean().nullable().optional(),
|
|
3345
|
+
affectsInspectedVersion: z3.boolean(),
|
|
3346
|
+
matchedAffectedVersionRanges: z3.array(z3.string()),
|
|
3347
|
+
duplicateIds: z3.array(z3.string())
|
|
3098
3348
|
});
|
|
3099
|
-
var
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3349
|
+
var pageInfoSchema = z3.object({
|
|
3350
|
+
hasNextPage: z3.boolean(),
|
|
3351
|
+
endCursor: z3.string().nullable().optional(),
|
|
3352
|
+
totalCount: z3.number().int()
|
|
3353
|
+
});
|
|
3354
|
+
var vulnerabilityAdvisoryPageSchema = z3.object({
|
|
3355
|
+
entries: z3.array(vulnerabilityDetailSchema),
|
|
3356
|
+
pageInfo: pageInfoSchema
|
|
3357
|
+
});
|
|
3358
|
+
var vulnerabilitySecurityDetailsSchema = z3.object({
|
|
3359
|
+
affectedVulnerabilityCount: z3.number().int(),
|
|
3360
|
+
nonAffectingVulnerabilityCount: z3.number().int(),
|
|
3361
|
+
allVulnerabilityCount: z3.number().int(),
|
|
3362
|
+
currentVersionAffected: z3.boolean().nullable().optional(),
|
|
3363
|
+
advisories: vulnerabilityAdvisoryPageSchema,
|
|
3364
|
+
upgradePaths: z3.array(z3.string()).nullable().optional()
|
|
3104
3365
|
}).nullable().optional();
|
|
3105
|
-
var vulnerabilityReportResponseSchema =
|
|
3366
|
+
var vulnerabilityReportResponseSchema = z3.object({
|
|
3106
3367
|
package: packageVersionIdentitySchema.nullable().optional(),
|
|
3107
3368
|
security: vulnerabilitySecurityDetailsSchema
|
|
3108
3369
|
});
|
|
3109
|
-
var vulnerabilitiesGraphQLResponseSchema =
|
|
3110
|
-
data:
|
|
3370
|
+
var vulnerabilitiesGraphQLResponseSchema = z3.object({
|
|
3371
|
+
data: z3.object({
|
|
3111
3372
|
packageVulnerabilities: vulnerabilityReportResponseSchema.nullable().optional()
|
|
3112
3373
|
}).nullable().optional(),
|
|
3113
|
-
errors:
|
|
3374
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3114
3375
|
});
|
|
3115
3376
|
var PACKAGE_VULNERABILITIES_QUERY = `
|
|
3116
3377
|
query PackageVulnerabilities(
|
|
@@ -3119,6 +3380,7 @@ query PackageVulnerabilities(
|
|
|
3119
3380
|
$version: String
|
|
3120
3381
|
$minSeverity: Float
|
|
3121
3382
|
$includeWithdrawn: Boolean
|
|
3383
|
+
$after: String
|
|
3122
3384
|
) {
|
|
3123
3385
|
packageVulnerabilities(
|
|
3124
3386
|
registry: $registry
|
|
@@ -3133,110 +3395,124 @@ query PackageVulnerabilities(
|
|
|
3133
3395
|
version
|
|
3134
3396
|
}
|
|
3135
3397
|
security {
|
|
3136
|
-
|
|
3398
|
+
affectedVulnerabilityCount
|
|
3399
|
+
nonAffectingVulnerabilityCount
|
|
3400
|
+
allVulnerabilityCount
|
|
3137
3401
|
currentVersionAffected
|
|
3138
3402
|
upgradePaths
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3403
|
+
advisories(scope: AFFECTED, first: 100, after: $after) {
|
|
3404
|
+
entries {
|
|
3405
|
+
osvId
|
|
3406
|
+
summary
|
|
3407
|
+
severityScore
|
|
3408
|
+
severityType
|
|
3409
|
+
affectedVersionRanges
|
|
3410
|
+
affectedVersionRangesCount
|
|
3411
|
+
affectedVersionRangesTruncated
|
|
3412
|
+
fixedInVersions
|
|
3413
|
+
publishedAt
|
|
3414
|
+
modifiedAt
|
|
3415
|
+
withdrawnAt
|
|
3416
|
+
aliases
|
|
3417
|
+
isMalicious
|
|
3418
|
+
affectsInspectedVersion
|
|
3419
|
+
matchedAffectedVersionRanges
|
|
3420
|
+
duplicateIds
|
|
3421
|
+
}
|
|
3422
|
+
pageInfo {
|
|
3423
|
+
hasNextPage
|
|
3424
|
+
endCursor
|
|
3425
|
+
totalCount
|
|
3426
|
+
}
|
|
3151
3427
|
}
|
|
3152
3428
|
}
|
|
3153
3429
|
}
|
|
3154
3430
|
}`;
|
|
3155
|
-
var directDependencySchema =
|
|
3156
|
-
name:
|
|
3157
|
-
versionConstraint:
|
|
3158
|
-
type:
|
|
3431
|
+
var directDependencySchema = z3.object({
|
|
3432
|
+
name: z3.string().nullable().optional(),
|
|
3433
|
+
versionConstraint: z3.string().nullable().optional(),
|
|
3434
|
+
type: z3.string().nullable().optional()
|
|
3159
3435
|
});
|
|
3160
|
-
var dependencyGraphNodeSchema =
|
|
3161
|
-
registry:
|
|
3162
|
-
name:
|
|
3163
|
-
version:
|
|
3436
|
+
var dependencyGraphNodeSchema = z3.object({
|
|
3437
|
+
registry: z3.string(),
|
|
3438
|
+
name: z3.string(),
|
|
3439
|
+
version: z3.string().nullable().optional()
|
|
3164
3440
|
});
|
|
3165
|
-
var dependencyGraphEdgeSchema =
|
|
3166
|
-
fromIndex:
|
|
3167
|
-
toIndex:
|
|
3168
|
-
constraint:
|
|
3169
|
-
dependencyType:
|
|
3441
|
+
var dependencyGraphEdgeSchema = z3.object({
|
|
3442
|
+
fromIndex: z3.number().int().nullable().optional(),
|
|
3443
|
+
toIndex: z3.number().int(),
|
|
3444
|
+
constraint: z3.string().nullable().optional(),
|
|
3445
|
+
dependencyType: z3.string().nullable().optional()
|
|
3170
3446
|
});
|
|
3171
|
-
var dependencyGraphSchema =
|
|
3172
|
-
formatVersion:
|
|
3173
|
-
nodes:
|
|
3174
|
-
edges:
|
|
3447
|
+
var dependencyGraphSchema = z3.object({
|
|
3448
|
+
formatVersion: z3.number().int(),
|
|
3449
|
+
nodes: z3.array(dependencyGraphNodeSchema),
|
|
3450
|
+
edges: z3.array(dependencyGraphEdgeSchema)
|
|
3175
3451
|
});
|
|
3176
|
-
var dependencyConflictEdgeSchema =
|
|
3177
|
-
fromIndex:
|
|
3178
|
-
toIndex:
|
|
3179
|
-
versionConstraint:
|
|
3180
|
-
dependencyType:
|
|
3452
|
+
var dependencyConflictEdgeSchema = z3.object({
|
|
3453
|
+
fromIndex: z3.number().int().nullable().optional(),
|
|
3454
|
+
toIndex: z3.number().int(),
|
|
3455
|
+
versionConstraint: z3.string(),
|
|
3456
|
+
dependencyType: z3.string()
|
|
3181
3457
|
});
|
|
3182
|
-
var dependencyConflictSchema =
|
|
3183
|
-
packageName:
|
|
3184
|
-
requiredVersions:
|
|
3185
|
-
conflictingEdges:
|
|
3458
|
+
var dependencyConflictSchema = z3.object({
|
|
3459
|
+
packageName: z3.string(),
|
|
3460
|
+
requiredVersions: z3.array(z3.string()),
|
|
3461
|
+
conflictingEdges: z3.array(dependencyConflictEdgeSchema)
|
|
3186
3462
|
});
|
|
3187
|
-
var circularDependencyCycleSchema =
|
|
3188
|
-
cycleStart:
|
|
3189
|
-
circularPath:
|
|
3190
|
-
displayChain:
|
|
3463
|
+
var circularDependencyCycleSchema = z3.object({
|
|
3464
|
+
cycleStart: z3.string(),
|
|
3465
|
+
circularPath: z3.array(z3.string()),
|
|
3466
|
+
displayChain: z3.string()
|
|
3191
3467
|
});
|
|
3192
|
-
var environmentMarkerSchema =
|
|
3193
|
-
type:
|
|
3194
|
-
value:
|
|
3195
|
-
raw:
|
|
3468
|
+
var environmentMarkerSchema = z3.object({
|
|
3469
|
+
type: z3.string().nullable().optional(),
|
|
3470
|
+
value: z3.string().nullable().optional(),
|
|
3471
|
+
raw: z3.string().nullable().optional()
|
|
3196
3472
|
});
|
|
3197
|
-
var transitiveDependencySchema =
|
|
3198
|
-
totalEdges:
|
|
3199
|
-
uniquePackagesCount:
|
|
3200
|
-
uniqueDependencies:
|
|
3201
|
-
dependencyConflicts:
|
|
3202
|
-
circularDependencyCycles:
|
|
3473
|
+
var transitiveDependencySchema = z3.object({
|
|
3474
|
+
totalEdges: z3.number().int().nullable().optional(),
|
|
3475
|
+
uniquePackagesCount: z3.number().int().nullable().optional(),
|
|
3476
|
+
uniqueDependencies: z3.array(z3.string()).nullable().optional(),
|
|
3477
|
+
dependencyConflicts: z3.array(dependencyConflictSchema).nullable().optional(),
|
|
3478
|
+
circularDependencyCycles: z3.array(circularDependencyCycleSchema).nullable().optional(),
|
|
3203
3479
|
dependencyGraph: dependencyGraphSchema.nullable().optional()
|
|
3204
3480
|
}).nullable().optional();
|
|
3205
|
-
var dependencyBundleSchema =
|
|
3206
|
-
direct:
|
|
3481
|
+
var dependencyBundleSchema = z3.object({
|
|
3482
|
+
direct: z3.array(directDependencySchema).nullable().optional(),
|
|
3207
3483
|
transitive: transitiveDependencySchema
|
|
3208
3484
|
}).nullable().optional();
|
|
3209
|
-
var groupDependencySchema =
|
|
3210
|
-
name:
|
|
3211
|
-
constraint:
|
|
3485
|
+
var groupDependencySchema = z3.object({
|
|
3486
|
+
name: z3.string(),
|
|
3487
|
+
constraint: z3.string().nullable().optional()
|
|
3212
3488
|
});
|
|
3213
|
-
var dependencyGroupSchema =
|
|
3214
|
-
name:
|
|
3215
|
-
lifecycle:
|
|
3216
|
-
conditionType:
|
|
3217
|
-
conditionValue:
|
|
3218
|
-
selectionMode:
|
|
3219
|
-
exclusiveGroup:
|
|
3220
|
-
fallbackPriority:
|
|
3221
|
-
compatibleWith:
|
|
3222
|
-
defaultEnabled:
|
|
3223
|
-
dependencies:
|
|
3489
|
+
var dependencyGroupSchema = z3.object({
|
|
3490
|
+
name: z3.string(),
|
|
3491
|
+
lifecycle: z3.string(),
|
|
3492
|
+
conditionType: z3.string(),
|
|
3493
|
+
conditionValue: z3.string().nullable().optional(),
|
|
3494
|
+
selectionMode: z3.string(),
|
|
3495
|
+
exclusiveGroup: z3.string().nullable().optional(),
|
|
3496
|
+
fallbackPriority: z3.number().int().nullable().optional(),
|
|
3497
|
+
compatibleWith: z3.array(z3.string()).nullable().optional(),
|
|
3498
|
+
defaultEnabled: z3.boolean().nullable().optional(),
|
|
3499
|
+
dependencies: z3.array(groupDependencySchema)
|
|
3224
3500
|
});
|
|
3225
|
-
var dependencyGroupsInfoSchema =
|
|
3226
|
-
primaryGroup:
|
|
3227
|
-
environmentMarkers:
|
|
3228
|
-
groups:
|
|
3501
|
+
var dependencyGroupsInfoSchema = z3.object({
|
|
3502
|
+
primaryGroup: z3.string().nullable().optional(),
|
|
3503
|
+
environmentMarkers: z3.array(environmentMarkerSchema).nullable().optional(),
|
|
3504
|
+
groups: z3.array(dependencyGroupSchema)
|
|
3229
3505
|
}).nullable().optional();
|
|
3230
|
-
var dependencyReportResponseSchema =
|
|
3506
|
+
var dependencyReportResponseSchema = z3.object({
|
|
3231
3507
|
package: packageVersionIdentitySchema.nullable().optional(),
|
|
3232
3508
|
dependencies: dependencyBundleSchema,
|
|
3233
3509
|
dependencyGroups: dependencyGroupsInfoSchema
|
|
3234
3510
|
});
|
|
3235
|
-
var dependenciesGraphQLResponseSchema =
|
|
3236
|
-
data:
|
|
3511
|
+
var dependenciesGraphQLResponseSchema = z3.object({
|
|
3512
|
+
data: z3.object({
|
|
3237
3513
|
packageDependencies: dependencyReportResponseSchema.nullable().optional()
|
|
3238
3514
|
}).nullable().optional(),
|
|
3239
|
-
errors:
|
|
3515
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3240
3516
|
});
|
|
3241
3517
|
var PACKAGE_DEPENDENCIES_QUERY = `
|
|
3242
3518
|
query PackageDependencies(
|
|
@@ -3330,32 +3606,32 @@ query PackageDependencies(
|
|
|
3330
3606
|
}
|
|
3331
3607
|
}
|
|
3332
3608
|
}`;
|
|
3333
|
-
var changelogPackageInfoSchema =
|
|
3334
|
-
name:
|
|
3335
|
-
registry:
|
|
3336
|
-
repoUrl:
|
|
3337
|
-
fromVersion:
|
|
3338
|
-
toVersion:
|
|
3339
|
-
limit:
|
|
3609
|
+
var changelogPackageInfoSchema = z3.object({
|
|
3610
|
+
name: z3.string().nullable().optional(),
|
|
3611
|
+
registry: z3.string().nullable().optional(),
|
|
3612
|
+
repoUrl: z3.string().nullable().optional(),
|
|
3613
|
+
fromVersion: z3.string().nullable().optional(),
|
|
3614
|
+
toVersion: z3.string().nullable().optional(),
|
|
3615
|
+
limit: z3.number().int().nullable().optional()
|
|
3340
3616
|
}).nullable().optional();
|
|
3341
|
-
var changelogEntryDetailSchema =
|
|
3342
|
-
version:
|
|
3343
|
-
normalizedVersion:
|
|
3344
|
-
body:
|
|
3345
|
-
htmlUrl:
|
|
3346
|
-
publishedAt:
|
|
3347
|
-
metadata:
|
|
3617
|
+
var changelogEntryDetailSchema = z3.object({
|
|
3618
|
+
version: z3.string().nullable().optional(),
|
|
3619
|
+
normalizedVersion: z3.string().nullable().optional(),
|
|
3620
|
+
body: z3.string().nullable().optional(),
|
|
3621
|
+
htmlUrl: z3.string().nullable().optional(),
|
|
3622
|
+
publishedAt: z3.string().nullable().optional(),
|
|
3623
|
+
metadata: z3.unknown().nullable().optional()
|
|
3348
3624
|
});
|
|
3349
|
-
var changelogReportResponseSchema =
|
|
3625
|
+
var changelogReportResponseSchema = z3.object({
|
|
3350
3626
|
package: changelogPackageInfoSchema,
|
|
3351
|
-
source:
|
|
3352
|
-
entries:
|
|
3627
|
+
source: z3.string().nullable().optional(),
|
|
3628
|
+
entries: z3.array(changelogEntryDetailSchema).nullable().optional()
|
|
3353
3629
|
});
|
|
3354
|
-
var changelogGraphQLResponseSchema =
|
|
3355
|
-
data:
|
|
3630
|
+
var changelogGraphQLResponseSchema = z3.object({
|
|
3631
|
+
data: z3.object({
|
|
3356
3632
|
packageChangelog: changelogReportResponseSchema.nullable().optional()
|
|
3357
3633
|
}).nullable().optional(),
|
|
3358
|
-
errors:
|
|
3634
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3359
3635
|
});
|
|
3360
3636
|
var PACKAGE_CHANGELOG_QUERY = `
|
|
3361
3637
|
query PackageChangelog(
|
|
@@ -3395,72 +3671,72 @@ query PackageChangelog(
|
|
|
3395
3671
|
}
|
|
3396
3672
|
}
|
|
3397
3673
|
}`;
|
|
3398
|
-
var packageDocSourceKindSchema =
|
|
3399
|
-
var packageDocPageSummarySchema =
|
|
3400
|
-
id:
|
|
3401
|
-
title:
|
|
3402
|
-
slug:
|
|
3403
|
-
order:
|
|
3404
|
-
linkName:
|
|
3405
|
-
lastUpdatedAt:
|
|
3674
|
+
var packageDocSourceKindSchema = z3.enum(["CRAWLED", "REPOSITORY"]);
|
|
3675
|
+
var packageDocPageSummarySchema = z3.object({
|
|
3676
|
+
id: z3.string().nullable().optional(),
|
|
3677
|
+
title: z3.string().nullable().optional(),
|
|
3678
|
+
slug: z3.string().nullable().optional(),
|
|
3679
|
+
order: z3.number().int().nullable().optional(),
|
|
3680
|
+
linkName: z3.string().nullable().optional(),
|
|
3681
|
+
lastUpdatedAt: z3.string().nullable().optional(),
|
|
3406
3682
|
sourceKind: packageDocSourceKindSchema.nullable().optional(),
|
|
3407
|
-
sourceUrl:
|
|
3408
|
-
repoUrl:
|
|
3409
|
-
gitRef:
|
|
3410
|
-
requestedRef:
|
|
3411
|
-
filePath:
|
|
3683
|
+
sourceUrl: z3.string().nullable().optional(),
|
|
3684
|
+
repoUrl: z3.string().nullable().optional(),
|
|
3685
|
+
gitRef: z3.string().nullable().optional(),
|
|
3686
|
+
requestedRef: z3.string().nullable().optional(),
|
|
3687
|
+
filePath: z3.string().nullable().optional()
|
|
3412
3688
|
});
|
|
3413
|
-
var packageDocsPageInfoSchema =
|
|
3414
|
-
hasNextPage:
|
|
3415
|
-
endCursor:
|
|
3416
|
-
totalCount:
|
|
3689
|
+
var packageDocsPageInfoSchema = z3.object({
|
|
3690
|
+
hasNextPage: z3.boolean(),
|
|
3691
|
+
endCursor: z3.string().nullable().optional(),
|
|
3692
|
+
totalCount: z3.number().int().nullable().optional()
|
|
3417
3693
|
}).nullable().optional();
|
|
3418
|
-
var packageDocsListResponseSchema =
|
|
3419
|
-
registry:
|
|
3420
|
-
packageName:
|
|
3421
|
-
version:
|
|
3422
|
-
stale:
|
|
3423
|
-
pages:
|
|
3694
|
+
var packageDocsListResponseSchema = z3.object({
|
|
3695
|
+
registry: z3.string().nullable().optional(),
|
|
3696
|
+
packageName: z3.string().nullable().optional(),
|
|
3697
|
+
version: z3.string().nullable().optional(),
|
|
3698
|
+
stale: z3.boolean().nullable().optional(),
|
|
3699
|
+
pages: z3.array(packageDocPageSummarySchema).nullable().optional(),
|
|
3424
3700
|
pageInfo: packageDocsPageInfoSchema
|
|
3425
3701
|
});
|
|
3426
|
-
var packageDocSourceSchema =
|
|
3427
|
-
url:
|
|
3428
|
-
label:
|
|
3702
|
+
var packageDocSourceSchema = z3.object({
|
|
3703
|
+
url: z3.string().nullable().optional(),
|
|
3704
|
+
label: z3.string().nullable().optional()
|
|
3429
3705
|
}).nullable().optional();
|
|
3430
|
-
var packageDocPageSchema =
|
|
3431
|
-
id:
|
|
3432
|
-
title:
|
|
3433
|
-
content:
|
|
3434
|
-
contentFormat:
|
|
3435
|
-
breadcrumbs:
|
|
3436
|
-
linkName:
|
|
3437
|
-
lastUpdatedAt:
|
|
3706
|
+
var packageDocPageSchema = z3.object({
|
|
3707
|
+
id: z3.string().nullable().optional(),
|
|
3708
|
+
title: z3.string().nullable().optional(),
|
|
3709
|
+
content: z3.string().nullable().optional(),
|
|
3710
|
+
contentFormat: z3.string().nullable().optional(),
|
|
3711
|
+
breadcrumbs: z3.array(z3.string()).nullable().optional(),
|
|
3712
|
+
linkName: z3.string().nullable().optional(),
|
|
3713
|
+
lastUpdatedAt: z3.string().nullable().optional(),
|
|
3438
3714
|
sourceKind: packageDocSourceKindSchema.nullable().optional(),
|
|
3439
3715
|
source: packageDocSourceSchema,
|
|
3440
|
-
repoUrl:
|
|
3441
|
-
gitRef:
|
|
3442
|
-
requestedRef:
|
|
3443
|
-
filePath:
|
|
3444
|
-
baseUrl:
|
|
3716
|
+
repoUrl: z3.string().nullable().optional(),
|
|
3717
|
+
gitRef: z3.string().nullable().optional(),
|
|
3718
|
+
requestedRef: z3.string().nullable().optional(),
|
|
3719
|
+
filePath: z3.string().nullable().optional(),
|
|
3720
|
+
baseUrl: z3.string().nullable().optional()
|
|
3445
3721
|
}).nullable().optional();
|
|
3446
|
-
var packageDocResultResponseSchema =
|
|
3447
|
-
registry:
|
|
3448
|
-
packageName:
|
|
3449
|
-
version:
|
|
3722
|
+
var packageDocResultResponseSchema = z3.object({
|
|
3723
|
+
registry: z3.string().nullable().optional(),
|
|
3724
|
+
packageName: z3.string().nullable().optional(),
|
|
3725
|
+
version: z3.string().nullable().optional(),
|
|
3450
3726
|
sourceKind: packageDocSourceKindSchema.nullable().optional(),
|
|
3451
3727
|
page: packageDocPageSchema
|
|
3452
3728
|
});
|
|
3453
|
-
var packageDocsListGraphQLResponseSchema =
|
|
3454
|
-
data:
|
|
3729
|
+
var packageDocsListGraphQLResponseSchema = z3.object({
|
|
3730
|
+
data: z3.object({
|
|
3455
3731
|
listPackageDocs: packageDocsListResponseSchema.nullable().optional()
|
|
3456
3732
|
}).nullable().optional(),
|
|
3457
|
-
errors:
|
|
3733
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3458
3734
|
});
|
|
3459
|
-
var packageDocReadGraphQLResponseSchema =
|
|
3460
|
-
data:
|
|
3735
|
+
var packageDocReadGraphQLResponseSchema = z3.object({
|
|
3736
|
+
data: z3.object({
|
|
3461
3737
|
getDocPage: packageDocResultResponseSchema.nullable().optional()
|
|
3462
3738
|
}).nullable().optional(),
|
|
3463
|
-
errors:
|
|
3739
|
+
errors: z3.array(graphQLErrorSchema2).optional()
|
|
3464
3740
|
});
|
|
3465
3741
|
var LIST_PACKAGE_DOCS_QUERY = `
|
|
3466
3742
|
query ListPackageDocs(
|
|
@@ -3602,6 +3878,9 @@ class PackageIntelligenceServiceImpl {
|
|
|
3602
3878
|
const extensions = getPrimaryExtensions2(errors);
|
|
3603
3879
|
const code = typeof extensions?.code === "string" ? extensions.code : undefined;
|
|
3604
3880
|
const retryable = typeof extensions?.retryable === "boolean" ? extensions.retryable : undefined;
|
|
3881
|
+
if (isClientUpdateRequiredGraphQLError({ message, code })) {
|
|
3882
|
+
return new ClientUpdateRequiredError;
|
|
3883
|
+
}
|
|
3605
3884
|
switch (code) {
|
|
3606
3885
|
case "NOT_FOUND":
|
|
3607
3886
|
case "PACKAGE_NOT_FOUND":
|
|
@@ -3692,6 +3971,56 @@ class PackageIntelligenceServiceImpl {
|
|
|
3692
3971
|
}));
|
|
3693
3972
|
}
|
|
3694
3973
|
async executePackageVulnerabilities(token, params) {
|
|
3974
|
+
let after = null;
|
|
3975
|
+
let firstPage;
|
|
3976
|
+
const entries = [];
|
|
3977
|
+
const seenCursors = new Set;
|
|
3978
|
+
do {
|
|
3979
|
+
const page = await this.fetchPackageVulnerabilitiesPage(token, params, after);
|
|
3980
|
+
if (!firstPage)
|
|
3981
|
+
firstPage = page;
|
|
3982
|
+
const advisoryPage = page.security?.advisories;
|
|
3983
|
+
if (!advisoryPage) {
|
|
3984
|
+
after = null;
|
|
3985
|
+
break;
|
|
3986
|
+
}
|
|
3987
|
+
entries.push(...advisoryPage.entries);
|
|
3988
|
+
if (advisoryPage.pageInfo.hasNextPage) {
|
|
3989
|
+
const nextCursor = advisoryPage.pageInfo.endCursor;
|
|
3990
|
+
if (!nextCursor) {
|
|
3991
|
+
throw new MalformedPackageIntelligenceResponseError("Vulnerability response pagination omitted next cursor.");
|
|
3992
|
+
}
|
|
3993
|
+
if (seenCursors.has(nextCursor)) {
|
|
3994
|
+
throw new MalformedPackageIntelligenceResponseError("Vulnerability response pagination repeated a cursor.");
|
|
3995
|
+
}
|
|
3996
|
+
seenCursors.add(nextCursor);
|
|
3997
|
+
after = nextCursor;
|
|
3998
|
+
} else {
|
|
3999
|
+
after = null;
|
|
4000
|
+
}
|
|
4001
|
+
} while (after !== null);
|
|
4002
|
+
if (!firstPage) {
|
|
4003
|
+
throw new MalformedPackageIntelligenceResponseError("Empty response from the package-intelligence service.");
|
|
4004
|
+
}
|
|
4005
|
+
if (firstPage.security) {
|
|
4006
|
+
const expectedCount = firstPage.security.advisories.pageInfo.totalCount;
|
|
4007
|
+
if (entries.length !== expectedCount) {
|
|
4008
|
+
throw new MalformedPackageIntelligenceResponseError("Vulnerability response pagination returned an incomplete advisory set.");
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
4011
|
+
const data = firstPage.security ? {
|
|
4012
|
+
...firstPage,
|
|
4013
|
+
security: {
|
|
4014
|
+
...firstPage.security,
|
|
4015
|
+
advisories: {
|
|
4016
|
+
...firstPage.security.advisories,
|
|
4017
|
+
entries
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
} : firstPage;
|
|
4021
|
+
return this.normaliseVulnerabilityReport(data);
|
|
4022
|
+
}
|
|
4023
|
+
async fetchPackageVulnerabilitiesPage(token, params, after) {
|
|
3695
4024
|
let response;
|
|
3696
4025
|
try {
|
|
3697
4026
|
response = await postPkgseerGraphql({
|
|
@@ -3703,7 +4032,8 @@ class PackageIntelligenceServiceImpl {
|
|
|
3703
4032
|
name: params.packageName,
|
|
3704
4033
|
version: params.version,
|
|
3705
4034
|
minSeverity: params.minSeverity,
|
|
3706
|
-
includeWithdrawn: params.includeWithdrawn
|
|
4035
|
+
includeWithdrawn: params.includeWithdrawn,
|
|
4036
|
+
after
|
|
3707
4037
|
},
|
|
3708
4038
|
fetchFn: this.fetchFn
|
|
3709
4039
|
});
|
|
@@ -3727,7 +4057,7 @@ class PackageIntelligenceServiceImpl {
|
|
|
3727
4057
|
if (!data) {
|
|
3728
4058
|
throw new MalformedPackageIntelligenceResponseError("Empty response from the package-intelligence service.");
|
|
3729
4059
|
}
|
|
3730
|
-
return
|
|
4060
|
+
return data;
|
|
3731
4061
|
}
|
|
3732
4062
|
normaliseVulnerabilityReport(data) {
|
|
3733
4063
|
const name = data.package?.name ?? undefined;
|
|
@@ -3741,21 +4071,28 @@ class PackageIntelligenceServiceImpl {
|
|
|
3741
4071
|
registry: data.package?.registry ?? undefined
|
|
3742
4072
|
};
|
|
3743
4073
|
const security = data.security ? {
|
|
3744
|
-
|
|
4074
|
+
affectedVulnerabilityCount: data.security.affectedVulnerabilityCount,
|
|
4075
|
+
nonAffectingVulnerabilityCount: data.security.nonAffectingVulnerabilityCount,
|
|
4076
|
+
allVulnerabilityCount: data.security.allVulnerabilityCount,
|
|
3745
4077
|
currentVersionAffected: data.security.currentVersionAffected ?? undefined,
|
|
3746
|
-
vulnerabilities: data.security.
|
|
4078
|
+
vulnerabilities: data.security.advisories.entries.map((vuln) => ({
|
|
3747
4079
|
osvId: vuln.osvId ?? undefined,
|
|
3748
4080
|
summary: vuln.summary ?? undefined,
|
|
3749
4081
|
severityScore: vuln.severityScore ?? undefined,
|
|
3750
4082
|
severityType: vuln.severityType ?? undefined,
|
|
3751
4083
|
affectedVersionRanges: vuln.affectedVersionRanges ?? undefined,
|
|
4084
|
+
affectedVersionRangesCount: vuln.affectedVersionRangesCount,
|
|
4085
|
+
affectedVersionRangesTruncated: vuln.affectedVersionRangesTruncated,
|
|
3752
4086
|
fixedInVersions: vuln.fixedInVersions ?? undefined,
|
|
3753
4087
|
publishedAt: vuln.publishedAt ?? undefined,
|
|
3754
4088
|
modifiedAt: vuln.modifiedAt ?? undefined,
|
|
3755
4089
|
withdrawnAt: vuln.withdrawnAt ?? undefined,
|
|
3756
4090
|
aliases: vuln.aliases ?? undefined,
|
|
3757
|
-
isMalicious: vuln.isMalicious ?? undefined
|
|
3758
|
-
|
|
4091
|
+
isMalicious: vuln.isMalicious ?? undefined,
|
|
4092
|
+
affectsInspectedVersion: vuln.affectsInspectedVersion,
|
|
4093
|
+
matchedAffectedVersionRanges: vuln.matchedAffectedVersionRanges,
|
|
4094
|
+
duplicateIds: vuln.duplicateIds
|
|
4095
|
+
})),
|
|
3759
4096
|
upgradePaths: data.security.upgradePaths ?? undefined
|
|
3760
4097
|
} : undefined;
|
|
3761
4098
|
return {
|
|
@@ -4311,18 +4648,371 @@ class TokenManager {
|
|
|
4311
4648
|
});
|
|
4312
4649
|
}
|
|
4313
4650
|
}
|
|
4314
|
-
// src/
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4651
|
+
// src/services/update-check-service.ts
|
|
4652
|
+
import semver from "semver";
|
|
4653
|
+
var NPM_DIST_TAGS_URL = "https://registry.npmjs.org/-/package/githits/dist-tags";
|
|
4654
|
+
var NPM_PACKAGE_VERSION_URL = "https://registry.npmjs.org/githits";
|
|
4655
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
4656
|
+
var FETCH_TIMEOUT_MS = 1000;
|
|
4657
|
+
var DIR_MODE2 = 448;
|
|
4658
|
+
var UPDATE_COMMAND = "npm i -g githits@latest";
|
|
4659
|
+
var MAX_DEPRECATION_REASON_LENGTH = 200;
|
|
4660
|
+
|
|
4661
|
+
class NpmRegistryUpdateCheckService {
|
|
4662
|
+
currentVersion;
|
|
4663
|
+
fs;
|
|
4664
|
+
fetcher;
|
|
4665
|
+
env;
|
|
4666
|
+
now;
|
|
4667
|
+
checkIntervalMs;
|
|
4668
|
+
fetchTimeoutMs;
|
|
4669
|
+
configDir;
|
|
4670
|
+
cachePath;
|
|
4671
|
+
constructor(options) {
|
|
4672
|
+
this.currentVersion = options.currentVersion;
|
|
4673
|
+
this.fs = options.fileSystemService;
|
|
4674
|
+
this.fetcher = options.fetcher ?? fetch;
|
|
4675
|
+
this.env = options.env ?? process.env;
|
|
4676
|
+
this.now = options.now ?? (() => new Date);
|
|
4677
|
+
this.checkIntervalMs = options.checkIntervalMs ?? CHECK_INTERVAL_MS;
|
|
4678
|
+
this.fetchTimeoutMs = options.fetchTimeoutMs ?? FETCH_TIMEOUT_MS;
|
|
4679
|
+
this.configDir = this.fs.joinPath(resolveConfigHome(this.env, this.fs), "githits");
|
|
4680
|
+
this.cachePath = this.fs.joinPath(this.configDir, "update-check.json");
|
|
4681
|
+
}
|
|
4682
|
+
async checkForUpdate(signal) {
|
|
4683
|
+
const cache = await this.loadCache();
|
|
4684
|
+
const latestDue = !cache || this.isCheckDue(cache);
|
|
4685
|
+
const currentVersionStatusDue = this.isCurrentVersionStatusDue(cache?.currentVersionStatus);
|
|
4686
|
+
const currentVersionStatus = await this.refreshCurrentVersionStatusIfDue(cache?.currentVersionStatus, signal);
|
|
4687
|
+
const currentVersionStatusChanged = currentVersionStatusDue && !sameCurrentVersionStatus(currentVersionStatus, cache?.currentVersionStatus);
|
|
4688
|
+
if (cache && !latestDue) {
|
|
4689
|
+
if (currentVersionStatusChanged) {
|
|
4690
|
+
await this.saveCache({
|
|
4691
|
+
...cache,
|
|
4692
|
+
currentVersionStatus
|
|
4693
|
+
});
|
|
4694
|
+
}
|
|
4695
|
+
return this.noticeFromLatest(cache.latestVersion);
|
|
4696
|
+
}
|
|
4697
|
+
const latestVersion = await this.fetchLatestVersion(signal);
|
|
4698
|
+
if (!latestVersion) {
|
|
4699
|
+
if (currentVersionStatusChanged) {
|
|
4700
|
+
await this.saveCache({
|
|
4701
|
+
...cache,
|
|
4702
|
+
currentVersionStatus
|
|
4703
|
+
});
|
|
4704
|
+
}
|
|
4705
|
+
return this.noticeFromLatest(cache?.latestVersion);
|
|
4706
|
+
}
|
|
4707
|
+
await this.saveCache({
|
|
4708
|
+
checkedAt: this.now().toISOString(),
|
|
4709
|
+
latestVersion,
|
|
4710
|
+
currentVersionStatus
|
|
4325
4711
|
});
|
|
4712
|
+
return this.noticeFromLatest(latestVersion);
|
|
4713
|
+
}
|
|
4714
|
+
async refreshRequiredUpdateStatus(signal) {
|
|
4715
|
+
const cache = await this.loadCache();
|
|
4716
|
+
const currentVersionStatusDue = this.isCurrentVersionStatusDue(cache?.currentVersionStatus);
|
|
4717
|
+
const currentVersionStatus = await this.refreshCurrentVersionStatusIfDue(cache?.currentVersionStatus, signal);
|
|
4718
|
+
if (currentVersionStatusDue && !sameCurrentVersionStatus(currentVersionStatus, cache?.currentVersionStatus)) {
|
|
4719
|
+
await this.saveCache({
|
|
4720
|
+
...cache,
|
|
4721
|
+
currentVersionStatus
|
|
4722
|
+
});
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
async getRequiredUpdateNotice() {
|
|
4726
|
+
const cache = await this.loadCache();
|
|
4727
|
+
const status = cache?.currentVersionStatus;
|
|
4728
|
+
if (!status || status.version !== this.currentVersion || !status.deprecatedReason) {
|
|
4729
|
+
return;
|
|
4730
|
+
}
|
|
4731
|
+
return {
|
|
4732
|
+
currentVersion: this.currentVersion,
|
|
4733
|
+
...cache.latestVersion ? { latestKnownVersion: cache.latestVersion } : {},
|
|
4734
|
+
reason: status.deprecatedReason,
|
|
4735
|
+
updateCommand: formatUpdateCommand(this.env)
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
noticeFromLatest(latestVersion) {
|
|
4739
|
+
if (!latestVersion || !semver.valid(latestVersion) || !semver.valid(this.currentVersion) || !semver.gt(latestVersion, this.currentVersion)) {
|
|
4740
|
+
return;
|
|
4741
|
+
}
|
|
4742
|
+
return {
|
|
4743
|
+
currentVersion: this.currentVersion,
|
|
4744
|
+
latestVersion,
|
|
4745
|
+
updateCommand: UPDATE_COMMAND
|
|
4746
|
+
};
|
|
4747
|
+
}
|
|
4748
|
+
isCheckDue(cache) {
|
|
4749
|
+
if (!cache.checkedAt || !cache.latestVersion) {
|
|
4750
|
+
return true;
|
|
4751
|
+
}
|
|
4752
|
+
const checkedAtMs = Date.parse(cache.checkedAt);
|
|
4753
|
+
if (Number.isNaN(checkedAtMs)) {
|
|
4754
|
+
return true;
|
|
4755
|
+
}
|
|
4756
|
+
return this.now().getTime() - checkedAtMs >= this.checkIntervalMs;
|
|
4757
|
+
}
|
|
4758
|
+
isCurrentVersionStatusDue(status) {
|
|
4759
|
+
if (!status || status.version !== this.currentVersion) {
|
|
4760
|
+
return true;
|
|
4761
|
+
}
|
|
4762
|
+
const checkedAtMs = Date.parse(status.checkedAt);
|
|
4763
|
+
if (Number.isNaN(checkedAtMs)) {
|
|
4764
|
+
return true;
|
|
4765
|
+
}
|
|
4766
|
+
return this.now().getTime() - checkedAtMs >= this.checkIntervalMs;
|
|
4767
|
+
}
|
|
4768
|
+
async refreshCurrentVersionStatusIfDue(cached, signal) {
|
|
4769
|
+
const reusableCached = cached?.version === this.currentVersion ? cached : undefined;
|
|
4770
|
+
if (!this.isCurrentVersionStatusDue(reusableCached)) {
|
|
4771
|
+
return reusableCached;
|
|
4772
|
+
}
|
|
4773
|
+
const remote = await this.fetchCurrentVersionStatus(signal);
|
|
4774
|
+
if (!remote) {
|
|
4775
|
+
return reusableCached;
|
|
4776
|
+
}
|
|
4777
|
+
return remote;
|
|
4778
|
+
}
|
|
4779
|
+
async fetchLatestVersion(signal) {
|
|
4780
|
+
try {
|
|
4781
|
+
const timeoutSignal = AbortSignal.timeout(this.fetchTimeoutMs);
|
|
4782
|
+
const response = await this.fetcher(NPM_DIST_TAGS_URL, {
|
|
4783
|
+
signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal
|
|
4784
|
+
});
|
|
4785
|
+
if (!response.ok) {
|
|
4786
|
+
return;
|
|
4787
|
+
}
|
|
4788
|
+
const body = await response.json();
|
|
4789
|
+
if (!body || typeof body !== "object" || typeof body.latest !== "string") {
|
|
4790
|
+
return;
|
|
4791
|
+
}
|
|
4792
|
+
const latest = body.latest;
|
|
4793
|
+
return semver.valid(latest) ? latest : undefined;
|
|
4794
|
+
} catch {
|
|
4795
|
+
return;
|
|
4796
|
+
}
|
|
4797
|
+
}
|
|
4798
|
+
async fetchCurrentVersionStatus(signal) {
|
|
4799
|
+
try {
|
|
4800
|
+
const timeoutSignal = AbortSignal.timeout(this.fetchTimeoutMs);
|
|
4801
|
+
const response = await this.fetcher(`${NPM_PACKAGE_VERSION_URL}/${this.currentVersion}`, {
|
|
4802
|
+
signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal
|
|
4803
|
+
});
|
|
4804
|
+
if (!response.ok) {
|
|
4805
|
+
return;
|
|
4806
|
+
}
|
|
4807
|
+
const body = await response.json();
|
|
4808
|
+
if (!body || typeof body !== "object") {
|
|
4809
|
+
return;
|
|
4810
|
+
}
|
|
4811
|
+
const rawDeprecated = body.deprecated;
|
|
4812
|
+
const deprecatedReason = typeof rawDeprecated === "string" ? sanitizeDeprecationReason(rawDeprecated) : undefined;
|
|
4813
|
+
return {
|
|
4814
|
+
version: this.currentVersion,
|
|
4815
|
+
checkedAt: this.now().toISOString(),
|
|
4816
|
+
...deprecatedReason ? { deprecatedReason } : {}
|
|
4817
|
+
};
|
|
4818
|
+
} catch {
|
|
4819
|
+
return;
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
async loadCache() {
|
|
4823
|
+
try {
|
|
4824
|
+
if (!await this.fs.exists(this.cachePath)) {
|
|
4825
|
+
return;
|
|
4826
|
+
}
|
|
4827
|
+
const raw = await this.fs.readFile(this.cachePath);
|
|
4828
|
+
const parsed = JSON.parse(raw);
|
|
4829
|
+
const currentVersionStatus = parseCurrentVersionStatus(parsed.currentVersionStatus);
|
|
4830
|
+
const hasLatest = typeof parsed.checkedAt === "string" && typeof parsed.latestVersion === "string";
|
|
4831
|
+
if (!hasLatest && !currentVersionStatus) {
|
|
4832
|
+
return;
|
|
4833
|
+
}
|
|
4834
|
+
return {
|
|
4835
|
+
...hasLatest ? {
|
|
4836
|
+
checkedAt: parsed.checkedAt,
|
|
4837
|
+
latestVersion: parsed.latestVersion
|
|
4838
|
+
} : {},
|
|
4839
|
+
currentVersionStatus
|
|
4840
|
+
};
|
|
4841
|
+
} catch {
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
}
|
|
4845
|
+
async saveCache(cache) {
|
|
4846
|
+
try {
|
|
4847
|
+
await this.fs.ensureDir(this.configDir, DIR_MODE2);
|
|
4848
|
+
if (typeof this.fs.atomicWriteFile === "function") {
|
|
4849
|
+
await this.fs.atomicWriteFile(this.cachePath, `${JSON.stringify(cache, null, 2)}
|
|
4850
|
+
`);
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4853
|
+
await this.fs.writeFile(this.cachePath, `${JSON.stringify(cache, null, 2)}
|
|
4854
|
+
`, 384);
|
|
4855
|
+
} catch {}
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
function resolveConfigHome(env, fs) {
|
|
4859
|
+
const xdgConfigHome = env.XDG_CONFIG_HOME?.trim();
|
|
4860
|
+
if (xdgConfigHome) {
|
|
4861
|
+
return xdgConfigHome;
|
|
4862
|
+
}
|
|
4863
|
+
return fs.joinPath(fs.getHomeDir(), ".config");
|
|
4864
|
+
}
|
|
4865
|
+
function shouldRunUpdateCheck(input) {
|
|
4866
|
+
if (input.stderrIsTTY !== true) {
|
|
4867
|
+
return false;
|
|
4868
|
+
}
|
|
4869
|
+
const env = input.env ?? process.env;
|
|
4870
|
+
if (env.CI || env.GITHITS_DISABLE_UPDATE_CHECK) {
|
|
4871
|
+
return false;
|
|
4872
|
+
}
|
|
4873
|
+
if (isHelpOrVersionInvocation(input.args)) {
|
|
4874
|
+
return false;
|
|
4875
|
+
}
|
|
4876
|
+
if (isLikelyEphemeralPackageRunner(env)) {
|
|
4877
|
+
return false;
|
|
4878
|
+
}
|
|
4879
|
+
if (isMcpStdioInvocation(input.args, input.stdinIsTTY === true, input.stdoutIsTTY === true)) {
|
|
4880
|
+
return false;
|
|
4881
|
+
}
|
|
4882
|
+
return true;
|
|
4883
|
+
}
|
|
4884
|
+
function shouldRunRequiredUpdateEnforcement(input) {
|
|
4885
|
+
if (isHelpOrVersionInvocation(input.args)) {
|
|
4886
|
+
return false;
|
|
4887
|
+
}
|
|
4888
|
+
const env = input.env ?? process.env;
|
|
4889
|
+
if (isLikelyEphemeralPackageRunner(env)) {
|
|
4890
|
+
return false;
|
|
4891
|
+
}
|
|
4892
|
+
return true;
|
|
4893
|
+
}
|
|
4894
|
+
function formatUpdateNotice(notice) {
|
|
4895
|
+
return `Update available: githits ${notice.currentVersion} -> ${notice.latestVersion}
|
|
4896
|
+
Run: ${notice.updateCommand}`;
|
|
4897
|
+
}
|
|
4898
|
+
function formatRequiredUpdateNotice(notice) {
|
|
4899
|
+
const lines = [
|
|
4900
|
+
`Update required: ${notice.reason}`,
|
|
4901
|
+
"",
|
|
4902
|
+
`Installed githits ${notice.currentVersion} is no longer supported.`
|
|
4903
|
+
];
|
|
4904
|
+
if (notice.latestKnownVersion) {
|
|
4905
|
+
lines.push(`Latest known version: ${notice.latestKnownVersion}`);
|
|
4906
|
+
}
|
|
4907
|
+
lines.push("Update with:", ` ${notice.updateCommand}`);
|
|
4908
|
+
return [...lines].join(`
|
|
4909
|
+
`);
|
|
4910
|
+
}
|
|
4911
|
+
function formatUpdateCommand(env = process.env) {
|
|
4912
|
+
const userAgent = env.npm_config_user_agent ?? "";
|
|
4913
|
+
const execPath = env.npm_execpath ?? "";
|
|
4914
|
+
const signal = `${userAgent} ${execPath}`.toLowerCase();
|
|
4915
|
+
if (signal.includes("pnpm")) {
|
|
4916
|
+
return "pnpm add -g githits@latest";
|
|
4917
|
+
}
|
|
4918
|
+
if (signal.includes("yarn")) {
|
|
4919
|
+
return "yarn global add githits@latest";
|
|
4920
|
+
}
|
|
4921
|
+
if (signal.includes("bun")) {
|
|
4922
|
+
return "bun add -g githits@latest";
|
|
4923
|
+
}
|
|
4924
|
+
return UPDATE_COMMAND;
|
|
4925
|
+
}
|
|
4926
|
+
function parseCurrentVersionStatus(value) {
|
|
4927
|
+
if (!value || typeof value !== "object") {
|
|
4928
|
+
return;
|
|
4929
|
+
}
|
|
4930
|
+
const status = value;
|
|
4931
|
+
if (typeof status.version !== "string") {
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4934
|
+
if (typeof status.checkedAt !== "string") {
|
|
4935
|
+
return;
|
|
4936
|
+
}
|
|
4937
|
+
const deprecatedReason = typeof status.deprecatedReason === "string" ? sanitizeDeprecationReason(status.deprecatedReason) : undefined;
|
|
4938
|
+
return {
|
|
4939
|
+
version: status.version,
|
|
4940
|
+
checkedAt: status.checkedAt,
|
|
4941
|
+
...deprecatedReason ? { deprecatedReason } : {}
|
|
4942
|
+
};
|
|
4943
|
+
}
|
|
4944
|
+
function sameCurrentVersionStatus(left, right) {
|
|
4945
|
+
return left?.version === right?.version && left?.checkedAt === right?.checkedAt && left?.deprecatedReason === right?.deprecatedReason;
|
|
4946
|
+
}
|
|
4947
|
+
function sanitizeDeprecationReason(value) {
|
|
4948
|
+
const sanitized = Array.from(value).map((character) => isControlCharacter(character) ? " " : character).join("").replace(/\s+/g, " ").trim().slice(0, MAX_DEPRECATION_REASON_LENGTH).trim();
|
|
4949
|
+
return sanitized.length > 0 ? sanitized : undefined;
|
|
4950
|
+
}
|
|
4951
|
+
function isControlCharacter(value) {
|
|
4952
|
+
const code = value.charCodeAt(0);
|
|
4953
|
+
return code <= 31 || code >= 127 && code <= 159;
|
|
4954
|
+
}
|
|
4955
|
+
function isHelpOrVersionInvocation(args) {
|
|
4956
|
+
return args.length === 0 || args[0] === "help" || args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-V");
|
|
4957
|
+
}
|
|
4958
|
+
function isLikelyEphemeralPackageRunner(env) {
|
|
4959
|
+
const lifecycleEvent = env.npm_lifecycle_event;
|
|
4960
|
+
if (lifecycleEvent === "npx" || lifecycleEvent === "bunx") {
|
|
4961
|
+
return true;
|
|
4962
|
+
}
|
|
4963
|
+
const userAgent = env.npm_config_user_agent ?? "";
|
|
4964
|
+
return env.npm_command === "exec" && (userAgent.startsWith("npm/") || userAgent.startsWith("bun/"));
|
|
4965
|
+
}
|
|
4966
|
+
function isMcpStdioInvocation(args, stdinIsTTY, stdoutIsTTY) {
|
|
4967
|
+
const firstTokenIndex = args.findIndex((arg) => !arg.startsWith("-"));
|
|
4968
|
+
if (firstTokenIndex === -1 || args[firstTokenIndex] !== "mcp") {
|
|
4969
|
+
return false;
|
|
4970
|
+
}
|
|
4971
|
+
const remainingArgs = args.slice(firstTokenIndex + 1);
|
|
4972
|
+
return remainingArgs.includes("start") || !stdinIsTTY || !stdoutIsTTY;
|
|
4973
|
+
}
|
|
4974
|
+
// src/container.ts
|
|
4975
|
+
async function createAuthStorage(fileSystemService) {
|
|
4976
|
+
return withTelemetrySpan("container.create-auth-storage", async () => {
|
|
4977
|
+
const authConfig = await loadAuthConfig(fileSystemService);
|
|
4978
|
+
return createAuthStorageForMode(fileSystemService, authConfig.storage, authConfig.configPath);
|
|
4979
|
+
});
|
|
4980
|
+
}
|
|
4981
|
+
function createAuthStorageForMode(fileSystemService, mode, configPath = "your GitHits config.toml") {
|
|
4982
|
+
const fileStorage = new ModeAwareFileAuthStorage(new AuthStorageImpl(fileSystemService, getAuthFileStorageDir(fileSystemService)), mode, configPath);
|
|
4983
|
+
const legacyStorage = new AuthStorageImpl(fileSystemService, getLegacyAuthStorageDir(fileSystemService));
|
|
4984
|
+
const rawKeyring = new KeyringServiceImpl;
|
|
4985
|
+
const keyring = process.platform === "win32" ? new ChunkingKeyringService(rawKeyring, WINDOWS_MAX_ENTRY_SIZE) : rawKeyring;
|
|
4986
|
+
const keychainStorage = new KeychainAuthStorage(keyring);
|
|
4987
|
+
return new MigratingAuthStorage(keychainStorage, fileStorage, legacyStorage, mode, configPath, (message) => console.error(message));
|
|
4988
|
+
}
|
|
4989
|
+
async function createAuthCommandDependencies() {
|
|
4990
|
+
return withTelemetrySpan("container.create-auth-command", async () => {
|
|
4991
|
+
const fileSystemService = new FileSystemServiceImpl;
|
|
4992
|
+
return {
|
|
4993
|
+
authStorage: await createAuthStorage(fileSystemService),
|
|
4994
|
+
authService: new AuthServiceImpl,
|
|
4995
|
+
browserService: new BrowserServiceImpl,
|
|
4996
|
+
fileSystemService,
|
|
4997
|
+
mcpUrl: getMcpUrl(),
|
|
4998
|
+
apiUrl: getApiUrl(),
|
|
4999
|
+
envApiToken: getEnvApiToken()
|
|
5000
|
+
};
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
async function createAuthStatusDependencies() {
|
|
5004
|
+
return withTelemetrySpan("container.create-auth-status", async () => {
|
|
5005
|
+
const fileSystemService = new FileSystemServiceImpl;
|
|
5006
|
+
const envApiToken = getEnvApiToken();
|
|
5007
|
+
return {
|
|
5008
|
+
authStorage: envApiToken ? createAuthStorageForMode(fileSystemService, "keychain") : await createAuthStorage(fileSystemService),
|
|
5009
|
+
authService: new AuthServiceImpl,
|
|
5010
|
+
browserService: new BrowserServiceImpl,
|
|
5011
|
+
fileSystemService,
|
|
5012
|
+
mcpUrl: getMcpUrl(),
|
|
5013
|
+
apiUrl: getApiUrl(),
|
|
5014
|
+
envApiToken
|
|
5015
|
+
};
|
|
4326
5016
|
});
|
|
4327
5017
|
}
|
|
4328
5018
|
function createStaticTokenProvider(token) {
|
|
@@ -4338,18 +5028,17 @@ async function createContainer() {
|
|
|
4338
5028
|
const mcpUrl = getMcpUrl();
|
|
4339
5029
|
const apiUrl = getApiUrl();
|
|
4340
5030
|
const codeNavigationUrl = getCodeNavigationUrl();
|
|
4341
|
-
const codeNavigationCliOverrideEnabled = isCodeNavigationCliOverrideEnabled();
|
|
4342
5031
|
const fileSystemService = new FileSystemServiceImpl;
|
|
4343
|
-
const authStorage = createAuthStorage(fileSystemService);
|
|
4344
5032
|
const authService = new AuthServiceImpl;
|
|
4345
5033
|
const browserService = new BrowserServiceImpl;
|
|
4346
5034
|
const envToken = getEnvApiToken();
|
|
4347
5035
|
if (envToken) {
|
|
5036
|
+
const authStorage2 = createAuthStorageForMode(fileSystemService, "keychain");
|
|
4348
5037
|
const tokenProvider = createStaticTokenProvider(envToken);
|
|
4349
|
-
const codeNavigationService2 =
|
|
4350
|
-
const packageIntelligenceService2 =
|
|
5038
|
+
const codeNavigationService2 = new CodeNavigationServiceImpl(codeNavigationUrl, tokenProvider);
|
|
5039
|
+
const packageIntelligenceService2 = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenProvider);
|
|
4351
5040
|
return {
|
|
4352
|
-
authStorage,
|
|
5041
|
+
authStorage: authStorage2,
|
|
4353
5042
|
authService,
|
|
4354
5043
|
browserService,
|
|
4355
5044
|
fileSystemService,
|
|
@@ -4358,18 +5047,17 @@ async function createContainer() {
|
|
|
4358
5047
|
apiToken: envToken,
|
|
4359
5048
|
hasValidToken: true,
|
|
4360
5049
|
envApiToken: envToken,
|
|
4361
|
-
codeNavigationCapability: getCodeNavigationCapability(envToken),
|
|
4362
|
-
codeNavigationCliOverrideEnabled,
|
|
4363
5050
|
codeNavigationUrl,
|
|
4364
5051
|
codeNavigationService: codeNavigationService2,
|
|
4365
5052
|
packageIntelligenceService: packageIntelligenceService2,
|
|
4366
5053
|
githitsService: new GitHitsServiceImpl(apiUrl, envToken)
|
|
4367
5054
|
};
|
|
4368
5055
|
}
|
|
5056
|
+
const authStorage = await createAuthStorage(fileSystemService);
|
|
4369
5057
|
const tokenManager = new TokenManager({ authService, authStorage, mcpUrl });
|
|
4370
5058
|
const apiToken = await withTelemetrySpan("container.token.get", () => tokenManager.getToken());
|
|
4371
|
-
const codeNavigationService =
|
|
4372
|
-
const packageIntelligenceService =
|
|
5059
|
+
const codeNavigationService = new CodeNavigationServiceImpl(codeNavigationUrl, tokenManager);
|
|
5060
|
+
const packageIntelligenceService = new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenManager);
|
|
4373
5061
|
return {
|
|
4374
5062
|
authStorage,
|
|
4375
5063
|
authService,
|
|
@@ -4380,8 +5068,6 @@ async function createContainer() {
|
|
|
4380
5068
|
apiToken,
|
|
4381
5069
|
hasValidToken: apiToken !== undefined,
|
|
4382
5070
|
envApiToken: undefined,
|
|
4383
|
-
codeNavigationCapability: getCodeNavigationCapability(apiToken),
|
|
4384
|
-
codeNavigationCliOverrideEnabled,
|
|
4385
5071
|
codeNavigationUrl,
|
|
4386
5072
|
codeNavigationService,
|
|
4387
5073
|
packageIntelligenceService,
|
|
@@ -4389,48 +5075,5 @@ async function createContainer() {
|
|
|
4389
5075
|
};
|
|
4390
5076
|
});
|
|
4391
5077
|
}
|
|
4392
|
-
async function resolveStartupCodeNavigationCapability() {
|
|
4393
|
-
const state = await resolveStartupCodeNavigationRegistrationState();
|
|
4394
|
-
return state.capability;
|
|
4395
|
-
}
|
|
4396
|
-
async function resolveStartupCodeNavigationRegistrationState() {
|
|
4397
|
-
return withTelemetrySpan("startup.resolve-code-nav-registration-state", async () => {
|
|
4398
|
-
const envToken = getEnvApiToken();
|
|
4399
|
-
if (envToken) {
|
|
4400
|
-
return {
|
|
4401
|
-
capability: getCodeNavigationCapability(envToken),
|
|
4402
|
-
expiredStoredAuth: false
|
|
4403
|
-
};
|
|
4404
|
-
}
|
|
4405
|
-
const tokens = await loadStartupTokens(getMcpUrl());
|
|
4406
|
-
if (tokens?.expiresAt && new Date(tokens.expiresAt) < new Date) {
|
|
4407
|
-
return { capability: "unknown", expiredStoredAuth: true };
|
|
4408
|
-
}
|
|
4409
|
-
return {
|
|
4410
|
-
capability: getCodeNavigationCapability(tokens?.accessToken),
|
|
4411
|
-
expiredStoredAuth: false
|
|
4412
|
-
};
|
|
4413
|
-
});
|
|
4414
|
-
}
|
|
4415
|
-
async function loadStartupTokens(mcpUrl) {
|
|
4416
|
-
return withTelemetrySpan("startup.load-tokens", async () => {
|
|
4417
|
-
const fileSystemService = new FileSystemServiceImpl;
|
|
4418
|
-
const fileStorage = new AuthStorageImpl(fileSystemService);
|
|
4419
|
-
try {
|
|
4420
|
-
const rawKeyring = new KeyringServiceImpl;
|
|
4421
|
-
const keyring = process.platform === "win32" ? new ChunkingKeyringService(rawKeyring, WINDOWS_MAX_ENTRY_SIZE) : rawKeyring;
|
|
4422
|
-
const keychainStorage = new KeychainAuthStorage(keyring);
|
|
4423
|
-
const keychainTokens = await keychainStorage.loadTokens(mcpUrl);
|
|
4424
|
-
if (keychainTokens) {
|
|
4425
|
-
return keychainTokens;
|
|
4426
|
-
}
|
|
4427
|
-
} catch (error) {
|
|
4428
|
-
if (!(error instanceof KeychainUnavailableError)) {
|
|
4429
|
-
throw error;
|
|
4430
|
-
}
|
|
4431
|
-
}
|
|
4432
|
-
return fileStorage.loadTokens(mcpUrl);
|
|
4433
|
-
});
|
|
4434
|
-
}
|
|
4435
5078
|
|
|
4436
|
-
export {
|
|
5079
|
+
export { AuthConfigError, CLIENT_UPDATE_REQUIRED_REASON, ClientUpdateRequiredError, debugLog, setMcpClientVersionProvider, setClientMode, isTelemetryEnabled, withTelemetrySpan, startTelemetrySpan, endTelemetrySpan, flushTelemetry, AuthenticationError, CodeNavigationAccessError, CodeNavigationGraphQLError, CodeNavigationIndexingError, CodeNavigationUnresolvableError, MalformedCodeNavigationResponseError, CodeNavigationTargetNotFoundError, CodeNavigationFileNotFoundError, CodeNavigationVersionNotFoundError, CodeNavigationValidationError, CodeNavigationFeatureFlagRequiredError, CodeNavigationNetworkError, CodeNavigationBackendError, getCodeNavigationUrl, ExecServiceImpl, FileSystemServiceImpl, AuthStoragePolicyError, PackageIntelligenceAccessError, PackageIntelligenceFeatureFlagRequiredError, PackageIntelligenceNetworkError, PackageIntelligenceBackendError, PackageIntelligenceGraphQLError, PackageIntelligenceTargetNotFoundError, PackageIntelligenceValidationError, PackageIntelligenceVersionNotFoundError, MalformedPackageIntelligenceResponseError, PackageIntelligenceChangelogSourceNotFoundError, PromptServiceImpl, refreshExpiredToken, NpmRegistryUpdateCheckService, shouldRunUpdateCheck, shouldRunRequiredUpdateEnforcement, formatUpdateNotice, formatRequiredUpdateNotice, createAuthCommandDependencies, createAuthStatusDependencies, createContainer };
|