affitor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +91 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +33 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/init.d.ts +3 -0
  7. package/dist/commands/init.d.ts.map +1 -0
  8. package/dist/commands/init.js +194 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/setup-stripe.d.ts +3 -0
  11. package/dist/commands/setup-stripe.d.ts.map +1 -0
  12. package/dist/commands/setup-stripe.js +188 -0
  13. package/dist/commands/setup-stripe.js.map +1 -0
  14. package/dist/commands/status.d.ts +3 -0
  15. package/dist/commands/status.d.ts.map +1 -0
  16. package/dist/commands/status.js +95 -0
  17. package/dist/commands/status.js.map +1 -0
  18. package/dist/commands/test.d.ts +3 -0
  19. package/dist/commands/test.d.ts.map +1 -0
  20. package/dist/commands/test.js +89 -0
  21. package/dist/commands/test.js.map +1 -0
  22. package/dist/lib/api-client.d.ts +37 -0
  23. package/dist/lib/api-client.d.ts.map +1 -0
  24. package/dist/lib/api-client.js +92 -0
  25. package/dist/lib/api-client.js.map +1 -0
  26. package/dist/lib/config.d.ts +12 -0
  27. package/dist/lib/config.d.ts.map +1 -0
  28. package/dist/lib/config.js +110 -0
  29. package/dist/lib/config.js.map +1 -0
  30. package/dist/lib/flags.d.ts +7 -0
  31. package/dist/lib/flags.d.ts.map +1 -0
  32. package/dist/lib/flags.js +20 -0
  33. package/dist/lib/flags.js.map +1 -0
  34. package/dist/lib/logger.d.ts +24 -0
  35. package/dist/lib/logger.d.ts.map +1 -0
  36. package/dist/lib/logger.js +78 -0
  37. package/dist/lib/logger.js.map +1 -0
  38. package/dist/lib/prompts.d.ts +9 -0
  39. package/dist/lib/prompts.d.ts.map +1 -0
  40. package/dist/lib/prompts.js +79 -0
  41. package/dist/lib/prompts.js.map +1 -0
  42. package/dist/lib/stripe-oauth.d.ts +15 -0
  43. package/dist/lib/stripe-oauth.d.ts.map +1 -0
  44. package/dist/lib/stripe-oauth.js +168 -0
  45. package/dist/lib/stripe-oauth.js.map +1 -0
  46. package/dist/types.d.ts +84 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +17 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # affitor
2
+
3
+ CLI-native affiliate tracking. Connect Stripe, track commissions, manage partners -- all from your terminal.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Create your affiliate program
9
+ npx affitor init
10
+
11
+ # Connect Stripe for automatic payment tracking
12
+ npx affitor setup stripe
13
+
14
+ # Check program health
15
+ npx affitor status
16
+
17
+ # Send test events
18
+ npx affitor test click
19
+ npx affitor test lead
20
+ npx affitor test sale
21
+ ```
22
+
23
+ ## Commands
24
+
25
+ | Command | Description |
26
+ |---|---|
27
+ | `affitor init` | Create a new affiliate program. Interactive prompts or `--no-interactive` with flags. |
28
+ | `affitor setup stripe` | Connect Stripe via OAuth. Auto-configures webhooks for payment tracking. |
29
+ | `affitor setup dns` | Set up DNS CNAME tracking (coming soon). |
30
+ | `affitor status` | Show program health: DNS, Stripe connection, recent events. |
31
+ | `affitor test [type]` | Send a test event (`click`, `lead`, or `sale`). |
32
+
33
+ ## Global Flags
34
+
35
+ | Flag | Description |
36
+ |---|---|
37
+ | `--json` | Output as JSON (for AI agents and scripts) |
38
+ | `--no-interactive` | Skip all prompts, fail on missing values |
39
+ | `--auto-confirm` | Auto-yes to confirmation prompts |
40
+ | `--quiet` | Suppress non-essential output |
41
+ | `--api-key <key>` | Override API key from config |
42
+ | `--api-url <url>` | Override API URL |
43
+ | `--verbose` | Debug output |
44
+
45
+ ## Non-Interactive Mode (for AI Agents)
46
+
47
+ ```bash
48
+ npx affitor init \
49
+ --name "My SaaS" \
50
+ --domain "example.com" \
51
+ --commission-type recurring_percent \
52
+ --commission-rate 20 \
53
+ --duration-months 12 \
54
+ --cookie-duration 90 \
55
+ --no-interactive \
56
+ --json
57
+ ```
58
+
59
+ ## What Gets Created
60
+
61
+ Running `npx affitor init` creates:
62
+
63
+ ```
64
+ .affitor/
65
+ config.json -- program configuration
66
+ .env.example -- environment variables template
67
+ skills.md -- AI agent instructions
68
+ ```
69
+
70
+ ## Stripe Auto-Connect
71
+
72
+ `npx affitor setup stripe` automates the entire Stripe integration:
73
+
74
+ 1. Opens Stripe Connect OAuth in your browser
75
+ 2. Creates webhook endpoint on your Stripe account
76
+ 3. Configures event listeners for:
77
+ - `customer.created` -- lead tracking
78
+ - `checkout.session.completed` -- sale tracking
79
+ - `invoice.paid` -- recurring commissions
80
+ - `invoice.payment_failed` -- failed payment alerts
81
+ - `charge.refunded` -- automatic commission clawback
82
+ - `customer.subscription.deleted` -- churn tracking
83
+
84
+ ## Requirements
85
+
86
+ - Node.js >= 18
87
+ - Stripe account (for `setup stripe`)
88
+
89
+ ## License
90
+
91
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { setLoggerOptions } from "./lib/logger.js";
4
+ import { registerInitCommand } from "./commands/init.js";
5
+ import { registerSetupCommand } from "./commands/setup-stripe.js";
6
+ import { registerStatusCommand } from "./commands/status.js";
7
+ import { registerTestCommand } from "./commands/test.js";
8
+ const program = new Command();
9
+ program
10
+ .name("affitor")
11
+ .description("CLI-native affiliate tracking. Connect Stripe, track commissions, manage partners.")
12
+ .version("0.1.0")
13
+ .option("--json", "Output as JSON (for agent parsing)", false)
14
+ .option("--no-interactive", "Skip all prompts, fail on missing values")
15
+ .option("--auto-confirm", "Auto-yes to all confirmation prompts", false)
16
+ .option("--quiet", "Suppress non-essential output", false)
17
+ .option("--api-key <key>", "Override API key from config")
18
+ .option("--api-url <url>", "Override API URL (default: api.affitor.com)")
19
+ .option("--verbose", "Debug-level output", false)
20
+ .hook("preAction", () => {
21
+ const opts = program.opts();
22
+ setLoggerOptions({
23
+ json: opts.json,
24
+ quiet: opts.quiet,
25
+ verbose: opts.verbose,
26
+ });
27
+ });
28
+ registerInitCommand(program);
29
+ registerSetupCommand(program);
30
+ registerStatusCommand(program);
31
+ registerTestCommand(program);
32
+ program.parse();
33
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CACV,oFAAoF,CACrF;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,QAAQ,EAAE,oCAAoC,EAAE,KAAK,CAAC;KAC7D,MAAM,CAAC,kBAAkB,EAAE,0CAA0C,CAAC;KACtE,MAAM,CAAC,gBAAgB,EAAE,sCAAsC,EAAE,KAAK,CAAC;KACvE,MAAM,CAAC,SAAS,EAAE,+BAA+B,EAAE,KAAK,CAAC;KACzD,MAAM,CAAC,iBAAiB,EAAE,8BAA8B,CAAC;KACzD,MAAM,CAAC,iBAAiB,EAAE,6CAA6C,CAAC;KACxE,MAAM,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC;KAChD,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC5B,gBAAgB,CAAC;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerInitCommand(program: Command): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAgBnD"}
@@ -0,0 +1,194 @@
1
+ import * as logger from "../lib/logger.js";
2
+ import { AffitorAPI, APIError, NetworkError } from "../lib/api-client.js";
3
+ import { configExists, writeConfig, writeEnvExample, writeSkillsFile, appendToGitignore, } from "../lib/config.js";
4
+ import { promptProgramName, promptDomain, promptCommissionType, promptCommissionRate, promptDurationMonths, promptCookieDuration, confirmAction, } from "../lib/prompts.js";
5
+ import { DEFAULT_API_URL } from "../types.js";
6
+ import { getFlags } from "../lib/flags.js";
7
+ export function registerInitCommand(program) {
8
+ program
9
+ .command("init")
10
+ .description("Initialize a new Affitor affiliate program")
11
+ .option("--name <name>", "Program name")
12
+ .option("--domain <domain>", "Root domain (e.g., example.com)")
13
+ .option("--commission-type <type>", "Commission type: percent, fixed, recurring_percent, recurring_fixed")
14
+ .option("--commission-rate <rate>", "Commission rate (% or $)", parseFloat)
15
+ .option("--cookie-duration <days>", "Cookie duration in days", parseInt)
16
+ .option("--duration-months <months>", "Commission duration in months (for recurring)", parseInt)
17
+ .action(async (opts, cmd) => {
18
+ await runInit(opts, getFlags(cmd));
19
+ });
20
+ }
21
+ async function runInit(opts, flags) {
22
+ if (configExists()) {
23
+ logger.error("Affitor already configured in this directory.\n" +
24
+ " Use `npx affitor status` to check your program.\n" +
25
+ " Delete `.affitor/` to reinitialize.");
26
+ if (flags.json) {
27
+ logger.json({ error: "already_configured" });
28
+ }
29
+ process.exit(1);
30
+ }
31
+ const interactive = !flags.noInteractive;
32
+ let name = opts.name;
33
+ let domain = opts.domain;
34
+ let commissionType = opts.commissionType;
35
+ let commissionRate = opts.commissionRate;
36
+ let cookieDuration = opts.cookieDuration;
37
+ let durationMonths = opts.durationMonths;
38
+ if (interactive) {
39
+ logger.box([
40
+ "",
41
+ " Welcome to Affitor",
42
+ " CLI-native affiliate tracking",
43
+ "",
44
+ ]);
45
+ name ??= await promptProgramName();
46
+ domain ??= await promptDomain();
47
+ commissionType ??= await promptCommissionType();
48
+ commissionRate ??= await promptCommissionRate(commissionType);
49
+ if (commissionType.startsWith("recurring")) {
50
+ durationMonths ??= await promptDurationMonths();
51
+ }
52
+ cookieDuration ??= await promptCookieDuration();
53
+ }
54
+ if (!name || !domain || !commissionType || commissionRate === undefined) {
55
+ logger.error("Missing required options. In non-interactive mode, provide:\n" +
56
+ " --name <name> --domain <domain> --commission-type <type> --commission-rate <rate>");
57
+ if (flags.json) {
58
+ logger.json({ error: "missing_options" });
59
+ }
60
+ process.exit(1);
61
+ }
62
+ // Clean domain
63
+ domain = domain
64
+ .trim()
65
+ .toLowerCase()
66
+ .replace(/^https?:\/\//, "")
67
+ .replace(/\/$/, "");
68
+ cookieDuration ??= 90;
69
+ if (interactive && !flags.autoConfirm) {
70
+ logger.newline();
71
+ logger.info(` Program: ${name}`);
72
+ logger.info(` Domain: ${domain}`);
73
+ logger.info(` Commission: ${formatCommission(commissionType, commissionRate, durationMonths)}`);
74
+ logger.info(` Cookie: ${cookieDuration} days`);
75
+ logger.newline();
76
+ const confirmed = await confirmAction("Create this program?");
77
+ if (!confirmed) {
78
+ logger.info("Cancelled.");
79
+ process.exit(0);
80
+ }
81
+ }
82
+ const apiUrl = flags.apiUrl ?? DEFAULT_API_URL;
83
+ const api = new AffitorAPI({ apiUrl });
84
+ logger.step("Creating program...");
85
+ let response;
86
+ try {
87
+ response = await api.initProgram({
88
+ name,
89
+ domain,
90
+ commission_type: commissionType,
91
+ commission_rate: commissionRate,
92
+ cookie_duration: cookieDuration,
93
+ duration_months: durationMonths,
94
+ });
95
+ }
96
+ catch (err) {
97
+ if (err instanceof APIError) {
98
+ logger.error(`API error: ${err.message}`);
99
+ if (flags.json)
100
+ logger.json({ error: err.message, status: err.status });
101
+ }
102
+ else if (err instanceof NetworkError) {
103
+ logger.error(err.message);
104
+ if (flags.json)
105
+ logger.json({ error: "network_error" });
106
+ }
107
+ else {
108
+ logger.error(`Unexpected error: ${err.message}`);
109
+ if (flags.json)
110
+ logger.json({ error: "unexpected_error" });
111
+ }
112
+ process.exit(1);
113
+ }
114
+ logger.success("Program created");
115
+ const config = {
116
+ version: 1,
117
+ program_id: response.program_id,
118
+ domain,
119
+ tracking_subdomain: `t.${domain}`,
120
+ commission: {
121
+ type: commissionType,
122
+ rate: commissionRate,
123
+ duration_months: durationMonths,
124
+ },
125
+ cookie: {
126
+ name: "_aff",
127
+ duration_days: cookieDuration,
128
+ },
129
+ ref_param: "aff",
130
+ stripe_connected: false,
131
+ api_key: response.api_key,
132
+ api_url: apiUrl,
133
+ created_at: new Date().toISOString(),
134
+ };
135
+ writeConfig(config);
136
+ logger.success("Config written to .affitor/config.json");
137
+ writeEnvExample(config);
138
+ logger.success("Env template written to .affitor/.env.example");
139
+ writeSkillsFile(config, name);
140
+ logger.success("Agent skills written to .affitor/skills.md");
141
+ appendToGitignore();
142
+ if (flags.json) {
143
+ logger.json({
144
+ program_id: response.program_id,
145
+ api_key: response.api_key,
146
+ domain,
147
+ tracking_subdomain: `t.${domain}`,
148
+ status: "created",
149
+ next_steps: [
150
+ `Add CNAME record: t.${domain} → track.affitor.com`,
151
+ "Run: npx affitor setup dns",
152
+ "Run: npx affitor setup stripe",
153
+ ],
154
+ });
155
+ return;
156
+ }
157
+ logger.box([
158
+ " Program created!",
159
+ "",
160
+ ` Program ID: ${response.program_id}`,
161
+ ` API Key: ${response.api_key}`,
162
+ ` Domain: ${domain}`,
163
+ ` Commission: ${formatCommission(commissionType, commissionRate, durationMonths)}`,
164
+ ]);
165
+ logger.info("Next steps:");
166
+ logger.newline();
167
+ logger.info(" 1. Add DNS record (required):");
168
+ logger.info(` CNAME t.${domain} → track.affitor.com`);
169
+ logger.newline();
170
+ logger.info(" 2. Verify DNS:");
171
+ logger.info(" $ npx affitor setup dns");
172
+ logger.newline();
173
+ logger.info(" 3. Connect Stripe (recommended):");
174
+ logger.info(" $ npx affitor setup stripe");
175
+ logger.newline();
176
+ logger.info(" 4. Test tracking:");
177
+ logger.info(" $ npx affitor test click");
178
+ logger.newline();
179
+ logger.info("Files created:");
180
+ logger.info(" .affitor/config.json — program configuration");
181
+ logger.info(" .affitor/skills.md — agent instructions");
182
+ logger.info(" .affitor/.env.example — environment variables template");
183
+ }
184
+ function formatCommission(type, rate, durationMonths) {
185
+ const isPercent = type.includes("percent");
186
+ const value = isPercent ? `${rate}%` : `$${rate}`;
187
+ const isRecurring = type.startsWith("recurring");
188
+ if (isRecurring) {
189
+ const duration = durationMonths === 0 ? "lifetime" : `${durationMonths} months`;
190
+ return `${value} recurring (${duration})`;
191
+ }
192
+ return `${value} per sale`;
193
+ }
194
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerSetupCommand(program: Command): void;
3
+ //# sourceMappingURL=setup-stripe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-stripe.d.ts","sourceRoot":"","sources":["../../src/commands/setup-stripe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAoBpD"}
@@ -0,0 +1,188 @@
1
+ import * as logger from "../lib/logger.js";
2
+ import { readConfig, updateConfig, writeEnvExample, ConfigNotFoundError } from "../lib/config.js";
3
+ import { runStripeOAuth, StripeOAuthError } from "../lib/stripe-oauth.js";
4
+ import { AffitorAPI, APIError, NetworkError } from "../lib/api-client.js";
5
+ import { getFlags } from "../lib/flags.js";
6
+ export function registerSetupCommand(program) {
7
+ const setup = program
8
+ .command("setup")
9
+ .description("Set up integrations (stripe, dns)");
10
+ setup
11
+ .command("stripe")
12
+ .description("Connect Stripe for automatic payment tracking")
13
+ .option("--stripe-client-id <id>", "Stripe Connect client ID override")
14
+ .option("--stripe-secret-key <key>", "Stripe secret key (for webhook creation)")
15
+ .action(async (opts, cmd) => {
16
+ await runSetupStripe(opts, getFlags(cmd));
17
+ });
18
+ setup
19
+ .command("dns")
20
+ .description("Set up DNS CNAME tracking (coming soon)")
21
+ .action(async (_opts, cmd) => {
22
+ runSetupDns(getFlags(cmd));
23
+ });
24
+ }
25
+ async function runSetupStripe(opts, flags) {
26
+ let config;
27
+ try {
28
+ config = readConfig();
29
+ }
30
+ catch (err) {
31
+ if (err instanceof ConfigNotFoundError) {
32
+ logger.error(err.message);
33
+ if (flags.json)
34
+ logger.json({ error: "no_config" });
35
+ process.exit(1);
36
+ }
37
+ throw err;
38
+ }
39
+ if (config.stripe_connected) {
40
+ logger.warn("Stripe is already connected.");
41
+ logger.info(` Account: ${config.stripe_account_id}`);
42
+ logger.info(" To reconnect, disconnect first via the dashboard.");
43
+ if (flags.json) {
44
+ logger.json({
45
+ status: "already_connected",
46
+ stripe_account_id: config.stripe_account_id,
47
+ });
48
+ }
49
+ process.exit(0);
50
+ }
51
+ const clientId = opts.stripeClientId ??
52
+ process.env.STRIPE_CONNECT_CLIENT_ID ??
53
+ process.env.AFFITOR_STRIPE_CLIENT_ID;
54
+ if (!clientId) {
55
+ logger.error("Stripe Connect client ID not configured.\n" +
56
+ " Set STRIPE_CONNECT_CLIENT_ID or AFFITOR_STRIPE_CLIENT_ID environment variable,\n" +
57
+ " or pass --stripe-client-id <id>.");
58
+ if (flags.json)
59
+ logger.json({ error: "missing_stripe_client_id" });
60
+ process.exit(1);
61
+ }
62
+ const stripeSecretKey = opts.stripeSecretKey ??
63
+ process.env.STRIPE_SECRET_KEY ??
64
+ process.env.AFFITOR_STRIPE_SECRET_KEY;
65
+ if (!stripeSecretKey) {
66
+ logger.error("Stripe secret key not configured.\n" +
67
+ " Set STRIPE_SECRET_KEY or AFFITOR_STRIPE_SECRET_KEY environment variable,\n" +
68
+ " or pass --stripe-secret-key <key>.");
69
+ if (flags.json)
70
+ logger.json({ error: "missing_stripe_secret_key" });
71
+ process.exit(1);
72
+ }
73
+ const apiUrl = flags.apiUrl ?? config.api_url;
74
+ const webhookUrl = `${apiUrl}/webhooks/stripe/${config.program_id}`;
75
+ try {
76
+ const result = await runStripeOAuth({
77
+ clientId,
78
+ programId: config.program_id,
79
+ webhookUrl,
80
+ stripeSecretKey,
81
+ });
82
+ // Save to Affitor API
83
+ const api = new AffitorAPI({
84
+ apiUrl: apiUrl,
85
+ apiKey: flags.apiKey ?? config.api_key,
86
+ });
87
+ logger.step("Saving connection...");
88
+ const saveResult = await api.saveStripeConnection({
89
+ program_id: config.program_id,
90
+ stripe_user_id: result.stripe_user_id,
91
+ webhook_endpoint_id: result.webhook_endpoint_id,
92
+ webhook_secret: result.webhook_secret,
93
+ });
94
+ // Update local config
95
+ const updated = updateConfig({
96
+ stripe_connected: true,
97
+ stripe_account_id: result.stripe_user_id,
98
+ });
99
+ writeEnvExample(updated);
100
+ if (flags.json) {
101
+ logger.json({
102
+ status: "connected",
103
+ stripe_account_id: result.stripe_user_id,
104
+ webhook_endpoint_id: result.webhook_endpoint_id,
105
+ charges_enabled: saveResult.charges_enabled,
106
+ payouts_enabled: saveResult.payouts_enabled,
107
+ });
108
+ return;
109
+ }
110
+ logger.box([
111
+ " Stripe connected!",
112
+ "",
113
+ ` Account: ${result.stripe_user_id}`,
114
+ ` Charges: ${saveResult.charges_enabled ? "✓ Enabled" : "⚠ Pending verification"}`,
115
+ ` Payouts: ${saveResult.payouts_enabled ? "✓ Enabled" : "⚠ Pending verification"}`,
116
+ "",
117
+ " Webhooks auto-configured:",
118
+ " ✓ customer.created → lead tracking",
119
+ " ✓ checkout.session.completed → sale tracking",
120
+ " ✓ invoice.paid → recurring commission",
121
+ " ✓ charge.refunded → auto clawback",
122
+ ]);
123
+ logger.info("Test it:");
124
+ logger.info(" $ npx affitor test sale");
125
+ }
126
+ catch (err) {
127
+ if (err instanceof StripeOAuthError) {
128
+ logger.error(err.message);
129
+ if (flags.json)
130
+ logger.json({ error: "stripe_oauth_error", message: err.message });
131
+ }
132
+ else if (err instanceof APIError) {
133
+ logger.error(`API error: ${err.message}`);
134
+ if (flags.json)
135
+ logger.json({ error: "api_error", message: err.message });
136
+ }
137
+ else if (err instanceof NetworkError) {
138
+ logger.error(err.message);
139
+ if (flags.json)
140
+ logger.json({ error: "network_error" });
141
+ }
142
+ else {
143
+ logger.error(`Unexpected error: ${err.message}`);
144
+ if (flags.json)
145
+ logger.json({ error: "unexpected_error", message: err.message });
146
+ }
147
+ process.exit(1);
148
+ }
149
+ }
150
+ function runSetupDns(flags) {
151
+ let config;
152
+ try {
153
+ config = readConfig();
154
+ }
155
+ catch (err) {
156
+ if (err instanceof ConfigNotFoundError) {
157
+ logger.error(err.message);
158
+ if (flags.json)
159
+ logger.json({ error: "no_config" });
160
+ process.exit(1);
161
+ }
162
+ throw err;
163
+ }
164
+ if (flags.json) {
165
+ logger.json({
166
+ status: "not_implemented",
167
+ message: "DNS tracking setup coming soon. Use Stripe tracking for now.",
168
+ cname: {
169
+ type: "CNAME",
170
+ name: `t.${config.domain}`,
171
+ target: "track.affitor.com",
172
+ },
173
+ });
174
+ return;
175
+ }
176
+ logger.info("DNS tracking setup is coming soon.");
177
+ logger.newline();
178
+ logger.info("When available, add this DNS record:");
179
+ logger.newline();
180
+ logger.info(` Type: CNAME`);
181
+ logger.info(` Name: t.${config.domain}`);
182
+ logger.info(` Target: track.affitor.com`);
183
+ logger.info(` TTL: Auto (or 300)`);
184
+ logger.newline();
185
+ logger.info("For now, use Stripe tracking:");
186
+ logger.info(" $ npx affitor setup stripe");
187
+ }
188
+ //# sourceMappingURL=setup-stripe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-stripe.js","sourceRoot":"","sources":["../../src/commands/setup-stripe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStatusCommand(program: Command): void;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAOrD"}
@@ -0,0 +1,95 @@
1
+ import * as logger from "../lib/logger.js";
2
+ import { readConfig, ConfigNotFoundError } from "../lib/config.js";
3
+ import { AffitorAPI, APIError, NetworkError } from "../lib/api-client.js";
4
+ import { getFlags } from "../lib/flags.js";
5
+ export function registerStatusCommand(program) {
6
+ program
7
+ .command("status")
8
+ .description("Show program health: DNS, Stripe, recent events")
9
+ .action(async (_opts, cmd) => {
10
+ await runStatus(getFlags(cmd));
11
+ });
12
+ }
13
+ async function runStatus(flags) {
14
+ let config;
15
+ try {
16
+ config = readConfig();
17
+ }
18
+ catch (err) {
19
+ if (err instanceof ConfigNotFoundError) {
20
+ logger.error(err.message);
21
+ if (flags.json)
22
+ logger.json({ error: "no_config" });
23
+ process.exit(1);
24
+ }
25
+ throw err;
26
+ }
27
+ const api = new AffitorAPI({
28
+ apiUrl: flags.apiUrl ?? config.api_url,
29
+ apiKey: flags.apiKey ?? config.api_key,
30
+ });
31
+ try {
32
+ const status = await api.getStatus(config.program_id);
33
+ if (flags.json) {
34
+ logger.json(status);
35
+ return;
36
+ }
37
+ logger.box([
38
+ ` ${status.name}`,
39
+ ` ${config.domain}`,
40
+ "",
41
+ ` Program ID: ${status.program_id}`,
42
+ ]);
43
+ // DNS status
44
+ if (status.dns_verified) {
45
+ logger.success(`DNS: verified (t.${config.domain})`);
46
+ }
47
+ else {
48
+ logger.warn(`DNS: not configured`);
49
+ logger.step(`Add CNAME: t.${config.domain} → track.affitor.com`);
50
+ }
51
+ // Stripe status
52
+ if (status.stripe_connected) {
53
+ logger.success(`Stripe: connected${status.stripe_charges_enabled ? "" : " (pending verification)"}`);
54
+ }
55
+ else {
56
+ logger.warn("Stripe: not connected");
57
+ logger.step("Run: npx affitor setup stripe");
58
+ }
59
+ logger.newline();
60
+ // Events (last 24h)
61
+ logger.info(" Events (last 24h):");
62
+ logger.info(` Clicks: ${status.recent_events.clicks_24h}`);
63
+ logger.info(` Leads: ${status.recent_events.leads_24h}`);
64
+ logger.info(` Sales: ${status.recent_events.sales_24h}`);
65
+ logger.newline();
66
+ // Partners & commissions
67
+ logger.info(` Active partners: ${status.active_partners}`);
68
+ logger.info(` Pending commissions: ${status.pending_commissions}`);
69
+ }
70
+ catch (err) {
71
+ if (err instanceof APIError) {
72
+ if (err.status === 401) {
73
+ logger.error("API key expired or invalid.\n" +
74
+ " Run `npx affitor init` to get a new API key.");
75
+ }
76
+ else {
77
+ logger.error(`API error: ${err.message}`);
78
+ }
79
+ if (flags.json)
80
+ logger.json({ error: err.message, status: err.status });
81
+ }
82
+ else if (err instanceof NetworkError) {
83
+ logger.error(err.message);
84
+ if (flags.json)
85
+ logger.json({ error: "network_error" });
86
+ }
87
+ else {
88
+ logger.error(`Unexpected error: ${err.message}`);
89
+ if (flags.json)
90
+ logger.json({ error: "unexpected_error" });
91
+ }
92
+ process.exit(1);
93
+ }
94
+ }
95
+ //# sourceMappingURL=status.js.map