@mostly-good-metrics/cli 0.1.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +126 -0
  3. package/bin/mgm.js +2 -0
  4. package/dist/auth.d.ts +8 -0
  5. package/dist/auth.js +146 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/client.d.ts +287 -0
  8. package/dist/client.js +123 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/commands/auth.d.ts +2 -0
  11. package/dist/commands/auth.js +286 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/dashboard.d.ts +2 -0
  14. package/dist/commands/dashboard.js +74 -0
  15. package/dist/commands/dashboard.js.map +1 -0
  16. package/dist/commands/discovery.d.ts +2 -0
  17. package/dist/commands/discovery.js +94 -0
  18. package/dist/commands/discovery.js.map +1 -0
  19. package/dist/commands/events.d.ts +2 -0
  20. package/dist/commands/events.js +100 -0
  21. package/dist/commands/events.js.map +1 -0
  22. package/dist/commands/experiments.d.ts +2 -0
  23. package/dist/commands/experiments.js +191 -0
  24. package/dist/commands/experiments.js.map +1 -0
  25. package/dist/commands/funnels.d.ts +2 -0
  26. package/dist/commands/funnels.js +186 -0
  27. package/dist/commands/funnels.js.map +1 -0
  28. package/dist/commands/init.d.ts +2 -0
  29. package/dist/commands/init.js +127 -0
  30. package/dist/commands/init.js.map +1 -0
  31. package/dist/commands/keys.d.ts +2 -0
  32. package/dist/commands/keys.js +71 -0
  33. package/dist/commands/keys.js.map +1 -0
  34. package/dist/commands/orgs.d.ts +2 -0
  35. package/dist/commands/orgs.js +92 -0
  36. package/dist/commands/orgs.js.map +1 -0
  37. package/dist/commands/projects.d.ts +2 -0
  38. package/dist/commands/projects.js +71 -0
  39. package/dist/commands/projects.js.map +1 -0
  40. package/dist/commands/queries.d.ts +2 -0
  41. package/dist/commands/queries.js +177 -0
  42. package/dist/commands/queries.js.map +1 -0
  43. package/dist/commands/retention.d.ts +2 -0
  44. package/dist/commands/retention.js +162 -0
  45. package/dist/commands/retention.js.map +1 -0
  46. package/dist/commands/widgets.d.ts +2 -0
  47. package/dist/commands/widgets.js +92 -0
  48. package/dist/commands/widgets.js.map +1 -0
  49. package/dist/context.d.ts +9 -0
  50. package/dist/context.js +42 -0
  51. package/dist/context.js.map +1 -0
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.js +16 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/output.d.ts +5 -0
  56. package/dist/output.js +42 -0
  57. package/dist/output.js.map +1 -0
  58. package/dist/program.d.ts +3 -0
  59. package/dist/program.js +44 -0
  60. package/dist/program.js.map +1 -0
  61. package/dist/runtime.d.ts +13 -0
  62. package/dist/runtime.js +35 -0
  63. package/dist/runtime.js.map +1 -0
  64. package/package.json +52 -0
package/dist/client.js ADDED
@@ -0,0 +1,123 @@
1
+ import { getToken } from "./auth.js";
2
+ const BASE_URL = process.env.MGM_API_URL ?? "https://api.mostlygoodmetrics.com/api/v2";
3
+ export class ApiError extends Error {
4
+ status;
5
+ code;
6
+ constructor(status, code, message) {
7
+ super(message);
8
+ this.status = status;
9
+ this.code = code;
10
+ this.name = "ApiError";
11
+ }
12
+ }
13
+ async function request(method, path, options = {}) {
14
+ const token = options.token ?? getToken();
15
+ const url = new URL(`${BASE_URL}${path}`);
16
+ if (options.params) {
17
+ for (const [k, v] of Object.entries(options.params)) {
18
+ if (v !== undefined)
19
+ url.searchParams.set(k, v);
20
+ }
21
+ }
22
+ const headers = {
23
+ Accept: "application/json",
24
+ };
25
+ if (token)
26
+ headers["Authorization"] = `Bearer ${token}`;
27
+ if (options.body)
28
+ headers["Content-Type"] = "application/json";
29
+ const res = await fetch(url.toString(), {
30
+ method,
31
+ headers,
32
+ body: options.body ? JSON.stringify(options.body) : undefined,
33
+ });
34
+ if (!res.ok) {
35
+ let code = "unknown";
36
+ let message = `HTTP ${res.status}`;
37
+ try {
38
+ const err = (await res.json());
39
+ code = err.error ?? code;
40
+ message = err.message ?? message;
41
+ }
42
+ catch { }
43
+ throw new ApiError(res.status, code, message);
44
+ }
45
+ if (res.status === 204)
46
+ return {};
47
+ return (await res.json());
48
+ }
49
+ // Auth
50
+ export const sendMagicLink = (email) => request("POST", "/auth/magic-link", {
51
+ body: { email },
52
+ });
53
+ export const verifyMagicLink = (token) => request("GET", `/auth/magic-link/${token}`);
54
+ export const completeRegistration = (token) => request("GET", `/auth/register/${token}`);
55
+ export const getMe = () => request("GET", "/auth/me");
56
+ export const logout = () => request("DELETE", "/auth/session");
57
+ // Organizations
58
+ export const listOrganizations = () => request("GET", "/organizations");
59
+ export const getOrganization = (slug) => request("GET", `/organizations/${slug}`);
60
+ export const createOrganization = (name) => request("POST", "/organizations", { body: { name } });
61
+ export const inviteMember = (orgSlug, email, role = "member") => request("POST", `/organizations/${orgSlug}/invitations`, {
62
+ body: { email, role },
63
+ });
64
+ // Projects
65
+ export const listProjects = () => request("GET", "/projects");
66
+ export const getProject = (id) => request("GET", `/projects/${id}`);
67
+ export const createProject = (orgSlug, name, timezone) => request("POST", `/organizations/${orgSlug}/projects`, {
68
+ body: { name, ...(timezone ? { timezone } : {}) },
69
+ });
70
+ export const updateProject = (id, attrs) => request("PATCH", `/projects/${id}`, { body: attrs });
71
+ export const deleteProject = (id) => request("DELETE", `/projects/${id}`);
72
+ // API Keys
73
+ export const listApiKeys = (projectId) => request("GET", `/projects/${projectId}/api-keys`);
74
+ export const createApiKey = (projectId, name) => request("POST", `/projects/${projectId}/api-keys`, {
75
+ body: { name },
76
+ });
77
+ export const revokeApiKey = (projectId, keyId) => request("DELETE", `/projects/${projectId}/api-keys/${keyId}`);
78
+ // Dashboard
79
+ export const getDashboard = (projectId, params) => request("GET", `/projects/${projectId}/dashboard`, { params });
80
+ export const getDashboardFilters = (projectId) => request("GET", `/projects/${projectId}/dashboard/filters`);
81
+ // Events
82
+ export const listEvents = (projectId, params) => request("GET", `/projects/${projectId}/events`, { params });
83
+ export const listEventTypes = (projectId, params) => request("GET", `/projects/${projectId}/events/types`, { params });
84
+ export const listEventDefinitions = (projectId) => request("GET", `/projects/${projectId}/events/definitions`);
85
+ // Insights (Saved Queries)
86
+ export const listInsights = (projectId) => request("GET", `/projects/${projectId}/insights`);
87
+ export const getInsight = (projectId, id) => request("GET", `/projects/${projectId}/insights/${id}`);
88
+ export const createInsight = (projectId, attrs) => request("POST", `/projects/${projectId}/insights`, { body: attrs });
89
+ export const updateInsight = (projectId, id, attrs) => request("PATCH", `/projects/${projectId}/insights/${id}`, { body: attrs });
90
+ export const deleteInsight = (projectId, id) => request("DELETE", `/projects/${projectId}/insights/${id}`);
91
+ export const executeInsight = (projectId, id) => request("GET", `/projects/${projectId}/insights/${id}/execute`);
92
+ export const executeAdHocQuery = (projectId, query) => request("POST", `/projects/${projectId}/insights/execute`, { body: query });
93
+ // Funnels
94
+ export const listFunnels = (projectId) => request("GET", `/projects/${projectId}/funnels`);
95
+ export const getFunnel = (projectId, id) => request("GET", `/projects/${projectId}/funnels/${id}`);
96
+ export const createFunnel = (projectId, attrs) => request("POST", `/projects/${projectId}/funnels`, { body: attrs });
97
+ export const updateFunnel = (projectId, id, attrs) => request("PATCH", `/projects/${projectId}/funnels/${id}`, { body: attrs });
98
+ export const deleteFunnel = (projectId, id) => request("DELETE", `/projects/${projectId}/funnels/${id}`);
99
+ export const executeFunnel = (projectId, id) => request("GET", `/projects/${projectId}/funnels/${id}/execute`);
100
+ export const executeAdHocFunnel = (projectId, funnel) => request("POST", `/projects/${projectId}/funnels/execute`, { body: funnel });
101
+ // Retention
102
+ export const listRetentions = (projectId) => request("GET", `/projects/${projectId}/retention`);
103
+ export const getRetention = (projectId, id) => request("GET", `/projects/${projectId}/retention/${id}`);
104
+ export const createRetention = (projectId, attrs) => request("POST", `/projects/${projectId}/retention`, { body: attrs });
105
+ export const updateRetention = (projectId, id, attrs) => request("PATCH", `/projects/${projectId}/retention/${id}`, { body: attrs });
106
+ export const deleteRetention = (projectId, id) => request("DELETE", `/projects/${projectId}/retention/${id}`);
107
+ export const executeRetention = (projectId, id) => request("GET", `/projects/${projectId}/retention/${id}/execute`);
108
+ export const executeAdHocRetention = (projectId, retention) => request("POST", `/projects/${projectId}/retention/execute`, { body: retention });
109
+ // Experiments
110
+ export const listExperiments = (projectId) => request("GET", `/projects/${projectId}/experiments`);
111
+ export const getExperiment = (projectId, id, params) => request("GET", `/projects/${projectId}/experiments/${id}`, { params });
112
+ export const createExperiment = (projectId, attrs) => request("POST", `/projects/${projectId}/experiments`, { body: attrs });
113
+ export const updateExperiment = (projectId, id, attrs) => request("PATCH", `/projects/${projectId}/experiments/${id}`, { body: attrs });
114
+ export const deleteExperiment = (projectId, id) => request("DELETE", `/projects/${projectId}/experiments/${id}`);
115
+ export const startExperiment = (projectId, id) => request("POST", `/projects/${projectId}/experiments/${id}/start`);
116
+ export const stopExperiment = (projectId, id) => request("POST", `/projects/${projectId}/experiments/${id}/stop`);
117
+ // Widgets
118
+ export const listWidgets = (projectId) => request("GET", `/projects/${projectId}/widgets`);
119
+ export const createWidget = (projectId, attrs) => request("POST", `/projects/${projectId}/widgets`, { body: attrs });
120
+ export const updateWidget = (projectId, id, attrs) => request("PATCH", `/projects/${projectId}/widgets/${id}`, { body: attrs });
121
+ export const deleteWidget = (projectId, id) => request("DELETE", `/projects/${projectId}/widgets/${id}`);
122
+ export const resetWidgets = (projectId) => request("POST", `/projects/${projectId}/widgets/reset`);
123
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerAuthCommands(program: Command): void;
@@ -0,0 +1,286 @@
1
+ import http from "node:http";
2
+ import crypto from "node:crypto";
3
+ import { execFileSync } from "node:child_process";
4
+ import * as client from "../client.js";
5
+ import * as auth from "../auth.js";
6
+ import * as output from "../output.js";
7
+ import { CliUsageError, isNoInput } from "../runtime.js";
8
+ const CLIENT_NAME = "MostlyGoodMetrics CLI";
9
+ function getAppUrl() {
10
+ const configuredUrl = process.env.MGM_APP_URL ?? "https://app.mostlygoodmetrics.com";
11
+ let appUrl;
12
+ try {
13
+ appUrl = new URL(configuredUrl);
14
+ }
15
+ catch {
16
+ throw new CliUsageError("MGM_APP_URL must be a valid URL.");
17
+ }
18
+ const localHttp = appUrl.protocol === "http:" &&
19
+ (appUrl.hostname === "localhost" || appUrl.hostname === "127.0.0.1" || appUrl.hostname === "::1");
20
+ if (appUrl.protocol !== "https:" && !localHttp) {
21
+ throw new CliUsageError("MGM_APP_URL must use HTTPS (except localhost development URLs).");
22
+ }
23
+ return appUrl;
24
+ }
25
+ // ============================================================================
26
+ // PKCE helpers
27
+ // ============================================================================
28
+ function generatePKCE() {
29
+ const verifier = crypto.randomBytes(32).toString("base64url");
30
+ const challenge = crypto
31
+ .createHash("sha256")
32
+ .update(verifier)
33
+ .digest("base64url");
34
+ return { verifier, challenge };
35
+ }
36
+ // ============================================================================
37
+ // Browser-based OAuth login
38
+ // ============================================================================
39
+ async function browserLogin(opts = {}) {
40
+ const appUrl = getAppUrl();
41
+ // 1. Start a local HTTP server to receive the callback
42
+ const { port, waitForCallback, server } = await startCallbackServer();
43
+ const redirectUri = `http://localhost:${port}/callback`;
44
+ // 2. Register as an OAuth client (or reuse cached if same redirect_uri)
45
+ let clientId = auth.getClientId();
46
+ const cachedRedirectUri = auth.getRedirectUri();
47
+ if (!clientId || cachedRedirectUri !== redirectUri) {
48
+ console.log("Registering CLI with MostlyGoodMetrics...");
49
+ const res = await fetch(new URL("/oauth/register", appUrl), {
50
+ method: "POST",
51
+ headers: { "Content-Type": "application/json" },
52
+ body: JSON.stringify({
53
+ client_name: CLIENT_NAME,
54
+ redirect_uris: [redirectUri],
55
+ }),
56
+ });
57
+ if (!res.ok) {
58
+ const err = await res.json().catch(() => ({}));
59
+ console.error(`Registration failed: ${err.error ?? res.statusText}`);
60
+ server.close();
61
+ process.exit(1);
62
+ }
63
+ const data = (await res.json());
64
+ clientId = data.client_id;
65
+ auth.saveClientId(clientId, redirectUri);
66
+ }
67
+ // 3. Generate PKCE challenge
68
+ const { verifier, challenge } = generatePKCE();
69
+ // 4. Build authorization URL and open browser
70
+ const state = crypto.randomBytes(16).toString("hex");
71
+ const params = new URLSearchParams({
72
+ client_id: clientId,
73
+ redirect_uri: redirectUri,
74
+ response_type: "code",
75
+ code_challenge: challenge,
76
+ code_challenge_method: "S256",
77
+ state,
78
+ scope: "mcp:tools",
79
+ });
80
+ if (opts.signup)
81
+ params.set("signup", "true");
82
+ const authorizeUrl = new URL("/oauth/authorize", appUrl);
83
+ authorizeUrl.search = params.toString();
84
+ console.log(opts.signup ? "Opening browser to create an account..." : "Opening browser to log in...");
85
+ console.log();
86
+ openBrowser(authorizeUrl.toString());
87
+ console.log("Waiting for authorization...");
88
+ console.log("(If your browser didn't open, visit this URL:)");
89
+ console.log(authorizeUrl.toString());
90
+ console.log();
91
+ // 5. Wait for the callback
92
+ const callbackResult = await waitForCallback();
93
+ server.close();
94
+ if (callbackResult.error) {
95
+ console.error(`Authorization failed: ${callbackResult.error}`);
96
+ process.exit(1);
97
+ }
98
+ if (callbackResult.state !== state) {
99
+ console.error("State mismatch — possible CSRF attack. Aborting.");
100
+ process.exit(1);
101
+ }
102
+ // 6. Exchange code for token
103
+ const tokenRes = await fetch(new URL("/oauth/token", appUrl), {
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/json" },
106
+ body: JSON.stringify({
107
+ grant_type: "authorization_code",
108
+ code: callbackResult.code,
109
+ code_verifier: verifier,
110
+ client_id: clientId,
111
+ redirect_uri: redirectUri,
112
+ }),
113
+ });
114
+ if (!tokenRes.ok) {
115
+ const err = (await tokenRes.json().catch(() => ({})));
116
+ console.error(`Token exchange failed: ${err.error ?? tokenRes.statusText}`);
117
+ process.exit(1);
118
+ }
119
+ const tokenData = (await tokenRes.json());
120
+ auth.saveToken(tokenData.access_token);
121
+ // Fetch user info
122
+ try {
123
+ const { user } = await client.getMe();
124
+ auth.saveToken(tokenData.access_token, user.email);
125
+ console.log(`Logged in as ${user.email}`);
126
+ }
127
+ catch {
128
+ console.log("Logged in. Run `mgm whoami` to verify.");
129
+ }
130
+ }
131
+ // ============================================================================
132
+ // Local callback server
133
+ // ============================================================================
134
+ function escapeHtml(text) {
135
+ return text
136
+ .replace(/&/g, "&")
137
+ .replace(/</g, "&lt;")
138
+ .replace(/>/g, "&gt;")
139
+ .replace(/"/g, "&quot;");
140
+ }
141
+ function startCallbackServer() {
142
+ return new Promise((resolve) => {
143
+ let onCallback;
144
+ const callbackPromise = new Promise((res) => {
145
+ onCallback = res;
146
+ });
147
+ const server = http.createServer((req, res) => {
148
+ const url = new URL(req.url ?? "/", `http://localhost`);
149
+ if (url.pathname === "/callback") {
150
+ const code = url.searchParams.get("code") ?? undefined;
151
+ const state = url.searchParams.get("state") ?? undefined;
152
+ const error = url.searchParams.get("error") ?? undefined;
153
+ // Show a nice page in the browser
154
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
155
+ if (code) {
156
+ res.end(`
157
+ <html><head><meta charset="utf-8"></head><body style="font-family: system-ui; text-align: center; padding: 60px;">
158
+ <h1 style="color: #667eea;">✓ Logged in!</h1>
159
+ <p>You can close this tab and return to the terminal.</p>
160
+ </body></html>
161
+ `);
162
+ }
163
+ else {
164
+ res.end(`
165
+ <html><head><meta charset="utf-8"></head><body style="font-family: system-ui; text-align: center; padding: 60px;">
166
+ <h1 style="color: #ef4444;">Authorization failed</h1>
167
+ <p>${escapeHtml(error ?? "Unknown error")}. Return to the terminal.</p>
168
+ </body></html>
169
+ `);
170
+ }
171
+ onCallback({ code, state, error });
172
+ }
173
+ else {
174
+ res.writeHead(404);
175
+ res.end();
176
+ }
177
+ });
178
+ // Try fixed port first (so cached client_id works), fall back to random
179
+ server.on("error", () => {
180
+ server.listen(0, "127.0.0.1", () => {
181
+ const addr = server.address();
182
+ const port = typeof addr === "object" && addr ? addr.port : 0;
183
+ resolve({ port, waitForCallback: () => callbackPromise, server });
184
+ });
185
+ });
186
+ server.listen(19891, "127.0.0.1", () => {
187
+ resolve({ port: 19891, waitForCallback: () => callbackPromise, server });
188
+ });
189
+ });
190
+ }
191
+ // ============================================================================
192
+ // Open browser (cross-platform)
193
+ // ============================================================================
194
+ function openBrowser(url) {
195
+ try {
196
+ const platform = process.platform;
197
+ if (platform === "darwin") {
198
+ execFileSync("/usr/bin/open", [url], { stdio: "ignore" });
199
+ }
200
+ else if (platform === "win32") {
201
+ execFileSync("rundll32.exe", ["url.dll,FileProtocolHandler", url], { stdio: "ignore" });
202
+ }
203
+ else {
204
+ execFileSync("xdg-open", [url], { stdio: "ignore" });
205
+ }
206
+ }
207
+ catch {
208
+ // Browser open failed — user will use the printed URL
209
+ }
210
+ }
211
+ // ============================================================================
212
+ // Commands
213
+ // ============================================================================
214
+ export function registerAuthCommands(program) {
215
+ program
216
+ .command("login")
217
+ .description("Log in via browser (opens authorization page)")
218
+ .option("--token <token>", "Use an existing session token directly")
219
+ .action(async (opts) => {
220
+ if (opts.token) {
221
+ // Direct token login (for CI, scripts, etc.)
222
+ auth.saveToken(opts.token);
223
+ try {
224
+ const { user } = await client.getMe();
225
+ auth.saveToken(opts.token, user.email);
226
+ console.log(`Logged in as ${user.email}`);
227
+ }
228
+ catch {
229
+ console.log("Token saved. Could not verify — check with `mgm whoami`.");
230
+ }
231
+ return;
232
+ }
233
+ if (isNoInput()) {
234
+ throw new CliUsageError("login requires --token when --no-input is set.");
235
+ }
236
+ await browserLogin();
237
+ });
238
+ program
239
+ .command("signup")
240
+ .description("Create a new MostlyGoodMetrics account (opens browser)")
241
+ .action(async () => {
242
+ if (isNoInput()) {
243
+ throw new CliUsageError("signup cannot run with --no-input. Create an account in the browser first.");
244
+ }
245
+ await browserLogin({ signup: true });
246
+ });
247
+ program
248
+ .command("whoami")
249
+ .description("Show current user and organization")
250
+ .option("--json", "Output as JSON")
251
+ .action(async (opts) => {
252
+ auth.requireToken();
253
+ const data = await client.getMe();
254
+ if (opts.json) {
255
+ output.json(data);
256
+ return;
257
+ }
258
+ console.log(`Email: ${data.user.email}`);
259
+ console.log(`User ID: ${data.user.id}`);
260
+ if (data.organizations.length > 0) {
261
+ console.log();
262
+ console.log("Organizations:");
263
+ output.table(["Name", "Slug", "Plan", "Role"], data.organizations.map((o) => [o.name, o.slug, o.plan ?? "-", o.role ?? "-"]));
264
+ }
265
+ });
266
+ program
267
+ .command("logout")
268
+ .description("Clear stored session token")
269
+ .option("--json", "Output as JSON")
270
+ .action(async (opts) => {
271
+ const token = auth.getToken();
272
+ if (token) {
273
+ try {
274
+ await client.logout();
275
+ }
276
+ catch { }
277
+ }
278
+ auth.clearToken();
279
+ if (opts.json) {
280
+ output.json({ status: "logged_out" });
281
+ return;
282
+ }
283
+ console.log("Logged out.");
284
+ });
285
+ }
286
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerDashboardCommands(program: Command): void;
@@ -0,0 +1,74 @@
1
+ import * as client from "../client.js";
2
+ import * as auth from "../auth.js";
3
+ import * as output from "../output.js";
4
+ import { requireProjectId } from "../context.js";
5
+ export function registerDashboardCommands(program) {
6
+ const dashboard = program
7
+ .command("dashboard")
8
+ .description("Show dashboard stats for current project");
9
+ dashboard
10
+ .option("--project <id>", "Project ID")
11
+ .option("--range <range>", "Date range (e.g. 7d, 30d, 90d)")
12
+ .option("--start <date>", "Start date (YYYY-MM-DD)")
13
+ .option("--end <date>", "End date (YYYY-MM-DD)")
14
+ .option("--environment <env>", "Filter by environment")
15
+ .option("--platform <platform>", "Filter by platform")
16
+ .option("--event <name>", "Filter by event name")
17
+ .option("--json", "Output as JSON")
18
+ .action(async (opts) => {
19
+ auth.requireToken();
20
+ const projectId = requireProjectId(opts.project);
21
+ const params = {};
22
+ if (opts.range)
23
+ params.date_range = opts.range;
24
+ if (opts.start)
25
+ params.start_date = opts.start;
26
+ if (opts.end)
27
+ params.end_date = opts.end;
28
+ if (opts.environment)
29
+ params.environment = opts.environment;
30
+ if (opts.platform)
31
+ params.platform = opts.platform;
32
+ if (opts.event)
33
+ params.event_name = opts.event;
34
+ const data = await client.getDashboard(projectId, params);
35
+ if (opts.json) {
36
+ output.json(data);
37
+ return;
38
+ }
39
+ const { stats } = data;
40
+ console.log("Dashboard Stats");
41
+ console.log("===============");
42
+ console.log(`Total Events: ${output.formatNumber(stats.total_events)} (${output.formatTrend(stats.events_trend)})`);
43
+ console.log(`Unique Users: ${output.formatNumber(stats.unique_users)} (${output.formatTrend(stats.users_trend)})`);
44
+ if (data.top_events.length > 0) {
45
+ console.log();
46
+ console.log("Top Events");
47
+ output.table(["Event", "Count"], data.top_events.map((e) => [e.name, output.formatNumber(e.count)]));
48
+ }
49
+ if (data.events_by_day.length > 0) {
50
+ console.log();
51
+ console.log("Events by Day");
52
+ output.table(["Date", "Count"], data.events_by_day.map((d) => [d.date, output.formatNumber(d.count)]));
53
+ }
54
+ });
55
+ dashboard
56
+ .command("filters")
57
+ .description("List available dashboard filter values")
58
+ .option("--project <id>", "Project ID")
59
+ .option("--json", "Output as JSON")
60
+ .action(async (opts, command) => {
61
+ auth.requireToken();
62
+ // Commander assigns duplicate parent/child options to the parent command
63
+ // when they appear after the subcommand, so accept either location.
64
+ const parentOpts = command.parent?.opts();
65
+ const projectId = requireProjectId(opts.project ?? parentOpts?.project);
66
+ const data = await client.getDashboardFilters(projectId);
67
+ if (opts.json ?? parentOpts?.json) {
68
+ output.json(data);
69
+ return;
70
+ }
71
+ output.json(data);
72
+ });
73
+ }
74
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerDiscoveryCommands(program: Command): void;
@@ -0,0 +1,94 @@
1
+ import * as output from "../output.js";
2
+ function schemaFor(command, path, root) {
3
+ const effectiveOptions = () => {
4
+ const commands = [];
5
+ let current = command;
6
+ while (current) {
7
+ commands.unshift(current);
8
+ if (current === root)
9
+ break;
10
+ current = current.parent;
11
+ }
12
+ const seen = new Set();
13
+ return commands.flatMap((item) => item.options).filter((option) => {
14
+ if (seen.has(option.flags))
15
+ return false;
16
+ seen.add(option.flags);
17
+ return true;
18
+ });
19
+ };
20
+ return {
21
+ path: path.join(" "),
22
+ description: command.description(),
23
+ arguments: command.registeredArguments.map((arg) => ({
24
+ name: arg.name(),
25
+ description: arg.description,
26
+ required: arg.required,
27
+ variadic: arg.variadic,
28
+ })),
29
+ options: effectiveOptions().map((option) => ({
30
+ flags: option.flags,
31
+ description: option.description,
32
+ required: option.mandatory,
33
+ ...(option.defaultValue !== undefined ? { default: option.defaultValue } : {}),
34
+ })),
35
+ subcommands: command.commands.map((subcommand) => subcommand.name()),
36
+ };
37
+ }
38
+ function findCommand(root, path) {
39
+ let command = root;
40
+ for (const name of path) {
41
+ const next = command.commands.find((subcommand) => subcommand.name() === name);
42
+ if (!next)
43
+ return undefined;
44
+ command = next;
45
+ }
46
+ return command;
47
+ }
48
+ function allSchemas(command, root, path = []) {
49
+ return command.commands
50
+ .flatMap((subcommand) => {
51
+ const subcommandPath = [...path, subcommand.name()];
52
+ return [schemaFor(subcommand, subcommandPath, root), ...allSchemas(subcommand, root, subcommandPath)];
53
+ });
54
+ }
55
+ export function registerDiscoveryCommands(program) {
56
+ program
57
+ .command("commands")
58
+ .description("List every available command and its capabilities")
59
+ .option("--json", "Output as JSON")
60
+ .action((opts) => {
61
+ const commands = allSchemas(program, program);
62
+ if (opts.json) {
63
+ output.json(commands);
64
+ return;
65
+ }
66
+ output.table(["Command", "Description"], commands.map((command) => [command.path, command.description]));
67
+ });
68
+ program
69
+ .command("schema <command...>")
70
+ .description("Show arguments, flags, and subcommands for a command path")
71
+ .option("--json", "Output as JSON")
72
+ .action((commandPath, opts) => {
73
+ const command = findCommand(program, commandPath);
74
+ if (!command) {
75
+ throw new Error(`Unknown command: mgm ${commandPath.join(" ")}`);
76
+ }
77
+ const schema = schemaFor(command, commandPath, program);
78
+ if (opts.json) {
79
+ output.json(schema);
80
+ return;
81
+ }
82
+ console.log(`mgm ${schema.path}`);
83
+ console.log(schema.description);
84
+ if (schema.arguments.length > 0) {
85
+ console.log("\nArguments:");
86
+ output.table(["Name", "Required", "Description"], schema.arguments.map((arg) => [arg.name, arg.required ? "yes" : "no", arg.description]));
87
+ }
88
+ if (schema.options.length > 0) {
89
+ console.log("\nOptions:");
90
+ output.table(["Flags", "Required", "Description"], schema.options.map((option) => [option.flags, option.required ? "yes" : "no", option.description]));
91
+ }
92
+ });
93
+ }
94
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/commands/discovery.ts"],"names":[],"mappings":"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"}