@gpc-cli/cli 0.9.45 → 0.9.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -15
- package/dist/anomalies-V3AFS4LD.js +66 -0
- package/dist/anomalies-V3AFS4LD.js.map +1 -0
- package/dist/{apps-J2446UDA.js → apps-FKD3ZG5X.js} +31 -35
- package/dist/apps-FKD3ZG5X.js.map +1 -0
- package/dist/{audit-N2CRHWUN.js → audit-JASSHRWN.js} +47 -62
- package/dist/audit-JASSHRWN.js.map +1 -0
- package/dist/{auth-XGSTT5G5.js → auth-OTA3SV3J.js} +145 -103
- package/dist/auth-OTA3SV3J.js.map +1 -0
- package/dist/bin.js +6 -4
- package/dist/bin.js.map +1 -1
- package/dist/bundle-F7MUVC5J.js +204 -0
- package/dist/bundle-F7MUVC5J.js.map +1 -0
- package/dist/{cache-SLNFRTI2.js → cache-XKPLZYEB.js} +4 -5
- package/dist/cache-XKPLZYEB.js.map +1 -0
- package/dist/changelog-QLDFG5TV.js +48 -0
- package/dist/changelog-QLDFG5TV.js.map +1 -0
- package/dist/{chunk-4O4D5SGL.js → chunk-3SJ6OXCZ.js} +4 -5
- package/dist/chunk-3SJ6OXCZ.js.map +1 -0
- package/dist/{chunk-U6ZTQ34I.js → chunk-BCBXQC7J.js} +45 -11
- package/dist/chunk-BCBXQC7J.js.map +1 -0
- package/dist/{chunk-AA577WVQ.js → chunk-NQH4G7BI.js} +9 -3
- package/dist/chunk-NQH4G7BI.js.map +1 -0
- package/dist/chunk-SLNJEAMK.js +23 -0
- package/dist/chunk-SLNJEAMK.js.map +1 -0
- package/dist/{chunk-SEVX56VN.js → chunk-WWVURXVO.js} +56 -49
- package/dist/chunk-WWVURXVO.js.map +1 -0
- package/dist/{chunk-NV75I5VP.js → chunk-YFUBD2XB.js} +10 -8
- package/dist/chunk-YFUBD2XB.js.map +1 -0
- package/dist/{config-BUXPDN7N.js → config-NY3TZGVS.js} +8 -5
- package/dist/config-NY3TZGVS.js.map +1 -0
- package/dist/{data-safety-Q7FTCEWU.js → data-safety-AFMD6MYI.js} +12 -27
- package/dist/data-safety-AFMD6MYI.js.map +1 -0
- package/dist/{device-tiers-MIOQEXYY.js → device-tiers-AQAMUQXI.js} +23 -38
- package/dist/device-tiers-AQAMUQXI.js.map +1 -0
- package/dist/diff-6EO4ID6W.js +91 -0
- package/dist/diff-6EO4ID6W.js.map +1 -0
- package/dist/{docs-7DUXIKA3.js → docs-4D2SJ4LY.js} +4 -3
- package/dist/docs-4D2SJ4LY.js.map +1 -0
- package/dist/doctor-QCCWG6Y3.js +708 -0
- package/dist/doctor-QCCWG6Y3.js.map +1 -0
- package/dist/{enterprise-7THXNBTC.js → enterprise-7PWXMSUN.js} +11 -21
- package/dist/enterprise-7PWXMSUN.js.map +1 -0
- package/dist/{external-transactions-2GWIMUVM.js → external-transactions-LCZALS3V.js} +12 -28
- package/dist/external-transactions-LCZALS3V.js.map +1 -0
- package/dist/{feedback-DPTO6DUT.js → feedback-CET2X67K.js} +4 -4
- package/dist/{games-BT777WUO.js → games-ZSNGEI7A.js} +17 -32
- package/dist/games-ZSNGEI7A.js.map +1 -0
- package/dist/{generated-apks-RJWTIX7L.js → generated-apks-RX2IUWSF.js} +30 -38
- package/dist/generated-apks-RX2IUWSF.js.map +1 -0
- package/dist/{grants-TKQJ3IER.js → grants-EBPECI26.js} +22 -40
- package/dist/grants-EBPECI26.js.map +1 -0
- package/dist/{iap-ICAEQLK5.js → iap-OUI5YYN4.js} +30 -51
- package/dist/iap-OUI5YYN4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{init-JZ2THPMS.js → init-WSTQTJOD.js} +5 -4
- package/dist/init-WSTQTJOD.js.map +1 -0
- package/dist/{install-skills-OV4HVANW.js → install-skills-6QDUXI5F.js} +5 -6
- package/dist/{install-skills-OV4HVANW.js.map → install-skills-6QDUXI5F.js.map} +1 -1
- package/dist/{internal-sharing-3U2XFHA4.js → internal-sharing-ONNIWIAT.js} +3 -4
- package/dist/{internal-sharing-3U2XFHA4.js.map → internal-sharing-ONNIWIAT.js.map} +1 -1
- package/dist/{listings-77HZW4S5.js → listings-7SGQ4SRX.js} +118 -157
- package/dist/listings-7SGQ4SRX.js.map +1 -0
- package/dist/migrate-ZQCJGQQS.js +138 -0
- package/dist/migrate-ZQCJGQQS.js.map +1 -0
- package/dist/{one-time-products-LHZAXQES.js → one-time-products-MGZTU7OM.js} +65 -120
- package/dist/one-time-products-MGZTU7OM.js.map +1 -0
- package/dist/{preflight-H3HEBYQW.js → preflight-N7ZRG2JI.js} +58 -55
- package/dist/preflight-N7ZRG2JI.js.map +1 -0
- package/dist/{pricing-XQSDTTK5.js → pricing-JJZFICFL.js} +8 -8
- package/dist/{pricing-XQSDTTK5.js.map → pricing-JJZFICFL.js.map} +1 -1
- package/dist/{prompt-BSV22CQZ.js → prompt-GXC2JSLA.js} +2 -2
- package/dist/{publish-Q5ZKEKZ5.js → publish-JPTI4EBT.js} +34 -30
- package/dist/publish-JPTI4EBT.js.map +1 -0
- package/dist/{purchase-options-CKRN4VIW.js → purchase-options-KFWW4JW2.js} +16 -11
- package/dist/purchase-options-KFWW4JW2.js.map +1 -0
- package/dist/{purchases-43AKV6HG.js → purchases-Z3QBM3UO.js} +121 -194
- package/dist/purchases-Z3QBM3UO.js.map +1 -0
- package/dist/{quickstart-4HB62YEL.js → quickstart-Z5Y3FYJU.js} +5 -3
- package/dist/quickstart-Z5Y3FYJU.js.map +1 -0
- package/dist/{quota-UHIQQYOY.js → quota-MZRWYJGR.js} +5 -15
- package/dist/quota-MZRWYJGR.js.map +1 -0
- package/dist/{recovery-5EV2R476.js → recovery-YE3Z7NIN.js} +32 -61
- package/dist/recovery-YE3Z7NIN.js.map +1 -0
- package/dist/{releases-C2WC2K4E.js → releases-276W3BR7.js} +188 -187
- package/dist/releases-276W3BR7.js.map +1 -0
- package/dist/{reports-2YX3RDOS.js → reports-CIB2T3XT.js} +19 -21
- package/dist/reports-CIB2T3XT.js.map +1 -0
- package/dist/reviews-YCBBM656.js +199 -0
- package/dist/reviews-YCBBM656.js.map +1 -0
- package/dist/rtdn-LID2B7XZ.js +87 -0
- package/dist/rtdn-LID2B7XZ.js.map +1 -0
- package/dist/{status-WHGLODGV.js → status-6LH5W4FU.js} +105 -83
- package/dist/status-6LH5W4FU.js.map +1 -0
- package/dist/{subscriptions-CI3JH3VQ.js → subscriptions-DZP3Y7O7.js} +142 -232
- package/dist/subscriptions-DZP3Y7O7.js.map +1 -0
- package/dist/{testers-NZOFA3EF.js → testers-LSMBXCA2.js} +24 -44
- package/dist/testers-LSMBXCA2.js.map +1 -0
- package/dist/tracks-YHMO2A6B.js +98 -0
- package/dist/tracks-YHMO2A6B.js.map +1 -0
- package/dist/{train-CJJVLY4B.js → train-MDD2EBHS.js} +35 -55
- package/dist/train-MDD2EBHS.js.map +1 -0
- package/dist/{update-NAK6CMUX.js → update-XAO5EZHC.js} +30 -15
- package/dist/update-XAO5EZHC.js.map +1 -0
- package/dist/{users-2YTC4Q36.js → users-UKG7VIQH.js} +45 -67
- package/dist/users-UKG7VIQH.js.map +1 -0
- package/dist/{validate-UOVTM6L3.js → validate-QIYSA3N7.js} +8 -10
- package/dist/validate-QIYSA3N7.js.map +1 -0
- package/dist/{version-N64UBW7A.js → version-R3P4NHCF.js} +4 -4
- package/dist/{vitals-A4CS4MSS.js → vitals-PJEQUUAK.js} +174 -165
- package/dist/vitals-PJEQUUAK.js.map +1 -0
- package/package.json +6 -6
- package/dist/anomalies-NU2IN2GJ.js +0 -54
- package/dist/anomalies-NU2IN2GJ.js.map +0 -1
- package/dist/apps-J2446UDA.js.map +0 -1
- package/dist/audit-N2CRHWUN.js.map +0 -1
- package/dist/auth-XGSTT5G5.js.map +0 -1
- package/dist/bundle-F43TD2BQ.js +0 -218
- package/dist/bundle-F43TD2BQ.js.map +0 -1
- package/dist/cache-SLNFRTI2.js.map +0 -1
- package/dist/changelog-ZYD6W5IV.js +0 -53
- package/dist/changelog-ZYD6W5IV.js.map +0 -1
- package/dist/chunk-4O4D5SGL.js.map +0 -1
- package/dist/chunk-AA577WVQ.js.map +0 -1
- package/dist/chunk-FWKYRLKY.js +0 -19
- package/dist/chunk-FWKYRLKY.js.map +0 -1
- package/dist/chunk-NV75I5VP.js.map +0 -1
- package/dist/chunk-SEVX56VN.js.map +0 -1
- package/dist/chunk-U6ZTQ34I.js.map +0 -1
- package/dist/config-BUXPDN7N.js.map +0 -1
- package/dist/data-safety-Q7FTCEWU.js.map +0 -1
- package/dist/device-tiers-MIOQEXYY.js.map +0 -1
- package/dist/diff-V77SMKAQ.js +0 -96
- package/dist/diff-V77SMKAQ.js.map +0 -1
- package/dist/docs-7DUXIKA3.js.map +0 -1
- package/dist/doctor-3Z4ARPM2.js +0 -372
- package/dist/doctor-3Z4ARPM2.js.map +0 -1
- package/dist/enterprise-7THXNBTC.js.map +0 -1
- package/dist/external-transactions-2GWIMUVM.js.map +0 -1
- package/dist/games-BT777WUO.js.map +0 -1
- package/dist/generated-apks-RJWTIX7L.js.map +0 -1
- package/dist/grants-TKQJ3IER.js.map +0 -1
- package/dist/iap-ICAEQLK5.js.map +0 -1
- package/dist/init-JZ2THPMS.js.map +0 -1
- package/dist/listings-77HZW4S5.js.map +0 -1
- package/dist/migrate-SQT6RD6T.js +0 -143
- package/dist/migrate-SQT6RD6T.js.map +0 -1
- package/dist/one-time-products-LHZAXQES.js.map +0 -1
- package/dist/preflight-H3HEBYQW.js.map +0 -1
- package/dist/publish-Q5ZKEKZ5.js.map +0 -1
- package/dist/purchase-options-CKRN4VIW.js.map +0 -1
- package/dist/purchases-43AKV6HG.js.map +0 -1
- package/dist/quickstart-4HB62YEL.js.map +0 -1
- package/dist/quota-UHIQQYOY.js.map +0 -1
- package/dist/recovery-5EV2R476.js.map +0 -1
- package/dist/releases-C2WC2K4E.js.map +0 -1
- package/dist/reports-2YX3RDOS.js.map +0 -1
- package/dist/reviews-2CWOI5CV.js +0 -213
- package/dist/reviews-2CWOI5CV.js.map +0 -1
- package/dist/status-WHGLODGV.js.map +0 -1
- package/dist/subscriptions-CI3JH3VQ.js.map +0 -1
- package/dist/testers-NZOFA3EF.js.map +0 -1
- package/dist/tracks-NERFFEDT.js +0 -107
- package/dist/tracks-NERFFEDT.js.map +0 -1
- package/dist/train-CJJVLY4B.js.map +0 -1
- package/dist/update-NAK6CMUX.js.map +0 -1
- package/dist/users-2YTC4Q36.js.map +0 -1
- package/dist/validate-UOVTM6L3.js.map +0 -1
- package/dist/vitals-A4CS4MSS.js.map +0 -1
- /package/dist/{feedback-DPTO6DUT.js.map → feedback-CET2X67K.js.map} +0 -0
- /package/dist/{prompt-BSV22CQZ.js.map → prompt-GXC2JSLA.js.map} +0 -0
- /package/dist/{version-N64UBW7A.js.map → version-R3P4NHCF.js.map} +0 -0
|
@@ -25,37 +25,13 @@ import {
|
|
|
25
25
|
runWatchLoop,
|
|
26
26
|
trackBreachState,
|
|
27
27
|
sendNotification,
|
|
28
|
+
relativeTime,
|
|
28
29
|
formatOutput,
|
|
29
30
|
createSpinner
|
|
30
31
|
} from "@gpc-cli/core";
|
|
31
32
|
var VALID_SECTIONS = /* @__PURE__ */ new Set(["releases", "vitals", "reviews"]);
|
|
32
33
|
var VALID_FORMATS = /* @__PURE__ */ new Set(["table", "summary"]);
|
|
33
|
-
|
|
34
|
-
const sections = raw.split(",").map((s) => s.trim().toLowerCase());
|
|
35
|
-
for (const s of sections) {
|
|
36
|
-
if (!VALID_SECTIONS.has(s)) {
|
|
37
|
-
console.error(`Error: Unknown section "${s}". Valid sections: releases, vitals, reviews`);
|
|
38
|
-
process.exit(2);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return sections;
|
|
42
|
-
}
|
|
43
|
-
function resolveVitalThresholds(config) {
|
|
44
|
-
const vitals = config["vitals"];
|
|
45
|
-
const t = vitals?.["thresholds"];
|
|
46
|
-
if (!t) return void 0;
|
|
47
|
-
const toN = (v) => {
|
|
48
|
-
if (v === void 0 || v === null) return void 0;
|
|
49
|
-
const n = Number(v);
|
|
50
|
-
return isNaN(n) ? void 0 : n;
|
|
51
|
-
};
|
|
52
|
-
return {
|
|
53
|
-
crashRate: toN(t["crashRate"]),
|
|
54
|
-
anrRate: toN(t["anrRate"]),
|
|
55
|
-
slowStartRate: toN(t["slowStartRate"]),
|
|
56
|
-
slowRenderingRate: toN(t["slowRenderingRate"])
|
|
57
|
-
};
|
|
58
|
-
}
|
|
34
|
+
var MAX_ALL_APPS = 5;
|
|
59
35
|
var THRESHOLD_KEYS = {
|
|
60
36
|
crashes: "crashRate",
|
|
61
37
|
crash: "crashRate",
|
|
@@ -65,6 +41,25 @@ var THRESHOLD_KEYS = {
|
|
|
65
41
|
"slow-render": "slowRenderingRate",
|
|
66
42
|
"slow-rendering": "slowRenderingRate"
|
|
67
43
|
};
|
|
44
|
+
function usageError(message, suggestion) {
|
|
45
|
+
throw Object.assign(new Error(message), {
|
|
46
|
+
code: "STATUS_USAGE_ERROR",
|
|
47
|
+
exitCode: 2,
|
|
48
|
+
suggestion
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function parseSections(raw) {
|
|
52
|
+
const sections = raw.split(",").map((s) => s.trim().toLowerCase());
|
|
53
|
+
for (const s of sections) {
|
|
54
|
+
if (!VALID_SECTIONS.has(s)) {
|
|
55
|
+
usageError(
|
|
56
|
+
`Unknown section "${s}"`,
|
|
57
|
+
"Valid sections: releases, vitals, reviews"
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return sections;
|
|
62
|
+
}
|
|
68
63
|
function parseThresholdOverrides(raw) {
|
|
69
64
|
const result = {};
|
|
70
65
|
for (const pair of raw.split(",")) {
|
|
@@ -72,22 +67,46 @@ function parseThresholdOverrides(raw) {
|
|
|
72
67
|
if (!key || !val) continue;
|
|
73
68
|
const mapped = THRESHOLD_KEYS[key.toLowerCase()];
|
|
74
69
|
if (!mapped) {
|
|
75
|
-
|
|
76
|
-
`
|
|
70
|
+
usageError(
|
|
71
|
+
`Unknown threshold "${key}"`,
|
|
72
|
+
"Valid: crashes, anr, slow-starts, slow-render"
|
|
77
73
|
);
|
|
78
|
-
process.exit(2);
|
|
79
74
|
}
|
|
80
75
|
const n = parseFloat(val);
|
|
81
76
|
if (isNaN(n) || n < 0) {
|
|
82
|
-
|
|
83
|
-
`
|
|
77
|
+
usageError(
|
|
78
|
+
`Invalid threshold value "${val}" for ${key}`,
|
|
79
|
+
"Must be a positive number (percent)"
|
|
84
80
|
);
|
|
85
|
-
process.exit(2);
|
|
86
81
|
}
|
|
87
82
|
result[mapped] = n / 100;
|
|
88
83
|
}
|
|
89
84
|
return result;
|
|
90
85
|
}
|
|
86
|
+
function resolveWatchInterval(watch) {
|
|
87
|
+
if (watch === void 0) return null;
|
|
88
|
+
if (watch === true || watch === "") return 30;
|
|
89
|
+
const n = parseInt(String(watch), 10);
|
|
90
|
+
return isNaN(n) ? 30 : n;
|
|
91
|
+
}
|
|
92
|
+
function resolveVitalThresholds(config) {
|
|
93
|
+
const raw = config;
|
|
94
|
+
const vitals = raw["vitals"];
|
|
95
|
+
if (!vitals || typeof vitals !== "object") return void 0;
|
|
96
|
+
const t = vitals["thresholds"];
|
|
97
|
+
if (!t || typeof t !== "object") return void 0;
|
|
98
|
+
const toN = (v) => {
|
|
99
|
+
if (v === void 0 || v === null) return void 0;
|
|
100
|
+
const n = Number(v);
|
|
101
|
+
return isNaN(n) ? void 0 : n;
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
crashRate: toN(t["crashRate"]),
|
|
105
|
+
anrRate: toN(t["anrRate"]),
|
|
106
|
+
slowStartRate: toN(t["slowStartRate"]),
|
|
107
|
+
slowRenderingRate: toN(t["slowRenderingRate"])
|
|
108
|
+
};
|
|
109
|
+
}
|
|
91
110
|
function resolvePackages(program, config, allApps) {
|
|
92
111
|
const rootApp = program.opts()["app"] || config.app;
|
|
93
112
|
if (!allApps) return rootApp ? [rootApp] : [];
|
|
@@ -105,12 +124,6 @@ function resolvePackages(program, config, allApps) {
|
|
|
105
124
|
}
|
|
106
125
|
return result;
|
|
107
126
|
}
|
|
108
|
-
function resolveWatchInterval(watch) {
|
|
109
|
-
if (watch === void 0) return null;
|
|
110
|
-
if (watch === true || watch === "") return 30;
|
|
111
|
-
const n = parseInt(String(watch), 10);
|
|
112
|
-
return isNaN(n) ? 30 : n;
|
|
113
|
-
}
|
|
114
127
|
function colorizeTrackStatus(s) {
|
|
115
128
|
switch (s) {
|
|
116
129
|
case "inProgress":
|
|
@@ -134,7 +147,7 @@ function applyStatusColors(status) {
|
|
|
134
147
|
}))
|
|
135
148
|
};
|
|
136
149
|
}
|
|
137
|
-
function makeRenderer(format, displayFormat) {
|
|
150
|
+
function makeRenderer(format, displayFormat, includeDiff) {
|
|
138
151
|
return (status) => {
|
|
139
152
|
if (format === "json") {
|
|
140
153
|
const sectionSet = new Set(status.sections);
|
|
@@ -147,6 +160,10 @@ function makeRenderer(format, displayFormat) {
|
|
|
147
160
|
if (sectionSet.has("releases")) filtered["releases"] = status.releases;
|
|
148
161
|
if (sectionSet.has("vitals")) filtered["vitals"] = status.vitals;
|
|
149
162
|
if (sectionSet.has("reviews")) filtered["reviews"] = status.reviews;
|
|
163
|
+
if (includeDiff?.sinceLast && includeDiff.prevStatus) {
|
|
164
|
+
filtered["diff"] = computeStatusDiff(includeDiff.prevStatus, status);
|
|
165
|
+
filtered["diffSince"] = includeDiff.prevStatus.fetchedAt;
|
|
166
|
+
}
|
|
150
167
|
return formatOutput(filtered, "json");
|
|
151
168
|
}
|
|
152
169
|
const colorized = applyStatusColors(status);
|
|
@@ -159,29 +176,24 @@ function registerStatusCommand(program) {
|
|
|
159
176
|
"--sections <list>",
|
|
160
177
|
"Comma-separated sections: releases,vitals,reviews",
|
|
161
178
|
"releases,vitals,reviews"
|
|
162
|
-
).option("--watch [seconds]", "Poll every N seconds (min 10, default 30)").option("--since-last", "Show diff from last cached status").option("--all-apps",
|
|
179
|
+
).option("--watch [seconds]", "Poll every N seconds (min 10, default 30)").option("--since-last", "Show diff from last cached status").option("--all-apps", `Run status for all configured app profiles (max ${MAX_ALL_APPS})`).option("--notify", "Send desktop notification on threshold breach or clear").option("--threshold <overrides>", "Override vitals thresholds: crashes=1.5,anr=0.5 (percent)").action(
|
|
163
180
|
async (opts) => {
|
|
164
181
|
if (!VALID_FORMATS.has(opts.format)) {
|
|
165
|
-
|
|
166
|
-
|
|
182
|
+
usageError(
|
|
183
|
+
`Unknown format "${opts.format}"`,
|
|
184
|
+
"Valid: table, summary"
|
|
185
|
+
);
|
|
167
186
|
}
|
|
168
187
|
const sections = parseSections(opts.sections);
|
|
169
188
|
if (!Number.isFinite(opts.days) || opts.days < 1) {
|
|
170
|
-
|
|
171
|
-
process.exit(2);
|
|
189
|
+
usageError(`--days must be a positive integer (got: ${opts.days})`);
|
|
172
190
|
}
|
|
173
191
|
if (!Number.isFinite(opts.reviewDays) || opts.reviewDays < 1) {
|
|
174
|
-
|
|
175
|
-
`Error: --review-days must be a positive integer (got: ${opts.reviewDays})`
|
|
176
|
-
);
|
|
177
|
-
process.exit(2);
|
|
192
|
+
usageError(`--review-days must be a positive integer (got: ${opts.reviewDays})`);
|
|
178
193
|
}
|
|
179
194
|
const config = await loadConfig();
|
|
180
195
|
const format = getOutputFormat(program, config);
|
|
181
|
-
|
|
182
|
-
let vitalThresholds = resolveVitalThresholds(
|
|
183
|
-
config
|
|
184
|
-
);
|
|
196
|
+
let vitalThresholds = resolveVitalThresholds(config);
|
|
185
197
|
if (opts.threshold) {
|
|
186
198
|
const overrides = parseThresholdOverrides(opts.threshold);
|
|
187
199
|
vitalThresholds = { ...vitalThresholds, ...overrides };
|
|
@@ -189,20 +201,22 @@ function registerStatusCommand(program) {
|
|
|
189
201
|
const watchInterval = resolveWatchInterval(opts.watch);
|
|
190
202
|
const packages = resolvePackages(program, config, opts.allApps);
|
|
191
203
|
if (packages.length === 0) {
|
|
192
|
-
|
|
193
|
-
"
|
|
204
|
+
usageError(
|
|
205
|
+
"No package name",
|
|
206
|
+
"Use --app <package> or gpc config set app <package>"
|
|
194
207
|
);
|
|
195
|
-
process.exit(2);
|
|
196
208
|
}
|
|
197
|
-
if (opts.allApps && packages.length >
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
if (opts.allApps && packages.length > MAX_ALL_APPS) {
|
|
210
|
+
usageError(
|
|
211
|
+
`--all-apps found ${packages.length} apps (max ${MAX_ALL_APPS})`,
|
|
212
|
+
"Use --app to target a specific app"
|
|
200
213
|
);
|
|
201
|
-
process.exit(2);
|
|
202
214
|
}
|
|
203
|
-
const authConfig = config
|
|
215
|
+
const authConfig = config.auth;
|
|
204
216
|
const makeClients = async () => {
|
|
205
|
-
const auth = await resolveAuth({
|
|
217
|
+
const auth = await resolveAuth({
|
|
218
|
+
serviceAccountPath: authConfig?.serviceAccount
|
|
219
|
+
});
|
|
206
220
|
return {
|
|
207
221
|
client: createApiClient({ auth }),
|
|
208
222
|
reporting: createReportingClient({ auth })
|
|
@@ -210,8 +224,12 @@ function registerStatusCommand(program) {
|
|
|
210
224
|
};
|
|
211
225
|
let anyBreach = false;
|
|
212
226
|
for (const packageName of packages) {
|
|
213
|
-
if (packages.length > 1)
|
|
214
|
-
|
|
227
|
+
if (packages.length > 1) {
|
|
228
|
+
const label = statusHasBreach ? `
|
|
229
|
+
=== ${packageName} ===` : `
|
|
230
|
+
=== ${packageName} ===`;
|
|
231
|
+
console.log(label);
|
|
232
|
+
}
|
|
215
233
|
try {
|
|
216
234
|
const breach = await runStatusForPackage({
|
|
217
235
|
packageName,
|
|
@@ -220,16 +238,15 @@ function registerStatusCommand(program) {
|
|
|
220
238
|
format,
|
|
221
239
|
vitalThresholds,
|
|
222
240
|
watchInterval,
|
|
223
|
-
render,
|
|
224
241
|
makeClients
|
|
225
242
|
});
|
|
226
243
|
if (breach) anyBreach = true;
|
|
227
244
|
} catch (error) {
|
|
245
|
+
if (packages.length === 1) throw error;
|
|
228
246
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
229
|
-
if (packages.length === 1) process.exit(4);
|
|
230
247
|
}
|
|
231
248
|
}
|
|
232
|
-
if (anyBreach) process.
|
|
249
|
+
if (anyBreach) process.exitCode = 6;
|
|
233
250
|
}
|
|
234
251
|
);
|
|
235
252
|
}
|
|
@@ -240,7 +257,7 @@ function applyDisplaySections(status, requestedSections) {
|
|
|
240
257
|
return { ...status, sections: filtered };
|
|
241
258
|
}
|
|
242
259
|
async function runStatusForPackage(ctx) {
|
|
243
|
-
const { packageName, opts, sections, vitalThresholds, watchInterval
|
|
260
|
+
const { packageName, opts, sections, vitalThresholds, watchInterval } = ctx;
|
|
244
261
|
const fetchLive = async () => {
|
|
245
262
|
const { client, reporting } = await ctx.makeClients();
|
|
246
263
|
return getAppStatus(client, reporting, packageName, {
|
|
@@ -251,6 +268,11 @@ async function runStatusForPackage(ctx) {
|
|
|
251
268
|
});
|
|
252
269
|
};
|
|
253
270
|
const save = (status2) => saveStatusCache(packageName, status2, opts.ttl);
|
|
271
|
+
const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;
|
|
272
|
+
const render = makeRenderer(ctx.format, opts.format, {
|
|
273
|
+
prevStatus,
|
|
274
|
+
sinceLast: opts.sinceLast
|
|
275
|
+
});
|
|
254
276
|
if (watchInterval !== null && opts.sinceLast) {
|
|
255
277
|
process.stderr.write(
|
|
256
278
|
"Warning: --since-last is not supported with --watch and will be ignored.\n"
|
|
@@ -263,15 +285,20 @@ async function runStatusForPackage(ctx) {
|
|
|
263
285
|
if (opts.cached) {
|
|
264
286
|
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
265
287
|
if (!cached) {
|
|
266
|
-
|
|
267
|
-
|
|
288
|
+
throw Object.assign(
|
|
289
|
+
new Error("No cached status found"),
|
|
290
|
+
{
|
|
291
|
+
code: "STATUS_NO_CACHE",
|
|
292
|
+
exitCode: 2,
|
|
293
|
+
suggestion: "Run without --cached to fetch live data"
|
|
294
|
+
}
|
|
295
|
+
);
|
|
268
296
|
}
|
|
269
297
|
const display = applyDisplaySections(cached, sections);
|
|
270
|
-
|
|
298
|
+
printWithDiff(display, prevStatus, opts.sinceLast, render, ctx.format);
|
|
271
299
|
await handleNotify(packageName, cached, opts.notify);
|
|
272
300
|
return statusHasBreach(cached);
|
|
273
301
|
}
|
|
274
|
-
const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;
|
|
275
302
|
if (!opts.refresh) {
|
|
276
303
|
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
277
304
|
if (cached) {
|
|
@@ -302,22 +329,14 @@ async function runStatusForPackage(ctx) {
|
|
|
302
329
|
await handleNotify(packageName, status, opts.notify);
|
|
303
330
|
return statusHasBreach(status);
|
|
304
331
|
}
|
|
305
|
-
function relativeTime(isoString) {
|
|
306
|
-
const diffMs = Date.now() - new Date(isoString).getTime();
|
|
307
|
-
const diffMin = Math.floor(diffMs / 6e4);
|
|
308
|
-
if (diffMin < 1) return "just now";
|
|
309
|
-
if (diffMin < 60) return `${diffMin} min ago`;
|
|
310
|
-
const diffHr = Math.floor(diffMin / 60);
|
|
311
|
-
if (diffHr < 24) return `${diffHr}h ago`;
|
|
312
|
-
return `${Math.floor(diffHr / 24)}d ago`;
|
|
313
|
-
}
|
|
314
332
|
function printWithDiff(status, prevStatus, sinceLast, render, format) {
|
|
315
333
|
console.log(render(status));
|
|
334
|
+
if (format === "json") return;
|
|
316
335
|
if (sinceLast && prevStatus) {
|
|
317
336
|
const since = relativeTime(prevStatus.fetchedAt);
|
|
318
337
|
console.log("");
|
|
319
338
|
console.log(formatStatusDiff(computeStatusDiff(prevStatus, status), since));
|
|
320
|
-
} else if (sinceLast && !prevStatus
|
|
339
|
+
} else if (sinceLast && !prevStatus) {
|
|
321
340
|
console.log("\n(No prior cached status to diff against)");
|
|
322
341
|
}
|
|
323
342
|
}
|
|
@@ -332,6 +351,9 @@ async function handleNotify(packageName, status, notify) {
|
|
|
332
351
|
}
|
|
333
352
|
}
|
|
334
353
|
export {
|
|
335
|
-
|
|
354
|
+
parseSections,
|
|
355
|
+
parseThresholdOverrides,
|
|
356
|
+
registerStatusCommand,
|
|
357
|
+
resolveWatchInterval
|
|
336
358
|
};
|
|
337
|
-
//# sourceMappingURL=status-
|
|
359
|
+
//# sourceMappingURL=status-6LH5W4FU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport type { ResolvedConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient, createReportingClient } from \"@gpc-cli/api\";\nimport {\n getAppStatus,\n formatStatusTable,\n formatStatusSummary,\n formatStatusDiff,\n computeStatusDiff,\n loadStatusCache,\n saveStatusCache,\n statusHasBreach,\n runWatchLoop,\n trackBreachState,\n sendNotification,\n relativeTime,\n formatOutput,\n createSpinner,\n} from \"@gpc-cli/core\";\nimport type { AppStatus } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\nimport { green, red, dim, gray } from \"../colors.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst VALID_SECTIONS = new Set([\"releases\", \"vitals\", \"reviews\"]);\nconst VALID_FORMATS = new Set([\"table\", \"summary\"]);\nconst MAX_ALL_APPS = 5;\n\nconst THRESHOLD_KEYS: Record<string, string> = {\n crashes: \"crashRate\",\n crash: \"crashRate\",\n anr: \"anrRate\",\n \"slow-starts\": \"slowStartRate\",\n \"slow-start\": \"slowStartRate\",\n \"slow-render\": \"slowRenderingRate\",\n \"slow-rendering\": \"slowRenderingRate\",\n};\n\n// ---------------------------------------------------------------------------\n// Validation error helper\n// ---------------------------------------------------------------------------\n\nfunction usageError(message: string, suggestion?: string): never {\n throw Object.assign(new Error(message), {\n code: \"STATUS_USAGE_ERROR\",\n exitCode: 2,\n suggestion,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Pure, testable helpers\n// ---------------------------------------------------------------------------\n\nexport function parseSections(raw: string): string[] {\n const sections = raw.split(\",\").map((s) => s.trim().toLowerCase());\n for (const s of sections) {\n if (!VALID_SECTIONS.has(s)) {\n usageError(\n `Unknown section \"${s}\"`,\n \"Valid sections: releases, vitals, reviews\",\n );\n }\n }\n return sections;\n}\n\nexport function parseThresholdOverrides(raw: string): Record<string, number> {\n const result: Record<string, number> = {};\n for (const pair of raw.split(\",\")) {\n const [key, val] = pair.split(\"=\").map((s) => s.trim());\n if (!key || !val) continue;\n const mapped = THRESHOLD_KEYS[key.toLowerCase()];\n if (!mapped) {\n usageError(\n `Unknown threshold \"${key}\"`,\n \"Valid: crashes, anr, slow-starts, slow-render\",\n );\n }\n const n = parseFloat(val);\n if (isNaN(n) || n < 0) {\n usageError(\n `Invalid threshold value \"${val}\" for ${key}`,\n \"Must be a positive number (percent)\",\n );\n }\n result[mapped] = n / 100; // Convert percent to decimal\n }\n return result;\n}\n\nexport function resolveWatchInterval(watch: string | boolean | undefined): number | null {\n if (watch === undefined) return null;\n if (watch === true || watch === \"\") return 30;\n const n = parseInt(String(watch), 10);\n return isNaN(n) ? 30 : n;\n}\n\nfunction resolveVitalThresholds(config: ResolvedConfig) {\n const raw = config as unknown as Record<string, unknown>;\n const vitals = raw[\"vitals\"] as Record<string, unknown> | undefined;\n if (!vitals || typeof vitals !== \"object\") return undefined;\n const t = vitals[\"thresholds\"] as Record<string, unknown> | undefined;\n if (!t || typeof t !== \"object\") return undefined;\n const toN = (v: unknown): number | undefined => {\n if (v === undefined || v === null) return undefined;\n const n = Number(v);\n return isNaN(n) ? undefined : n;\n };\n return {\n crashRate: toN(t[\"crashRate\"]),\n anrRate: toN(t[\"anrRate\"]),\n slowStartRate: toN(t[\"slowStartRate\"]),\n slowRenderingRate: toN(t[\"slowRenderingRate\"]),\n };\n}\n\nfunction resolvePackages(\n program: Command,\n config: ResolvedConfig,\n allApps?: boolean,\n): string[] {\n const rootApp = (program.opts()[\"app\"] || config.app) as string | undefined;\n if (!allApps) return rootApp ? [rootApp] : [];\n\n const seen = new Set<string>();\n const result: string[] = [];\n if (rootApp) {\n seen.add(rootApp);\n result.push(rootApp);\n }\n for (const profile of Object.values(config.profiles ?? {})) {\n if (profile.app && !seen.has(profile.app)) {\n seen.add(profile.app);\n result.push(profile.app);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Display helpers\n// ---------------------------------------------------------------------------\n\nfunction colorizeTrackStatus(s: string): string {\n switch (s) {\n case \"inProgress\":\n case \"completed\":\n return green(s);\n case \"halted\":\n return red(s);\n case \"draft\":\n return dim(s);\n default:\n return gray(s);\n }\n}\n\nfunction applyStatusColors(status: AppStatus): AppStatus {\n if (!status.releases || status.releases.length === 0) return status;\n return {\n ...status,\n releases: status.releases.map((r) => ({\n ...r,\n status: colorizeTrackStatus(r.status),\n })),\n };\n}\n\nfunction makeRenderer(\n format: string,\n displayFormat: string,\n includeDiff?: { prevStatus: AppStatus | null; sinceLast?: boolean },\n): (status: AppStatus) => string {\n return (status: AppStatus): string => {\n if (format === \"json\") {\n const sectionSet = new Set(status.sections);\n const filtered: Record<string, unknown> = {\n packageName: status.packageName,\n fetchedAt: status.fetchedAt,\n cached: status.cached,\n sections: status.sections,\n };\n if (sectionSet.has(\"releases\")) filtered[\"releases\"] = status.releases;\n if (sectionSet.has(\"vitals\")) filtered[\"vitals\"] = status.vitals;\n if (sectionSet.has(\"reviews\")) filtered[\"reviews\"] = status.reviews;\n\n // Embed diff in JSON output when --since-last is used\n if (includeDiff?.sinceLast && includeDiff.prevStatus) {\n filtered[\"diff\"] = computeStatusDiff(includeDiff.prevStatus, status);\n filtered[\"diffSince\"] = includeDiff.prevStatus.fetchedAt;\n }\n\n return formatOutput(filtered, \"json\");\n }\n const colorized = applyStatusColors(status);\n if (displayFormat === \"summary\") return formatStatusSummary(colorized);\n return formatStatusTable(colorized);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Command registration\n// ---------------------------------------------------------------------------\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Unified app health snapshot: releases, vitals, and reviews\")\n .option(\"--days <n>\", \"Vitals window in days\", (v) => parseInt(v, 10), 7)\n .option(\"--review-days <n>\", \"Reviews window in days\", (v) => parseInt(v, 10), 30)\n .option(\"--cached\", \"Use last fetched data, skip API calls\")\n .option(\"--refresh\", \"Force live fetch, ignore cache TTL\")\n .option(\"--ttl <seconds>\", \"Cache TTL in seconds\", (v) => parseInt(v, 10), 3600)\n .option(\"--format <fmt>\", \"Display style: table (default) or summary\", \"table\")\n .option(\n \"--sections <list>\",\n \"Comma-separated sections: releases,vitals,reviews\",\n \"releases,vitals,reviews\",\n )\n .option(\"--watch [seconds]\", \"Poll every N seconds (min 10, default 30)\")\n .option(\"--since-last\", \"Show diff from last cached status\")\n .option(\"--all-apps\", `Run status for all configured app profiles (max ${MAX_ALL_APPS})`)\n .option(\"--notify\", \"Send desktop notification on threshold breach or clear\")\n .option(\"--threshold <overrides>\", \"Override vitals thresholds: crashes=1.5,anr=0.5 (percent)\")\n .action(\n async (opts: {\n days: number;\n reviewDays: number;\n cached?: boolean;\n refresh?: boolean;\n ttl: number;\n format: string;\n sections: string;\n watch?: string | boolean;\n sinceLast?: boolean;\n allApps?: boolean;\n threshold?: string;\n notify?: boolean;\n }) => {\n if (!VALID_FORMATS.has(opts.format)) {\n usageError(\n `Unknown format \"${opts.format}\"`,\n \"Valid: table, summary\",\n );\n }\n\n const sections = parseSections(opts.sections);\n\n if (!Number.isFinite(opts.days) || opts.days < 1) {\n usageError(`--days must be a positive integer (got: ${opts.days})`);\n }\n\n if (!Number.isFinite(opts.reviewDays) || opts.reviewDays < 1) {\n usageError(`--review-days must be a positive integer (got: ${opts.reviewDays})`);\n }\n\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n let vitalThresholds: RunCtx[\"vitalThresholds\"] = resolveVitalThresholds(config);\n if (opts.threshold) {\n const overrides = parseThresholdOverrides(opts.threshold);\n vitalThresholds = { ...vitalThresholds, ...overrides } as RunCtx[\"vitalThresholds\"];\n }\n const watchInterval = resolveWatchInterval(opts.watch);\n const packages = resolvePackages(program, config, opts.allApps);\n\n if (packages.length === 0) {\n usageError(\n \"No package name\",\n \"Use --app <package> or gpc config set app <package>\",\n );\n }\n if (opts.allApps && packages.length > MAX_ALL_APPS) {\n usageError(\n `--all-apps found ${packages.length} apps (max ${MAX_ALL_APPS})`,\n \"Use --app to target a specific app\",\n );\n }\n\n const authConfig = config.auth;\n\n const makeClients = async () => {\n const auth = await resolveAuth({\n serviceAccountPath: authConfig?.serviceAccount,\n });\n return {\n client: createApiClient({ auth }),\n reporting: createReportingClient({ auth }),\n };\n };\n\n let anyBreach = false;\n\n for (const packageName of packages) {\n if (packages.length > 1) {\n const label = statusHasBreach\n ? `\\n=== ${packageName} ===`\n : `\\n=== ${packageName} ===`;\n console.log(label);\n }\n\n try {\n const breach = await runStatusForPackage({\n packageName,\n opts,\n sections,\n format,\n vitalThresholds,\n watchInterval,\n makeClients,\n });\n if (breach) anyBreach = true;\n } catch (error) {\n if (packages.length === 1) throw error;\n // For --all-apps, print error and continue to next app\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n if (anyBreach) process.exitCode = 6;\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// Per-package status runner\n// ---------------------------------------------------------------------------\n\ninterface RunCtx {\n packageName: string;\n opts: {\n days: number;\n reviewDays: number;\n cached?: boolean;\n refresh?: boolean;\n ttl: number;\n format: string;\n sinceLast?: boolean;\n notify?: boolean;\n };\n sections: string[];\n format: string;\n vitalThresholds:\n | {\n crashRate?: number;\n anrRate?: number;\n slowStartRate?: number;\n slowRenderingRate?: number;\n }\n | undefined;\n watchInterval: number | null;\n makeClients: () => Promise<{\n client: ReturnType<typeof createApiClient>;\n reporting: ReturnType<typeof createReportingClient>;\n }>;\n}\n\n/** Override sections on a cached AppStatus with the user-requested sections for display. */\nfunction applyDisplaySections(status: AppStatus, requestedSections: string[]): AppStatus {\n const requested = new Set(requestedSections);\n const filtered = status.sections.filter((s) => requested.has(s));\n if (filtered.length === status.sections.length) return status;\n return { ...status, sections: filtered };\n}\n\n/** Returns true if a breach was detected. */\nasync function runStatusForPackage(ctx: RunCtx): Promise<boolean> {\n const { packageName, opts, sections, vitalThresholds, watchInterval } = ctx;\n\n const fetchLive = async (): Promise<AppStatus> => {\n const { client, reporting } = await ctx.makeClients();\n return getAppStatus(client, reporting, packageName, {\n days: opts.days,\n reviewDays: opts.reviewDays,\n sections,\n vitalThresholds: vitalThresholds ?? undefined,\n });\n };\n\n const save = (status: AppStatus) => saveStatusCache(packageName, status, opts.ttl);\n\n // Capture prev status early (for --since-last)\n const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;\n\n // Build the renderer — for JSON mode with --since-last, diff is embedded\n const render = makeRenderer(ctx.format, opts.format, {\n prevStatus,\n sinceLast: opts.sinceLast,\n });\n\n if (watchInterval !== null && opts.sinceLast) {\n process.stderr.write(\n \"Warning: --since-last is not supported with --watch and will be ignored.\\n\",\n );\n }\n\n // --watch: hand off entirely to runWatchLoop\n if (watchInterval !== null) {\n await runWatchLoop({ intervalSeconds: watchInterval, render, fetch: fetchLive, save });\n return false;\n }\n\n // --cached: serve from cache only\n if (opts.cached) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (!cached) {\n throw Object.assign(\n new Error(\"No cached status found\"),\n {\n code: \"STATUS_NO_CACHE\",\n exitCode: 2,\n suggestion: \"Run without --cached to fetch live data\",\n },\n );\n }\n const display = applyDisplaySections(cached, sections);\n printWithDiff(display, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n\n // Try cache (unless --refresh)\n if (!opts.refresh) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (cached) {\n const display = applyDisplaySections(cached, sections);\n if (ctx.format !== \"json\" && display.sections.length < cached.sections.length) {\n process.stderr.write(\n `Tip: cache contains all sections. Add --refresh to fetch only the requested sections and reduce API calls.\\n`,\n );\n }\n printWithDiff(display, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n }\n\n // Live fetch (with spinner in TTY mode)\n const spinner = createSpinner(\"Fetching app status...\");\n if (ctx.format !== \"json\") spinner.start();\n let status: AppStatus;\n try {\n status = await fetchLive();\n } catch (err) {\n spinner.fail(\"Failed to fetch app status\");\n throw err;\n }\n spinner.stop(\"Done\");\n await save(status);\n\n printWithDiff(status, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, status, opts.notify);\n return statusHasBreach(status);\n}\n\n// ---------------------------------------------------------------------------\n// Output helpers\n// ---------------------------------------------------------------------------\n\nfunction printWithDiff(\n status: AppStatus,\n prevStatus: AppStatus | null,\n sinceLast: boolean | undefined,\n render: (s: AppStatus) => string,\n format: string,\n): void {\n console.log(render(status));\n\n // In JSON mode, diff is embedded by makeRenderer — no extra text output\n if (format === \"json\") return;\n\n if (sinceLast && prevStatus) {\n const since = relativeTime(prevStatus.fetchedAt);\n console.log(\"\");\n console.log(formatStatusDiff(computeStatusDiff(prevStatus, status), since));\n } else if (sinceLast && !prevStatus) {\n console.log(\"\\n(No prior cached status to diff against)\");\n }\n}\n\nasync function handleNotify(\n packageName: string,\n status: AppStatus,\n notify: boolean | undefined,\n): Promise<void> {\n if (!notify) return;\n const breaching = statusHasBreach(status);\n const changed = await trackBreachState(packageName, breaching);\n if (changed) {\n const title = breaching ? \"GPC Alert\" : \"GPC Status\";\n const body = breaching\n ? `${packageName}: vitals threshold breached`\n : `${packageName}: vitals back to normal`;\n sendNotification(title, body);\n }\n}\n"],"mappings":"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","names":["status"]}
|