@kitesdk/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.
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,446 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/index.ts
5
+ var import_node_fs2 = require("fs");
6
+ var import_commander = require("commander");
7
+ var import_prompts = require("@clack/prompts");
8
+
9
+ // src/api.ts
10
+ var KiteApiError = class extends Error {
11
+ constructor(message, status) {
12
+ super(message);
13
+ this.status = status;
14
+ this.name = "KiteApiError";
15
+ }
16
+ status;
17
+ };
18
+ async function postJourneyDefinition(config, definition) {
19
+ return request(config, "/v1/journey/define", {
20
+ method: "POST",
21
+ body: JSON.stringify(definition)
22
+ });
23
+ }
24
+ async function getJourneyDefinition(config) {
25
+ return request(config, "/v1/journey/definition");
26
+ }
27
+ async function getUnmappedEvents(config) {
28
+ return request(config, "/v1/audit/unmapped-events");
29
+ }
30
+ async function getStatusOverview(config) {
31
+ return request(config, "/v1/status/overview");
32
+ }
33
+ async function getGraphEdges(config, options = {}) {
34
+ const query = options.includeLowSample ? "?include_low_sample=true" : "";
35
+ return request(config, `/v1/graph-edges${query}`);
36
+ }
37
+ async function request(config, path, init = {}) {
38
+ const response = await fetch(`${config.apiUrl.replace(/\/$/, "")}${path}`, {
39
+ ...init,
40
+ headers: {
41
+ "Authorization": `Bearer ${config.writeKey}`,
42
+ "Content-Type": "application/json",
43
+ ...init.headers
44
+ }
45
+ });
46
+ if (!response.ok) {
47
+ const body = await response.text();
48
+ throw new KiteApiError(body || response.statusText, response.status);
49
+ }
50
+ return await response.json();
51
+ }
52
+
53
+ // src/config.ts
54
+ var import_node_fs = require("fs");
55
+ var import_node_path = require("path");
56
+ var import_node_os = require("os");
57
+ var defaultApiUrl = process.env.KITE_API_URL || "http://localhost:8000";
58
+ function configPath() {
59
+ if (process.env.KITE_CONFIG_PATH) {
60
+ return process.env.KITE_CONFIG_PATH;
61
+ }
62
+ return (0, import_node_path.join)((0, import_node_os.homedir)(), ".kitesdk", "config.json");
63
+ }
64
+ function loadConfig() {
65
+ const path = configPath();
66
+ if (!(0, import_node_fs.existsSync)(path)) {
67
+ return null;
68
+ }
69
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
70
+ if (!parsed.writeKey || !parsed.apiUrl) {
71
+ return null;
72
+ }
73
+ return { writeKey: parsed.writeKey, apiUrl: parsed.apiUrl };
74
+ }
75
+ function saveConfig(config) {
76
+ const path = configPath();
77
+ (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(path), { recursive: true });
78
+ (0, import_node_fs.writeFileSync)(path, `${JSON.stringify(config, null, 2)}
79
+ `, { mode: 384 });
80
+ }
81
+ function resolveConfig(options) {
82
+ const stored = loadConfig();
83
+ const writeKey = options.writeKey || process.env.KITE_WRITE_KEY || stored?.writeKey;
84
+ const apiUrl = options.apiUrl || process.env.KITE_API_URL || stored?.apiUrl || defaultApiUrl;
85
+ if (!writeKey) {
86
+ throw new Error("No write key found. Run `kite-sdk init` or set KITE_WRITE_KEY.");
87
+ }
88
+ return { writeKey, apiUrl };
89
+ }
90
+
91
+ // src/format.ts
92
+ function validateWriteKey(value) {
93
+ if (!value.trim()) {
94
+ return "Write key is required.";
95
+ }
96
+ if (!value.startsWith("kite_")) {
97
+ return "Write key must start with 'kite_'.";
98
+ }
99
+ return void 0;
100
+ }
101
+ function parseEventList(value) {
102
+ return value.split(",").map((event) => event.trim()).filter(Boolean);
103
+ }
104
+ function formatJourneyConfig(definition) {
105
+ return `import type { JourneyDefinition } from "kite-sdk";
106
+
107
+ export const journeyDefinition: JourneyDefinition = ${JSON.stringify(
108
+ definition,
109
+ null,
110
+ 2
111
+ )};
112
+ `;
113
+ }
114
+ function formatSeconds(seconds) {
115
+ if (seconds === null) {
116
+ return "n/a";
117
+ }
118
+ const minutes = Math.floor(seconds / 60);
119
+ const remainingSeconds = seconds % 60;
120
+ if (minutes <= 0) {
121
+ return `${remainingSeconds}s`;
122
+ }
123
+ return `${minutes}m ${remainingSeconds}s`;
124
+ }
125
+ function formatPercent(value) {
126
+ return `${Math.round(value * 100)}%`;
127
+ }
128
+ function formatMilestoneItems(items) {
129
+ if (!items || items.length === 0) {
130
+ return "(none defined)";
131
+ }
132
+ return items.map((item) => typeof item === "string" ? item : item.event).join(", ");
133
+ }
134
+ function renderBucketBars(overview) {
135
+ const buckets = [
136
+ ["Thriving", overview.success_buckets.thriving],
137
+ ["Progressing", overview.success_buckets.progressing],
138
+ ["At-Risk", overview.success_buckets.at_risk],
139
+ ["Churned", overview.success_buckets.churned]
140
+ ];
141
+ const max = Math.max(...buckets.map(([, count]) => count), 1);
142
+ return buckets.map(([label, count]) => {
143
+ const width = count === 0 ? 0 : Math.max(1, Math.round(count / max * 20));
144
+ return `${label.padEnd(12)} ${"#".repeat(width).padEnd(20)} ${count} users`;
145
+ });
146
+ }
147
+
148
+ // src/templates.ts
149
+ var templates = {
150
+ analytics_saas: {
151
+ label: "Analytics SaaS",
152
+ suggestions: [
153
+ "report_created",
154
+ "data_source_connected",
155
+ "report_shared",
156
+ "insight_saved",
157
+ "report_viewed",
158
+ "team_member_invited",
159
+ "plan_upgraded"
160
+ ],
161
+ defaults: {
162
+ activation: ["report_created", "data_source_connected"],
163
+ ahaMoment: ["report_shared"],
164
+ retention: [{ event: "report_viewed", minCount: 5, withinDays: 14 }],
165
+ expansion: ["team_member_invited", "plan_upgraded"]
166
+ }
167
+ },
168
+ devtools: {
169
+ label: "Developer Tool",
170
+ suggestions: [
171
+ "api_key_created",
172
+ "first_api_call_success",
173
+ "integration_deployed_to_production",
174
+ "api_call",
175
+ "second_project_created",
176
+ "paid_plan_selected"
177
+ ],
178
+ defaults: {
179
+ activation: ["api_key_created", "first_api_call_success"],
180
+ ahaMoment: ["integration_deployed_to_production"],
181
+ retention: [{ event: "api_call", minCount: 100, withinDays: 7 }],
182
+ expansion: ["second_project_created", "paid_plan_selected"]
183
+ }
184
+ },
185
+ project_management: {
186
+ label: "Project Management",
187
+ suggestions: [
188
+ "project_created",
189
+ "first_task_created",
190
+ "teammate_invited",
191
+ "first_task_completed",
192
+ "task_updated",
193
+ "workspace_created",
194
+ "integration_enabled"
195
+ ],
196
+ defaults: {
197
+ activation: ["project_created", "first_task_created", "teammate_invited"],
198
+ ahaMoment: ["first_task_completed"],
199
+ retention: [{ event: "task_updated", minCount: 10, withinDays: 7 }],
200
+ expansion: ["workspace_created", "integration_enabled"]
201
+ }
202
+ },
203
+ other: {
204
+ label: "Other",
205
+ suggestions: [
206
+ "account_created",
207
+ "integration_connected",
208
+ "value_event_completed",
209
+ "team_member_invited",
210
+ "plan_upgraded"
211
+ ],
212
+ defaults: {
213
+ activation: ["account_created", "value_event_completed"],
214
+ ahaMoment: ["value_event_completed"],
215
+ retention: [{ event: "value_event_completed", minCount: 3, withinDays: 14 }],
216
+ expansion: ["team_member_invited", "plan_upgraded"]
217
+ }
218
+ }
219
+ };
220
+
221
+ // src/index.ts
222
+ var program = new import_commander.Command();
223
+ program.name("kite-sdk").description("Configure and inspect Kite SDK journey definitions").version("0.1.0").option("--api-url <url>", "Kite API URL").option("--write-key <key>", "Kite write key");
224
+ program.command("init").description("Create and publish a journey definition").option("--write-key <key>", "Kite write key").option("--api-url <url>", "Kite API URL").option("--product-type <type>", "Product template").option("--activation <events>", "Comma-separated activation events").option("--aha-moment <event>", "Aha Moment event").option("--expansion <events>", "Comma-separated expansion events").option("--yes", "Run without interactive prompts").action(runInit);
225
+ program.command("audit").description("Show journey mapping and unmapped events").action(runAudit);
226
+ program.command("status").description("Show user success metrics").action(runStatus);
227
+ program.command("suggest").description("Analyze whether an event should be mapped to a milestone").requiredOption("--event <event_name>", "Event name to analyze").action(runSuggest);
228
+ program.parseAsync(process.argv).catch((error) => {
229
+ if (error instanceof Error) {
230
+ console.error(error.message);
231
+ } else {
232
+ console.error("Unexpected CLI error.");
233
+ }
234
+ process.exitCode = 1;
235
+ });
236
+ async function runInit(options) {
237
+ if (options.yes) {
238
+ await runNonInteractiveInit(options);
239
+ return;
240
+ }
241
+ (0, import_prompts.intro)("Kite SDK setup");
242
+ const writeKey = await (0, import_prompts.text)({
243
+ message: "What's your Kite SDK write key?",
244
+ validate: (value) => validateWriteKey(value)
245
+ });
246
+ exitIfCancelled(writeKey);
247
+ const apiUrl = await (0, import_prompts.text)({
248
+ message: "Kite API URL",
249
+ placeholder: defaultApiUrl,
250
+ defaultValue: defaultApiUrl
251
+ });
252
+ exitIfCancelled(apiUrl);
253
+ const productType = await (0, import_prompts.select)({
254
+ message: "What type of product are you building?",
255
+ options: [
256
+ { value: "analytics_saas", label: "Analytics SaaS" },
257
+ { value: "devtools", label: "Developer Tool" },
258
+ { value: "project_management", label: "Project Management" },
259
+ { value: "other", label: "Other" }
260
+ ]
261
+ });
262
+ exitIfCancelled(productType);
263
+ const template = templates[productType];
264
+ const activation = await chooseEvents(
265
+ "Which events signal activation?",
266
+ template.suggestions,
267
+ template.defaults.activation.filter((item) => typeof item === "string")
268
+ );
269
+ const ahaMoment = await (0, import_prompts.select)({
270
+ message: "Which event is your Aha Moment?",
271
+ options: template.suggestions.map((event) => ({ value: event, label: event })),
272
+ initialValue: formatMilestoneItems(template.defaults.ahaMoment).split(", ")[0]
273
+ });
274
+ exitIfCancelled(ahaMoment);
275
+ const expansion = await chooseEvents(
276
+ "Which events signal expansion?",
277
+ template.suggestions,
278
+ template.defaults.expansion.filter((item) => typeof item === "string")
279
+ );
280
+ const customEvents = await (0, import_prompts.text)({
281
+ message: "Any additional activation events? (comma-separated, optional)",
282
+ placeholder: "dashboard_exported, invite_sent"
283
+ });
284
+ exitIfCancelled(customEvents);
285
+ const definition = {
286
+ activation: [...activation, ...parseEventList(customEvents)],
287
+ ahaMoment: [String(ahaMoment)],
288
+ retention: template.defaults.retention,
289
+ expansion
290
+ };
291
+ (0, import_node_fs2.writeFileSync)("journey.config.ts", formatJourneyConfig(definition));
292
+ const config = { writeKey: String(writeKey), apiUrl: String(apiUrl) };
293
+ saveConfig(config);
294
+ const result = await postJourneyDefinition(config, definition);
295
+ (0, import_prompts.note)(
296
+ [
297
+ `Generated journey.config.ts`,
298
+ `Published journey definition v${result.version}`,
299
+ `Stored credentials in ~/.kitesdk/config.json`,
300
+ "Next: import journeyDefinition into your app and call journey.define(journeyDefinition)."
301
+ ].join("\n"),
302
+ "Setup complete"
303
+ );
304
+ (0, import_prompts.outro)("Run `kite-sdk audit` to inspect your mapping.");
305
+ }
306
+ async function runAudit() {
307
+ const config = resolveConfig(program.opts());
308
+ const [journey, unmappedEvents] = await Promise.all([
309
+ getJourneyDefinition(config),
310
+ getUnmappedEvents(config)
311
+ ]);
312
+ if (journey.version === null) {
313
+ console.info("! No journey definition found. Run `kite-sdk init`.");
314
+ return;
315
+ }
316
+ console.info(`Journey Definition (v${journey.version})`);
317
+ console.info(` Activation: ${formatMilestoneItems(journey.definition.activation)}`);
318
+ console.info(` Aha Moment: ${formatMilestoneItems(journey.definition.ahaMoment)}`);
319
+ console.info(` Retention: ${formatMilestoneItems(journey.definition.retention)}`);
320
+ console.info(` Expansion: ${formatMilestoneItems(journey.definition.expansion)}`);
321
+ console.info("");
322
+ if (unmappedEvents.length === 0) {
323
+ console.info("All events are mapped to milestones.");
324
+ return;
325
+ }
326
+ console.info("Unmapped Events (last 24h)");
327
+ for (const event of unmappedEvents) {
328
+ console.info(` ${event.event_name.padEnd(24)} (${event.occurrence_count} occurrences)`);
329
+ }
330
+ console.info("");
331
+ console.info(`Run \`kite-sdk suggest --event ${unmappedEvents[0]?.event_name}\` for analysis.`);
332
+ }
333
+ async function runStatus() {
334
+ const config = resolveConfig(program.opts());
335
+ const overview = await getStatusOverview(config);
336
+ if (overview.total_users === 0) {
337
+ console.info("No users tracked yet. Integrate the SDK and call identify().");
338
+ return;
339
+ }
340
+ console.info("User Success Snapshot (last 30 days)");
341
+ console.info("-------------------------------------");
342
+ console.info(`Activation Rate: ${formatPercent(overview.activation_rate)}`);
343
+ console.info(`Aha Moment Rate: ${formatPercent(overview.aha_moment_rate)}`);
344
+ console.info(`Avg Time-to-Value: ${formatSeconds(overview.avg_time_to_activation_seconds)}`);
345
+ console.info("");
346
+ console.info("Bucket Distribution:");
347
+ for (const line of renderBucketBars(overview)) {
348
+ console.info(line);
349
+ }
350
+ }
351
+ async function runSuggest(options) {
352
+ const config = resolveConfig(program.opts());
353
+ const [journey, edges] = await Promise.all([
354
+ getJourneyDefinition(config),
355
+ getGraphEdges(config, { includeLowSample: true })
356
+ ]);
357
+ const eventName = options.event;
358
+ const mappedTo = findMappedMilestone(journey.definition, eventName);
359
+ const edge = edges.find((candidate) => candidate.from_event === eventName);
360
+ console.info(`Event: ${eventName}`);
361
+ if (mappedTo) {
362
+ console.info(`Already mapped to: ${mappedTo}`);
363
+ }
364
+ if (!edge) {
365
+ console.info("Not enough data yet (0 samples, minimum 30).");
366
+ return;
367
+ }
368
+ if (edge.sample_size < 30) {
369
+ console.info(`Not enough data yet (${edge.sample_size} samples, minimum 30).`);
370
+ return;
371
+ }
372
+ console.info(`Retention lift: ${edge.retention_lift_multiplier.toFixed(2)}x`);
373
+ console.info(`Sample size: ${edge.sample_size}`);
374
+ console.info(`Correlation: ${edge.correlation_coefficient.toFixed(2)}`);
375
+ if (!mappedTo && edge.retention_lift_multiplier >= 2) {
376
+ console.info("Suggestion: add this event to activation or retention and validate the hypothesis.");
377
+ } else if (!mappedTo) {
378
+ console.info("Suggestion: monitor this event, but do not promote it to a milestone yet.");
379
+ }
380
+ }
381
+ async function runNonInteractiveInit(options) {
382
+ const writeKey = options.writeKey || program.opts().writeKey || process.env.KITE_WRITE_KEY;
383
+ const apiUrl = options.apiUrl || program.opts().apiUrl || defaultApiUrl;
384
+ const productType = normalizeProductType(options.productType || "analytics_saas");
385
+ const validationError = validateWriteKey(writeKey || "");
386
+ if (validationError) {
387
+ throw new Error(validationError);
388
+ }
389
+ const template = templates[productType];
390
+ const definition = {
391
+ activation: options.activation !== void 0 ? parseEventList(options.activation) : template.defaults.activation,
392
+ ahaMoment: [options.ahaMoment || String(template.defaults.ahaMoment[0])],
393
+ retention: template.defaults.retention,
394
+ expansion: options.expansion !== void 0 ? parseEventList(options.expansion) : template.defaults.expansion
395
+ };
396
+ (0, import_node_fs2.writeFileSync)("journey.config.ts", formatJourneyConfig(definition));
397
+ const config = { writeKey: String(writeKey), apiUrl: String(apiUrl) };
398
+ saveConfig(config);
399
+ const result = await postJourneyDefinition(config, definition);
400
+ console.info(`Generated journey.config.ts`);
401
+ console.info(`Published journey definition v${result.version}`);
402
+ console.info("Next: import journeyDefinition into your app and call journey.define(journeyDefinition).");
403
+ }
404
+ function normalizeProductType(value) {
405
+ if (value in templates) {
406
+ return value;
407
+ }
408
+ throw new Error(
409
+ `Unknown product type '${value}'. Use analytics_saas, devtools, project_management, or other.`
410
+ );
411
+ }
412
+ async function chooseEvents(message, suggestions, defaults) {
413
+ const selected = await (0, import_prompts.multiselect)({
414
+ message,
415
+ options: suggestions.map((event) => ({ value: event, label: event })),
416
+ initialValues: defaults,
417
+ required: false
418
+ });
419
+ exitIfCancelled(selected);
420
+ if (selected.length > 0) {
421
+ return selected.map(String);
422
+ }
423
+ const keepEmpty = await (0, import_prompts.confirm)({ message: "Leave this milestone empty?", initialValue: false });
424
+ exitIfCancelled(keepEmpty);
425
+ return keepEmpty ? [] : defaults;
426
+ }
427
+ function findMappedMilestone(definition, eventName) {
428
+ for (const [milestone, items] of Object.entries({
429
+ activation: definition.activation,
430
+ aha_moment: definition.ahaMoment,
431
+ retention: definition.retention,
432
+ expansion: definition.expansion
433
+ })) {
434
+ if (items?.some((item) => (typeof item === "string" ? item : item.event) === eventName)) {
435
+ return milestone;
436
+ }
437
+ }
438
+ return null;
439
+ }
440
+ function exitIfCancelled(value) {
441
+ if ((0, import_prompts.isCancel)(value)) {
442
+ (0, import_prompts.cancel)("Setup cancelled.");
443
+ process.exit(0);
444
+ }
445
+ }
446
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/api.ts","../src/config.ts","../src/format.ts","../src/templates.ts"],"sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport { Command } from \"commander\";\nimport { cancel, confirm, intro, isCancel, multiselect, note, outro, select, text } from \"@clack/prompts\";\n\nimport {\n getGraphEdges,\n getJourneyDefinition,\n getStatusOverview,\n getUnmappedEvents,\n postJourneyDefinition,\n} from \"./api\";\nimport { defaultApiUrl, resolveConfig, saveConfig } from \"./config\";\nimport {\n formatJourneyConfig,\n formatMilestoneItems,\n formatPercent,\n formatSeconds,\n parseEventList,\n renderBucketBars,\n validateWriteKey,\n} from \"./format\";\nimport { templates, type ProductType } from \"./templates\";\nimport type { JourneyDefinition } from \"./types\";\n\nconst program = new Command();\n\nprogram\n .name(\"kite-sdk\")\n .description(\"Configure and inspect Kite SDK journey definitions\")\n .version(\"0.1.0\")\n .option(\"--api-url <url>\", \"Kite API URL\")\n .option(\"--write-key <key>\", \"Kite write key\");\n\nprogram\n .command(\"init\")\n .description(\"Create and publish a journey definition\")\n .option(\"--write-key <key>\", \"Kite write key\")\n .option(\"--api-url <url>\", \"Kite API URL\")\n .option(\"--product-type <type>\", \"Product template\")\n .option(\"--activation <events>\", \"Comma-separated activation events\")\n .option(\"--aha-moment <event>\", \"Aha Moment event\")\n .option(\"--expansion <events>\", \"Comma-separated expansion events\")\n .option(\"--yes\", \"Run without interactive prompts\")\n .action(runInit);\nprogram.command(\"audit\").description(\"Show journey mapping and unmapped events\").action(runAudit);\nprogram.command(\"status\").description(\"Show user success metrics\").action(runStatus);\nprogram\n .command(\"suggest\")\n .description(\"Analyze whether an event should be mapped to a milestone\")\n .requiredOption(\"--event <event_name>\", \"Event name to analyze\")\n .action(runSuggest);\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n if (error instanceof Error) {\n console.error(error.message);\n } else {\n console.error(\"Unexpected CLI error.\");\n }\n process.exitCode = 1;\n});\n\ninterface InitOptions {\n writeKey?: string;\n apiUrl?: string;\n productType?: string;\n activation?: string;\n ahaMoment?: string;\n expansion?: string;\n yes?: boolean;\n}\n\nasync function runInit(options: InitOptions): Promise<void> {\n if (options.yes) {\n await runNonInteractiveInit(options);\n return;\n }\n\n intro(\"Kite SDK setup\");\n\n const writeKey = await text({\n message: \"What's your Kite SDK write key?\",\n validate: (value) => validateWriteKey(value),\n });\n exitIfCancelled(writeKey);\n\n const apiUrl = await text({\n message: \"Kite API URL\",\n placeholder: defaultApiUrl,\n defaultValue: defaultApiUrl,\n });\n exitIfCancelled(apiUrl);\n\n const productType = await select({\n message: \"What type of product are you building?\",\n options: [\n { value: \"analytics_saas\", label: \"Analytics SaaS\" },\n { value: \"devtools\", label: \"Developer Tool\" },\n { value: \"project_management\", label: \"Project Management\" },\n { value: \"other\", label: \"Other\" },\n ],\n });\n exitIfCancelled(productType);\n\n const template = templates[productType as ProductType];\n const activation = await chooseEvents(\n \"Which events signal activation?\",\n template.suggestions,\n template.defaults.activation.filter((item): item is string => typeof item === \"string\"),\n );\n const ahaMoment = await select({\n message: \"Which event is your Aha Moment?\",\n options: template.suggestions.map((event) => ({ value: event, label: event })),\n initialValue: formatMilestoneItems(template.defaults.ahaMoment).split(\", \")[0],\n });\n exitIfCancelled(ahaMoment);\n const expansion = await chooseEvents(\n \"Which events signal expansion?\",\n template.suggestions,\n template.defaults.expansion.filter((item): item is string => typeof item === \"string\"),\n );\n\n const customEvents = await text({\n message: \"Any additional activation events? (comma-separated, optional)\",\n placeholder: \"dashboard_exported, invite_sent\",\n });\n exitIfCancelled(customEvents);\n\n const definition: JourneyDefinition = {\n activation: [...activation, ...parseEventList(customEvents)],\n ahaMoment: [String(ahaMoment)],\n retention: template.defaults.retention,\n expansion,\n };\n\n writeFileSync(\"journey.config.ts\", formatJourneyConfig(definition));\n const config = { writeKey: String(writeKey), apiUrl: String(apiUrl) };\n saveConfig(config);\n const result = await postJourneyDefinition(config, definition);\n\n note(\n [\n `Generated journey.config.ts`,\n `Published journey definition v${result.version}`,\n `Stored credentials in ~/.kitesdk/config.json`,\n \"Next: import journeyDefinition into your app and call journey.define(journeyDefinition).\",\n ].join(\"\\n\"),\n \"Setup complete\",\n );\n outro(\"Run `kite-sdk audit` to inspect your mapping.\");\n}\n\nasync function runAudit(): Promise<void> {\n const config = resolveConfig(program.opts());\n const [journey, unmappedEvents] = await Promise.all([\n getJourneyDefinition(config),\n getUnmappedEvents(config),\n ]);\n\n if (journey.version === null) {\n console.info(\"! No journey definition found. Run `kite-sdk init`.\");\n return;\n }\n\n console.info(`Journey Definition (v${journey.version})`);\n console.info(` Activation: ${formatMilestoneItems(journey.definition.activation)}`);\n console.info(` Aha Moment: ${formatMilestoneItems(journey.definition.ahaMoment)}`);\n console.info(` Retention: ${formatMilestoneItems(journey.definition.retention)}`);\n console.info(` Expansion: ${formatMilestoneItems(journey.definition.expansion)}`);\n console.info(\"\");\n\n if (unmappedEvents.length === 0) {\n console.info(\"All events are mapped to milestones.\");\n return;\n }\n\n console.info(\"Unmapped Events (last 24h)\");\n for (const event of unmappedEvents) {\n console.info(` ${event.event_name.padEnd(24)} (${event.occurrence_count} occurrences)`);\n }\n console.info(\"\");\n console.info(`Run \\`kite-sdk suggest --event ${unmappedEvents[0]?.event_name}\\` for analysis.`);\n}\n\nasync function runStatus(): Promise<void> {\n const config = resolveConfig(program.opts());\n const overview = await getStatusOverview(config);\n if (overview.total_users === 0) {\n console.info(\"No users tracked yet. Integrate the SDK and call identify().\");\n return;\n }\n\n console.info(\"User Success Snapshot (last 30 days)\");\n console.info(\"-------------------------------------\");\n console.info(`Activation Rate: ${formatPercent(overview.activation_rate)}`);\n console.info(`Aha Moment Rate: ${formatPercent(overview.aha_moment_rate)}`);\n console.info(`Avg Time-to-Value: ${formatSeconds(overview.avg_time_to_activation_seconds)}`);\n console.info(\"\");\n console.info(\"Bucket Distribution:\");\n for (const line of renderBucketBars(overview)) {\n console.info(line);\n }\n}\n\nasync function runSuggest(options: { event: string }): Promise<void> {\n const config = resolveConfig(program.opts());\n const [journey, edges] = await Promise.all([\n getJourneyDefinition(config),\n getGraphEdges(config, { includeLowSample: true }),\n ]);\n const eventName = options.event;\n const mappedTo = findMappedMilestone(journey.definition, eventName);\n const edge = edges.find((candidate) => candidate.from_event === eventName);\n\n console.info(`Event: ${eventName}`);\n if (mappedTo) {\n console.info(`Already mapped to: ${mappedTo}`);\n }\n if (!edge) {\n console.info(\"Not enough data yet (0 samples, minimum 30).\");\n return;\n }\n if (edge.sample_size < 30) {\n console.info(`Not enough data yet (${edge.sample_size} samples, minimum 30).`);\n return;\n }\n\n console.info(`Retention lift: ${edge.retention_lift_multiplier.toFixed(2)}x`);\n console.info(`Sample size: ${edge.sample_size}`);\n console.info(`Correlation: ${edge.correlation_coefficient.toFixed(2)}`);\n if (!mappedTo && edge.retention_lift_multiplier >= 2) {\n console.info(\"Suggestion: add this event to activation or retention and validate the hypothesis.\");\n } else if (!mappedTo) {\n console.info(\"Suggestion: monitor this event, but do not promote it to a milestone yet.\");\n }\n}\n\nasync function runNonInteractiveInit(options: InitOptions): Promise<void> {\n const writeKey = options.writeKey || program.opts().writeKey || process.env.KITE_WRITE_KEY;\n const apiUrl = options.apiUrl || program.opts().apiUrl || defaultApiUrl;\n const productType = normalizeProductType(options.productType || \"analytics_saas\");\n const validationError = validateWriteKey(writeKey || \"\");\n if (validationError) {\n throw new Error(validationError);\n }\n\n const template = templates[productType];\n const definition: JourneyDefinition = {\n activation:\n options.activation !== undefined\n ? parseEventList(options.activation)\n : template.defaults.activation,\n ahaMoment: [options.ahaMoment || String(template.defaults.ahaMoment[0])],\n retention: template.defaults.retention,\n expansion:\n options.expansion !== undefined\n ? parseEventList(options.expansion)\n : template.defaults.expansion,\n };\n\n writeFileSync(\"journey.config.ts\", formatJourneyConfig(definition));\n const config = { writeKey: String(writeKey), apiUrl: String(apiUrl) };\n saveConfig(config);\n const result = await postJourneyDefinition(config, definition);\n console.info(`Generated journey.config.ts`);\n console.info(`Published journey definition v${result.version}`);\n console.info(\"Next: import journeyDefinition into your app and call journey.define(journeyDefinition).\");\n}\n\nfunction normalizeProductType(value: string): ProductType {\n if (value in templates) {\n return value as ProductType;\n }\n throw new Error(\n `Unknown product type '${value}'. Use analytics_saas, devtools, project_management, or other.`,\n );\n}\n\nasync function chooseEvents(message: string, suggestions: string[], defaults: string[]): Promise<string[]> {\n const selected = await multiselect({\n message,\n options: suggestions.map((event) => ({ value: event, label: event })),\n initialValues: defaults,\n required: false,\n });\n exitIfCancelled(selected);\n if (selected.length > 0) {\n return selected.map(String);\n }\n const keepEmpty = await confirm({ message: \"Leave this milestone empty?\", initialValue: false });\n exitIfCancelled(keepEmpty);\n return keepEmpty ? [] : defaults;\n}\n\nfunction findMappedMilestone(definition: JourneyDefinition, eventName: string): string | null {\n for (const [milestone, items] of Object.entries({\n activation: definition.activation,\n aha_moment: definition.ahaMoment,\n retention: definition.retention,\n expansion: definition.expansion,\n })) {\n if (items?.some((item) => (typeof item === \"string\" ? item : item.event) === eventName)) {\n return milestone;\n }\n }\n return null;\n}\n\nfunction exitIfCancelled<T>(value: T | symbol): asserts value is T {\n if (isCancel(value)) {\n cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n}\n","import type {\n CliConfig,\n GraphEdge,\n JourneyDefinition,\n JourneyDefinitionResponse,\n StatusOverview,\n UnmappedEvent,\n} from \"./types\";\n\nexport class KiteApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"KiteApiError\";\n }\n}\n\nexport async function postJourneyDefinition(\n config: CliConfig,\n definition: JourneyDefinition,\n): Promise<{ version: number; milestones_defined: string[] }> {\n return request(config, \"/v1/journey/define\", {\n method: \"POST\",\n body: JSON.stringify(definition),\n });\n}\n\nexport async function getJourneyDefinition(config: CliConfig): Promise<JourneyDefinitionResponse> {\n return request(config, \"/v1/journey/definition\");\n}\n\nexport async function getUnmappedEvents(config: CliConfig): Promise<UnmappedEvent[]> {\n return request(config, \"/v1/audit/unmapped-events\");\n}\n\nexport async function getStatusOverview(config: CliConfig): Promise<StatusOverview> {\n return request(config, \"/v1/status/overview\");\n}\n\nexport async function getGraphEdges(\n config: CliConfig,\n options: { includeLowSample?: boolean } = {},\n): Promise<GraphEdge[]> {\n const query = options.includeLowSample ? \"?include_low_sample=true\" : \"\";\n return request(config, `/v1/graph-edges${query}`);\n}\n\nasync function request<T>(config: CliConfig, path: string, init: RequestInit = {}): Promise<T> {\n const response = await fetch(`${config.apiUrl.replace(/\\/$/, \"\")}${path}`, {\n ...init,\n headers: {\n \"Authorization\": `Bearer ${config.writeKey}`,\n \"Content-Type\": \"application/json\",\n ...init.headers,\n },\n });\n\n if (!response.ok) {\n const body = await response.text();\n throw new KiteApiError(body || response.statusText, response.status);\n }\n return (await response.json()) as T;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nimport type { CliConfig } from \"./types\";\n\nexport const defaultApiUrl = process.env.KITE_API_URL || \"http://localhost:8000\";\n\nexport function configPath(): string {\n if (process.env.KITE_CONFIG_PATH) {\n return process.env.KITE_CONFIG_PATH;\n }\n return join(homedir(), \".kitesdk\", \"config.json\");\n}\n\nexport function loadConfig(): CliConfig | null {\n const path = configPath();\n if (!existsSync(path)) {\n return null;\n }\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<CliConfig>;\n if (!parsed.writeKey || !parsed.apiUrl) {\n return null;\n }\n return { writeKey: parsed.writeKey, apiUrl: parsed.apiUrl };\n}\n\nexport function saveConfig(config: CliConfig): void {\n const path = configPath();\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n}\n\nexport function resolveConfig(options: { apiUrl?: string; writeKey?: string }): CliConfig {\n const stored = loadConfig();\n const writeKey = options.writeKey || process.env.KITE_WRITE_KEY || stored?.writeKey;\n const apiUrl = options.apiUrl || process.env.KITE_API_URL || stored?.apiUrl || defaultApiUrl;\n if (!writeKey) {\n throw new Error(\"No write key found. Run `kite-sdk init` or set KITE_WRITE_KEY.\");\n }\n return { writeKey, apiUrl };\n}\n","import type { JourneyDefinition, MilestoneCondition, StatusOverview } from \"./types\";\n\nexport function validateWriteKey(value: string): string | undefined {\n if (!value.trim()) {\n return \"Write key is required.\";\n }\n if (!value.startsWith(\"kite_\")) {\n return \"Write key must start with 'kite_'.\";\n }\n return undefined;\n}\n\nexport function parseEventList(value: string): string[] {\n return value\n .split(\",\")\n .map((event) => event.trim())\n .filter(Boolean);\n}\n\nexport function formatJourneyConfig(definition: JourneyDefinition): string {\n return `import type { JourneyDefinition } from \"kite-sdk\";\\n\\nexport const journeyDefinition: JourneyDefinition = ${JSON.stringify(\n definition,\n null,\n 2,\n )};\\n`;\n}\n\nexport function formatSeconds(seconds: number | null): string {\n if (seconds === null) {\n return \"n/a\";\n }\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = seconds % 60;\n if (minutes <= 0) {\n return `${remainingSeconds}s`;\n }\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function formatPercent(value: number): string {\n return `${Math.round(value * 100)}%`;\n}\n\nexport function formatMilestoneItems(items: (string | MilestoneCondition)[] | undefined): string {\n if (!items || items.length === 0) {\n return \"(none defined)\";\n }\n return items.map((item) => (typeof item === \"string\" ? item : item.event)).join(\", \");\n}\n\nexport function renderBucketBars(overview: StatusOverview): string[] {\n const buckets = [\n [\"Thriving\", overview.success_buckets.thriving],\n [\"Progressing\", overview.success_buckets.progressing],\n [\"At-Risk\", overview.success_buckets.at_risk],\n [\"Churned\", overview.success_buckets.churned],\n ] as const;\n const max = Math.max(...buckets.map(([, count]) => count), 1);\n return buckets.map(([label, count]) => {\n const width = count === 0 ? 0 : Math.max(1, Math.round((count / max) * 20));\n return `${label.padEnd(12)} ${\"#\".repeat(width).padEnd(20)} ${count} users`;\n });\n}\n","import type { JourneyDefinition } from \"./types\";\n\nexport type ProductType = \"analytics_saas\" | \"devtools\" | \"project_management\" | \"other\";\n\ninterface JourneyTemplate {\n label: string;\n suggestions: string[];\n defaults: Required<JourneyDefinition>;\n}\n\nexport const templates: Record<ProductType, JourneyTemplate> = {\n analytics_saas: {\n label: \"Analytics SaaS\",\n suggestions: [\n \"report_created\",\n \"data_source_connected\",\n \"report_shared\",\n \"insight_saved\",\n \"report_viewed\",\n \"team_member_invited\",\n \"plan_upgraded\",\n ],\n defaults: {\n activation: [\"report_created\", \"data_source_connected\"],\n ahaMoment: [\"report_shared\"],\n retention: [{ event: \"report_viewed\", minCount: 5, withinDays: 14 }],\n expansion: [\"team_member_invited\", \"plan_upgraded\"],\n },\n },\n devtools: {\n label: \"Developer Tool\",\n suggestions: [\n \"api_key_created\",\n \"first_api_call_success\",\n \"integration_deployed_to_production\",\n \"api_call\",\n \"second_project_created\",\n \"paid_plan_selected\",\n ],\n defaults: {\n activation: [\"api_key_created\", \"first_api_call_success\"],\n ahaMoment: [\"integration_deployed_to_production\"],\n retention: [{ event: \"api_call\", minCount: 100, withinDays: 7 }],\n expansion: [\"second_project_created\", \"paid_plan_selected\"],\n },\n },\n project_management: {\n label: \"Project Management\",\n suggestions: [\n \"project_created\",\n \"first_task_created\",\n \"teammate_invited\",\n \"first_task_completed\",\n \"task_updated\",\n \"workspace_created\",\n \"integration_enabled\",\n ],\n defaults: {\n activation: [\"project_created\", \"first_task_created\", \"teammate_invited\"],\n ahaMoment: [\"first_task_completed\"],\n retention: [{ event: \"task_updated\", minCount: 10, withinDays: 7 }],\n expansion: [\"workspace_created\", \"integration_enabled\"],\n },\n },\n other: {\n label: \"Other\",\n suggestions: [\n \"account_created\",\n \"integration_connected\",\n \"value_event_completed\",\n \"team_member_invited\",\n \"plan_upgraded\",\n ],\n defaults: {\n activation: [\"account_created\", \"value_event_completed\"],\n ahaMoment: [\"value_event_completed\"],\n retention: [{ event: \"value_event_completed\", minCount: 3, withinDays: 14 }],\n expansion: [\"team_member_invited\", \"plan_upgraded\"],\n },\n },\n};\n"],"mappings":"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","names":["import_node_fs"]}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@kitesdk/cli",
3
+ "version": "0.1.0",
4
+ "description": "Kite SDK command line companion",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "kite-sdk": "dist/index.js"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "lint": "eslint .",
18
+ "test": "vitest run"
19
+ },
20
+ "dependencies": {
21
+ "@clack/prompts": "^0.8.2",
22
+ "commander": "^12.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^22.10.6",
26
+ "tsup": "^8.3.5",
27
+ "vitest": "^2.1.8"
28
+ },
29
+ "engines": {
30
+ "node": ">=18"
31
+ }
32
+ }