@nebulr-group/bridge-cli 0.1.4 → 0.4.0-beta.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 (43) hide show
  1. package/README.md +26 -4
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +4 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/app.command.d.ts.map +1 -1
  6. package/dist/commands/app.command.js +2 -0
  7. package/dist/commands/app.command.js.map +1 -1
  8. package/dist/commands/flag-init.command.d.ts +13 -0
  9. package/dist/commands/flag-init.command.d.ts.map +1 -0
  10. package/dist/commands/flag-init.command.js +353 -0
  11. package/dist/commands/flag-init.command.js.map +1 -0
  12. package/dist/commands/flag.command.d.ts +92 -0
  13. package/dist/commands/flag.command.d.ts.map +1 -1
  14. package/dist/commands/flag.command.js +784 -25
  15. package/dist/commands/flag.command.js.map +1 -1
  16. package/dist/commands/guide.command.d.ts +21 -0
  17. package/dist/commands/guide.command.d.ts.map +1 -1
  18. package/dist/commands/guide.command.js +297 -21
  19. package/dist/commands/guide.command.js.map +1 -1
  20. package/dist/commands/integrate.command.js +3 -3
  21. package/dist/commands/integrate.command.js.map +1 -1
  22. package/dist/commands/ops.command.d.ts +17 -0
  23. package/dist/commands/ops.command.d.ts.map +1 -0
  24. package/dist/commands/ops.command.js +129 -0
  25. package/dist/commands/ops.command.js.map +1 -0
  26. package/dist/commands/plan.command.d.ts +31 -0
  27. package/dist/commands/plan.command.d.ts.map +1 -1
  28. package/dist/commands/plan.command.js +182 -1
  29. package/dist/commands/plan.command.js.map +1 -1
  30. package/dist/commands/stripe.command.d.ts +3 -0
  31. package/dist/commands/stripe.command.d.ts.map +1 -0
  32. package/dist/commands/stripe.command.js +43 -0
  33. package/dist/commands/stripe.command.js.map +1 -0
  34. package/dist/output.d.ts +8 -0
  35. package/dist/output.d.ts.map +1 -1
  36. package/dist/output.js +10 -0
  37. package/dist/output.js.map +1 -1
  38. package/dist/prompts/architecture.md +560 -0
  39. package/dist/prompts/auth-master-integration-prompt.md +251 -0
  40. package/dist/prompts/billing/master.md +269 -0
  41. package/dist/prompts/flags/master.md +215 -0
  42. package/dist/prompts/integration-success.md +107 -0
  43. package/package.json +4 -3
@@ -0,0 +1,129 @@
1
+ import { DEFAULT_BASE_URL } from '../config.js';
2
+ import { isExpired, readCredentials } from '../credentials.js';
3
+ import { outputError, outputSuccess } from '../output.js';
4
+ export function registerOpsCommands(program) {
5
+ const ops = program
6
+ .command('ops')
7
+ .description('Operator / platform-internal commands');
8
+ ops
9
+ .command('reconcile')
10
+ .description('Trigger Bridge↔Stripe usage reconciliation for a workspace (Billing 2.0 US-18). ' +
11
+ 'Diffs Bridge raw events against Stripe usage records and replays the missing ones.')
12
+ .requiredOption('--workspace <id>', 'Workspace (tenant) id to reconcile')
13
+ .option('--metric <metric>', 'Scope to one metric instead of all metered metrics')
14
+ .option('--json', 'Emit raw JSON instead of the human-readable table')
15
+ .action(async (opts) => {
16
+ try {
17
+ const result = await callReconcile(opts.workspace, opts.metric);
18
+ if (opts.json) {
19
+ outputSuccess(result);
20
+ return;
21
+ }
22
+ // Default: render a friendly table; still go through outputSuccess so
23
+ // the success envelope + exit code stay consistent with the rest of the
24
+ // CLI. The pretty table is appended to stderr so machine parsers that
25
+ // only watch stdout get the JSON.
26
+ printReconciliationTable(result);
27
+ outputSuccess(result);
28
+ }
29
+ catch (err) {
30
+ outputError(err);
31
+ }
32
+ });
33
+ }
34
+ async function callReconcile(workspaceId, metric) {
35
+ const { apiKey, baseUrl } = resolveCredentials();
36
+ const path = metric
37
+ ? `/v1/admin/reconcile/${encodeURIComponent(workspaceId)}/${encodeURIComponent(metric)}`
38
+ : `/v1/admin/reconcile/${encodeURIComponent(workspaceId)}`;
39
+ const url = `${baseUrl.replace(/\/$/, '')}${path}`;
40
+ const res = await fetch(url, {
41
+ method: 'POST',
42
+ headers: {
43
+ 'content-type': 'application/json',
44
+ 'x-api-key': apiKey,
45
+ },
46
+ body: '{}',
47
+ });
48
+ if (!res.ok) {
49
+ let body;
50
+ try {
51
+ body = await res.json();
52
+ }
53
+ catch {
54
+ body = await res.text().catch(() => '');
55
+ }
56
+ const message = (body && typeof body === 'object' && 'message' in body
57
+ ? String(body.message)
58
+ : '') || `HTTP ${res.status}`;
59
+ const err = new Error(message);
60
+ err.status = res.status;
61
+ err.body = body;
62
+ throw err;
63
+ }
64
+ return (await res.json());
65
+ }
66
+ function resolveCredentials() {
67
+ const envKey = process.env.BRIDGE_API_KEY?.trim();
68
+ const envBase = process.env.BRIDGE_BASE_URL?.trim();
69
+ const creds = safeReadCredentials();
70
+ if (creds && !isExpired(creds)) {
71
+ return {
72
+ apiKey: creds.apiKey,
73
+ baseUrl: envBase && envBase.length > 0 ? envBase : creds.baseUrl,
74
+ };
75
+ }
76
+ if (envKey && envKey.length > 0) {
77
+ return {
78
+ apiKey: envKey,
79
+ baseUrl: envBase && envBase.length > 0 ? envBase : DEFAULT_BASE_URL,
80
+ };
81
+ }
82
+ throw new Error('Not logged in. Run `bridge auth login`.');
83
+ }
84
+ function safeReadCredentials() {
85
+ try {
86
+ return readCredentials();
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ function printReconciliationTable(result) {
93
+ const lines = [];
94
+ lines.push('');
95
+ lines.push(`workspace=${result.workspaceId} app=${result.appId}`);
96
+ if (result.metrics.length === 0) {
97
+ lines.push(' (no metered metrics reconciled)');
98
+ process.stderr.write(lines.join('\n') + '\n');
99
+ return;
100
+ }
101
+ const header = [
102
+ 'metric'.padEnd(28),
103
+ 'status'.padEnd(14),
104
+ 'bridge'.padStart(7),
105
+ 'provider'.padStart(9),
106
+ 'missing'.padStart(8),
107
+ 'healed'.padStart(7),
108
+ 'attempts'.padStart(9),
109
+ ].join(' ');
110
+ lines.push(header);
111
+ lines.push('-'.repeat(header.length));
112
+ for (const m of result.metrics) {
113
+ lines.push([
114
+ m.metric.padEnd(28).slice(0, 28),
115
+ m.status.padEnd(14),
116
+ String(m.bridgeCount).padStart(7),
117
+ String(m.providerCount).padStart(9),
118
+ String(m.missing).padStart(8),
119
+ String(m.healed).padStart(7),
120
+ String(m.attempts).padStart(9),
121
+ ].join(' '));
122
+ if (m.failed.length > 0) {
123
+ lines.push(` failed: ${m.failed.slice(0, 3).join('; ')}`);
124
+ }
125
+ }
126
+ lines.push('');
127
+ process.stderr.write(lines.join('\n') + '\n');
128
+ }
129
+ //# sourceMappingURL=ops.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.command.js","sourceRoot":"","sources":["../../src/commands/ops.command.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,34 @@
1
1
  import { Command } from 'commander';
2
+ export type QuotaPolicy = 'hard' | 'metered';
3
+ export interface Quota {
4
+ metric: string;
5
+ limit: number;
6
+ policy: QuotaPolicy;
7
+ }
8
+ export declare function validateQuotaEntry(entry: {
9
+ metric?: string;
10
+ limit?: number;
11
+ policy?: string;
12
+ }): Quota;
13
+ /** Upsert a quota by metric (replace if present, append otherwise). Pure. */
14
+ export declare function upsertQuota(quotas: Quota[], entry: Quota): Quota[];
15
+ export type RecurrenceInterval = 'day' | 'week' | 'month' | 'year';
16
+ export interface PlanPriceInput {
17
+ currency: string;
18
+ recurrenceInterval: RecurrenceInterval;
19
+ amount: number;
20
+ }
21
+ /**
22
+ * Validate + normalise one price entry from CLI flags. A plan can carry several
23
+ * prices (e.g. monthly + yearly); each is set independently and identified by
24
+ * its currency + interval. `--interval` is always required.
25
+ */
26
+ export declare function buildPriceEntry(opts: {
27
+ amount?: number;
28
+ currency?: string;
29
+ interval?: string;
30
+ }): PlanPriceInput;
31
+ /** Upsert a price by (currency + interval): replace if present, append otherwise. Pure. */
32
+ export declare function upsertPrice(prices: PlanPriceInput[], entry: PlanPriceInput): PlanPriceInput[];
2
33
  export declare function registerPlanCommands(program: Command): void;
3
34
  //# sourceMappingURL=plan.command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../src/commands/plan.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyC3D"}
1
+ {"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../src/commands/plan.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;CACrB;AAID,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,KAAK,CAsBR;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,CAElE;AAID,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAQnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,cAAc,CAcjB;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,EAAE,cAAc,GACpB,cAAc,EAAE,CAWlB;AAcD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyD3D"}
@@ -1,5 +1,70 @@
1
1
  import { getManagementClient } from '../config.js';
2
2
  import { outputSuccess, outputError } from '../output.js';
3
+ const QUOTA_POLICIES = ['hard', 'metered'];
4
+ export function validateQuotaEntry(entry) {
5
+ const metric = (entry.metric ?? '').trim();
6
+ if (!metric)
7
+ throw new Error('--metric is required and must be non-empty.');
8
+ const limit = entry.limit;
9
+ if (typeof limit !== 'number' ||
10
+ !Number.isFinite(limit) ||
11
+ !Number.isInteger(limit) ||
12
+ limit < 0) {
13
+ throw new Error(`--limit must be an integer >= 0, got "${entry.limit}".`);
14
+ }
15
+ const policy = entry.policy;
16
+ if (!QUOTA_POLICIES.includes(policy)) {
17
+ throw new Error(`--policy must be one of ${QUOTA_POLICIES.join(', ')}, got "${entry.policy}".`);
18
+ }
19
+ return { metric, limit, policy };
20
+ }
21
+ /** Upsert a quota by metric (replace if present, append otherwise). Pure. */
22
+ export function upsertQuota(quotas, entry) {
23
+ return [...quotas.filter((q) => q.metric !== entry.metric), entry];
24
+ }
25
+ const VALID_INTERVALS = [
26
+ 'day',
27
+ 'week',
28
+ 'month',
29
+ 'year',
30
+ ];
31
+ /**
32
+ * Validate + normalise one price entry from CLI flags. A plan can carry several
33
+ * prices (e.g. monthly + yearly); each is set independently and identified by
34
+ * its currency + interval. `--interval` is always required.
35
+ */
36
+ export function buildPriceEntry(opts) {
37
+ const amount = opts.amount;
38
+ if (typeof amount !== 'number' || !Number.isFinite(amount) || amount < 0) {
39
+ throw new Error(`--amount must be a number >= 0, got "${opts.amount}".`);
40
+ }
41
+ const interval = (opts.interval ?? '');
42
+ if (!VALID_INTERVALS.includes(interval)) {
43
+ throw new Error(`--interval is required and must be one of ${VALID_INTERVALS.join(', ')}, got "${opts.interval}".`);
44
+ }
45
+ const currency = (opts.currency ?? 'USD').trim().toUpperCase();
46
+ if (!currency)
47
+ throw new Error('--currency must be non-empty.');
48
+ return { amount, currency, recurrenceInterval: interval };
49
+ }
50
+ /** Upsert a price by (currency + interval): replace if present, append otherwise. Pure. */
51
+ export function upsertPrice(prices, entry) {
52
+ return [
53
+ ...prices.filter((p) => !(p.currency === entry.currency &&
54
+ p.recurrenceInterval === entry.recurrenceInterval)),
55
+ entry,
56
+ ];
57
+ }
58
+ /** Fetch a plan + its quotas/prices (read defensively — list() may omit them). */
59
+ async function getPlan(key) {
60
+ const plans = (await getManagementClient().plans.list());
61
+ const plan = plans.find((p) => p.key === key);
62
+ if (!plan)
63
+ throw new Error(`Plan not found: ${key}`);
64
+ const quotas = (plan.quotas ?? []);
65
+ const prices = (plan.prices ?? []);
66
+ return { plan, quotas, prices };
67
+ }
3
68
  export function registerPlanCommands(program) {
4
69
  const plan = program.command('plan').description('Manage subscription plans');
5
70
  plan.command('list')
@@ -12,8 +77,20 @@ export function registerPlanCommands(program) {
12
77
  outputError(err);
13
78
  }
14
79
  });
80
+ plan.command('get')
81
+ .description('Get a plan by key (includes usage quotas)')
82
+ .argument('<key>', 'Plan key')
83
+ .action(async (key) => {
84
+ try {
85
+ const { plan: found, quotas } = await getPlan(key);
86
+ outputSuccess({ ...found, quotas });
87
+ }
88
+ catch (err) {
89
+ outputError(err);
90
+ }
91
+ });
15
92
  plan.command('create')
16
- .description('Create a new plan')
93
+ .description('Create a new plan (no prices — add them with `plan price set`)')
17
94
  .requiredOption('--key <key>', 'Plan key')
18
95
  .requiredOption('--name <name>', 'Plan name')
19
96
  .option('--description <desc>', 'Description')
@@ -27,6 +104,9 @@ export function registerPlanCommands(program) {
27
104
  description: opts.description,
28
105
  trial: opts.trial,
29
106
  trialDays: opts.trialDays,
107
+ // Start with no prices so the server doesn't apply its default
108
+ // placeholder price; add prices explicitly via `plan price set`.
109
+ prices: [],
30
110
  }));
31
111
  }
32
112
  catch (err) {
@@ -48,5 +128,106 @@ export function registerPlanCommands(program) {
48
128
  outputError(err);
49
129
  }
50
130
  });
131
+ registerPriceCommands(plan);
132
+ registerQuotaCommands(plan);
133
+ }
134
+ // ── plan price (recurring prices) ────────────────────────────────────────────
135
+ function registerPriceCommands(plan) {
136
+ const price = plan
137
+ .command('price')
138
+ .description("Manage a plan's recurring prices (one per currency + interval)");
139
+ price.command('set')
140
+ .description('Add or update a price on a plan (idempotent by currency + interval)')
141
+ .argument('<key>', 'Plan key')
142
+ .requiredOption('--amount <amount>', 'Price amount (>= 0)', parseFloat)
143
+ .requiredOption('--interval <interval>', `Billing interval: ${VALID_INTERVALS.join(' | ')}`)
144
+ .option('--currency <currency>', 'Currency (default USD)', 'USD')
145
+ .action(async (key, opts) => {
146
+ try {
147
+ const entry = buildPriceEntry({
148
+ amount: opts.amount,
149
+ interval: opts.interval,
150
+ currency: opts.currency,
151
+ });
152
+ const { prices } = await getPlan(key);
153
+ const next = upsertPrice(prices, entry);
154
+ outputSuccess(await getManagementClient().plans.update(key, { prices: next }));
155
+ }
156
+ catch (err) {
157
+ outputError(err);
158
+ }
159
+ });
160
+ price.command('rm')
161
+ .description('Remove a price from a plan by interval (+ currency)')
162
+ .argument('<key>', 'Plan key')
163
+ .requiredOption('--interval <interval>', `Billing interval: ${VALID_INTERVALS.join(' | ')}`)
164
+ .option('--currency <currency>', 'Currency (default USD)', 'USD')
165
+ .action(async (key, opts) => {
166
+ try {
167
+ const currency = String(opts.currency ?? 'USD').trim().toUpperCase();
168
+ const interval = opts.interval;
169
+ const { prices } = await getPlan(key);
170
+ const next = prices.filter((p) => !(p.currency === currency && p.recurrenceInterval === interval));
171
+ if (next.length === prices.length) {
172
+ throw new Error(`No ${currency} ${interval} price on plan "${key}".`);
173
+ }
174
+ outputSuccess(await getManagementClient().plans.update(key, { prices: next }));
175
+ }
176
+ catch (err) {
177
+ outputError(err);
178
+ }
179
+ });
180
+ }
181
+ // ── plan quota (usage caps) ──────────────────────────────────────────────────
182
+ function registerQuotaCommands(plan) {
183
+ const quota = plan
184
+ .command('quota')
185
+ .description('Manage a plan\'s usage quotas (hard | metered caps)');
186
+ quota.command('list')
187
+ .description('List the usage quotas on a plan')
188
+ .argument('<key>', 'Plan key')
189
+ .action(async (key) => {
190
+ try {
191
+ const { quotas } = await getPlan(key);
192
+ outputSuccess(quotas);
193
+ }
194
+ catch (err) {
195
+ outputError(err);
196
+ }
197
+ });
198
+ quota.command('set')
199
+ .description('Add or update a usage quota on a plan')
200
+ .argument('<key>', 'Plan key')
201
+ .requiredOption('--metric <metric>', 'Metric key (e.g. num.clicks)')
202
+ .requiredOption('--limit <n>', 'Limit (integer >= 0)', parseInt)
203
+ .requiredOption('--policy <policy>', `Cap policy: ${QUOTA_POLICIES.join(' | ')}`)
204
+ .action(async (key, opts) => {
205
+ try {
206
+ const entry = validateQuotaEntry({ metric: opts.metric, limit: opts.limit, policy: opts.policy });
207
+ const { quotas } = await getPlan(key);
208
+ const next = upsertQuota(quotas, entry);
209
+ outputSuccess(await getManagementClient().plans.update(key, { quotas: next }));
210
+ }
211
+ catch (err) {
212
+ outputError(err);
213
+ }
214
+ });
215
+ quota.command('rm')
216
+ .description('Remove a usage quota from a plan')
217
+ .argument('<key>', 'Plan key')
218
+ .requiredOption('--metric <metric>', 'Metric key to remove')
219
+ .action(async (key, opts) => {
220
+ try {
221
+ const { quotas } = await getPlan(key);
222
+ const next = quotas.filter((q) => q.metric !== opts.metric);
223
+ if (next.length === quotas.length) {
224
+ throw new Error(`No quota for metric "${opts.metric}" on plan "${key}".`);
225
+ }
226
+ outputSuccess(await getManagementClient().plans.update(key, { quotas: next }));
227
+ }
228
+ catch (err) {
229
+ outputError(err);
230
+ }
231
+ });
51
232
  }
52
233
  //# sourceMappingURL=plan.command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.command.js","sourceRoot":"","sources":["../../src/commands/plan.command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAE9E,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;SACjB,WAAW,CAAC,6BAA6B,CAAC;SAC1C,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YAAC,aAAa,CAAC,MAAM,mBAAmB,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAAC,CAAC;QAChE,OAAO,GAAG,EAAE,CAAC;YAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEL,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;SACnB,WAAW,CAAC,mBAAmB,CAAC;SAChC,cAAc,CAAC,aAAa,EAAE,UAAU,CAAC;SACzC,cAAc,CAAC,eAAe,EAAE,WAAW,CAAC;SAC5C,MAAM,CAAC,sBAAsB,EAAE,aAAa,CAAC;SAC7C,MAAM,CAAC,SAAS,EAAE,sBAAsB,EAAE,KAAK,CAAC;SAChD,MAAM,CAAC,qBAAqB,EAAE,sBAAsB,EAAE,QAAQ,CAAC;SAC/D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,aAAa,CAAC,MAAM,mBAAmB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;gBACrD,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC,CAAC;QACN,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEL,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;SACnB,WAAW,CAAC,eAAe,CAAC;SAC5B,cAAc,CAAC,aAAa,EAAE,UAAU,CAAC;SACzC,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC;SACpC,MAAM,CAAC,sBAAsB,EAAE,aAAa,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;YAC5F,aAAa,CAAC,MAAM,mBAAmB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"plan.command.js","sourceRoot":"","sources":["../../src/commands/plan.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerStripeCommands(program: Command): void;
3
+ //# sourceMappingURL=stripe.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.command.d.ts","sourceRoot":"","sources":["../../src/commands/stripe.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmC7D"}
@@ -0,0 +1,43 @@
1
+ import { getManagementClient } from '../config.js';
2
+ import { outputSuccess, outputError } from '../output.js';
3
+ export function registerStripeCommands(program) {
4
+ const stripe = program.command('stripe').description('Manage Stripe integration');
5
+ stripe.command('status')
6
+ .description('Show whether Stripe credentials are configured')
7
+ .action(async () => {
8
+ try {
9
+ const state = await getManagementClient().app.getCredentialsState();
10
+ outputSuccess({
11
+ connected: state.hasStripeCredentials,
12
+ message: state.hasStripeCredentials
13
+ ? 'Stripe is connected'
14
+ : 'Stripe is not connected — run: bridge stripe connect --secret-key sk_... --publishable-key pk_...',
15
+ });
16
+ }
17
+ catch (err) {
18
+ outputError(err);
19
+ }
20
+ });
21
+ stripe.command('connect')
22
+ .description('Set Stripe API credentials')
23
+ .requiredOption('--secret-key <key>', 'Stripe secret key (sk_live_... or sk_test_...)')
24
+ .requiredOption('--publishable-key <key>', 'Stripe publishable key (pk_live_... or pk_test_...)')
25
+ .action(async (opts) => {
26
+ try {
27
+ const state = await getManagementClient().app.updateCredentials({
28
+ stripeSecretKey: opts.secretKey,
29
+ stripePublicKey: opts.publishableKey,
30
+ });
31
+ outputSuccess({
32
+ connected: state.hasStripeCredentials,
33
+ message: state.hasStripeCredentials
34
+ ? 'Stripe connected successfully'
35
+ : 'Credentials saved but Stripe did not confirm — check your keys and try again',
36
+ });
37
+ }
38
+ catch (err) {
39
+ outputError(err);
40
+ }
41
+ });
42
+ }
43
+ //# sourceMappingURL=stripe.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.command.js","sourceRoot":"","sources":["../../src/commands/stripe.command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAElF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;SACrB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,mBAAmB,EAAE,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;YACpE,aAAa,CAAC;gBACZ,SAAS,EAAE,KAAK,CAAC,oBAAoB;gBACrC,OAAO,EAAE,KAAK,CAAC,oBAAoB;oBACjC,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,mGAAmG;aACxG,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEL,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;SACtB,WAAW,CAAC,4BAA4B,CAAC;SACzC,cAAc,CAAC,oBAAoB,EAAE,gDAAgD,CAAC;SACtF,cAAc,CAAC,yBAAyB,EAAE,qDAAqD,CAAC;SAChG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,mBAAmB,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC;gBAC9D,eAAe,EAAE,IAAI,CAAC,SAAS;gBAC/B,eAAe,EAAE,IAAI,CAAC,cAAc;aACrC,CAAC,CAAC;YACH,aAAa,CAAC;gBACZ,SAAS,EAAE,KAAK,CAAC,oBAAoB;gBACrC,OAAO,EAAE,KAAK,CAAC,oBAAoB;oBACjC,CAAC,CAAC,+BAA+B;oBACjC,CAAC,CAAC,8EAA8E;aACnF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/output.d.ts CHANGED
@@ -1,3 +1,11 @@
1
1
  export declare function outputSuccess(data: unknown): void;
2
+ /**
3
+ * Emit a prompt body verbatim to stdout — used by `bridge guide …` commands
4
+ * whose output is intended to be read by a human or pasted to an AI agent.
5
+ * Wrapping the markdown in a JSON envelope makes it unreadable in a terminal
6
+ * and forces scripts to parse JSON to recover the original text. Use the
7
+ * `--json` flag on each guide command if the envelope is needed for tooling.
8
+ */
9
+ export declare function outputPrompt(content: string): void;
2
10
  export declare function outputError(error: unknown): void;
3
11
  //# sourceMappingURL=output.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CA2BhD"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CA2BhD"}
package/dist/output.js CHANGED
@@ -4,6 +4,16 @@ export function outputSuccess(data) {
4
4
  const output = { success: true, data };
5
5
  process.stdout.write(JSON.stringify(output, null, 2) + '\n');
6
6
  }
7
+ /**
8
+ * Emit a prompt body verbatim to stdout — used by `bridge guide …` commands
9
+ * whose output is intended to be read by a human or pasted to an AI agent.
10
+ * Wrapping the markdown in a JSON envelope makes it unreadable in a terminal
11
+ * and forces scripts to parse JSON to recover the original text. Use the
12
+ * `--json` flag on each guide command if the envelope is needed for tooling.
13
+ */
14
+ export function outputPrompt(content) {
15
+ process.stdout.write(content.endsWith('\n') ? content : content + '\n');
16
+ }
7
17
  export function outputError(error) {
8
18
  let code = 'UNKNOWN_ERROR';
9
19
  let message = 'An unknown error occurred';
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,IAAI,GAAG,eAAe,CAAC;IAC3B,IAAI,OAAO,GAAG,2BAA2B,CAAC;IAC1C,IAAI,OAAO,GAAY,SAAS,CAAC;IACjC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,IAAI,GAAG,cAAc,CAAC;QACtB,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QACxB,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;SAAM,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QACtC,IAAI,GAAG,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QACxB,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;QACrB,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvC,iCAAiC;QACjC,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,aAAa,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAChF,IAAI,GAAI,KAAK,CAAC,IAA+B,CAAC,WAAW,CAAC;QAC5D,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAClC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IAC3G,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,IAAI,GAAG,eAAe,CAAC;IAC3B,IAAI,OAAO,GAAG,2BAA2B,CAAC;IAC1C,IAAI,OAAO,GAAY,SAAS,CAAC;IACjC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,IAAI,GAAG,cAAc,CAAC;QACtB,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QACxB,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;SAAM,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QACtC,IAAI,GAAG,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QACxB,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;QACrB,QAAQ,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvC,iCAAiC;QACjC,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,aAAa,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAChF,IAAI,GAAI,KAAK,CAAC,IAA+B,CAAC,WAAW,CAAC;QAC5D,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAClC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IAC3G,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC9B,CAAC"}