@gpc-cli/cli 0.9.25 → 0.9.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1 -1
- package/dist/{chunk-P6TYWHCR.js → chunk-NTOE6MAR.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/status-3ER7XK6K.js +210 -0
- package/dist/status-3ER7XK6K.js.map +1 -0
- package/package.json +2 -2
- package/dist/status-5TOOZAGT.js +0 -96
- package/dist/status-5TOOZAGT.js.map +0 -1
- /package/dist/{chunk-P6TYWHCR.js.map → chunk-NTOE6MAR.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -94,7 +94,7 @@ async function createProgram(pluginManager) {
|
|
|
94
94
|
(await import("./tracks-XFUN7JJX.js")).registerTracksCommands(program);
|
|
95
95
|
},
|
|
96
96
|
status: async () => {
|
|
97
|
-
(await import("./status-
|
|
97
|
+
(await import("./status-3ER7XK6K.js")).registerStatusCommand(program);
|
|
98
98
|
},
|
|
99
99
|
listings: async () => {
|
|
100
100
|
(await import("./listings-VSBHQY5H.js")).registerListingsCommands(program);
|
|
@@ -308,4 +308,4 @@ export {
|
|
|
308
308
|
createProgram,
|
|
309
309
|
handleCliError
|
|
310
310
|
};
|
|
311
|
-
//# sourceMappingURL=chunk-
|
|
311
|
+
//# sourceMappingURL=chunk-NTOE6MAR.js.map
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getOutputFormat
|
|
4
|
+
} from "./chunk-ELXAK7GI.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/status.ts
|
|
7
|
+
import { loadConfig } from "@gpc-cli/config";
|
|
8
|
+
import { resolveAuth } from "@gpc-cli/auth";
|
|
9
|
+
import { createApiClient, createReportingClient } from "@gpc-cli/api";
|
|
10
|
+
import {
|
|
11
|
+
getAppStatus,
|
|
12
|
+
formatStatusTable,
|
|
13
|
+
formatStatusSummary,
|
|
14
|
+
formatStatusDiff,
|
|
15
|
+
computeStatusDiff,
|
|
16
|
+
loadStatusCache,
|
|
17
|
+
saveStatusCache,
|
|
18
|
+
statusHasBreach,
|
|
19
|
+
runWatchLoop,
|
|
20
|
+
trackBreachState,
|
|
21
|
+
sendNotification,
|
|
22
|
+
formatOutput
|
|
23
|
+
} from "@gpc-cli/core";
|
|
24
|
+
var VALID_SECTIONS = /* @__PURE__ */ new Set(["releases", "vitals", "reviews"]);
|
|
25
|
+
var VALID_FORMATS = /* @__PURE__ */ new Set(["table", "summary"]);
|
|
26
|
+
function parseSections(raw) {
|
|
27
|
+
const sections = raw.split(",").map((s) => s.trim().toLowerCase());
|
|
28
|
+
for (const s of sections) {
|
|
29
|
+
if (!VALID_SECTIONS.has(s)) {
|
|
30
|
+
console.error(`Error: Unknown section "${s}". Valid sections: releases, vitals, reviews`);
|
|
31
|
+
process.exit(2);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return sections;
|
|
35
|
+
}
|
|
36
|
+
function resolveVitalThresholds(config) {
|
|
37
|
+
const vitals = config["vitals"];
|
|
38
|
+
const t = vitals?.["thresholds"];
|
|
39
|
+
if (!t) return void 0;
|
|
40
|
+
const toN = (v) => {
|
|
41
|
+
if (v === void 0 || v === null) return void 0;
|
|
42
|
+
const n = Number(v);
|
|
43
|
+
return isNaN(n) ? void 0 : n;
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
crashRate: toN(t["crashRate"]),
|
|
47
|
+
anrRate: toN(t["anrRate"]),
|
|
48
|
+
slowStartRate: toN(t["slowStartRate"]),
|
|
49
|
+
slowRenderingRate: toN(t["slowRenderingRate"])
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function resolvePackages(program, config, allApps) {
|
|
53
|
+
const rootApp = program.opts()["app"] || config.app;
|
|
54
|
+
if (!allApps) return rootApp ? [rootApp] : [];
|
|
55
|
+
const seen = /* @__PURE__ */ new Set();
|
|
56
|
+
const result = [];
|
|
57
|
+
if (rootApp) {
|
|
58
|
+
seen.add(rootApp);
|
|
59
|
+
result.push(rootApp);
|
|
60
|
+
}
|
|
61
|
+
for (const profile of Object.values(config.profiles ?? {})) {
|
|
62
|
+
if (profile.app && !seen.has(profile.app)) {
|
|
63
|
+
seen.add(profile.app);
|
|
64
|
+
result.push(profile.app);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
function resolveWatchInterval(watch) {
|
|
70
|
+
if (watch === void 0) return null;
|
|
71
|
+
if (watch === true || watch === "") return 30;
|
|
72
|
+
const n = parseInt(String(watch), 10);
|
|
73
|
+
return isNaN(n) ? 30 : n;
|
|
74
|
+
}
|
|
75
|
+
function makeRenderer(format, displayFormat) {
|
|
76
|
+
return (status) => {
|
|
77
|
+
if (format === "json") return formatOutput(status, "json");
|
|
78
|
+
if (displayFormat === "summary") return formatStatusSummary(status);
|
|
79
|
+
return formatStatusTable(status);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function registerStatusCommand(program) {
|
|
83
|
+
program.command("status").description("Unified app health snapshot: releases, vitals, and reviews").option("--days <n>", "Vitals window in days", (v) => parseInt(v, 10), 7).option("--cached", "Use last fetched data, skip API calls").option("--refresh", "Force live fetch, ignore cache TTL").option("--ttl <seconds>", "Cache TTL in seconds", (v) => parseInt(v, 10), 3600).option("--format <fmt>", "Display style: table (default) or summary", "table").option(
|
|
84
|
+
"--sections <list>",
|
|
85
|
+
"Comma-separated sections: releases,vitals,reviews",
|
|
86
|
+
"releases,vitals,reviews"
|
|
87
|
+
).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 5)").option("--notify", "Send desktop notification on threshold breach or clear").action(
|
|
88
|
+
async (opts) => {
|
|
89
|
+
if (!VALID_FORMATS.has(opts.format)) {
|
|
90
|
+
console.error(`Error: Unknown format "${opts.format}". Valid: table, summary`);
|
|
91
|
+
process.exit(2);
|
|
92
|
+
}
|
|
93
|
+
const sections = parseSections(opts.sections);
|
|
94
|
+
const config = await loadConfig();
|
|
95
|
+
const format = getOutputFormat(program, config);
|
|
96
|
+
const render = makeRenderer(format, opts.format);
|
|
97
|
+
const vitalThresholds = resolveVitalThresholds(
|
|
98
|
+
config
|
|
99
|
+
);
|
|
100
|
+
const watchInterval = resolveWatchInterval(opts.watch);
|
|
101
|
+
const packages = resolvePackages(program, config, opts.allApps);
|
|
102
|
+
if (packages.length === 0) {
|
|
103
|
+
console.error(
|
|
104
|
+
"Error: No package name. Use --app <package> or gpc config set app <package>"
|
|
105
|
+
);
|
|
106
|
+
process.exit(2);
|
|
107
|
+
}
|
|
108
|
+
if (opts.allApps && packages.length > 5) {
|
|
109
|
+
console.error(
|
|
110
|
+
`Error: --all-apps found ${packages.length} apps (max 5). Use --app to target a specific app.`
|
|
111
|
+
);
|
|
112
|
+
process.exit(2);
|
|
113
|
+
}
|
|
114
|
+
const authConfig = config["auth"];
|
|
115
|
+
const makeClients = async () => {
|
|
116
|
+
const auth = await resolveAuth({ serviceAccountPath: authConfig?.["serviceAccount"] });
|
|
117
|
+
return {
|
|
118
|
+
client: createApiClient({ auth }),
|
|
119
|
+
reporting: createReportingClient({ auth })
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
let anyBreach = false;
|
|
123
|
+
for (const packageName of packages) {
|
|
124
|
+
if (packages.length > 1) console.log(`
|
|
125
|
+
=== ${packageName} ===`);
|
|
126
|
+
try {
|
|
127
|
+
const breach = await runStatusForPackage({
|
|
128
|
+
packageName,
|
|
129
|
+
opts,
|
|
130
|
+
sections,
|
|
131
|
+
format,
|
|
132
|
+
vitalThresholds,
|
|
133
|
+
watchInterval,
|
|
134
|
+
render,
|
|
135
|
+
makeClients
|
|
136
|
+
});
|
|
137
|
+
if (breach) anyBreach = true;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
140
|
+
if (packages.length === 1) process.exit(4);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (anyBreach) process.exit(6);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
async function runStatusForPackage(ctx) {
|
|
148
|
+
const { packageName, opts, sections, vitalThresholds, watchInterval, render } = ctx;
|
|
149
|
+
const fetchLive = async () => {
|
|
150
|
+
const { client, reporting } = await ctx.makeClients();
|
|
151
|
+
return getAppStatus(client, reporting, packageName, {
|
|
152
|
+
days: opts.days,
|
|
153
|
+
sections,
|
|
154
|
+
vitalThresholds: vitalThresholds ?? void 0
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const save = (status2) => saveStatusCache(packageName, status2, opts.ttl);
|
|
158
|
+
if (watchInterval !== null) {
|
|
159
|
+
await runWatchLoop({ intervalSeconds: watchInterval, render, fetch: fetchLive, save });
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (opts.cached) {
|
|
163
|
+
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
164
|
+
if (!cached) {
|
|
165
|
+
console.error("Error: No cached status found. Run without --cached to fetch live data.");
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
console.log(render(cached));
|
|
169
|
+
await handleNotify(packageName, cached, opts.notify);
|
|
170
|
+
return statusHasBreach(cached);
|
|
171
|
+
}
|
|
172
|
+
const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;
|
|
173
|
+
if (!opts.refresh) {
|
|
174
|
+
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
175
|
+
if (cached) {
|
|
176
|
+
printWithDiff(cached, prevStatus, opts.sinceLast, render, ctx.format);
|
|
177
|
+
await handleNotify(packageName, cached, opts.notify);
|
|
178
|
+
return statusHasBreach(cached);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const status = await fetchLive();
|
|
182
|
+
await save(status);
|
|
183
|
+
printWithDiff(status, prevStatus, opts.sinceLast, render, ctx.format);
|
|
184
|
+
await handleNotify(packageName, status, opts.notify);
|
|
185
|
+
return statusHasBreach(status);
|
|
186
|
+
}
|
|
187
|
+
function printWithDiff(status, prevStatus, sinceLast, render, format) {
|
|
188
|
+
console.log(render(status));
|
|
189
|
+
if (sinceLast && prevStatus) {
|
|
190
|
+
const since = new Date(prevStatus.fetchedAt).toLocaleString();
|
|
191
|
+
console.log("");
|
|
192
|
+
console.log(formatStatusDiff(computeStatusDiff(prevStatus, status), since));
|
|
193
|
+
} else if (sinceLast && !prevStatus && format !== "json") {
|
|
194
|
+
console.log("\n(No prior cached status to diff against)");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function handleNotify(packageName, status, notify) {
|
|
198
|
+
if (!notify) return;
|
|
199
|
+
const breaching = statusHasBreach(status);
|
|
200
|
+
const changed = await trackBreachState(packageName, breaching);
|
|
201
|
+
if (changed) {
|
|
202
|
+
const title = breaching ? "GPC Alert" : "GPC Status";
|
|
203
|
+
const body = breaching ? `${packageName}: vitals threshold breached` : `${packageName}: vitals back to normal`;
|
|
204
|
+
sendNotification(title, body);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
export {
|
|
208
|
+
registerStatusCommand
|
|
209
|
+
};
|
|
210
|
+
//# sourceMappingURL=status-3ER7XK6K.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 { 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 formatOutput,\n} from \"@gpc-cli/core\";\nimport type { AppStatus } from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\n\nconst VALID_SECTIONS = new Set([\"releases\", \"vitals\", \"reviews\"]);\nconst VALID_FORMATS = new Set([\"table\", \"summary\"]);\n\nfunction 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 console.error(`Error: Unknown section \"${s}\". Valid sections: releases, vitals, reviews`);\n process.exit(2);\n }\n }\n return sections;\n}\n\nfunction resolveVitalThresholds(config: Record<string, unknown>) {\n const vitals = config[\"vitals\"] as Record<string, unknown> | undefined;\n const t = vitals?.[\"thresholds\"] as Record<string, unknown> | undefined;\n if (!t) 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: { app?: string; profiles?: Record<string, { app?: string }> },\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\nfunction 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 makeRenderer(\n format: string,\n displayFormat: string,\n): (status: AppStatus) => string {\n return (status: AppStatus): string => {\n if (format === \"json\") return formatOutput(status, \"json\");\n if (displayFormat === \"summary\") return formatStatusSummary(status);\n return formatStatusTable(status);\n };\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(\"--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 5)\")\n .option(\"--notify\", \"Send desktop notification on threshold breach or clear\")\n .action(\n async (opts: {\n days: 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 notify?: boolean;\n }) => {\n if (!VALID_FORMATS.has(opts.format)) {\n console.error(`Error: Unknown format \"${opts.format}\". Valid: table, summary`);\n process.exit(2);\n }\n\n const sections = parseSections(opts.sections);\n const config = await loadConfig();\n const format = getOutputFormat(program, config);\n const render = makeRenderer(format, opts.format);\n const vitalThresholds = resolveVitalThresholds(\n config as unknown as Record<string, unknown>,\n );\n const watchInterval = resolveWatchInterval(opts.watch);\n const packages = resolvePackages(program, config, opts.allApps);\n\n if (packages.length === 0) {\n console.error(\n \"Error: No package name. Use --app <package> or gpc config set app <package>\",\n );\n process.exit(2);\n }\n if (opts.allApps && packages.length > 5) {\n console.error(\n `Error: --all-apps found ${packages.length} apps (max 5). Use --app to target a specific app.`,\n );\n process.exit(2);\n }\n\n const authConfig = (config as unknown as Record<string, unknown>)[\"auth\"] as\n | Record<string, string>\n | undefined;\n\n const makeClients = async () => {\n const auth = await resolveAuth({ serviceAccountPath: authConfig?.[\"serviceAccount\"] });\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) console.log(`\\n=== ${packageName} ===`);\n\n try {\n const breach = await runStatusForPackage({\n packageName,\n opts,\n sections,\n format,\n vitalThresholds,\n watchInterval,\n render,\n makeClients,\n });\n if (breach) anyBreach = true;\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n if (packages.length === 1) process.exit(4);\n // For --all-apps, continue to next app on error\n }\n }\n\n if (anyBreach) process.exit(6);\n },\n );\n}\n\ninterface RunCtx {\n packageName: string;\n opts: {\n days: number;\n cached?: boolean;\n refresh?: boolean;\n ttl: number;\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 render: (status: AppStatus) => string;\n makeClients: () => Promise<{\n client: ReturnType<typeof createApiClient>;\n reporting: ReturnType<typeof createReportingClient>;\n }>;\n}\n\n/** Returns true if a breach was detected. */\nasync function runStatusForPackage(ctx: RunCtx): Promise<boolean> {\n const { packageName, opts, sections, vitalThresholds, watchInterval, render } = 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 sections,\n vitalThresholds: vitalThresholds ?? undefined,\n });\n };\n\n const save = (status: AppStatus) => saveStatusCache(packageName, status, opts.ttl);\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 console.error(\"Error: No cached status found. Run without --cached to fetch live data.\");\n process.exit(1);\n }\n console.log(render(cached));\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n\n // Capture prev status before fetching (for --since-last)\n const prevStatus = opts.sinceLast ? await loadStatusCache(packageName, Infinity) : null;\n\n // Try cache (unless --refresh)\n if (!opts.refresh) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (cached) {\n printWithDiff(cached, prevStatus, opts.sinceLast, render, ctx.format);\n await handleNotify(packageName, cached, opts.notify);\n return statusHasBreach(cached);\n }\n }\n\n // Live fetch\n const status = await fetchLive();\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\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 if (sinceLast && prevStatus) {\n const since = new Date(prevStatus.fetchedAt).toLocaleString();\n console.log(\"\");\n console.log(formatStatusDiff(computeStatusDiff(prevStatus, status), since));\n } else if (sinceLast && !prevStatus && format !== \"json\") {\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpc-cli/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.26",
|
|
4
4
|
"description": "The complete Google Play CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
22
|
"@gpc-cli/api": "1.0.17",
|
|
23
23
|
"@gpc-cli/auth": "^0.9.9",
|
|
24
|
+
"@gpc-cli/core": "0.9.24",
|
|
24
25
|
"@gpc-cli/config": "0.9.8",
|
|
25
|
-
"@gpc-cli/core": "0.9.23",
|
|
26
26
|
"@gpc-cli/plugin-sdk": "0.9.6"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|
package/dist/status-5TOOZAGT.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
getOutputFormat
|
|
4
|
-
} from "./chunk-ELXAK7GI.js";
|
|
5
|
-
|
|
6
|
-
// src/commands/status.ts
|
|
7
|
-
import { loadConfig } from "@gpc-cli/config";
|
|
8
|
-
import { resolveAuth } from "@gpc-cli/auth";
|
|
9
|
-
import { createApiClient, createReportingClient } from "@gpc-cli/api";
|
|
10
|
-
import {
|
|
11
|
-
getAppStatus,
|
|
12
|
-
formatStatusTable,
|
|
13
|
-
loadStatusCache,
|
|
14
|
-
saveStatusCache,
|
|
15
|
-
statusHasBreach,
|
|
16
|
-
formatOutput
|
|
17
|
-
} from "@gpc-cli/core";
|
|
18
|
-
function registerStatusCommand(program) {
|
|
19
|
-
program.command("status").description("Unified app health snapshot: releases, vitals, and reviews").option("--days <n>", "Vitals window in days", (v) => parseInt(v, 10), 7).option("--cached", "Use last fetched data, skip API calls").option("--refresh", "Force live fetch, ignore cache TTL").option("--ttl <seconds>", "Cache TTL in seconds", (v) => parseInt(v, 10), 3600).action(async (opts) => {
|
|
20
|
-
const config = await loadConfig();
|
|
21
|
-
const packageName = program.opts()["app"] || config.app;
|
|
22
|
-
if (!packageName) {
|
|
23
|
-
console.error(
|
|
24
|
-
"Error: No package name. Use --app <package> or gpc config set app <package>"
|
|
25
|
-
);
|
|
26
|
-
process.exit(2);
|
|
27
|
-
}
|
|
28
|
-
const format = getOutputFormat(program, config);
|
|
29
|
-
try {
|
|
30
|
-
if (opts.cached) {
|
|
31
|
-
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
32
|
-
if (!cached) {
|
|
33
|
-
console.error(
|
|
34
|
-
"Error: No cached status found. Run without --cached to fetch live data."
|
|
35
|
-
);
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
if (format === "json") {
|
|
39
|
-
console.log(formatOutput(cached, format));
|
|
40
|
-
} else {
|
|
41
|
-
console.log(formatStatusTable(cached));
|
|
42
|
-
}
|
|
43
|
-
if (statusHasBreach(cached)) process.exit(6);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (!opts.refresh) {
|
|
47
|
-
const cached = await loadStatusCache(packageName, opts.ttl);
|
|
48
|
-
if (cached) {
|
|
49
|
-
if (format === "json") {
|
|
50
|
-
console.log(formatOutput(cached, format));
|
|
51
|
-
} else {
|
|
52
|
-
console.log(formatStatusTable(cached));
|
|
53
|
-
}
|
|
54
|
-
if (statusHasBreach(cached)) process.exit(6);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });
|
|
59
|
-
const client = createApiClient({ auth });
|
|
60
|
-
const reporting = createReportingClient({ auth });
|
|
61
|
-
const vitalThresholds = config["vitals"] ? (() => {
|
|
62
|
-
const vitals = config["vitals"];
|
|
63
|
-
const t = vitals["thresholds"];
|
|
64
|
-
const toThreshold = (v) => {
|
|
65
|
-
if (v === void 0 || v === null) return void 0;
|
|
66
|
-
const n = Number(v);
|
|
67
|
-
return isNaN(n) ? void 0 : n;
|
|
68
|
-
};
|
|
69
|
-
return t ? {
|
|
70
|
-
crashRate: toThreshold(t["crashRate"]),
|
|
71
|
-
anrRate: toThreshold(t["anrRate"]),
|
|
72
|
-
slowStartRate: toThreshold(t["slowStartRate"]),
|
|
73
|
-
slowRenderingRate: toThreshold(t["slowRenderingRate"])
|
|
74
|
-
} : void 0;
|
|
75
|
-
})() : void 0;
|
|
76
|
-
const status = await getAppStatus(client, reporting, packageName, {
|
|
77
|
-
days: opts.days,
|
|
78
|
-
vitalThresholds
|
|
79
|
-
});
|
|
80
|
-
await saveStatusCache(packageName, status, opts.ttl);
|
|
81
|
-
if (format === "json") {
|
|
82
|
-
console.log(formatOutput(status, format));
|
|
83
|
-
} else {
|
|
84
|
-
console.log(formatStatusTable(status));
|
|
85
|
-
}
|
|
86
|
-
if (statusHasBreach(status)) process.exit(6);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
89
|
-
process.exit(4);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
export {
|
|
94
|
-
registerStatusCommand
|
|
95
|
-
};
|
|
96
|
-
//# sourceMappingURL=status-5TOOZAGT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"@gpc-cli/config\";\nimport { resolveAuth } from \"@gpc-cli/auth\";\nimport { createApiClient, createReportingClient } from \"@gpc-cli/api\";\nimport {\n getAppStatus,\n formatStatusTable,\n loadStatusCache,\n saveStatusCache,\n statusHasBreach,\n formatOutput,\n} from \"@gpc-cli/core\";\nimport { getOutputFormat } from \"../format.js\";\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(\"--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 .action(async (opts: { days: number; cached?: boolean; refresh?: boolean; ttl: number }) => {\n const config = await loadConfig();\n const packageName = program.opts()[\"app\"] || config.app;\n if (!packageName) {\n console.error(\n \"Error: No package name. Use --app <package> or gpc config set app <package>\",\n );\n process.exit(2);\n }\n\n const format = getOutputFormat(program, config);\n\n try {\n // --cached: read from cache, skip API\n if (opts.cached) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (!cached) {\n console.error(\n \"Error: No cached status found. Run without --cached to fetch live data.\",\n );\n process.exit(1);\n }\n if (format === \"json\") {\n console.log(formatOutput(cached, format));\n } else {\n console.log(formatStatusTable(cached));\n }\n if (statusHasBreach(cached)) process.exit(6);\n return;\n }\n\n // Check cache unless --refresh\n if (!opts.refresh) {\n const cached = await loadStatusCache(packageName, opts.ttl);\n if (cached) {\n if (format === \"json\") {\n console.log(formatOutput(cached, format));\n } else {\n console.log(formatStatusTable(cached));\n }\n if (statusHasBreach(cached)) process.exit(6);\n return;\n }\n }\n\n // Live fetch\n const auth = await resolveAuth({ serviceAccountPath: config.auth?.serviceAccount });\n const client = createApiClient({ auth });\n const reporting = createReportingClient({ auth });\n\n const vitalThresholds = (config as Record<string, unknown>)[\"vitals\"]\n ? (() => {\n const vitals = (config as Record<string, unknown>)[\"vitals\"] as Record<\n string,\n unknown\n >;\n const t = vitals[\"thresholds\"] as Record<string, unknown> | undefined;\n const toThreshold = (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 t\n ? {\n crashRate: toThreshold(t[\"crashRate\"]),\n anrRate: toThreshold(t[\"anrRate\"]),\n slowStartRate: toThreshold(t[\"slowStartRate\"]),\n slowRenderingRate: toThreshold(t[\"slowRenderingRate\"]),\n }\n : undefined;\n })()\n : undefined;\n\n const status = await getAppStatus(client, reporting, packageName, {\n days: opts.days,\n vitalThresholds,\n });\n\n await saveStatusCache(packageName, status, opts.ttl);\n\n if (format === \"json\") {\n console.log(formatOutput(status, format));\n } else {\n console.log(formatStatusTable(status));\n }\n\n if (statusHasBreach(status)) process.exit(6);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(4);\n }\n });\n}\n"],"mappings":";;;;;;AACA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB,6BAA6B;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,SAAS,sBAAsB,SAAwB;AAC5D,UACG,QAAQ,QAAQ,EAChB,YAAY,4DAA4D,EACxE,OAAO,cAAc,yBAAyB,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EACvE,OAAO,YAAY,uCAAuC,EAC1D,OAAO,aAAa,oCAAoC,EACxD,OAAO,mBAAmB,wBAAwB,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,EAC9E,OAAO,OAAO,SAA6E;AAC1F,UAAM,SAAS,MAAM,WAAW;AAChC,UAAM,cAAc,QAAQ,KAAK,EAAE,KAAK,KAAK,OAAO;AACpD,QAAI,CAAC,aAAa;AAChB,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS,gBAAgB,SAAS,MAAM;AAE9C,QAAI;AAEF,UAAI,KAAK,QAAQ;AACf,cAAM,SAAS,MAAM,gBAAgB,aAAa,KAAK,GAAG;AAC1D,YAAI,CAAC,QAAQ;AACX,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,kBAAQ,KAAK,CAAC;AAAA,QAChB;AACA,YAAI,WAAW,QAAQ;AACrB,kBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,QAC1C,OAAO;AACL,kBAAQ,IAAI,kBAAkB,MAAM,CAAC;AAAA,QACvC;AACA,YAAI,gBAAgB,MAAM,EAAG,SAAQ,KAAK,CAAC;AAC3C;AAAA,MACF;AAGA,UAAI,CAAC,KAAK,SAAS;AACjB,cAAM,SAAS,MAAM,gBAAgB,aAAa,KAAK,GAAG;AAC1D,YAAI,QAAQ;AACV,cAAI,WAAW,QAAQ;AACrB,oBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,UAC1C,OAAO;AACL,oBAAQ,IAAI,kBAAkB,MAAM,CAAC;AAAA,UACvC;AACA,cAAI,gBAAgB,MAAM,EAAG,SAAQ,KAAK,CAAC;AAC3C;AAAA,QACF;AAAA,MACF;AAGA,YAAM,OAAO,MAAM,YAAY,EAAE,oBAAoB,OAAO,MAAM,eAAe,CAAC;AAClF,YAAM,SAAS,gBAAgB,EAAE,KAAK,CAAC;AACvC,YAAM,YAAY,sBAAsB,EAAE,KAAK,CAAC;AAEhD,YAAM,kBAAmB,OAAmC,QAAQ,KAC/D,MAAM;AACL,cAAM,SAAU,OAAmC,QAAQ;AAI3D,cAAM,IAAI,OAAO,YAAY;AAC7B,cAAM,cAAc,CAAC,MAAmC;AACtD,cAAI,MAAM,UAAa,MAAM,KAAM,QAAO;AAC1C,gBAAM,IAAI,OAAO,CAAC;AAClB,iBAAO,MAAM,CAAC,IAAI,SAAY;AAAA,QAChC;AACA,eAAO,IACH;AAAA,UACE,WAAW,YAAY,EAAE,WAAW,CAAC;AAAA,UACrC,SAAS,YAAY,EAAE,SAAS,CAAC;AAAA,UACjC,eAAe,YAAY,EAAE,eAAe,CAAC;AAAA,UAC7C,mBAAmB,YAAY,EAAE,mBAAmB,CAAC;AAAA,QACvD,IACA;AAAA,MACN,GAAG,IACH;AAEJ,YAAM,SAAS,MAAM,aAAa,QAAQ,WAAW,aAAa;AAAA,QAChE,MAAM,KAAK;AAAA,QACX;AAAA,MACF,CAAC;AAED,YAAM,gBAAgB,aAAa,QAAQ,KAAK,GAAG;AAEnD,UAAI,WAAW,QAAQ;AACrB,gBAAQ,IAAI,aAAa,QAAQ,MAAM,CAAC;AAAA,MAC1C,OAAO;AACL,gBAAQ,IAAI,kBAAkB,MAAM,CAAC;AAAA,MACvC;AAEA,UAAI,gBAAgB,MAAM,EAAG,SAAQ,KAAK,CAAC;AAAA,IAC7C,SAAS,OAAO;AACd,cAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;","names":[]}
|
|
File without changes
|