@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
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerEventsCommands(program: Command): void;
@@ -0,0 +1,100 @@
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 registerEventsCommands(program) {
6
+ const events = program
7
+ .command("events")
8
+ .description("View and send events");
9
+ events
10
+ .command("list")
11
+ .description("List recent events")
12
+ .option("--project <id>", "Project ID")
13
+ .option("--limit <n>", "Number of events (max 200)", "50")
14
+ .option("--range <range>", "Date range (default 7d)")
15
+ .option("--json", "Output as JSON")
16
+ .action(async (opts) => {
17
+ auth.requireToken();
18
+ const projectId = requireProjectId(opts.project);
19
+ const params = {};
20
+ if (opts.limit)
21
+ params.limit = opts.limit;
22
+ if (opts.range)
23
+ params.date_range = opts.range;
24
+ const data = await client.listEvents(projectId, params);
25
+ if (opts.json) {
26
+ output.json(data.events);
27
+ return;
28
+ }
29
+ if (data.events.length === 0) {
30
+ console.log("No events found.");
31
+ return;
32
+ }
33
+ output.table(["Timestamp", "Event", "User ID"], data.events.map((e) => [
34
+ e.timestamp,
35
+ e.name,
36
+ e.user_id ?? "-",
37
+ ]));
38
+ });
39
+ events
40
+ .command("types")
41
+ .description("List event types with counts")
42
+ .option("--project <id>", "Project ID")
43
+ .option("--range <range>", "Date range (default 30d)")
44
+ .option("--json", "Output as JSON")
45
+ .action(async (opts) => {
46
+ auth.requireToken();
47
+ const projectId = requireProjectId(opts.project);
48
+ const params = {};
49
+ if (opts.range)
50
+ params.date_range = opts.range;
51
+ const data = await client.listEventTypes(projectId, params);
52
+ if (opts.json) {
53
+ output.json(data.event_types);
54
+ return;
55
+ }
56
+ if (data.event_types.length === 0) {
57
+ console.log("No event types found.");
58
+ return;
59
+ }
60
+ output.table(["Event", "Count"], data.event_types.map((t) => [t.name, output.formatNumber(t.count)]));
61
+ });
62
+ events
63
+ .command("send")
64
+ .description("Send a test event")
65
+ .argument("<event>", "Event JSON (e.g. '{\"name\":\"test\"}')")
66
+ .option("--project <id>", "Project ID")
67
+ .option("--json", "Output as JSON")
68
+ .action(async (eventJson, opts) => {
69
+ auth.requireToken();
70
+ const projectId = requireProjectId(opts.project);
71
+ let event;
72
+ try {
73
+ event = JSON.parse(eventJson);
74
+ }
75
+ catch {
76
+ console.error("Invalid JSON. Example: '{\"name\":\"test_event\"}'");
77
+ process.exit(1);
78
+ }
79
+ // Send via the ingestion endpoint
80
+ const res = await fetch("https://ingest.mostlygoodmetrics.com/v1/events", {
81
+ method: "POST",
82
+ headers: {
83
+ "Content-Type": "application/json",
84
+ Authorization: `Bearer ${auth.requireToken()}`,
85
+ },
86
+ body: JSON.stringify({ events: [event] }),
87
+ });
88
+ if (!res.ok) {
89
+ const body = await res.text();
90
+ console.error(`Failed to send event: ${res.status} ${body}`);
91
+ process.exit(1);
92
+ }
93
+ if (opts.json) {
94
+ output.json({ status: "sent", event });
95
+ return;
96
+ }
97
+ console.log("Event sent.");
98
+ });
99
+ }
100
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAEvC,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,oBAAoB,CAAC;SACjC,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC;SACtC,MAAM,CAAC,aAAa,EAAE,4BAA4B,EAAE,IAAI,CAAC;SACzD,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;SACpD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAA0E,EAAE,EAAE;QAC3F,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1C,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC;QAE/C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAExD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CACV,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,EACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACrB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,OAAO,IAAI,GAAG;SACjB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC;SACtC,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,CAAC;SACrD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAA0D,EAAE,EAAE;QAC3E,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC;QAE/C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAE5D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,OAAO;QACT,CAAC;QAED,MAAM,CAAC,KAAK,CACV,CAAC,OAAO,EAAE,OAAO,CAAC,EAClB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CACpE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mBAAmB,CAAC;SAChC,QAAQ,CAAC,SAAS,EAAE,yCAAyC,CAAC;SAC9D,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC;SACtC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,IAA0C,EAAE,EAAE;QAC9E,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEjD,IAAI,KAA8B,CAAC;QACnC,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,kCAAkC;QAClC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,gDAAgD,EAAE;YACxE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,YAAY,EAAE,EAAE;aAC/C;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;SAC1C,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerExperimentsCommands(program: Command): void;
@@ -0,0 +1,191 @@
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
+ import { requireConfirmation } from "../runtime.js";
6
+ export function registerExperimentsCommands(program) {
7
+ const experiments = program
8
+ .command("experiments")
9
+ .description("Manage A/B experiments");
10
+ experiments
11
+ .command("list")
12
+ .description("List experiments")
13
+ .option("--project <id>", "Project ID")
14
+ .option("--json", "Output as JSON")
15
+ .action(async (opts) => {
16
+ auth.requireToken();
17
+ const projectId = requireProjectId(opts.project);
18
+ const data = await client.listExperiments(projectId);
19
+ if (opts.json) {
20
+ output.json(data.experiments);
21
+ return;
22
+ }
23
+ if (data.experiments.length === 0) {
24
+ console.log("No experiments found.");
25
+ return;
26
+ }
27
+ output.table(["ID", "Name", "Status", "Variants", "Goal"], data.experiments.map((e) => [
28
+ e.id,
29
+ e.name,
30
+ e.status ?? "-",
31
+ e.variants.join(", "),
32
+ e.goal_event,
33
+ ]));
34
+ });
35
+ experiments
36
+ .command("create")
37
+ .description("Create an experiment")
38
+ .requiredOption("--name <name>", "Experiment name")
39
+ .requiredOption("--variants <variants>", "Comma-separated variant names")
40
+ .requiredOption("--goal <event>", "Goal event name")
41
+ .option("--project <id>", "Project ID")
42
+ .option("--json", "Output as JSON")
43
+ .action(async (opts) => {
44
+ auth.requireToken();
45
+ const projectId = requireProjectId(opts.project);
46
+ const data = await client.createExperiment(projectId, {
47
+ name: opts.name,
48
+ variants: opts.variants.split(",").map((v) => v.trim()),
49
+ goal_event: opts.goal,
50
+ });
51
+ if (opts.json) {
52
+ output.json(data.experiment);
53
+ return;
54
+ }
55
+ console.log(`Experiment created: ${data.experiment.name}`);
56
+ console.log(`ID: ${data.experiment.id}`);
57
+ });
58
+ experiments
59
+ .command("show")
60
+ .description("Show an experiment and its results")
61
+ .argument("<id>", "Experiment ID")
62
+ .option("--window-days <days>", "Observation window in days")
63
+ .option("--goal <event>", "Alternative goal event")
64
+ .option("--project <id>", "Project ID")
65
+ .option("--json", "Output as JSON")
66
+ .action(async (id, opts) => {
67
+ auth.requireToken();
68
+ const params = {};
69
+ if (opts.windowDays)
70
+ params.observation_window_days = opts.windowDays;
71
+ if (opts.goal)
72
+ params.goal_event = opts.goal;
73
+ const data = await client.getExperiment(requireProjectId(opts.project), id, params);
74
+ if (opts.json) {
75
+ output.json(data);
76
+ return;
77
+ }
78
+ console.log(`Experiment: ${data.experiment.name}`);
79
+ console.log(`Status: ${data.experiment.status ?? "-"}`);
80
+ console.log(`Goal: ${data.experiment.goal_event}`);
81
+ });
82
+ experiments
83
+ .command("update")
84
+ .description("Update an experiment")
85
+ .argument("<id>", "Experiment ID")
86
+ .option("--name <name>", "Experiment name")
87
+ .option("--description <description>", "Experiment description")
88
+ .option("--variants <variants>", "Comma-separated variant names")
89
+ .option("--goal <event>", "Goal event name")
90
+ .option("--conversion-window-days <days>", "Conversion window in days")
91
+ .option("--project <id>", "Project ID")
92
+ .option("--json", "Output as JSON")
93
+ .action(async (id, opts) => {
94
+ auth.requireToken();
95
+ const attrs = {};
96
+ if (opts.name)
97
+ attrs.name = opts.name;
98
+ if (opts.description)
99
+ attrs.description = opts.description;
100
+ if (opts.variants)
101
+ attrs.variants = opts.variants.split(",").map((variant) => variant.trim());
102
+ if (opts.goal)
103
+ attrs.goal_event = opts.goal;
104
+ if (opts.conversionWindowDays) {
105
+ if (!/^[1-9]\d*$/.test(opts.conversionWindowDays)) {
106
+ throw new Error("--conversion-window-days must be a positive whole number.");
107
+ }
108
+ attrs.conversion_window_days = parseInt(opts.conversionWindowDays, 10);
109
+ }
110
+ if (Object.keys(attrs).length === 0)
111
+ throw new Error("Provide at least one field to update.");
112
+ const data = await client.updateExperiment(requireProjectId(opts.project), id, attrs);
113
+ if (opts.json) {
114
+ output.json(data.experiment);
115
+ return;
116
+ }
117
+ console.log(`Experiment updated: ${data.experiment.name}`);
118
+ });
119
+ experiments
120
+ .command("start")
121
+ .description("Start an experiment")
122
+ .argument("<id>", "Experiment ID")
123
+ .option("--project <id>", "Project ID")
124
+ .option("--json", "Output as JSON")
125
+ .action(async (id, opts) => {
126
+ auth.requireToken();
127
+ const projectId = requireProjectId(opts.project);
128
+ const data = await client.startExperiment(projectId, id);
129
+ if (opts.json) {
130
+ output.json(data);
131
+ return;
132
+ }
133
+ console.log("Experiment started.");
134
+ });
135
+ experiments
136
+ .command("stop")
137
+ .description("Stop an experiment")
138
+ .argument("<id>", "Experiment ID")
139
+ .option("--project <id>", "Project ID")
140
+ .option("--json", "Output as JSON")
141
+ .action(async (id, opts) => {
142
+ auth.requireToken();
143
+ const projectId = requireProjectId(opts.project);
144
+ await requireConfirmation(`Stop experiment ${id}`);
145
+ const data = await client.stopExperiment(projectId, id);
146
+ if (opts.json) {
147
+ output.json(data.experiment);
148
+ return;
149
+ }
150
+ console.log("Experiment stopped.");
151
+ });
152
+ experiments
153
+ .command("results")
154
+ .description("Show experiment results")
155
+ .argument("<id>", "Experiment ID")
156
+ .option("--project <id>", "Project ID")
157
+ .option("--json", "Output as JSON")
158
+ .action(async (id, opts) => {
159
+ auth.requireToken();
160
+ const projectId = requireProjectId(opts.project);
161
+ const data = await client.getExperiment(projectId, id);
162
+ if (opts.json) {
163
+ output.json(data.experiment);
164
+ return;
165
+ }
166
+ const exp = data.experiment;
167
+ console.log(`Experiment: ${exp.name}`);
168
+ console.log(`Status: ${exp.status ?? "-"}`);
169
+ console.log(`Goal: ${exp.goal_event}`);
170
+ console.log(`Variants: ${exp.variants.join(", ")}`);
171
+ console.log();
172
+ output.json(data.results ?? data.experiment);
173
+ });
174
+ experiments
175
+ .command("delete")
176
+ .description("Delete an experiment")
177
+ .argument("<id>", "Experiment ID")
178
+ .option("--project <id>", "Project ID")
179
+ .option("--json", "Output as JSON")
180
+ .action(async (id, opts) => {
181
+ auth.requireToken();
182
+ await requireConfirmation(`Delete experiment ${id}`);
183
+ const data = await client.deleteExperiment(requireProjectId(opts.project), id);
184
+ if (opts.json) {
185
+ output.json(data);
186
+ return;
187
+ }
188
+ console.log("Experiment deleted.");
189
+ });
190
+ }
191
+ //# sourceMappingURL=experiments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"experiments.js","sourceRoot":"","sources":["../../src/commands/experiments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerFunnelsCommands(program: Command): void;
@@ -0,0 +1,186 @@
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
+ import { requireConfirmation } from "../runtime.js";
6
+ export function registerFunnelsCommands(program) {
7
+ const funnels = program
8
+ .command("funnels")
9
+ .description("Manage and execute funnels");
10
+ funnels
11
+ .command("list")
12
+ .description("List saved funnels")
13
+ .option("--project <id>", "Project ID")
14
+ .option("--json", "Output as JSON")
15
+ .action(async (opts) => {
16
+ auth.requireToken();
17
+ const projectId = requireProjectId(opts.project);
18
+ const data = await client.listFunnels(projectId);
19
+ if (opts.json) {
20
+ output.json(data.funnels);
21
+ return;
22
+ }
23
+ if (data.funnels.length === 0) {
24
+ console.log("No funnels found. Create one with `mgm funnels create`.");
25
+ return;
26
+ }
27
+ output.table(["ID", "Name", "Steps"], data.funnels.map((f) => [
28
+ f.id,
29
+ f.name,
30
+ f.steps.map((s) => s.event_name).join(" -> "),
31
+ ]));
32
+ });
33
+ funnels
34
+ .command("create")
35
+ .description("Create a funnel")
36
+ .requiredOption("--name <name>", "Funnel name")
37
+ .requiredOption("--steps <steps>", "Comma-separated event names")
38
+ .option("--window <window>", "Conversion window (e.g. 7d)")
39
+ .option("--range <range>", "Date range (e.g. 30d)")
40
+ .option("--project <id>", "Project ID")
41
+ .option("--json", "Output as JSON")
42
+ .action(async (opts) => {
43
+ auth.requireToken();
44
+ const projectId = requireProjectId(opts.project);
45
+ const steps = opts.steps.split(",").map((s) => ({
46
+ event_name: s.trim(),
47
+ name: s.trim(),
48
+ }));
49
+ const attrs = {
50
+ name: opts.name,
51
+ steps,
52
+ };
53
+ if (opts.window) {
54
+ const match = opts.window.match(/^(\d+)d$/);
55
+ if (match) {
56
+ attrs.conversion_window_minutes = parseInt(match[1]) * 24 * 60;
57
+ }
58
+ }
59
+ if (opts.range)
60
+ attrs.date_range = opts.range;
61
+ const data = await client.createFunnel(projectId, attrs);
62
+ if (opts.json) {
63
+ output.json(data.funnel);
64
+ return;
65
+ }
66
+ console.log(`Funnel created: ${data.funnel.name}`);
67
+ console.log(`ID: ${data.funnel.id}`);
68
+ });
69
+ funnels
70
+ .command("show")
71
+ .description("Show a saved funnel's full definition")
72
+ .argument("<id>", "Funnel ID")
73
+ .option("--project <id>", "Project ID")
74
+ .option("--json", "Output as JSON")
75
+ .action(async (id, opts) => {
76
+ auth.requireToken();
77
+ const data = await client.getFunnel(requireProjectId(opts.project), id);
78
+ if (opts.json) {
79
+ output.json(data.funnel);
80
+ return;
81
+ }
82
+ console.log(`Funnel: ${data.funnel.name}`);
83
+ console.log(`ID: ${data.funnel.id}`);
84
+ console.log(`Steps: ${data.funnel.steps.map((step) => step.event_name).join(" -> ")}`);
85
+ });
86
+ funnels
87
+ .command("update")
88
+ .description("Update a saved funnel")
89
+ .argument("<id>", "Funnel ID")
90
+ .option("--name <name>", "Funnel name")
91
+ .option("--steps <steps>", "Comma-separated event names")
92
+ .option("--window <window>", "Conversion window (e.g. 7d)")
93
+ .option("--range <range>", "Date range (e.g. 30d)")
94
+ .option("--project <id>", "Project ID")
95
+ .option("--json", "Output as JSON")
96
+ .action(async (id, opts) => {
97
+ auth.requireToken();
98
+ const attrs = {};
99
+ if (opts.name)
100
+ attrs.name = opts.name;
101
+ if (opts.steps)
102
+ attrs.steps = opts.steps.split(",").map((s) => ({ event_name: s.trim(), name: s.trim() }));
103
+ if (opts.window) {
104
+ const match = opts.window.match(/^(\d+)d$/);
105
+ if (!match)
106
+ throw new Error("--window must be in days, for example 7d.");
107
+ attrs.conversion_window_minutes = parseInt(match[1]) * 24 * 60;
108
+ }
109
+ if (opts.range)
110
+ attrs.date_range = opts.range;
111
+ if (Object.keys(attrs).length === 0)
112
+ throw new Error("Provide at least one field to update.");
113
+ const data = await client.updateFunnel(requireProjectId(opts.project), id, attrs);
114
+ if (opts.json) {
115
+ output.json(data.funnel);
116
+ return;
117
+ }
118
+ console.log(`Funnel updated: ${data.funnel.name}`);
119
+ });
120
+ funnels
121
+ .command("execute")
122
+ .description("Execute a saved or ad-hoc funnel")
123
+ .argument("[id]", "Funnel ID (omit for ad-hoc)")
124
+ .option("--steps <steps>", "Comma-separated event names (ad-hoc)")
125
+ .option("--range <range>", "Date range")
126
+ .option("--project <id>", "Project ID")
127
+ .option("--json", "Output as JSON")
128
+ .action(async (id, opts) => {
129
+ auth.requireToken();
130
+ const projectId = requireProjectId(opts.project);
131
+ let result;
132
+ if (id) {
133
+ result = await client.executeFunnel(projectId, id);
134
+ }
135
+ else if (opts.steps) {
136
+ const steps = opts.steps.split(",").map((s) => ({
137
+ event_name: s.trim(),
138
+ name: s.trim(),
139
+ }));
140
+ const body = { steps };
141
+ if (opts.range)
142
+ body.date_range = opts.range;
143
+ result = await client.executeAdHocFunnel(projectId, body);
144
+ }
145
+ else {
146
+ console.error("Provide a funnel ID or --steps for ad-hoc execution.");
147
+ process.exit(1);
148
+ }
149
+ if (opts.json) {
150
+ output.json(result);
151
+ return;
152
+ }
153
+ const results = result.results;
154
+ if (results.steps) {
155
+ output.table(["Step", "Count", "Conversion"], results.steps.map((s) => [
156
+ s.name,
157
+ output.formatNumber(s.count),
158
+ `${(s.conversion_rate * 100).toFixed(1)}%`,
159
+ ]));
160
+ if (results.overall_conversion !== undefined) {
161
+ console.log(`\nOverall: ${(results.overall_conversion * 100).toFixed(1)}%`);
162
+ }
163
+ }
164
+ else {
165
+ output.json(results);
166
+ }
167
+ });
168
+ funnels
169
+ .command("delete")
170
+ .description("Delete a funnel")
171
+ .argument("<id>", "Funnel ID")
172
+ .option("--project <id>", "Project ID")
173
+ .option("--json", "Output as JSON")
174
+ .action(async (id, opts) => {
175
+ auth.requireToken();
176
+ const projectId = requireProjectId(opts.project);
177
+ await requireConfirmation(`Delete funnel ${id}`);
178
+ const data = await client.deleteFunnel(projectId, id);
179
+ if (opts.json) {
180
+ output.json(data);
181
+ return;
182
+ }
183
+ console.log("Funnel deleted.");
184
+ });
185
+ }
186
+ //# sourceMappingURL=funnels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funnels.js","sourceRoot":"","sources":["../../src/commands/funnels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerInitCommand(program: Command): void;
@@ -0,0 +1,127 @@
1
+ import * as client from "../client.js";
2
+ import * as auth from "../auth.js";
3
+ import { saveContext } from "../context.js";
4
+ import readline from "node:readline";
5
+ import { CliUsageError, isNoInput } from "../runtime.js";
6
+ function prompt(question) {
7
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8
+ return new Promise((resolve) => {
9
+ rl.question(question, (answer) => {
10
+ rl.close();
11
+ resolve(answer.trim());
12
+ });
13
+ });
14
+ }
15
+ export function registerInitCommand(program) {
16
+ program
17
+ .command("init")
18
+ .description("Set up a project in the current directory")
19
+ .option("--project <name>", "Project name (skip prompt)")
20
+ .option("--org <slug>", "Organization slug")
21
+ .option("--sdk <type>", "SDK type (js, react-native, swift, android, flutter)")
22
+ .option("--json", "Output as JSON")
23
+ .action(async (opts) => {
24
+ auth.requireToken();
25
+ const { user, organizations } = await client.getMe();
26
+ if (organizations.length === 0) {
27
+ console.error("No organizations found. Create one at app.mostlygoodmetrics.com first.");
28
+ process.exit(1);
29
+ }
30
+ let orgSlug = opts.org;
31
+ if (!orgSlug) {
32
+ if (organizations.length === 1) {
33
+ orgSlug = organizations[0].slug;
34
+ }
35
+ else {
36
+ if (isNoInput()) {
37
+ throw new CliUsageError("init requires --org when --no-input is set and multiple organizations are available.");
38
+ }
39
+ console.log("Organizations:");
40
+ organizations.forEach((o, i) => console.log(` ${i + 1}. ${o.name} (${o.slug})`));
41
+ const choice = await prompt("Select organization [1]: ");
42
+ const idx = (parseInt(choice) || 1) - 1;
43
+ orgSlug = organizations[idx]?.slug ?? organizations[0].slug;
44
+ }
45
+ }
46
+ if (isNoInput() && !opts.project) {
47
+ throw new CliUsageError("init requires --project when --no-input is set.");
48
+ }
49
+ const projectName = opts.project ?? (await prompt("Project name: "));
50
+ if (!projectName) {
51
+ console.error("Project name is required.");
52
+ process.exit(1);
53
+ }
54
+ if (!opts.json)
55
+ console.log(`Creating project "${projectName}" in ${orgSlug}...`);
56
+ const { project } = await client.createProject(orgSlug, projectName);
57
+ if (!opts.json)
58
+ console.log("Creating API key...");
59
+ const { api_key } = await client.createApiKey(project.id, "Development");
60
+ saveContext(project.id, orgSlug);
61
+ if (opts.json) {
62
+ const { json } = await import("../output.js");
63
+ json({ project, api_key });
64
+ return;
65
+ }
66
+ console.log();
67
+ console.log("Project initialized!");
68
+ console.log(` Project: ${project.name} (${project.id})`);
69
+ console.log(` API Key: ${api_key.key}`);
70
+ console.log();
71
+ console.log("A .mgm.json file has been created in this directory.");
72
+ console.log();
73
+ if (opts.sdk) {
74
+ printSdkInstructions(opts.sdk, api_key.key);
75
+ }
76
+ else {
77
+ console.log("Install an SDK to start tracking events:");
78
+ console.log(" npm install @mostly-good-metrics/javascript");
79
+ console.log(" npm install @mostly-good-metrics/react-native");
80
+ console.log();
81
+ console.log("See https://docs.mostlygoodmetrics.com for all platforms.");
82
+ }
83
+ });
84
+ }
85
+ function printSdkInstructions(sdk, apiKey) {
86
+ console.log("SDK setup:");
87
+ console.log();
88
+ switch (sdk) {
89
+ case "js":
90
+ case "javascript":
91
+ console.log(" npm install @mostly-good-metrics/javascript");
92
+ console.log();
93
+ console.log(" import MostlyGoodMetrics from '@mostly-good-metrics/javascript';");
94
+ console.log(` MostlyGoodMetrics.init('${apiKey}');`);
95
+ break;
96
+ case "react-native":
97
+ console.log(" npm install @mostly-good-metrics/react-native");
98
+ console.log();
99
+ console.log(" import MostlyGoodMetrics from '@mostly-good-metrics/react-native';");
100
+ console.log(` MostlyGoodMetrics.init('${apiKey}');`);
101
+ break;
102
+ case "swift":
103
+ console.log(" // Add to Package.swift:");
104
+ console.log(' .package(url: "https://github.com/Mostly-Good-Metrics/mostly-good-metrics-swift-sdk.git", from: "1.0.0")');
105
+ console.log();
106
+ console.log(" import MostlyGoodMetrics");
107
+ console.log(` MostlyGoodMetrics.configure(apiKey: "${apiKey}")`);
108
+ break;
109
+ case "android":
110
+ case "kotlin":
111
+ console.log(' implementation("io.github.mostly-good-metrics:mgm-sdk:1.0.0")');
112
+ console.log();
113
+ console.log(` MostlyGoodMetrics.configure(context, "${apiKey}")`);
114
+ break;
115
+ case "flutter":
116
+ case "dart":
117
+ console.log(" # pubspec.yaml:");
118
+ console.log(" mostly_good_metrics_flutter: ^1.0.0");
119
+ console.log();
120
+ console.log(` MostlyGoodMetrics.configure(apiKey: '${apiKey}');`);
121
+ break;
122
+ default:
123
+ console.log(` Unknown SDK type: ${sdk}`);
124
+ console.log(" Supported: js, react-native, swift, android, flutter");
125
+ }
126
+ }
127
+ //# sourceMappingURL=init.js.map