@stephendolan/chartmogul-cli 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Stephen Dolan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # ChartMogul CLI
2
+
3
+ [![npm version](https://badge.fury.io/js/%40stephendolan%2Fchartmogul-cli.svg)](https://www.npmjs.com/package/@stephendolan/chartmogul-cli)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A command-line interface for ChartMogul analytics, designed for developers and LLMs.
7
+
8
+ ## Features
9
+
10
+ - **LLM-first design** - JSON output for easy parsing and automation
11
+ - **Analytics focused** - MRR, ARR, churn rates, LTV, customer counts
12
+ - **Secure auth** - Credentials stored in OS keychain
13
+ - **Read-only** - Query your data safely without risk of modification
14
+
15
+ ## Installation
16
+
17
+ ### From npm (recommended)
18
+
19
+ ```bash
20
+ npm install -g @stephendolan/chartmogul-cli
21
+ # or
22
+ bun install -g @stephendolan/chartmogul-cli
23
+ ```
24
+
25
+ ### From source
26
+
27
+ ```bash
28
+ git clone https://github.com/stephendolan/chartmogul-cli.git
29
+ cd chartmogul-cli
30
+ bun install
31
+ bun run link
32
+ ```
33
+
34
+ ### Linux prerequisites
35
+
36
+ On Linux, install libsecret for keychain support:
37
+
38
+ ```bash
39
+ sudo apt-get install libsecret-1-dev
40
+ ```
41
+
42
+ ## Authentication
43
+
44
+ ### Using API Key (recommended)
45
+
46
+ ```bash
47
+ # Store API key in OS keychain
48
+ chartmogul auth login --api-key YOUR_API_KEY
49
+
50
+ # Check authentication status
51
+ chartmogul auth status
52
+
53
+ # Remove stored credentials
54
+ chartmogul auth logout
55
+ ```
56
+
57
+ ### Using environment variable
58
+
59
+ ```bash
60
+ export CHARTMOGUL_API_KEY=your_api_key
61
+ ```
62
+
63
+ Get your API key from ChartMogul: Profile → API Keys
64
+
65
+ ## Usage
66
+
67
+ ### Account
68
+
69
+ ```bash
70
+ # View account details
71
+ chartmogul account view
72
+ ```
73
+
74
+ ### Metrics
75
+
76
+ ```bash
77
+ # Get all metrics (last 30 days by default)
78
+ chartmogul metrics all
79
+
80
+ # MRR (Monthly Recurring Revenue)
81
+ chartmogul metrics mrr
82
+ chartmogul metrics mrr --start-date 2024-01-01 --end-date 2024-12-31
83
+
84
+ # ARR (Annual Recurring Revenue)
85
+ chartmogul metrics arr --interval month
86
+
87
+ # ARPA (Average Revenue Per Account)
88
+ chartmogul metrics arpa
89
+
90
+ # ASP (Average Sale Price)
91
+ chartmogul metrics asp
92
+
93
+ # Customer count
94
+ chartmogul metrics customer-count
95
+
96
+ # Customer churn rate
97
+ chartmogul metrics customer-churn
98
+
99
+ # MRR churn rate
100
+ chartmogul metrics mrr-churn
101
+
102
+ # LTV (Customer Lifetime Value)
103
+ chartmogul metrics ltv
104
+ ```
105
+
106
+ ### Customers
107
+
108
+ ```bash
109
+ # List customers
110
+ chartmogul customers list
111
+ chartmogul customers list --status Active
112
+ chartmogul customers list --data-source <uuid>
113
+
114
+ # View a customer
115
+ chartmogul customers view <uuid>
116
+
117
+ # Search by email
118
+ chartmogul customers search --email user@example.com
119
+
120
+ # View customer activities
121
+ chartmogul customers activities <uuid>
122
+
123
+ # View customer subscriptions
124
+ chartmogul customers subscriptions <uuid>
125
+ ```
126
+
127
+ ### Plans
128
+
129
+ ```bash
130
+ # List plans
131
+ chartmogul plans list
132
+
133
+ # View a plan
134
+ chartmogul plans view <uuid>
135
+ ```
136
+
137
+ ### Invoices
138
+
139
+ ```bash
140
+ # List invoices
141
+ chartmogul invoices list
142
+ chartmogul invoices list --customer <uuid>
143
+
144
+ # View an invoice
145
+ chartmogul invoices view <uuid>
146
+ ```
147
+
148
+ ### Data Sources
149
+
150
+ ```bash
151
+ # List data sources
152
+ chartmogul data-sources list
153
+
154
+ # View a data source
155
+ chartmogul data-sources view <uuid>
156
+
157
+ # Set default data source for filtering
158
+ chartmogul data-sources set-default <uuid>
159
+ ```
160
+
161
+ ### Activities
162
+
163
+ ```bash
164
+ # List activities
165
+ chartmogul activities list
166
+ chartmogul activities list --type new_biz
167
+ chartmogul activities list --start-date 2024-01-01 --end-date 2024-12-31
168
+ ```
169
+
170
+ ## Output Formatting
171
+
172
+ All commands output JSON by default:
173
+
174
+ ```bash
175
+ # Pretty-printed JSON (default)
176
+ chartmogul metrics mrr
177
+
178
+ # Compact JSON (single line)
179
+ chartmogul -c metrics mrr
180
+ chartmogul --compact customers list
181
+ ```
182
+
183
+ ## Environment Variables
184
+
185
+ | Variable | Description |
186
+ |----------|-------------|
187
+ | `CHARTMOGUL_API_KEY` | API key (alternative to keychain) |
188
+ | `CHARTMOGUL_DATA_SOURCE` | Default data source UUID |
189
+
190
+ ## Common Patterns
191
+
192
+ ### Get current MRR
193
+
194
+ ```bash
195
+ chartmogul metrics mrr --start-date $(date +%Y-%m-%d) --end-date $(date +%Y-%m-%d)
196
+ ```
197
+
198
+ ### Get monthly MRR trend
199
+
200
+ ```bash
201
+ chartmogul metrics mrr --start-date 2024-01-01 --end-date 2024-12-31 --interval month
202
+ ```
203
+
204
+ ### Find high-value customers
205
+
206
+ ```bash
207
+ chartmogul customers list | jq '.entries | sort_by(.mrr) | reverse | .[0:10]'
208
+ ```
209
+
210
+ ### Get churn analysis
211
+
212
+ ```bash
213
+ chartmogul metrics customer-churn --start-date 2024-01-01 --end-date 2024-12-31 --interval month
214
+ ```
215
+
216
+ ### View recent activities
217
+
218
+ ```bash
219
+ chartmogul activities list --type churn --start-date 2024-12-01
220
+ ```
221
+
222
+ ## Error Handling
223
+
224
+ Errors are returned as JSON:
225
+
226
+ ```json
227
+ {
228
+ "error": {
229
+ "name": "unauthorized",
230
+ "detail": "Invalid API key",
231
+ "statusCode": 401
232
+ }
233
+ }
234
+ ```
235
+
236
+ ## License
237
+
238
+ MIT
package/dist/cli.js ADDED
@@ -0,0 +1,615 @@
1
+ #!/usr/bin/env bun
2
+
3
+ // src/cli.ts
4
+ import { Command as Command9 } from "commander";
5
+
6
+ // src/lib/output.ts
7
+ var globalOutputOptions = {};
8
+ function setOutputOptions(options) {
9
+ globalOutputOptions = options;
10
+ }
11
+ function outputJson(data, options = {}) {
12
+ const mergedOptions = { ...globalOutputOptions, ...options };
13
+ const jsonString = mergedOptions.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);
14
+ console.log(jsonString);
15
+ }
16
+
17
+ // src/commands/auth.ts
18
+ import { Command } from "commander";
19
+
20
+ // src/lib/auth.ts
21
+ import { Entry } from "@napi-rs/keyring";
22
+
23
+ // src/lib/config.ts
24
+ import Conf from "conf";
25
+ var store = new Conf({
26
+ projectName: "chartmogul-cli"
27
+ });
28
+ var config = {
29
+ getDefaultDataSource() {
30
+ return store.get("defaultDataSource") || process.env.CHARTMOGUL_DATA_SOURCE;
31
+ },
32
+ setDefaultDataSource(dataSourceUuid) {
33
+ store.set("defaultDataSource", dataSourceUuid);
34
+ },
35
+ clearDefaultDataSource() {
36
+ store.delete("defaultDataSource");
37
+ },
38
+ clear() {
39
+ store.clear();
40
+ }
41
+ };
42
+
43
+ // src/lib/auth.ts
44
+ var SERVICE_NAME = "chartmogul-cli";
45
+ var API_KEY_ACCOUNT = "api-key";
46
+ var KEYRING_UNAVAILABLE_ERROR = "Keychain storage unavailable. Cannot store credentials securely.\nOn Linux, install libsecret: sudo apt-get install libsecret-1-dev\nThen reinstall: bun install -g @stephendolan/chartmogul-cli\nAlternatively, use CHARTMOGUL_API_KEY environment variable.";
47
+ function getKeyring(account) {
48
+ try {
49
+ return new Entry(SERVICE_NAME, account);
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+ function getPassword(account) {
55
+ const entry = getKeyring(account);
56
+ if (entry) {
57
+ try {
58
+ return entry.getPassword();
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ function setPassword(account, value) {
66
+ const entry = getKeyring(account);
67
+ if (!entry) {
68
+ throw new Error(KEYRING_UNAVAILABLE_ERROR);
69
+ }
70
+ entry.setPassword(value);
71
+ }
72
+ function deletePassword(account) {
73
+ const entry = getKeyring(account);
74
+ if (entry) {
75
+ return entry.deletePassword();
76
+ }
77
+ return false;
78
+ }
79
+ var AuthManager = class {
80
+ getApiKey() {
81
+ return getPassword(API_KEY_ACCOUNT) || process.env.CHARTMOGUL_API_KEY || null;
82
+ }
83
+ setApiKey(apiKey) {
84
+ setPassword(API_KEY_ACCOUNT, apiKey);
85
+ }
86
+ isAuthenticated() {
87
+ return this.getApiKey() !== null;
88
+ }
89
+ logout() {
90
+ deletePassword(API_KEY_ACCOUNT);
91
+ config.clearDefaultDataSource();
92
+ }
93
+ };
94
+ var auth = new AuthManager();
95
+
96
+ // src/lib/errors.ts
97
+ var ChartMogulCliError = class extends Error {
98
+ constructor(message, statusCode) {
99
+ super(message);
100
+ this.statusCode = statusCode;
101
+ this.name = "ChartMogulCliError";
102
+ }
103
+ };
104
+ var ChartMogulApiError = class extends Error {
105
+ constructor(message, apiError, statusCode) {
106
+ super(message);
107
+ this.apiError = apiError;
108
+ this.statusCode = statusCode;
109
+ this.name = "ChartMogulApiError";
110
+ }
111
+ };
112
+ function sanitizeErrorMessage(message) {
113
+ const sensitivePatterns = [
114
+ /Bearer\s+[\w\-._~+/]+=*/gi,
115
+ /token[=:]\s*[\w\-._~+/]+=*/gi,
116
+ /api[_-]?key[=:]\s*[\w\-._~+/]+=*/gi,
117
+ /authorization:\s*basic\s+[\w\-._~+/]+=*/gi
118
+ ];
119
+ let sanitized = message;
120
+ for (const pattern of sensitivePatterns) {
121
+ sanitized = sanitized.replace(pattern, "[REDACTED]");
122
+ }
123
+ return sanitized.length > 500 ? sanitized.substring(0, 500) + "..." : sanitized;
124
+ }
125
+ function isErrorObject(value) {
126
+ return typeof value === "object" && value !== null;
127
+ }
128
+ function sanitizeApiError(error) {
129
+ if (!isErrorObject(error)) {
130
+ return {
131
+ name: "api_error",
132
+ detail: "An error occurred"
133
+ };
134
+ }
135
+ const apiError = error;
136
+ let detail = "An error occurred";
137
+ if (apiError.message) {
138
+ detail = apiError.message;
139
+ } else if (apiError.errors?.length) {
140
+ detail = apiError.errors.map((e) => e.message || e.key).filter(Boolean).join("; ");
141
+ }
142
+ return {
143
+ name: apiError.error || "api_error",
144
+ detail: sanitizeErrorMessage(detail)
145
+ };
146
+ }
147
+ function formatErrorResponse(name, detail, statusCode) {
148
+ const hint = name === "too_many_requests" ? "ChartMogul API rate limit exceeded. Wait a moment and retry." : void 0;
149
+ const response = {
150
+ error: { name, detail, statusCode }
151
+ };
152
+ if (hint) {
153
+ response.hint = hint;
154
+ }
155
+ outputJson(response);
156
+ process.exit(1);
157
+ }
158
+ function handleChartMogulError(error) {
159
+ if (error instanceof ChartMogulCliError) {
160
+ const sanitized = sanitizeErrorMessage(error.message);
161
+ formatErrorResponse("cli_error", sanitized, error.statusCode || 1);
162
+ }
163
+ if (error instanceof ChartMogulApiError) {
164
+ const cmError = sanitizeApiError(error.apiError);
165
+ formatErrorResponse(cmError.name, cmError.detail, error.statusCode);
166
+ }
167
+ if (error instanceof Error) {
168
+ const sanitized = sanitizeErrorMessage(error.message);
169
+ formatErrorResponse("unknown_error", sanitized, 1);
170
+ }
171
+ formatErrorResponse("unknown_error", "An unexpected error occurred", 1);
172
+ }
173
+
174
+ // src/lib/api-client.ts
175
+ var API_BASE = "https://api.chartmogul.com/v1";
176
+ var ChartMogulClient = class {
177
+ getAuthHeader() {
178
+ const apiKey = auth.getApiKey();
179
+ if (!apiKey) {
180
+ throw new ChartMogulCliError("Not authenticated. Please run: chartmogul auth login", 401);
181
+ }
182
+ return `Basic ${Buffer.from(`${apiKey}:`).toString("base64")}`;
183
+ }
184
+ async request(method, path, options = {}) {
185
+ const { params, body } = options;
186
+ const url = new URL(`${API_BASE}${path}`);
187
+ if (params) {
188
+ Object.entries(params).forEach(([key, value]) => {
189
+ if (value !== void 0) {
190
+ url.searchParams.set(key, String(value));
191
+ }
192
+ });
193
+ }
194
+ const authHeader = this.getAuthHeader();
195
+ const fetchOptions = {
196
+ method,
197
+ headers: {
198
+ Authorization: authHeader,
199
+ "Content-Type": "application/json"
200
+ }
201
+ };
202
+ if (body) {
203
+ fetchOptions.body = JSON.stringify(body);
204
+ }
205
+ let response;
206
+ try {
207
+ response = await fetch(url.toString(), fetchOptions);
208
+ } catch (error) {
209
+ const message = error instanceof Error ? error.message : "Unknown network error";
210
+ throw new ChartMogulCliError(`Network request failed: ${message}`, 0);
211
+ }
212
+ if (response.status === 429) {
213
+ const retryAfter = response.headers.get("Retry-After") || "60";
214
+ throw new ChartMogulCliError(
215
+ `Rate limited by ChartMogul API. Retry after ${retryAfter} seconds.`,
216
+ 429
217
+ );
218
+ }
219
+ if (response.status === 204) {
220
+ return {};
221
+ }
222
+ if (!response.ok) {
223
+ const error = await response.json().catch(() => ({}));
224
+ throw new ChartMogulApiError("API request failed", error, response.status);
225
+ }
226
+ return response.json();
227
+ }
228
+ async getAccount() {
229
+ return this.request("GET", "/account");
230
+ }
231
+ async ping() {
232
+ return this.request("GET", "/ping");
233
+ }
234
+ async listDataSources() {
235
+ return this.request("GET", "/data_sources");
236
+ }
237
+ async getDataSource(uuid) {
238
+ return this.request("GET", `/data_sources/${uuid}`);
239
+ }
240
+ async listCustomers(params = {}) {
241
+ return this.request("GET", "/customers", { params });
242
+ }
243
+ async getCustomer(uuid) {
244
+ return this.request("GET", `/customers/${uuid}`);
245
+ }
246
+ async searchCustomers(email) {
247
+ return this.request("GET", "/customers/search", {
248
+ params: { email }
249
+ });
250
+ }
251
+ async getCustomerActivities(uuid, params = {}) {
252
+ return this.request("GET", `/customers/${uuid}/activities`, {
253
+ params
254
+ });
255
+ }
256
+ async getCustomerSubscriptions(uuid) {
257
+ return this.request("GET", `/customers/${uuid}/subscriptions`);
258
+ }
259
+ async listPlans(params = {}) {
260
+ return this.request(
261
+ "GET",
262
+ "/plans",
263
+ { params }
264
+ );
265
+ }
266
+ async getPlan(uuid) {
267
+ return this.request("GET", `/plans/${uuid}`);
268
+ }
269
+ async listInvoices(params = {}) {
270
+ return this.request("GET", "/invoices", { params });
271
+ }
272
+ async getInvoice(uuid) {
273
+ return this.request("GET", `/invoices/${uuid}`);
274
+ }
275
+ async getMrr(params) {
276
+ return this.request("GET", "/metrics/mrr", { params });
277
+ }
278
+ async getArr(params) {
279
+ return this.request("GET", "/metrics/arr", { params });
280
+ }
281
+ async getArpa(params) {
282
+ return this.request("GET", "/metrics/arpa", { params });
283
+ }
284
+ async getAsp(params) {
285
+ return this.request("GET", "/metrics/asp", { params });
286
+ }
287
+ async getCustomerCount(params) {
288
+ return this.request("GET", "/metrics/customer-count", { params });
289
+ }
290
+ async getCustomerChurnRate(params) {
291
+ return this.request("GET", "/metrics/customer-churn-rate", { params });
292
+ }
293
+ async getMrrChurnRate(params) {
294
+ return this.request("GET", "/metrics/mrr-churn-rate", { params });
295
+ }
296
+ async getLtv(params) {
297
+ return this.request("GET", "/metrics/ltv", { params });
298
+ }
299
+ async getAllMetrics(params) {
300
+ return this.request("GET", "/metrics/all", { params });
301
+ }
302
+ async listActivities(params = {}) {
303
+ return this.request("GET", "/activities", { params });
304
+ }
305
+ };
306
+ var client = new ChartMogulClient();
307
+
308
+ // src/lib/command-utils.ts
309
+ function withErrorHandling(fn) {
310
+ return async (...args) => {
311
+ try {
312
+ await fn(...args);
313
+ } catch (error) {
314
+ handleChartMogulError(error);
315
+ }
316
+ };
317
+ }
318
+
319
+ // src/commands/auth.ts
320
+ function createAuthCommand() {
321
+ const cmd = new Command("auth").description("Authentication operations");
322
+ cmd.command("login").description("Configure ChartMogul API credentials").requiredOption("--api-key <key>", "ChartMogul API Key").action(
323
+ withErrorHandling(async (options) => {
324
+ auth.setApiKey(options.apiKey);
325
+ await client.ping();
326
+ outputJson({ message: "Successfully authenticated with ChartMogul" });
327
+ })
328
+ );
329
+ cmd.command("logout").description("Remove stored credentials").action(
330
+ withErrorHandling(async () => {
331
+ auth.logout();
332
+ outputJson({ message: "Logged out successfully" });
333
+ })
334
+ );
335
+ cmd.command("status").description("Check authentication status").action(
336
+ withErrorHandling(async () => {
337
+ outputJson({ authenticated: auth.isAuthenticated() });
338
+ })
339
+ );
340
+ return cmd;
341
+ }
342
+
343
+ // src/commands/account.ts
344
+ import { Command as Command2 } from "commander";
345
+ function createAccountCommand() {
346
+ const cmd = new Command2("account").description("Account operations");
347
+ cmd.command("view").description("View account details").action(
348
+ withErrorHandling(async () => {
349
+ const account = await client.getAccount();
350
+ outputJson(account);
351
+ })
352
+ );
353
+ return cmd;
354
+ }
355
+
356
+ // src/commands/data-sources.ts
357
+ import { Command as Command3 } from "commander";
358
+ function createDataSourcesCommand() {
359
+ const cmd = new Command3("data-sources").description("Data source operations");
360
+ cmd.command("list").description("List all data sources").action(
361
+ withErrorHandling(async () => {
362
+ const result = await client.listDataSources();
363
+ outputJson(result.data_sources);
364
+ })
365
+ );
366
+ cmd.command("view").description("View a data source").argument("<uuid>", "Data source UUID").action(
367
+ withErrorHandling(async (uuid) => {
368
+ const dataSource = await client.getDataSource(uuid);
369
+ outputJson(dataSource);
370
+ })
371
+ );
372
+ cmd.command("set-default").description("Set default data source for filtering").argument("<uuid>", "Data source UUID").action(
373
+ withErrorHandling(async (uuid) => {
374
+ config.setDefaultDataSource(uuid);
375
+ outputJson({ message: `Default data source set to ${uuid}` });
376
+ })
377
+ );
378
+ cmd.command("get-default").description("Get default data source").action(
379
+ withErrorHandling(async () => {
380
+ const defaultDs = config.getDefaultDataSource();
381
+ outputJson({ default_data_source: defaultDs || null });
382
+ })
383
+ );
384
+ return cmd;
385
+ }
386
+
387
+ // src/commands/customers.ts
388
+ import { Command as Command4 } from "commander";
389
+ function createCustomersCommand() {
390
+ const cmd = new Command4("customers").description("Customer queries");
391
+ cmd.command("list").description("List customers").option("--data-source <uuid>", "Filter by data source UUID").option("--status <status>", "Filter by status (Lead, Active, Cancelled)").option("--external-id <id>", "Filter by external ID").option("--page <number>", "Page number").option("--per-page <number>", "Results per page (max 200)").action(
392
+ withErrorHandling(
393
+ async (options) => {
394
+ const result = await client.listCustomers({
395
+ data_source_uuid: options.dataSource || config.getDefaultDataSource(),
396
+ status: options.status,
397
+ external_id: options.externalId,
398
+ page: options.page ? parseInt(options.page, 10) : void 0,
399
+ per_page: options.perPage ? parseInt(options.perPage, 10) : void 0
400
+ });
401
+ outputJson(result);
402
+ }
403
+ )
404
+ );
405
+ cmd.command("view").description("View a customer").argument("<uuid>", "Customer UUID").action(
406
+ withErrorHandling(async (uuid) => {
407
+ const customer = await client.getCustomer(uuid);
408
+ outputJson(customer);
409
+ })
410
+ );
411
+ cmd.command("search").description("Search customers by email").requiredOption("--email <email>", "Email address to search").action(
412
+ withErrorHandling(async (options) => {
413
+ const result = await client.searchCustomers(options.email);
414
+ outputJson(result.entries);
415
+ })
416
+ );
417
+ cmd.command("activities").description("List customer activities").argument("<uuid>", "Customer UUID").option("--page <number>", "Page number").option("--per-page <number>", "Results per page").action(
418
+ withErrorHandling(async (uuid, options) => {
419
+ const result = await client.getCustomerActivities(uuid, {
420
+ page: options.page ? parseInt(options.page, 10) : void 0,
421
+ per_page: options.perPage ? parseInt(options.perPage, 10) : void 0
422
+ });
423
+ outputJson(result);
424
+ })
425
+ );
426
+ cmd.command("subscriptions").description("List customer subscriptions").argument("<uuid>", "Customer UUID").action(
427
+ withErrorHandling(async (uuid) => {
428
+ const result = await client.getCustomerSubscriptions(uuid);
429
+ outputJson(result.entries);
430
+ })
431
+ );
432
+ return cmd;
433
+ }
434
+
435
+ // src/commands/plans.ts
436
+ import { Command as Command5 } from "commander";
437
+ function createPlansCommand() {
438
+ const cmd = new Command5("plans").description("Plan queries");
439
+ cmd.command("list").description("List plans").option("--data-source <uuid>", "Filter by data source UUID").option("--page <number>", "Page number").option("--per-page <number>", "Results per page").action(
440
+ withErrorHandling(
441
+ async (options) => {
442
+ const result = await client.listPlans({
443
+ data_source_uuid: options.dataSource || config.getDefaultDataSource(),
444
+ page: options.page ? parseInt(options.page, 10) : void 0,
445
+ per_page: options.perPage ? parseInt(options.perPage, 10) : void 0
446
+ });
447
+ outputJson(result);
448
+ }
449
+ )
450
+ );
451
+ cmd.command("view").description("View a plan").argument("<uuid>", "Plan UUID").action(
452
+ withErrorHandling(async (uuid) => {
453
+ const plan = await client.getPlan(uuid);
454
+ outputJson(plan);
455
+ })
456
+ );
457
+ return cmd;
458
+ }
459
+
460
+ // src/commands/invoices.ts
461
+ import { Command as Command6 } from "commander";
462
+ function createInvoicesCommand() {
463
+ const cmd = new Command6("invoices").description("Invoice queries");
464
+ cmd.command("list").description("List invoices").option("--customer <uuid>", "Filter by customer UUID").option("--data-source <uuid>", "Filter by data source UUID").option("--external-id <id>", "Filter by external ID").option("--page <number>", "Page number").option("--per-page <number>", "Results per page").action(
465
+ withErrorHandling(
466
+ async (options) => {
467
+ const result = await client.listInvoices({
468
+ customer_uuid: options.customer,
469
+ data_source_uuid: options.dataSource || config.getDefaultDataSource(),
470
+ external_id: options.externalId,
471
+ page: options.page ? parseInt(options.page, 10) : void 0,
472
+ per_page: options.perPage ? parseInt(options.perPage, 10) : void 0
473
+ });
474
+ outputJson(result);
475
+ }
476
+ )
477
+ );
478
+ cmd.command("view").description("View an invoice").argument("<uuid>", "Invoice UUID").action(
479
+ withErrorHandling(async (uuid) => {
480
+ const invoice = await client.getInvoice(uuid);
481
+ outputJson(invoice);
482
+ })
483
+ );
484
+ return cmd;
485
+ }
486
+
487
+ // src/commands/metrics.ts
488
+ import { Command as Command7 } from "commander";
489
+
490
+ // src/lib/dates.ts
491
+ import dayjs from "dayjs";
492
+ function parseDate(input) {
493
+ const d = dayjs(input);
494
+ if (!d.isValid()) {
495
+ throw new ChartMogulCliError(`Invalid date: ${input}`, 400);
496
+ }
497
+ return d.format("YYYY-MM-DD");
498
+ }
499
+ function getDefaultDateRange() {
500
+ return {
501
+ startDate: dayjs().subtract(30, "day").format("YYYY-MM-DD"),
502
+ endDate: dayjs().format("YYYY-MM-DD")
503
+ };
504
+ }
505
+
506
+ // src/commands/metrics.ts
507
+ function buildMetricParams(options) {
508
+ const defaults = getDefaultDateRange();
509
+ return {
510
+ "start-date": options.startDate ? parseDate(options.startDate) : defaults.startDate,
511
+ "end-date": options.endDate ? parseDate(options.endDate) : defaults.endDate,
512
+ interval: options.interval
513
+ };
514
+ }
515
+ function createMetricsCommand() {
516
+ const cmd = new Command7("metrics").description("Metrics and analytics");
517
+ cmd.command("all").description("Get all key metrics").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
518
+ withErrorHandling(async (options) => {
519
+ const result = await client.getAllMetrics(buildMetricParams(options));
520
+ outputJson(result);
521
+ })
522
+ );
523
+ cmd.command("mrr").description("Get Monthly Recurring Revenue").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
524
+ withErrorHandling(async (options) => {
525
+ const result = await client.getMrr(buildMetricParams(options));
526
+ outputJson(result);
527
+ })
528
+ );
529
+ cmd.command("arr").description("Get Annual Recurring Revenue").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
530
+ withErrorHandling(async (options) => {
531
+ const result = await client.getArr(buildMetricParams(options));
532
+ outputJson(result);
533
+ })
534
+ );
535
+ cmd.command("arpa").description("Get Average Revenue Per Account").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
536
+ withErrorHandling(async (options) => {
537
+ const result = await client.getArpa(buildMetricParams(options));
538
+ outputJson(result);
539
+ })
540
+ );
541
+ cmd.command("asp").description("Get Average Sale Price").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
542
+ withErrorHandling(async (options) => {
543
+ const result = await client.getAsp(buildMetricParams(options));
544
+ outputJson(result);
545
+ })
546
+ );
547
+ cmd.command("customer-count").description("Get customer count over time").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
548
+ withErrorHandling(async (options) => {
549
+ const result = await client.getCustomerCount(buildMetricParams(options));
550
+ outputJson(result);
551
+ })
552
+ );
553
+ cmd.command("customer-churn").description("Get customer churn rate").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
554
+ withErrorHandling(async (options) => {
555
+ const result = await client.getCustomerChurnRate(buildMetricParams(options));
556
+ outputJson(result);
557
+ })
558
+ );
559
+ cmd.command("mrr-churn").description("Get MRR churn rate").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
560
+ withErrorHandling(async (options) => {
561
+ const result = await client.getMrrChurnRate(buildMetricParams(options));
562
+ outputJson(result);
563
+ })
564
+ );
565
+ cmd.command("ltv").description("Get Customer Lifetime Value").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--interval <interval>", "Interval (day, week, month, quarter)").action(
566
+ withErrorHandling(async (options) => {
567
+ const result = await client.getLtv(buildMetricParams(options));
568
+ outputJson(result);
569
+ })
570
+ );
571
+ return cmd;
572
+ }
573
+
574
+ // src/commands/activities.ts
575
+ import { Command as Command8 } from "commander";
576
+ function createActivitiesCommand() {
577
+ const cmd = new Command8("activities").description("Activity operations");
578
+ cmd.command("list").description("List activities").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").option("--type <type>", "Activity type (new_biz, expansion, contraction, churn, reactivation)").option("--page <number>", "Page number").option("--per-page <number>", "Results per page").action(
579
+ withErrorHandling(
580
+ async (options) => {
581
+ const result = await client.listActivities({
582
+ "start-date": options.startDate,
583
+ "end-date": options.endDate,
584
+ type: options.type,
585
+ page: options.page ? parseInt(options.page, 10) : void 0,
586
+ per_page: options.perPage ? parseInt(options.perPage, 10) : void 0
587
+ });
588
+ outputJson(result);
589
+ }
590
+ )
591
+ );
592
+ return cmd;
593
+ }
594
+
595
+ // src/cli.ts
596
+ var version = true ? "1.0.0" : "0.0.0-dev";
597
+ var program = new Command9();
598
+ program.name("chartmogul").description("A command-line interface for ChartMogul analytics").version(version).option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
599
+ const options = thisCommand.opts();
600
+ setOutputOptions({
601
+ compact: options.compact
602
+ });
603
+ });
604
+ program.addCommand(createAuthCommand());
605
+ program.addCommand(createAccountCommand());
606
+ program.addCommand(createDataSourcesCommand());
607
+ program.addCommand(createCustomersCommand());
608
+ program.addCommand(createPlansCommand());
609
+ program.addCommand(createInvoicesCommand());
610
+ program.addCommand(createMetricsCommand());
611
+ program.addCommand(createActivitiesCommand());
612
+ program.parseAsync().catch(() => {
613
+ process.exit(1);
614
+ });
615
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/lib/output.ts","../src/commands/auth.ts","../src/lib/auth.ts","../src/lib/config.ts","../src/lib/errors.ts","../src/lib/api-client.ts","../src/lib/command-utils.ts","../src/commands/account.ts","../src/commands/data-sources.ts","../src/commands/customers.ts","../src/commands/plans.ts","../src/commands/invoices.ts","../src/commands/metrics.ts","../src/lib/dates.ts","../src/commands/activities.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { Command } from 'commander';\nimport { setOutputOptions } from './lib/output.js';\nimport { createAuthCommand } from './commands/auth.js';\nimport { createAccountCommand } from './commands/account.js';\nimport { createDataSourcesCommand } from './commands/data-sources.js';\nimport { createCustomersCommand } from './commands/customers.js';\nimport { createPlansCommand } from './commands/plans.js';\nimport { createInvoicesCommand } from './commands/invoices.js';\nimport { createMetricsCommand } from './commands/metrics.js';\nimport { createActivitiesCommand } from './commands/activities.js';\n\ndeclare const __VERSION__: string | undefined;\n\nconst version = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev';\n\nconst program = new Command();\n\nprogram\n .name('chartmogul')\n .description('A command-line interface for ChartMogul analytics')\n .version(version)\n .option('-c, --compact', 'Minified JSON output (single line)')\n .hook('preAction', (thisCommand) => {\n const options = thisCommand.opts();\n setOutputOptions({\n compact: options.compact,\n });\n });\n\nprogram.addCommand(createAuthCommand());\nprogram.addCommand(createAccountCommand());\nprogram.addCommand(createDataSourcesCommand());\nprogram.addCommand(createCustomersCommand());\nprogram.addCommand(createPlansCommand());\nprogram.addCommand(createInvoicesCommand());\nprogram.addCommand(createMetricsCommand());\nprogram.addCommand(createActivitiesCommand());\n\nprogram.parseAsync().catch(() => {\n process.exit(1);\n});\n","import type { OutputOptions } from '../types/index.js';\n\nlet globalOutputOptions: OutputOptions = {};\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOutputOptions = options;\n}\n\nexport function outputJson(data: unknown, options: OutputOptions = {}): void {\n const mergedOptions = { ...globalOutputOptions, ...options };\n\n const jsonString = mergedOptions.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);\n\n console.log(jsonString);\n}\n","import { Command } from 'commander';\nimport { auth } from '../lib/auth.js';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createAuthCommand(): Command {\n const cmd = new Command('auth').description('Authentication operations');\n\n cmd\n .command('login')\n .description('Configure ChartMogul API credentials')\n .requiredOption('--api-key <key>', 'ChartMogul API Key')\n .action(\n withErrorHandling(async (options: { apiKey: string }) => {\n auth.setApiKey(options.apiKey);\n await client.ping();\n outputJson({ message: 'Successfully authenticated with ChartMogul' });\n })\n );\n\n cmd\n .command('logout')\n .description('Remove stored credentials')\n .action(\n withErrorHandling(async () => {\n auth.logout();\n outputJson({ message: 'Logged out successfully' });\n })\n );\n\n cmd\n .command('status')\n .description('Check authentication status')\n .action(\n withErrorHandling(async () => {\n outputJson({ authenticated: auth.isAuthenticated() });\n })\n );\n\n return cmd;\n}\n","import { Entry } from '@napi-rs/keyring';\nimport { config } from './config.js';\n\nconst SERVICE_NAME = 'chartmogul-cli';\nconst API_KEY_ACCOUNT = 'api-key';\n\nconst KEYRING_UNAVAILABLE_ERROR =\n 'Keychain storage unavailable. Cannot store credentials securely.\\n' +\n 'On Linux, install libsecret: sudo apt-get install libsecret-1-dev\\n' +\n 'Then reinstall: bun install -g @stephendolan/chartmogul-cli\\n' +\n 'Alternatively, use CHARTMOGUL_API_KEY environment variable.';\n\nfunction getKeyring(account: string): Entry | null {\n try {\n return new Entry(SERVICE_NAME, account);\n } catch {\n return null;\n }\n}\n\nfunction getPassword(account: string): string | null {\n const entry = getKeyring(account);\n if (entry) {\n try {\n return entry.getPassword();\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction setPassword(account: string, value: string): void {\n const entry = getKeyring(account);\n if (!entry) {\n throw new Error(KEYRING_UNAVAILABLE_ERROR);\n }\n entry.setPassword(value);\n}\n\nfunction deletePassword(account: string): boolean {\n const entry = getKeyring(account);\n if (entry) {\n return entry.deletePassword();\n }\n return false;\n}\n\nexport class AuthManager {\n getApiKey(): string | null {\n return getPassword(API_KEY_ACCOUNT) || process.env.CHARTMOGUL_API_KEY || null;\n }\n\n setApiKey(apiKey: string): void {\n setPassword(API_KEY_ACCOUNT, apiKey);\n }\n\n isAuthenticated(): boolean {\n return this.getApiKey() !== null;\n }\n\n logout(): void {\n deletePassword(API_KEY_ACCOUNT);\n config.clearDefaultDataSource();\n }\n}\n\nexport const auth = new AuthManager();\n","import Conf from 'conf';\n\ninterface ConfigSchema {\n defaultDataSource?: string;\n}\n\nconst store = new Conf<ConfigSchema>({\n projectName: 'chartmogul-cli',\n});\n\nexport const config = {\n getDefaultDataSource(): string | undefined {\n return store.get('defaultDataSource') || process.env.CHARTMOGUL_DATA_SOURCE;\n },\n\n setDefaultDataSource(dataSourceUuid: string): void {\n store.set('defaultDataSource', dataSourceUuid);\n },\n\n clearDefaultDataSource(): void {\n store.delete('defaultDataSource');\n },\n\n clear(): void {\n store.clear();\n },\n};\n","import type { ChartMogulError } from '../types/index.js';\nimport { outputJson } from './output.js';\n\nexport class ChartMogulCliError extends Error {\n constructor(\n message: string,\n public statusCode?: number\n ) {\n super(message);\n this.name = 'ChartMogulCliError';\n }\n}\n\nexport class ChartMogulApiError extends Error {\n constructor(\n message: string,\n public apiError: unknown,\n public statusCode: number\n ) {\n super(message);\n this.name = 'ChartMogulApiError';\n }\n}\n\nexport function sanitizeErrorMessage(message: string): string {\n const sensitivePatterns = [\n /Bearer\\s+[\\w\\-._~+/]+=*/gi,\n /token[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /api[_-]?key[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /authorization:\\s*basic\\s+[\\w\\-._~+/]+=*/gi,\n ];\n\n let sanitized = message;\n for (const pattern of sensitivePatterns) {\n sanitized = sanitized.replace(pattern, '[REDACTED]');\n }\n\n return sanitized.length > 500 ? sanitized.substring(0, 500) + '...' : sanitized;\n}\n\ninterface ApiErrorResponse {\n error?: string;\n message?: string;\n errors?: Array<{\n key?: string;\n message?: string;\n }>;\n}\n\nfunction isErrorObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function sanitizeApiError(error: unknown): ChartMogulError {\n if (!isErrorObject(error)) {\n return {\n name: 'api_error',\n detail: 'An error occurred',\n };\n }\n\n const apiError = error as ApiErrorResponse;\n\n let detail = 'An error occurred';\n if (apiError.message) {\n detail = apiError.message;\n } else if (apiError.errors?.length) {\n detail = apiError.errors\n .map((e) => e.message || e.key)\n .filter(Boolean)\n .join('; ');\n }\n\n return {\n name: apiError.error || 'api_error',\n detail: sanitizeErrorMessage(detail),\n };\n}\n\nfunction formatErrorResponse(name: string, detail: string, statusCode: number): never {\n const hint =\n name === 'too_many_requests'\n ? 'ChartMogul API rate limit exceeded. Wait a moment and retry.'\n : undefined;\n\n const response: { error: { name: string; detail: string; statusCode: number }; hint?: string } = {\n error: { name, detail, statusCode },\n };\n\n if (hint) {\n response.hint = hint;\n }\n\n outputJson(response);\n process.exit(1);\n}\n\nexport function handleChartMogulError(error: unknown): never {\n if (error instanceof ChartMogulCliError) {\n const sanitized = sanitizeErrorMessage(error.message);\n formatErrorResponse('cli_error', sanitized, error.statusCode || 1);\n }\n\n if (error instanceof ChartMogulApiError) {\n const cmError = sanitizeApiError(error.apiError);\n formatErrorResponse(cmError.name, cmError.detail, error.statusCode);\n }\n\n if (error instanceof Error) {\n const sanitized = sanitizeErrorMessage(error.message);\n formatErrorResponse('unknown_error', sanitized, 1);\n }\n\n formatErrorResponse('unknown_error', 'An unexpected error occurred', 1);\n}\n","import { auth } from './auth.js';\nimport { ChartMogulCliError, ChartMogulApiError } from './errors.js';\nimport type {\n Account,\n DataSource,\n Customer,\n Plan,\n Subscription,\n Invoice,\n MetricsResponse,\n Activity,\n CustomerListResponse,\n PaginatedResponse,\n} from '../types/index.js';\n\nconst API_BASE = 'https://api.chartmogul.com/v1';\n\nexport class ChartMogulClient {\n private getAuthHeader(): string {\n const apiKey = auth.getApiKey();\n if (!apiKey) {\n throw new ChartMogulCliError('Not authenticated. Please run: chartmogul auth login', 401);\n }\n return `Basic ${Buffer.from(`${apiKey}:`).toString('base64')}`;\n }\n\n private async request<T>(\n method: string,\n path: string,\n options: {\n params?: Record<string, string | number | boolean | undefined>;\n body?: unknown;\n } = {}\n ): Promise<T> {\n const { params, body } = options;\n\n const url = new URL(`${API_BASE}${path}`);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n\n const authHeader = this.getAuthHeader();\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n };\n if (body) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n let response: Response;\n try {\n response = await fetch(url.toString(), fetchOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown network error';\n throw new ChartMogulCliError(`Network request failed: ${message}`, 0);\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After') || '60';\n throw new ChartMogulCliError(\n `Rate limited by ChartMogul API. Retry after ${retryAfter} seconds.`,\n 429\n );\n }\n\n if (response.status === 204) {\n return {} as T;\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new ChartMogulApiError('API request failed', error, response.status);\n }\n\n return response.json() as Promise<T>;\n }\n\n async getAccount() {\n return this.request<Account>('GET', '/account');\n }\n\n async ping() {\n return this.request<{ data: string }>('GET', '/ping');\n }\n\n async listDataSources() {\n return this.request<{ data_sources: DataSource[] }>('GET', '/data_sources');\n }\n\n async getDataSource(uuid: string) {\n return this.request<DataSource>('GET', `/data_sources/${uuid}`);\n }\n\n async listCustomers(\n params: {\n data_source_uuid?: string;\n status?: string;\n system?: string;\n external_id?: string;\n page?: number;\n per_page?: number;\n } = {}\n ) {\n return this.request<CustomerListResponse>('GET', '/customers', { params });\n }\n\n async getCustomer(uuid: string) {\n return this.request<Customer>('GET', `/customers/${uuid}`);\n }\n\n async searchCustomers(email: string) {\n return this.request<{ entries: Customer[] }>('GET', '/customers/search', {\n params: { email },\n });\n }\n\n async getCustomerActivities(uuid: string, params: { page?: number; per_page?: number } = {}) {\n return this.request<PaginatedResponse<Activity>>('GET', `/customers/${uuid}/activities`, {\n params,\n });\n }\n\n async getCustomerSubscriptions(uuid: string) {\n return this.request<{ entries: Subscription[] }>('GET', `/customers/${uuid}/subscriptions`);\n }\n\n async listPlans(params: { data_source_uuid?: string; page?: number; per_page?: number } = {}) {\n return this.request<{ plans: Plan[]; has_more: boolean; per_page: number; page: number }>(\n 'GET',\n '/plans',\n { params }\n );\n }\n\n async getPlan(uuid: string) {\n return this.request<Plan>('GET', `/plans/${uuid}`);\n }\n\n async listInvoices(\n params: {\n customer_uuid?: string;\n data_source_uuid?: string;\n external_id?: string;\n page?: number;\n per_page?: number;\n } = {}\n ) {\n return this.request<{ invoices: Invoice[]; has_more: boolean }>('GET', '/invoices', { params });\n }\n\n async getInvoice(uuid: string) {\n return this.request<Invoice>('GET', `/invoices/${uuid}`);\n }\n\n async getMrr(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/mrr', { params });\n }\n\n async getArr(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/arr', { params });\n }\n\n async getArpa(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/arpa', { params });\n }\n\n async getAsp(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/asp', { params });\n }\n\n async getCustomerCount(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/customer-count', { params });\n }\n\n async getCustomerChurnRate(params: {\n 'start-date': string;\n 'end-date': string;\n interval?: string;\n }) {\n return this.request<MetricsResponse>('GET', '/metrics/customer-churn-rate', { params });\n }\n\n async getMrrChurnRate(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/mrr-churn-rate', { params });\n }\n\n async getLtv(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/ltv', { params });\n }\n\n async getAllMetrics(params: { 'start-date': string; 'end-date': string; interval?: string }) {\n return this.request<MetricsResponse>('GET', '/metrics/all', { params });\n }\n\n async listActivities(\n params: {\n 'start-date'?: string;\n 'end-date'?: string;\n type?: string;\n page?: number;\n per_page?: number;\n } = {}\n ) {\n return this.request<PaginatedResponse<Activity>>('GET', '/activities', { params });\n }\n}\n\nexport const client = new ChartMogulClient();\n","import { handleChartMogulError } from './errors.js';\n\nexport function withErrorHandling<T extends unknown[], R>(\n fn: (...args: T) => Promise<R>\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args);\n } catch (error) {\n handleChartMogulError(error);\n }\n };\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createAccountCommand(): Command {\n const cmd = new Command('account').description('Account operations');\n\n cmd\n .command('view')\n .description('View account details')\n .action(\n withErrorHandling(async () => {\n const account = await client.getAccount();\n outputJson(account);\n })\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createDataSourcesCommand(): Command {\n const cmd = new Command('data-sources').description('Data source operations');\n\n cmd\n .command('list')\n .description('List all data sources')\n .action(\n withErrorHandling(async () => {\n const result = await client.listDataSources();\n outputJson(result.data_sources);\n })\n );\n\n cmd\n .command('view')\n .description('View a data source')\n .argument('<uuid>', 'Data source UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n const dataSource = await client.getDataSource(uuid);\n outputJson(dataSource);\n })\n );\n\n cmd\n .command('set-default')\n .description('Set default data source for filtering')\n .argument('<uuid>', 'Data source UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n config.setDefaultDataSource(uuid);\n outputJson({ message: `Default data source set to ${uuid}` });\n })\n );\n\n cmd\n .command('get-default')\n .description('Get default data source')\n .action(\n withErrorHandling(async () => {\n const defaultDs = config.getDefaultDataSource();\n outputJson({ default_data_source: defaultDs || null });\n })\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createCustomersCommand(): Command {\n const cmd = new Command('customers').description('Customer queries');\n\n cmd\n .command('list')\n .description('List customers')\n .option('--data-source <uuid>', 'Filter by data source UUID')\n .option('--status <status>', 'Filter by status (Lead, Active, Cancelled)')\n .option('--external-id <id>', 'Filter by external ID')\n .option('--page <number>', 'Page number')\n .option('--per-page <number>', 'Results per page (max 200)')\n .action(\n withErrorHandling(\n async (options: {\n dataSource?: string;\n status?: string;\n externalId?: string;\n page?: string;\n perPage?: string;\n }) => {\n const result = await client.listCustomers({\n data_source_uuid: options.dataSource || config.getDefaultDataSource(),\n status: options.status,\n external_id: options.externalId,\n page: options.page ? parseInt(options.page, 10) : undefined,\n per_page: options.perPage ? parseInt(options.perPage, 10) : undefined,\n });\n outputJson(result);\n }\n )\n );\n\n cmd\n .command('view')\n .description('View a customer')\n .argument('<uuid>', 'Customer UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n const customer = await client.getCustomer(uuid);\n outputJson(customer);\n })\n );\n\n cmd\n .command('search')\n .description('Search customers by email')\n .requiredOption('--email <email>', 'Email address to search')\n .action(\n withErrorHandling(async (options: { email: string }) => {\n const result = await client.searchCustomers(options.email);\n outputJson(result.entries);\n })\n );\n\n cmd\n .command('activities')\n .description('List customer activities')\n .argument('<uuid>', 'Customer UUID')\n .option('--page <number>', 'Page number')\n .option('--per-page <number>', 'Results per page')\n .action(\n withErrorHandling(async (uuid: string, options: { page?: string; perPage?: string }) => {\n const result = await client.getCustomerActivities(uuid, {\n page: options.page ? parseInt(options.page, 10) : undefined,\n per_page: options.perPage ? parseInt(options.perPage, 10) : undefined,\n });\n outputJson(result);\n })\n );\n\n cmd\n .command('subscriptions')\n .description('List customer subscriptions')\n .argument('<uuid>', 'Customer UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n const result = await client.getCustomerSubscriptions(uuid);\n outputJson(result.entries);\n })\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createPlansCommand(): Command {\n const cmd = new Command('plans').description('Plan queries');\n\n cmd\n .command('list')\n .description('List plans')\n .option('--data-source <uuid>', 'Filter by data source UUID')\n .option('--page <number>', 'Page number')\n .option('--per-page <number>', 'Results per page')\n .action(\n withErrorHandling(\n async (options: { dataSource?: string; page?: string; perPage?: string }) => {\n const result = await client.listPlans({\n data_source_uuid: options.dataSource || config.getDefaultDataSource(),\n page: options.page ? parseInt(options.page, 10) : undefined,\n per_page: options.perPage ? parseInt(options.perPage, 10) : undefined,\n });\n outputJson(result);\n }\n )\n );\n\n cmd\n .command('view')\n .description('View a plan')\n .argument('<uuid>', 'Plan UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n const plan = await client.getPlan(uuid);\n outputJson(plan);\n })\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createInvoicesCommand(): Command {\n const cmd = new Command('invoices').description('Invoice queries');\n\n cmd\n .command('list')\n .description('List invoices')\n .option('--customer <uuid>', 'Filter by customer UUID')\n .option('--data-source <uuid>', 'Filter by data source UUID')\n .option('--external-id <id>', 'Filter by external ID')\n .option('--page <number>', 'Page number')\n .option('--per-page <number>', 'Results per page')\n .action(\n withErrorHandling(\n async (options: {\n customer?: string;\n dataSource?: string;\n externalId?: string;\n page?: string;\n perPage?: string;\n }) => {\n const result = await client.listInvoices({\n customer_uuid: options.customer,\n data_source_uuid: options.dataSource || config.getDefaultDataSource(),\n external_id: options.externalId,\n page: options.page ? parseInt(options.page, 10) : undefined,\n per_page: options.perPage ? parseInt(options.perPage, 10) : undefined,\n });\n outputJson(result);\n }\n )\n );\n\n cmd\n .command('view')\n .description('View an invoice')\n .argument('<uuid>', 'Invoice UUID')\n .action(\n withErrorHandling(async (uuid: string) => {\n const invoice = await client.getInvoice(uuid);\n outputJson(invoice);\n })\n );\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { getDefaultDateRange, parseDate } from '../lib/dates.js';\n\ninterface MetricOptions {\n startDate?: string;\n endDate?: string;\n interval?: string;\n}\n\nfunction buildMetricParams(options: MetricOptions) {\n const defaults = getDefaultDateRange();\n return {\n 'start-date': options.startDate ? parseDate(options.startDate) : defaults.startDate,\n 'end-date': options.endDate ? parseDate(options.endDate) : defaults.endDate,\n interval: options.interval,\n };\n}\n\nexport function createMetricsCommand(): Command {\n const cmd = new Command('metrics').description('Metrics and analytics');\n\n cmd\n .command('all')\n .description('Get all key metrics')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getAllMetrics(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('mrr')\n .description('Get Monthly Recurring Revenue')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getMrr(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('arr')\n .description('Get Annual Recurring Revenue')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getArr(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('arpa')\n .description('Get Average Revenue Per Account')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getArpa(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('asp')\n .description('Get Average Sale Price')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getAsp(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('customer-count')\n .description('Get customer count over time')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getCustomerCount(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('customer-churn')\n .description('Get customer churn rate')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getCustomerChurnRate(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('mrr-churn')\n .description('Get MRR churn rate')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getMrrChurnRate(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n cmd\n .command('ltv')\n .description('Get Customer Lifetime Value')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--interval <interval>', 'Interval (day, week, month, quarter)')\n .action(\n withErrorHandling(async (options: MetricOptions) => {\n const result = await client.getLtv(buildMetricParams(options));\n outputJson(result);\n })\n );\n\n return cmd;\n}\n","import dayjs from 'dayjs';\nimport { ChartMogulCliError } from './errors.js';\n\nexport function parseDate(input: string): string {\n const d = dayjs(input);\n if (!d.isValid()) {\n throw new ChartMogulCliError(`Invalid date: ${input}`, 400);\n }\n return d.format('YYYY-MM-DD');\n}\n\nexport function getDefaultDateRange(): { startDate: string; endDate: string } {\n return {\n startDate: dayjs().subtract(30, 'day').format('YYYY-MM-DD'),\n endDate: dayjs().format('YYYY-MM-DD'),\n };\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createActivitiesCommand(): Command {\n const cmd = new Command('activities').description('Activity operations');\n\n cmd\n .command('list')\n .description('List activities')\n .option('--start-date <date>', 'Start date (YYYY-MM-DD)')\n .option('--end-date <date>', 'End date (YYYY-MM-DD)')\n .option('--type <type>', 'Activity type (new_biz, expansion, contraction, churn, reactivation)')\n .option('--page <number>', 'Page number')\n .option('--per-page <number>', 'Results per page')\n .action(\n withErrorHandling(\n async (options: {\n startDate?: string;\n endDate?: string;\n type?: string;\n page?: string;\n perPage?: string;\n }) => {\n const result = await client.listActivities({\n 'start-date': options.startDate,\n 'end-date': options.endDate,\n type: options.type,\n page: options.page ? parseInt(options.page, 10) : undefined,\n per_page: options.perPage ? parseInt(options.perPage, 10) : undefined,\n });\n outputJson(result);\n }\n )\n );\n\n return cmd;\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@stephendolan/chartmogul-cli",
3
+ "version": "1.0.0",
4
+ "description": "A command-line interface for ChartMogul analytics",
5
+ "type": "module",
6
+ "main": "./dist/cli.js",
7
+ "bin": {
8
+ "chartmogul": "dist/cli.js"
9
+ },
10
+ "scripts": {
11
+ "dev": "bun run src/cli.ts",
12
+ "build": "bun run tsup",
13
+ "test": "bun run vitest",
14
+ "lint": "bun run oxlint src",
15
+ "format": "bun run biome format --write src",
16
+ "format:check": "bun run biome format src",
17
+ "typecheck": "bun run tsc --noEmit",
18
+ "link": "bun run build && bun link",
19
+ "start": "bun dist/cli.js",
20
+ "prepublishOnly": "bun run build"
21
+ },
22
+ "keywords": [
23
+ "chartmogul",
24
+ "analytics",
25
+ "cli",
26
+ "revenue",
27
+ "mrr",
28
+ "arr",
29
+ "churn",
30
+ "subscription",
31
+ "saas",
32
+ "command-line",
33
+ "llm",
34
+ "ai-friendly"
35
+ ],
36
+ "author": "Stephen Dolan <https://github.com/stephendolan>",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/stephendolan/chartmogul-cli.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/stephendolan/chartmogul-cli/issues"
44
+ },
45
+ "homepage": "https://github.com/stephendolan/chartmogul-cli#readme",
46
+ "files": [
47
+ "dist",
48
+ "README.md",
49
+ "LICENSE"
50
+ ],
51
+ "dependencies": {
52
+ "@napi-rs/keyring": "^1.2.0",
53
+ "commander": "^12.0.0",
54
+ "conf": "^12.0.0",
55
+ "dayjs": "^1.11.19"
56
+ },
57
+ "devDependencies": {
58
+ "@biomejs/biome": "^1.9.4",
59
+ "@types/node": "^20.0.0",
60
+ "oxlint": "^0.16.0",
61
+ "tsup": "^8.0.0",
62
+ "tsx": "^4.7.0",
63
+ "typescript": "^5.3.0",
64
+ "vitest": "^4.0.4"
65
+ },
66
+ "engines": {
67
+ "bun": ">=1.0.0"
68
+ }
69
+ }