@gpc-cli/core 0.9.30 → 0.9.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1
- package/dist/index.js +61 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OutputFormat, ResolvedConfig, WebhookConfig } from '@gpc-cli/config';
|
|
2
2
|
import { AuthClient } from '@gpc-cli/auth';
|
|
3
3
|
import { GpcPlugin, PluginManifest, CommandEvent, CommandResult, PluginError, RequestEvent, ResponseEvent, PluginCommand } from '@gpc-cli/plugin-sdk';
|
|
4
|
-
import { PlayApiClient, Track, ExternallyHostedApk, ExternallyHostedApkResponse, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, SubscriptionDeferResponse, ProductPurchase, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, ReportBucket, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafety, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesApiClient, Achievement, GameEvent, Leaderboard, EnterpriseApiClient, CustomApp, GeneratedApk, PurchaseOption, PurchaseOptionsListResponse } from '@gpc-cli/api';
|
|
4
|
+
import { PlayApiClient, Track, ExternallyHostedApk, ExternallyHostedApkResponse, UploadProgressEvent, ResumableUploadOptions, Listing, ImageType, CountryAvailability, Image, AppDetails, Review, ReviewReplyResponse, Subscription, SubscriptionOffer, OffersListResponse, BasePlanMigratePricesRequest, InAppProduct, SubscriptionDeferResponse, ProductPurchase, SubscriptionPurchaseV2, VoidedPurchase, UsersApiClient, User, DeveloperPermission, Grant, MetricRow, ReportingDimension, ReportingAggregation, VitalsMetricSet, ReportingApiClient, AnomalyDetectionResponse, MetricSetResponse, ErrorIssuesResponse, ConvertRegionPricesResponse, ReportType, StatsDimension, ReportBucket, Testers, AppRecoveryTargeting, AppRecoveryAction, CreateAppRecoveryActionRequest, DataSafety, ExternalTransaction, ExternalTransactionRefund, DeviceTierConfig, OneTimeOffer, OneTimeProduct, OneTimeOffersListResponse, OneTimeProductsListResponse, GamesApiClient, Achievement, GameEvent, Leaderboard, EnterpriseApiClient, CustomApp, GeneratedApk, PurchaseOption, PurchaseOptionsListResponse } from '@gpc-cli/api';
|
|
5
5
|
|
|
6
6
|
declare class GpcError extends Error {
|
|
7
7
|
readonly code: string;
|
|
@@ -155,6 +155,8 @@ declare function uploadRelease(client: PlayApiClient, packageName: string, fileP
|
|
|
155
155
|
mappingFile?: string;
|
|
156
156
|
dryRun?: boolean;
|
|
157
157
|
onProgress?: (uploaded: number, total: number) => void;
|
|
158
|
+
onUploadProgress?: (event: UploadProgressEvent) => void;
|
|
159
|
+
uploadOptions?: Pick<ResumableUploadOptions, "chunkSize" | "resumeSessionUri" | "maxResumeAttempts">;
|
|
158
160
|
}): Promise<UploadResult | DryRunUploadResult>;
|
|
159
161
|
declare function getReleasesStatus(client: PlayApiClient, packageName: string, trackFilter?: string): Promise<ReleaseStatusResult[]>;
|
|
160
162
|
declare function promoteRelease(client: PlayApiClient, packageName: string, fromTrack: string, toTrack: string, options?: {
|
package/dist/index.js
CHANGED
|
@@ -560,14 +560,14 @@ async function getAppInfo(client, packageName) {
|
|
|
560
560
|
|
|
561
561
|
// src/commands/releases.ts
|
|
562
562
|
import { stat as stat2 } from "fs/promises";
|
|
563
|
-
import {
|
|
563
|
+
import { PlayApiError } from "@gpc-cli/api";
|
|
564
564
|
|
|
565
565
|
// src/utils/file-validation.ts
|
|
566
|
-
import {
|
|
566
|
+
import { open, stat } from "fs/promises";
|
|
567
567
|
import { extname } from "path";
|
|
568
568
|
var ZIP_MAGIC = Buffer.from([80, 75, 3, 4]);
|
|
569
|
-
var MAX_APK_SIZE =
|
|
570
|
-
var MAX_AAB_SIZE =
|
|
569
|
+
var MAX_APK_SIZE = 1024 * 1024 * 1024;
|
|
570
|
+
var MAX_AAB_SIZE = 2 * 1024 * 1024 * 1024;
|
|
571
571
|
var LARGE_FILE_THRESHOLD = 100 * 1024 * 1024;
|
|
572
572
|
async function validateUploadFile(filePath) {
|
|
573
573
|
const errors = [];
|
|
@@ -594,11 +594,11 @@ async function validateUploadFile(filePath) {
|
|
|
594
594
|
}
|
|
595
595
|
if (fileType === "apk" && sizeBytes > MAX_APK_SIZE) {
|
|
596
596
|
errors.push(
|
|
597
|
-
`APK exceeds
|
|
597
|
+
`APK exceeds 1 GB limit (${formatSize(sizeBytes)}). Consider using AAB format instead.`
|
|
598
598
|
);
|
|
599
599
|
}
|
|
600
600
|
if (fileType === "aab" && sizeBytes > MAX_AAB_SIZE) {
|
|
601
|
-
errors.push(`AAB exceeds
|
|
601
|
+
errors.push(`AAB exceeds 2 GB limit (${formatSize(sizeBytes)}).`);
|
|
602
602
|
}
|
|
603
603
|
if (sizeBytes > LARGE_FILE_THRESHOLD && errors.length === 0) {
|
|
604
604
|
warnings.push(
|
|
@@ -606,16 +606,20 @@ async function validateUploadFile(filePath) {
|
|
|
606
606
|
);
|
|
607
607
|
}
|
|
608
608
|
if (sizeBytes > 0) {
|
|
609
|
+
let fh;
|
|
609
610
|
try {
|
|
610
|
-
|
|
611
|
-
const
|
|
612
|
-
|
|
611
|
+
fh = await open(filePath, "r");
|
|
612
|
+
const buf = Buffer.alloc(4);
|
|
613
|
+
await fh.read(buf, 0, 4, 0);
|
|
614
|
+
if (!buf.equals(ZIP_MAGIC)) {
|
|
613
615
|
errors.push(
|
|
614
616
|
"File does not have valid ZIP magic bytes (PK\\x03\\x04). Both AAB and APK files must be valid ZIP archives."
|
|
615
617
|
);
|
|
616
618
|
}
|
|
617
619
|
} catch {
|
|
618
620
|
errors.push("Unable to read file header for validation");
|
|
621
|
+
} finally {
|
|
622
|
+
await fh?.close();
|
|
619
623
|
}
|
|
620
624
|
}
|
|
621
625
|
return {
|
|
@@ -640,6 +644,18 @@ function formatSize(bytes) {
|
|
|
640
644
|
}
|
|
641
645
|
|
|
642
646
|
// src/commands/releases.ts
|
|
647
|
+
function warnIfEditExpiring(edit) {
|
|
648
|
+
if (!edit.expiryTimeSeconds) return;
|
|
649
|
+
const expiryMs = Number(edit.expiryTimeSeconds) * 1e3;
|
|
650
|
+
const remainingMs = expiryMs - Date.now();
|
|
651
|
+
if (remainingMs < 5 * 60 * 1e3 && remainingMs > 0) {
|
|
652
|
+
const minutes = Math.round(remainingMs / 6e4);
|
|
653
|
+
process.emitWarning?.(
|
|
654
|
+
`Edit session expires in ~${minutes} minute${minutes !== 1 ? "s" : ""}. Long uploads may fail. Consider starting a fresh operation.`,
|
|
655
|
+
"EditExpiryWarning"
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
643
659
|
async function uploadRelease(client, packageName, filePath, options) {
|
|
644
660
|
const validation = await validateUploadFile(filePath);
|
|
645
661
|
if (options.dryRun) {
|
|
@@ -691,9 +707,15 @@ ${validation.errors.join("\n")}`,
|
|
|
691
707
|
}
|
|
692
708
|
if (options.onProgress) options.onProgress(0, fileSize);
|
|
693
709
|
const edit = await client.edits.insert(packageName);
|
|
710
|
+
warnIfEditExpiring(edit);
|
|
694
711
|
try {
|
|
695
|
-
const bundle = await client.bundles.upload(packageName, edit.id, filePath
|
|
696
|
-
|
|
712
|
+
const bundle = await client.bundles.upload(packageName, edit.id, filePath, {
|
|
713
|
+
...options.uploadOptions,
|
|
714
|
+
onProgress: (event) => {
|
|
715
|
+
if (options.onProgress) options.onProgress(event.bytesUploaded, event.totalBytes);
|
|
716
|
+
if (options.onUploadProgress) options.onUploadProgress(event);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
697
719
|
if (options.mappingFile) {
|
|
698
720
|
await client.deobfuscation.upload(
|
|
699
721
|
packageName,
|
|
@@ -1132,7 +1154,7 @@ function formatSize2(bytes) {
|
|
|
1132
1154
|
}
|
|
1133
1155
|
|
|
1134
1156
|
// src/utils/fastlane.ts
|
|
1135
|
-
import { readFile
|
|
1157
|
+
import { readFile, writeFile, mkdir, readdir, stat as stat4 } from "fs/promises";
|
|
1136
1158
|
import { join } from "path";
|
|
1137
1159
|
var FILE_MAP = {
|
|
1138
1160
|
"title.txt": "title",
|
|
@@ -1170,7 +1192,7 @@ async function readListingsFromDir(dir) {
|
|
|
1170
1192
|
for (const [fileName, field] of Object.entries(FILE_MAP)) {
|
|
1171
1193
|
const filePath = join(langDir, fileName);
|
|
1172
1194
|
if (await exists(filePath)) {
|
|
1173
|
-
const content = await
|
|
1195
|
+
const content = await readFile(filePath, "utf-8");
|
|
1174
1196
|
listing[field] = content.trimEnd();
|
|
1175
1197
|
}
|
|
1176
1198
|
}
|
|
@@ -1639,7 +1661,7 @@ async function updateAppDetails(client, packageName, details) {
|
|
|
1639
1661
|
}
|
|
1640
1662
|
|
|
1641
1663
|
// src/commands/migrate.ts
|
|
1642
|
-
import { readdir as readdir2, readFile as
|
|
1664
|
+
import { readdir as readdir2, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access } from "fs/promises";
|
|
1643
1665
|
import { join as join2 } from "path";
|
|
1644
1666
|
var COMPLEX_RUBY_RE = /\b(begin|rescue|ensure|if |unless |case |while |until |for )\b/;
|
|
1645
1667
|
async function fileExists(path) {
|
|
@@ -1679,7 +1701,7 @@ async function detectFastlane(cwd) {
|
|
|
1679
1701
|
}
|
|
1680
1702
|
if (result.hasFastfile) {
|
|
1681
1703
|
try {
|
|
1682
|
-
const content = await
|
|
1704
|
+
const content = await readFile2(fastfilePath, "utf-8");
|
|
1683
1705
|
result.lanes = parseFastfile(content);
|
|
1684
1706
|
if (COMPLEX_RUBY_RE.test(content)) {
|
|
1685
1707
|
result.parseWarnings.push(
|
|
@@ -1692,7 +1714,7 @@ async function detectFastlane(cwd) {
|
|
|
1692
1714
|
}
|
|
1693
1715
|
if (result.hasAppfile) {
|
|
1694
1716
|
try {
|
|
1695
|
-
const content = await
|
|
1717
|
+
const content = await readFile2(appfilePath, "utf-8");
|
|
1696
1718
|
const parsed = parseAppfile(content);
|
|
1697
1719
|
result.packageName = parsed.packageName;
|
|
1698
1720
|
result.jsonKeyPath = parsed.jsonKeyPath;
|
|
@@ -1923,7 +1945,7 @@ function validateSku(sku) {
|
|
|
1923
1945
|
}
|
|
1924
1946
|
|
|
1925
1947
|
// src/utils/release-notes.ts
|
|
1926
|
-
import { readdir as readdir3, readFile as
|
|
1948
|
+
import { readdir as readdir3, readFile as readFile3, stat as stat5 } from "fs/promises";
|
|
1927
1949
|
import { extname as extname3, basename, join as join3 } from "path";
|
|
1928
1950
|
var MAX_NOTES_LENGTH = 500;
|
|
1929
1951
|
async function readReleaseNotesFromDir(dir) {
|
|
@@ -1945,7 +1967,7 @@ async function readReleaseNotesFromDir(dir) {
|
|
|
1945
1967
|
const filePath = join3(dir, entry);
|
|
1946
1968
|
const stats = await stat5(filePath);
|
|
1947
1969
|
if (!stats.isFile()) continue;
|
|
1948
|
-
const text = (await
|
|
1970
|
+
const text = (await readFile3(filePath, "utf-8")).trim();
|
|
1949
1971
|
if (text.length === 0) continue;
|
|
1950
1972
|
notes.push({ language, text });
|
|
1951
1973
|
}
|
|
@@ -2770,8 +2792,8 @@ var METRIC_SET_METRICS = {
|
|
|
2770
2792
|
slowStartRateMetricSet: ["slowStartRate", "distinctUsers"],
|
|
2771
2793
|
slowRenderingRateMetricSet: ["slowRenderingRate", "distinctUsers"],
|
|
2772
2794
|
excessiveWakeupRateMetricSet: ["excessiveWakeupRate", "distinctUsers"],
|
|
2773
|
-
// API requires the weighted variants — base `stuckBackgroundWakelockRate` is not a valid metric
|
|
2774
2795
|
stuckBackgroundWakelockRateMetricSet: [
|
|
2796
|
+
"stuckBackgroundWakelockRate",
|
|
2775
2797
|
"stuckBackgroundWakelockRate7dUserWeighted",
|
|
2776
2798
|
"stuckBackgroundWakelockRate28dUserWeighted",
|
|
2777
2799
|
"distinctUsers"
|
|
@@ -2841,7 +2863,8 @@ async function getVitalsAnr(reporting, packageName, options) {
|
|
|
2841
2863
|
return queryMetric(reporting, packageName, "anrRateMetricSet", options);
|
|
2842
2864
|
}
|
|
2843
2865
|
async function getVitalsStartup(reporting, packageName, options) {
|
|
2844
|
-
|
|
2866
|
+
const opts = options?.dimension ? options : { ...options, dimension: "startType" };
|
|
2867
|
+
return queryMetric(reporting, packageName, "slowStartRateMetricSet", opts);
|
|
2845
2868
|
}
|
|
2846
2869
|
async function getVitalsRendering(reporting, packageName, options) {
|
|
2847
2870
|
return queryMetric(reporting, packageName, "slowRenderingRateMetricSet", options);
|
|
@@ -3013,7 +3036,7 @@ function watchVitalsWithAutoHalt(reporting, packageName, options) {
|
|
|
3013
3036
|
}
|
|
3014
3037
|
|
|
3015
3038
|
// src/commands/iap.ts
|
|
3016
|
-
import { readdir as readdir4, readFile as
|
|
3039
|
+
import { readdir as readdir4, readFile as readFile4 } from "fs/promises";
|
|
3017
3040
|
import { join as join4 } from "path";
|
|
3018
3041
|
import { paginateAll as paginateAll3 } from "@gpc-cli/api";
|
|
3019
3042
|
async function listInAppProducts(client, packageName, options) {
|
|
@@ -3103,7 +3126,7 @@ async function readProductsFromDir(dir) {
|
|
|
3103
3126
|
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
3104
3127
|
const localProducts = [];
|
|
3105
3128
|
for (const file of jsonFiles) {
|
|
3106
|
-
const content = await
|
|
3129
|
+
const content = await readFile4(join4(dir, file), "utf-8");
|
|
3107
3130
|
try {
|
|
3108
3131
|
localProducts.push(JSON.parse(content));
|
|
3109
3132
|
} catch {
|
|
@@ -3409,7 +3432,7 @@ async function deleteGrant(client, developerId, email, packageName) {
|
|
|
3409
3432
|
}
|
|
3410
3433
|
|
|
3411
3434
|
// src/commands/testers.ts
|
|
3412
|
-
import { readFile as
|
|
3435
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
3413
3436
|
async function listTesters(client, packageName, track) {
|
|
3414
3437
|
const edit = await client.edits.insert(packageName);
|
|
3415
3438
|
try {
|
|
@@ -3458,7 +3481,7 @@ async function removeTesters(client, packageName, track, groupEmails) {
|
|
|
3458
3481
|
}
|
|
3459
3482
|
}
|
|
3460
3483
|
async function importTestersFromCsv(client, packageName, track, csvPath) {
|
|
3461
|
-
const content = await
|
|
3484
|
+
const content = await readFile5(csvPath, "utf-8");
|
|
3462
3485
|
const emails = content.split(/[,\n\r]+/).map((e) => e.trim()).filter((e) => e.length > 0 && e.includes("@"));
|
|
3463
3486
|
if (emails.length === 0) {
|
|
3464
3487
|
throw new GpcError(
|
|
@@ -3601,7 +3624,7 @@ async function addRecoveryTargeting(client, packageName, actionId, targeting) {
|
|
|
3601
3624
|
}
|
|
3602
3625
|
|
|
3603
3626
|
// src/commands/data-safety.ts
|
|
3604
|
-
import { readFile as
|
|
3627
|
+
import { readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
|
|
3605
3628
|
async function getDataSafety(client, packageName) {
|
|
3606
3629
|
return client.dataSafety.get(packageName);
|
|
3607
3630
|
}
|
|
@@ -3614,7 +3637,7 @@ async function exportDataSafety(client, packageName, outputPath) {
|
|
|
3614
3637
|
return dataSafety;
|
|
3615
3638
|
}
|
|
3616
3639
|
async function importDataSafety(client, packageName, filePath) {
|
|
3617
|
-
const content = await
|
|
3640
|
+
const content = await readFile6(filePath, "utf-8");
|
|
3618
3641
|
let data;
|
|
3619
3642
|
try {
|
|
3620
3643
|
data = JSON.parse(content);
|
|
@@ -3911,7 +3934,7 @@ function createSpinner(message) {
|
|
|
3911
3934
|
}
|
|
3912
3935
|
|
|
3913
3936
|
// src/utils/train-state.ts
|
|
3914
|
-
import { mkdir as mkdir3, readFile as
|
|
3937
|
+
import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
|
|
3915
3938
|
import { join as join5 } from "path";
|
|
3916
3939
|
import { getCacheDir } from "@gpc-cli/config";
|
|
3917
3940
|
function stateFile(packageName) {
|
|
@@ -3920,7 +3943,7 @@ function stateFile(packageName) {
|
|
|
3920
3943
|
async function readTrainState(packageName) {
|
|
3921
3944
|
const path = stateFile(packageName);
|
|
3922
3945
|
try {
|
|
3923
|
-
const raw = await
|
|
3946
|
+
const raw = await readFile7(path, "utf-8");
|
|
3924
3947
|
return JSON.parse(raw);
|
|
3925
3948
|
} catch {
|
|
3926
3949
|
return null;
|
|
@@ -4085,7 +4108,7 @@ async function createEnterpriseApp(client, organizationId, app) {
|
|
|
4085
4108
|
}
|
|
4086
4109
|
|
|
4087
4110
|
// src/audit.ts
|
|
4088
|
-
import { appendFile, chmod, mkdir as mkdir4, readFile as
|
|
4111
|
+
import { appendFile, chmod, mkdir as mkdir4, readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
|
|
4089
4112
|
import { join as join6 } from "path";
|
|
4090
4113
|
var auditDir = null;
|
|
4091
4114
|
function initAudit(configDir) {
|
|
@@ -4153,7 +4176,7 @@ async function listAuditEvents(options) {
|
|
|
4153
4176
|
const logPath = join6(auditDir, "audit.log");
|
|
4154
4177
|
let content;
|
|
4155
4178
|
try {
|
|
4156
|
-
content = await
|
|
4179
|
+
content = await readFile8(logPath, "utf-8");
|
|
4157
4180
|
} catch {
|
|
4158
4181
|
return [];
|
|
4159
4182
|
}
|
|
@@ -4191,7 +4214,7 @@ async function clearAuditLog(options) {
|
|
|
4191
4214
|
const logPath = join6(auditDir, "audit.log");
|
|
4192
4215
|
let content;
|
|
4193
4216
|
try {
|
|
4194
|
-
content = await
|
|
4217
|
+
content = await readFile8(logPath, "utf-8");
|
|
4195
4218
|
} catch {
|
|
4196
4219
|
return { deleted: 0, remaining: 0 };
|
|
4197
4220
|
}
|
|
@@ -4684,7 +4707,7 @@ async function deactivatePurchaseOption(client, packageName, purchaseOptionId) {
|
|
|
4684
4707
|
}
|
|
4685
4708
|
|
|
4686
4709
|
// src/commands/bundle-analysis.ts
|
|
4687
|
-
import { readFile as
|
|
4710
|
+
import { readFile as readFile9, stat as stat7 } from "fs/promises";
|
|
4688
4711
|
var EOCD_SIGNATURE = 101010256;
|
|
4689
4712
|
var CD_SIGNATURE = 33639248;
|
|
4690
4713
|
var MODULE_SUBDIRS = /* @__PURE__ */ new Set(["dex", "manifest", "res", "assets", "lib", "resources.pb", "root"]);
|
|
@@ -4764,7 +4787,7 @@ async function analyzeBundle(filePath) {
|
|
|
4764
4787
|
if (!fileInfo || !fileInfo.isFile()) {
|
|
4765
4788
|
throw new Error(`File not found: ${filePath}`);
|
|
4766
4789
|
}
|
|
4767
|
-
const buf = await
|
|
4790
|
+
const buf = await readFile9(filePath);
|
|
4768
4791
|
const cdEntries = parseCentralDirectory(buf);
|
|
4769
4792
|
const fileType = detectFileType2(filePath);
|
|
4770
4793
|
const isAab = fileType === "aab";
|
|
@@ -4850,7 +4873,7 @@ function topFiles(analysis, n = 20) {
|
|
|
4850
4873
|
async function checkBundleSize(analysis, configPath = ".bundlesize.json") {
|
|
4851
4874
|
let config;
|
|
4852
4875
|
try {
|
|
4853
|
-
const raw = await
|
|
4876
|
+
const raw = await readFile9(configPath, "utf-8");
|
|
4854
4877
|
config = JSON.parse(raw);
|
|
4855
4878
|
} catch {
|
|
4856
4879
|
return { passed: true, violations: [] };
|
|
@@ -4879,7 +4902,7 @@ async function checkBundleSize(analysis, configPath = ".bundlesize.json") {
|
|
|
4879
4902
|
}
|
|
4880
4903
|
|
|
4881
4904
|
// src/commands/status.ts
|
|
4882
|
-
import { mkdir as mkdir6, readFile as
|
|
4905
|
+
import { mkdir as mkdir6, readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
|
|
4883
4906
|
import { execFile as execFile2 } from "child_process";
|
|
4884
4907
|
import { join as join8 } from "path";
|
|
4885
4908
|
import { getCacheDir as getCacheDir2 } from "@gpc-cli/config";
|
|
@@ -4889,7 +4912,7 @@ function cacheFilePath(packageName) {
|
|
|
4889
4912
|
}
|
|
4890
4913
|
async function loadStatusCache(packageName, ttlSeconds = DEFAULT_TTL_SECONDS) {
|
|
4891
4914
|
try {
|
|
4892
|
-
const raw = await
|
|
4915
|
+
const raw = await readFile10(cacheFilePath(packageName), "utf-8");
|
|
4893
4916
|
const entry = JSON.parse(raw);
|
|
4894
4917
|
const age = (Date.now() - new Date(entry.fetchedAt).getTime()) / 1e3;
|
|
4895
4918
|
if (age > (entry.ttl ?? ttlSeconds)) return null;
|
|
@@ -5257,8 +5280,7 @@ function formatStatusDiff(diff, since) {
|
|
|
5257
5280
|
}
|
|
5258
5281
|
async function runWatchLoop(opts) {
|
|
5259
5282
|
if (opts.intervalSeconds < 10) {
|
|
5260
|
-
|
|
5261
|
-
process.exit(2);
|
|
5283
|
+
throw new Error("--watch interval must be at least 10 seconds");
|
|
5262
5284
|
}
|
|
5263
5285
|
let running = true;
|
|
5264
5286
|
const cleanup = () => {
|
|
@@ -5291,7 +5313,7 @@ async function trackBreachState(packageName, isBreaching) {
|
|
|
5291
5313
|
const filePath = breachStateFilePath(packageName);
|
|
5292
5314
|
let prevBreaching = false;
|
|
5293
5315
|
try {
|
|
5294
|
-
const raw = await
|
|
5316
|
+
const raw = await readFile10(filePath, "utf-8");
|
|
5295
5317
|
prevBreaching = JSON.parse(raw).breaching;
|
|
5296
5318
|
} catch {
|
|
5297
5319
|
}
|