@garuhq/cli 0.1.2 → 0.3.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/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to `@garuhq/cli` are documented in this file. Format:
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/).
5
5
 
6
+ ## [0.3.0] — 2026-04-28
7
+
8
+ Rolls up the unpublished 0.2.0 work plus a new update notifier into a single
9
+ release.
10
+
11
+ ### Added
12
+
13
+ - `charges list` command — paginated listing of the authenticated seller's
14
+ charges with status, search, and payment-method filters. (Originally
15
+ shipped to git as 0.2.0 but never published to npm.)
16
+ - Startup version-update notifier. The CLI now checks the npm registry once
17
+ every 24h (in a detached background process) and prints a banner at process
18
+ exit when a newer `@garuhq/cli` is available, suggesting how to update.
19
+ Silent on offline / network failures.
20
+
21
+ ### Changed
22
+
23
+ - `@garuhq/node` SDK bumped to 0.2.0 (also from the unpublished 0.2.0 batch).
24
+
6
25
  ## [0.1.2] — 2026-04-08
7
26
 
8
27
  Post-review batch — addresses all findings from an internal code review.
package/README.md CHANGED
@@ -1,57 +1,82 @@
1
- # garu-cli
1
+ # Garu CLI
2
2
 
3
- Official command-line interface for the [Garu](https://garu.com.br) payment gateway.
3
+ The official CLI for [Garu](https://garu.com.br), the Brazilian payment gateway.
4
+
5
+ Built for developers, AI agents, and CI/CD pipelines.
4
6
 
5
7
  ```
6
- $ garu charges create --type pix --product-id prod-uuid \
7
- --customer-name "Maria Silva" \
8
- --customer-email maria@exemplo.com.br \
9
- --customer-document 12345678909 \
10
- --customer-phone 11987654321
11
- Charge 4472
12
- status: pending
13
- amount: 4990
14
- method: pix
15
- date: 2026-04-08T18:30:00.000Z
8
+ ██████╗ █████╗ ██████╗ ██╗ ██╗
9
+ ██╔════╝ ██╔══██╗██╔══██╗██║ ██║
10
+ ██║ ███╗███████║██████╔╝██║ ██║
11
+ ██║ ██║██╔══██║██╔══██╗██║ ██║
12
+ ╚██████╔╝██║ ██║██║ ██║╚██████╔╝
13
+ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝
16
14
  ```
17
15
 
18
16
  ## Install
19
17
 
20
- ```bash
21
- # curl | bash (Linux, macOS)
18
+ ### cURL (Linux, macOS)
19
+
20
+ ```sh
22
21
  curl -fsSL https://raw.githubusercontent.com/Garu-Pagamentos/garu-cli/main/install.sh | bash
22
+ ```
23
23
 
24
- # npm (all platforms, including Windows)
24
+ ### Node.js (all platforms)
25
+
26
+ ```sh
25
27
  npm install -g @garuhq/cli
26
28
  ```
27
29
 
28
- > The pretty URL `curl -fsSL https://garu.com.br/install.sh | bash` is coming —
29
- > waiting on the marketing site rebuild (SPEC W1). Use the GitHub raw URL for now.
30
-
31
30
  Verify the install:
32
31
 
33
32
  ```bash
34
33
  garu doctor
35
34
  ```
36
35
 
36
+ ## Quickstart
37
+
38
+ ```bash
39
+ # Authenticate
40
+ garu login
41
+
42
+ # Create a PIX charge
43
+ garu charges create --type pix --product-id prod-uuid \
44
+ --customer-name "Maria Silva" \
45
+ --customer-email maria@exemplo.com.br \
46
+ --customer-document 12345678909 \
47
+ --customer-phone 11987654321
48
+
49
+ # List recent charges
50
+ garu charges list
51
+
52
+ # Check your environment
53
+ garu doctor
54
+ ```
55
+
56
+ ---
57
+
37
58
  ## Authentication
38
59
 
39
- The CLI resolves your API key from the first of:
60
+ The CLI resolves your API key using the following priority chain:
61
+
62
+ | Priority | Source | How to set |
63
+ | ----------- | ------------------------ | --------------------------------------- |
64
+ | 1 (highest) | `--api-key` flag | `garu --api-key sk_live_... charges list` |
65
+ | 2 | `GARU_API_KEY` env var | `export GARU_API_KEY=sk_live_...` |
66
+ | 3 (lowest) | Config file | `garu login` |
40
67
 
41
- 1. `--api-key <key>` flag
42
- 2. `GARU_API_KEY` environment variable
43
- 3. `~/.config/garu/credentials.json` (created by `garu login`, mode `0600`)
68
+ If no key is found from any source, the CLI errors with code `auth_error`.
44
69
 
45
- ### Interactive
70
+ ### Interactive mode (default in terminals)
46
71
 
47
72
  ```bash
48
73
  $ garu login
49
74
  ? Paste your Garu API key (sk_live_... or sk_test_...) ****************
50
- Validating key with Garu...
51
- Saved profile 'default' to ~/.config/garu/credentials.json
75
+ -> Validating key with Garu...
76
+ Saved profile 'default' to ~/.config/garu/credentials.json
52
77
  ```
53
78
 
54
- ### Scripted (CI)
79
+ ### Non-interactive mode (CI, pipes, scripts)
55
80
 
56
81
  ```bash
57
82
  export GARU_API_KEY=sk_live_...
@@ -60,54 +85,172 @@ garu charges create --type pix ...
60
85
 
61
86
  ### Multi-profile
62
87
 
88
+ Switch between test and production without logging in and out:
89
+
63
90
  ```bash
64
91
  garu login --profile test --api-key sk_test_...
65
92
  garu login --profile live --api-key sk_live_...
66
93
  garu auth switch live
67
94
  ```
68
95
 
96
+ You can also use the global `--profile` (or `-p`) flag on any command:
97
+
98
+ ```bash
99
+ garu charges list --profile production
100
+ ```
101
+
102
+ ---
103
+
69
104
  ## Commands
70
105
 
71
- | Command | Description |
72
- | -------------------------------- | ------------------------------------------- |
73
- | `garu login` | Paste an API key, validate, save |
74
- | `garu logout [--profile <name>]` | Remove saved credentials |
75
- | `garu auth switch <profile>` | Set the active credentials profile |
76
- | `garu charges create` | Create a PIX, credit-card, or boleto charge |
77
- | `garu charges get <id>` | Fetch a single charge |
78
- | `garu charges refund <id>` | Refund a charge (full or partial) |
79
- | `garu doctor` | Environment diagnostic |
80
- | `garu --version` | Print the CLI version |
81
- | `garu --help` | Top-level help |
106
+ ### `garu login`
107
+
108
+ Authenticate by storing your API key locally. The key is validated against the Garu API before being saved.
109
+
110
+ ```bash
111
+ garu login
112
+ garu login --api-key sk_live_... --profile production
113
+ ```
114
+
115
+ | Flag | Description |
116
+ | ---------------------- | ---------------------------------------- |
117
+ | `--api-key <key>` | Pre-supply the key instead of prompting |
118
+ | `-p, --profile <name>` | Profile name to store under (default: `default`) |
82
119
 
83
- See `garu <command> --help` for per-command flags.
120
+ On success, credentials are saved to `~/.config/garu/credentials.json` with `0600` permissions (owner read/write only).
84
121
 
85
- ## Output modes
122
+ ---
86
123
 
87
- The CLI auto-detects whether it's running interactively:
124
+ ### `garu logout`
88
125
 
89
- - **TTY (pretty):** colored output, status lines on stderr, formatted result on stdout.
90
- - **Pipe / CI / `--json`:** strict JSON on stdout, errors as `{"error":{"code","message"}}` on stdout with exit code 1. Nothing on stderr in this mode.
126
+ Remove saved credentials.
91
127
 
92
128
  ```bash
93
- # Pipe-safe
94
- garu charges get 4472 | jq '.status'
129
+ garu logout
130
+ garu logout --profile test
131
+ ```
132
+
133
+ | Flag | Description |
134
+ | ---------------------- | ---------------------------------------------------- |
135
+ | `-p, --profile <name>` | Only remove this profile instead of the whole file |
136
+
137
+ ---
138
+
139
+ ### `garu auth switch`
140
+
141
+ Set the active credentials profile.
142
+
143
+ ```bash
144
+ garu auth switch live
145
+ ```
146
+
147
+ ---
148
+
149
+ ### `garu charges list`
150
+
151
+ List charges with pagination and filters.
152
+
153
+ ```bash
154
+ garu charges list
155
+ garu charges list --status paid --limit 50
156
+ garu charges list --search "Maria" --payment-method pix
95
157
  ```
96
158
 
97
- Global flags:
159
+ | Flag | Description |
160
+ | --------------------------- | ---------------------------------------------- |
161
+ | `--page <n>` | Page number (1-based) |
162
+ | `--limit <n>` | Items per page (1-100) |
163
+ | `--status <status>` | Filter by status (e.g. `paid`, `pending`) |
164
+ | `--search <query>` | Search by customer name, email, or document |
165
+ | `--payment-method <method>` | Filter: `pix`, `creditcard`, `boleto` |
166
+
167
+ ---
168
+
169
+ ### `garu charges create`
98
170
 
99
- - `--api-key <key>` override auth chain
100
- - `-p, --profile <name>` — use a specific credentials profile
101
- - `--json` — force JSON output
102
- - `-q, --quiet` — suppress status lines
171
+ Create a PIX, credit card, or boleto charge.
103
172
 
104
- ## `garu doctor`
173
+ ```bash
174
+ # PIX charge
175
+ garu charges create --type pix --product-id prod-uuid \
176
+ --customer-name "Maria Silva" \
177
+ --customer-email maria@exemplo.com.br \
178
+ --customer-document 12345678909 \
179
+ --customer-phone 11987654321
180
+
181
+ # Credit card charge
182
+ garu charges create --type credit_card --product-id prod-uuid \
183
+ --customer-name "Maria Silva" \
184
+ --customer-email maria@exemplo.com.br \
185
+ --customer-document 12345678909 \
186
+ --customer-phone 11987654321 \
187
+ --card-number 4111111111111111 \
188
+ --card-cvv 123 \
189
+ --card-expiration 2030-12 \
190
+ --card-holder "MARIA SILVA" \
191
+ --installments 3
192
+ ```
105
193
 
106
- Prints a structured report of your environment:
194
+ | Flag | Required | Description |
195
+ | -------------------------------- | -------- | ------------------------------------------ |
196
+ | `--type <type>` | Yes | Payment method: `pix`, `credit_card`, `boleto` |
197
+ | `--product-id <uuid>` | Yes | Product UUID |
198
+ | `--customer-name <name>` | Yes | Customer full name |
199
+ | `--customer-email <email>` | Yes | Customer email |
200
+ | `--customer-document <doc>` | Yes | CPF (11 digits) or CNPJ (14 digits) |
201
+ | `--customer-phone <phone>` | Yes | Phone with area code, digits only |
202
+ | `--card-number <number>` | credit_card | Credit card number |
203
+ | `--card-cvv <cvv>` | credit_card | Credit card CVV |
204
+ | `--card-expiration <yyyy-mm>` | credit_card | Expiration date |
205
+ | `--card-holder <name>` | credit_card | Cardholder name |
206
+ | `--installments <n>` | No | Number of installments, 1-12 (default: 1) |
207
+ | `--additional-info <text>` | No | Free-form metadata |
208
+ | `--idempotency-key <key>` | No | Idempotency key (auto-generated if omitted) |
209
+
210
+ ---
211
+
212
+ ### `garu charges get`
213
+
214
+ Fetch a single charge by ID.
215
+
216
+ ```bash
217
+ garu charges get 4472
218
+ garu charges get 4472 --json | jq '.status'
219
+ ```
220
+
221
+ ---
222
+
223
+ ### `garu charges refund`
224
+
225
+ Refund a charge (full or partial).
226
+
227
+ ```bash
228
+ # Full refund
229
+ garu charges refund 4472
230
+
231
+ # Partial refund (1000 centavos = R$10.00)
232
+ garu charges refund 4472 --amount 1000 --reason "customer_request"
233
+ ```
234
+
235
+ | Flag | Description |
236
+ | ------------------------- | --------------------------------------------- |
237
+ | `--amount <centavos>` | Partial refund amount in centavos (omit for full) |
238
+ | `--reason <text>` | Optional refund reason |
239
+ | `--idempotency-key <key>` | Idempotency key (auto-generated if omitted) |
240
+
241
+ ---
242
+
243
+ ### `garu doctor`
244
+
245
+ Run environment diagnostics. Verifies your CLI version, API connectivity, credentials, and detects AI agent integrations.
246
+
247
+ ```bash
248
+ garu doctor
249
+ ```
107
250
 
108
251
  ```json
109
252
  {
110
- "cli": { "version": "0.1.0" },
253
+ "cli": { "version": "0.2.0" },
111
254
  "api": { "reachable": true, "url": "https://garu.com.br", "version": "1.3.2" },
112
255
  "credentials": { "path": "...", "source": "file", "profile": "default", "fileMode": "0600" },
113
256
  "agents": {
@@ -121,6 +264,94 @@ Prints a structured report of your environment:
121
264
  }
122
265
  ```
123
266
 
267
+ ---
268
+
269
+ ## Global options
270
+
271
+ These flags work on every command:
272
+
273
+ ```bash
274
+ garu [global options] <command> [command options]
275
+ ```
276
+
277
+ | Flag | Description |
278
+ | ---------------------- | ------------------------------------------------------------ |
279
+ | `--api-key <key>` | Override API key for this invocation (takes highest priority) |
280
+ | `-p, --profile <name>` | Credentials profile to use |
281
+ | `--json` | Force JSON output even in interactive terminals |
282
+ | `-q, --quiet` | Suppress status output; only print results and errors |
283
+ | `-v, --version` | Print version and exit |
284
+ | `--help` | Show help text |
285
+
286
+ ---
287
+
288
+ ## Output behavior
289
+
290
+ The CLI has two output modes:
291
+
292
+ | Mode | When | Stdout | Stderr |
293
+ | --------------- | ---------------------- | -------------- | ---------------- |
294
+ | **Interactive** | Terminal (TTY) | Formatted text | Status lines |
295
+ | **Machine** | Piped, CI, or `--json` | JSON | Nothing |
296
+
297
+ Switching is automatic -- pipe to another command and JSON output activates:
298
+
299
+ ```bash
300
+ garu charges get 4472 | jq '.status'
301
+ garu charges list --status paid | jq '.data[].id'
302
+ ```
303
+
304
+ ### Error output
305
+
306
+ Errors exit with code `1` and output structured JSON to stdout:
307
+
308
+ ```json
309
+ { "error": { "code": "auth_error", "message": "No API key found" } }
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Agent & CI/CD usage
315
+
316
+ ### CI/CD
317
+
318
+ Set `GARU_API_KEY` as an environment variable -- no `garu login` needed:
319
+
320
+ ```yaml
321
+ # GitHub Actions
322
+ env:
323
+ GARU_API_KEY: ${{ secrets.GARU_API_KEY }}
324
+ steps:
325
+ - run: garu charges list --status pending --json
326
+ ```
327
+
328
+ ### AI agents
329
+
330
+ Agents calling the CLI as a subprocess automatically get JSON output (non-TTY detection). The contract:
331
+
332
+ - **Input:** All required flags must be provided (no interactive prompts)
333
+ - **Output:** JSON to stdout, nothing to stderr
334
+ - **Exit code:** `0` success, `1` error
335
+ - **Errors:** Always include `code` and `message` fields
336
+
337
+ ---
338
+
339
+ ## Configuration
340
+
341
+ | Item | Path | Notes |
342
+ | ----------------- | --------------------------------- | ----------------------------------------- |
343
+ | Config directory | `~/.config/garu/` | Respects `$XDG_CONFIG_HOME` |
344
+ | Credentials | `~/.config/garu/credentials.json` | `0600` permissions (owner read/write) |
345
+ | Override path | `$GARU_CREDENTIALS_PATH` | Point to a custom credentials file |
346
+
347
+ ---
348
+
349
+ ## Security
350
+
351
+ See [SECURITY.md](SECURITY.md) for our vulnerability disclosure policy.
352
+
353
+ > **Note on credit card flags:** The `--card-number`, `--card-cvv`, and `--card-expiration` flags pass data via command-line arguments, which may be visible in shell history and process listings. For production card processing, use the [`@garuhq/node`](https://www.npmjs.com/package/@garuhq/node) SDK directly.
354
+
124
355
  ## License
125
356
 
126
- MIT.
357
+ MIT
package/dist/index.cjs CHANGED
@@ -15,7 +15,7 @@ var pc__default = /*#__PURE__*/_interopDefault(pc);
15
15
  // src/index.ts
16
16
 
17
17
  // src/version.ts
18
- var CLI_VERSION = "0.1.2";
18
+ var CLI_VERSION = "0.3.0";
19
19
  var CliError = class extends Error {
20
20
  code;
21
21
  exitCode;
@@ -289,6 +289,28 @@ async function chargesRefundCommand(opts) {
289
289
  printResult(charge, { ...opts, prettyPrint: prettyCharge });
290
290
  return charge;
291
291
  }
292
+ async function chargesListCommand(opts) {
293
+ const garu = await getClient(opts);
294
+ const params = {};
295
+ if (opts.page !== void 0) params.page = opts.page;
296
+ if (opts.limit !== void 0) params.limit = opts.limit;
297
+ if (opts.status !== void 0) params.status = opts.status;
298
+ if (opts.search !== void 0) params.search = opts.search;
299
+ if (opts.paymentMethod !== void 0) params.paymentMethod = opts.paymentMethod;
300
+ const result = await garu.charges.list(params);
301
+ printResult(result, { ...opts, prettyPrint: prettyChargeList });
302
+ return result;
303
+ }
304
+ function prettyChargeList(list) {
305
+ if (list.data.length === 0) {
306
+ return `No charges found (page ${list.meta.page}/${list.meta.totalPages || 1})`;
307
+ }
308
+ const header = `Charges (page ${list.meta.page}/${list.meta.totalPages || "?"}, ${list.meta.total} total)`;
309
+ const rows = list.data.map(
310
+ (c) => ` ${String(c.id).padStart(6)} ${String(c.status).padEnd(14)} ${c.paymentMethodId?.padEnd(10) ?? ""} ${c.date}`
311
+ );
312
+ return [header, ...rows].join("\n");
313
+ }
292
314
  function prettyCharge(charge) {
293
315
  const lines = [
294
316
  `Charge ${charge.id}`,
@@ -467,6 +489,17 @@ function buildCli() {
467
489
  );
468
490
  });
469
491
  const charges = program.command("charges").description("Create, fetch, and refund charges");
492
+ charges.command("list").description("List charges with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option("--status <status>", "filter by status (e.g. paid, pending)").option("--search <query>", "search by customer name, email, or document").option("--payment-method <method>", "filter: pix, creditcard, boleto").action(async (cmdOpts) => {
493
+ const base = toCommandOptions(program);
494
+ await chargesListCommand({
495
+ ...base,
496
+ page: cmdOpts.page,
497
+ limit: cmdOpts.limit,
498
+ status: cmdOpts.status,
499
+ search: cmdOpts.search,
500
+ paymentMethod: cmdOpts.paymentMethod
501
+ }).catch((err) => printErrorAndExit(err, base));
502
+ });
470
503
  charges.command("create").description("Create a charge (PIX, credit card, or boleto)").requiredOption("--type <type>", "payment method: pix | credit_card | boleto").requiredOption("--product-id <uuid>", "product UUID").requiredOption("--customer-name <name>", "customer full name").requiredOption("--customer-email <email>", "customer email").requiredOption(
471
504
  "--customer-document <document>",
472
505
  "CPF (11 digits) or CNPJ (14 digits), digits only"
@@ -534,7 +567,18 @@ function parseId(raw) {
534
567
  }
535
568
  return id;
536
569
  }
570
+ async function setupUpdateNotifier() {
571
+ try {
572
+ const { default: updateNotifier } = await import('update-notifier');
573
+ updateNotifier({
574
+ pkg: { name: "@garuhq/cli", version: CLI_VERSION },
575
+ updateCheckInterval: 1e3 * 60 * 60 * 24
576
+ }).notify();
577
+ } catch {
578
+ }
579
+ }
537
580
  async function main(argv = process.argv) {
581
+ await setupUpdateNotifier();
538
582
  const program = buildCli();
539
583
  await program.parseAsync(argv);
540
584
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garuhq/cli",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Official command-line interface for the Garu payment gateway.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://garu.com.br",
@@ -27,7 +27,8 @@
27
27
  "types": "./dist/index.d.ts",
28
28
  "files": [
29
29
  "bin",
30
- "dist",
30
+ "dist/index.cjs",
31
+ "dist/index.d.cts",
31
32
  "README.md",
32
33
  "CHANGELOG.md",
33
34
  "LICENSE"
@@ -44,13 +45,15 @@
44
45
  "prepublishOnly": "npm run typecheck && npm test && npm run build"
45
46
  },
46
47
  "dependencies": {
47
- "@garuhq/node": "0.1.0",
48
+ "@garuhq/node": "0.2.0",
48
49
  "@inquirer/prompts": "8.4.1",
49
50
  "commander": "12.0.0",
50
- "picocolors": "1.0.0"
51
+ "picocolors": "1.0.0",
52
+ "update-notifier": "7.3.1"
51
53
  },
52
54
  "devDependencies": {
53
55
  "@types/node": "20.12.7",
56
+ "@types/update-notifier": "6.0.8",
54
57
  "tsup": "8.5.1",
55
58
  "tsx": "4.21.0",
56
59
  "typescript": "5.4.5",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/version.ts","../src/lib/errors.ts","../src/lib/credentials.ts","../src/lib/output.ts","../src/commands/auth-switch.ts","../src/lib/auth.ts","../src/lib/client.ts","../src/commands/charges.ts","../src/commands/doctor.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/index.ts"],"names":["GaruError","join","homedir","readFile","path","mkdir","dirname","writeFile","rm","stat","pc","Garu","platform","existsSync","Command","Option"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * CLI version.\n *\n * Kept as a plain string so `bun build --compile` can inline it at compile time\n * and the resulting binary has no runtime dependency on `package.json`.\n * The release workflow bumps this in lockstep with `package.json` on `v*` tags.\n */\nexport const CLI_VERSION = '0.1.2';\n","/**\n * CLI error model. All user-visible failures flow through these types so that\n * the output layer can render them consistently — pretty with a red prefix in\n * TTY mode, strict `{\"error\":{\"code\",\"message\"}}` on stdout + exit 1 in JSON mode.\n */\n\nimport { GaruError } from '@garuhq/node';\n\nexport type CliErrorCode =\n | 'auth_error'\n | 'not_found'\n | 'validation_error'\n | 'rate_limited'\n | 'server_error'\n | 'connection_error'\n | 'signature_verification_failed'\n | 'user_cancelled'\n | 'invalid_input'\n | 'unknown_error';\n\nexport class CliError extends Error {\n public readonly code: CliErrorCode;\n public readonly exitCode: number;\n\n constructor(code: CliErrorCode, message: string, exitCode = 1) {\n super(message);\n this.name = 'CliError';\n this.code = code;\n this.exitCode = exitCode;\n }\n}\n\n/** Wrap an unknown thrown value as a {@link CliError}. */\nexport function toCliError(err: unknown): CliError {\n if (err instanceof CliError) return err;\n if (err instanceof GaruError) {\n return new CliError(mapSdkCodeToCliCode(err.code), err.message, 1);\n }\n if (err instanceof Error) return new CliError('unknown_error', err.message);\n return new CliError('unknown_error', String(err));\n}\n\nfunction mapSdkCodeToCliCode(sdkCode: string): CliErrorCode {\n switch (sdkCode) {\n case 'authentication_error':\n case 'permission_error':\n return 'auth_error';\n case 'not_found':\n return 'not_found';\n case 'validation_error':\n return 'validation_error';\n case 'rate_limited':\n return 'rate_limited';\n case 'server_error':\n return 'server_error';\n case 'connection_error':\n return 'connection_error';\n case 'signature_verification_failed':\n return 'signature_verification_failed';\n default:\n return 'unknown_error';\n }\n}\n","import { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { mkdir, readFile, writeFile, rm, stat } from 'node:fs/promises';\n\nimport { CliError } from './errors.js';\n\nexport interface CredentialProfile {\n apiKey: string;\n /** Optional seller ID to render in `garu doctor` output. */\n sellerId?: number;\n /** Human-readable label for multi-profile setups. */\n label?: string;\n}\n\nexport interface CredentialsFile {\n version: 1;\n activeProfile: string;\n profiles: Record<string, CredentialProfile>;\n}\n\nconst DEFAULT_FILE: CredentialsFile = {\n version: 1,\n activeProfile: 'default',\n profiles: {}\n};\n\n/**\n * Resolve the credentials file path.\n *\n * Honors `$XDG_CONFIG_HOME` per the XDG base-dir spec, falling back to\n * `~/.config/garu/credentials.json`. Override with `$GARU_CREDENTIALS_PATH`\n * (primarily for tests).\n */\nexport function credentialsPath(env: NodeJS.ProcessEnv = process.env): string {\n if (env.GARU_CREDENTIALS_PATH) return env.GARU_CREDENTIALS_PATH;\n const base = env.XDG_CONFIG_HOME || join(homedir(), '.config');\n return join(base, 'garu', 'credentials.json');\n}\n\n/** Read the credentials file. Returns the default (empty) file if it doesn't exist. */\nexport async function loadCredentials(\n env: NodeJS.ProcessEnv = process.env\n): Promise<CredentialsFile> {\n const path = credentialsPath(env);\n try {\n const raw = await readFile(path, 'utf8');\n const parsed = JSON.parse(raw);\n return normalize(parsed);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return { ...DEFAULT_FILE };\n }\n throw new CliError(\n 'invalid_input',\n `Failed to read credentials at ${path}: ${(err as Error).message}`\n );\n }\n}\n\n/**\n * Write the credentials file atomically with tight file-mode (0600) and\n * directory-mode (0700).\n */\nexport async function saveCredentials(\n file: CredentialsFile,\n env: NodeJS.ProcessEnv = process.env\n): Promise<void> {\n const path = credentialsPath(env);\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n await writeFile(path, JSON.stringify(file, null, 2) + '\\n', { mode: 0o600 });\n}\n\n/** Delete the credentials file. No-op if it doesn't exist. */\nexport async function deleteCredentials(env: NodeJS.ProcessEnv = process.env): Promise<void> {\n const path = credentialsPath(env);\n try {\n await rm(path);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n}\n\n/** Add or replace a profile and set it active. */\nexport function upsertProfile(\n file: CredentialsFile,\n name: string,\n profile: CredentialProfile\n): CredentialsFile {\n return {\n ...file,\n activeProfile: name,\n profiles: { ...file.profiles, [name]: profile }\n };\n}\n\n/** Check whether the credentials file has the expected 0600 mode. Returns null on any error. */\nexport async function credentialsFileMode(\n env: NodeJS.ProcessEnv = process.env\n): Promise<number | null> {\n try {\n const s = await stat(credentialsPath(env));\n return s.mode & 0o777;\n } catch {\n return null;\n }\n}\n\nfunction normalize(raw: unknown): CredentialsFile {\n if (!raw || typeof raw !== 'object') return { ...DEFAULT_FILE };\n const obj = raw as Partial<CredentialsFile>;\n return {\n version: 1,\n activeProfile: obj.activeProfile ?? 'default',\n profiles: obj.profiles && typeof obj.profiles === 'object' ? obj.profiles : {}\n };\n}\n","import pc from 'picocolors';\n\nimport { CliError, toCliError } from './errors.js';\n\nexport type OutputMode = 'pretty' | 'json';\n\nexport interface OutputOptions {\n /** Force a mode. If omitted, auto-detect from TTY. */\n mode?: OutputMode;\n /** Passed by `--quiet`; suppresses everything except errors and the final value. */\n quiet?: boolean;\n}\n\n/**\n * Resolve the output mode. Rules:\n * - Explicit `--json` (or `opts.mode === 'json'`) wins.\n * - Non-TTY stdout (pipe, CI) → `json`.\n * - Everything else → `pretty`.\n */\nexport function resolveMode(\n opts: OutputOptions = {},\n stdout: NodeJS.WriteStream = process.stdout\n): OutputMode {\n if (opts.mode) return opts.mode;\n return stdout.isTTY ? 'pretty' : 'json';\n}\n\n/**\n * Print a successful command result. In JSON mode the full object is written\n * to stdout with a trailing newline. In pretty mode the caller's `prettyPrint`\n * fallback (if provided) is used; otherwise the JSON is indented.\n */\nexport function printResult<T>(\n value: T,\n opts: OutputOptions & { prettyPrint?: (value: T) => string } = {}\n): void {\n const mode = resolveMode(opts);\n if (mode === 'json') {\n process.stdout.write(`${JSON.stringify(value)}\\n`);\n return;\n }\n if (opts.prettyPrint) {\n process.stdout.write(`${opts.prettyPrint(value)}\\n`);\n return;\n }\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\n/** Print a short status line — suppressed in JSON mode and when `--quiet`. */\nexport function printStatus(message: string, opts: OutputOptions = {}): void {\n if (opts.quiet) return;\n if (resolveMode(opts) === 'json') return;\n process.stderr.write(`${pc.dim('→')} ${message}\\n`);\n}\n\n/** Print a success line — suppressed in JSON mode and when `--quiet`. */\nexport function printSuccess(message: string, opts: OutputOptions = {}): void {\n if (opts.quiet) return;\n if (resolveMode(opts) === 'json') return;\n process.stderr.write(`${pc.green('✓')} ${message}\\n`);\n}\n\n/**\n * Print an error and exit with the appropriate code. Always uses the\n * CLI-standard shape `{\"error\":{\"code\",\"message\"}}` on stdout in JSON mode,\n * or a red `Error:` line on stderr in pretty mode.\n */\nexport function printErrorAndExit(err: unknown, opts: OutputOptions = {}): never {\n const cliErr: CliError = toCliError(err);\n const payload = { error: { code: cliErr.code, message: cliErr.message } };\n\n if (resolveMode(opts) === 'json') {\n process.stdout.write(`${JSON.stringify(payload)}\\n`);\n } else {\n process.stderr.write(`${pc.red('Error:')} ${cliErr.message}\\n`);\n if (cliErr.code !== 'unknown_error') {\n process.stderr.write(`${pc.dim(` code: ${cliErr.code}`)}\\n`);\n }\n }\n process.exit(cliErr.exitCode);\n}\n","import { loadCredentials, saveCredentials } from '../lib/credentials.js';\nimport { CliError } from '../lib/errors.js';\nimport { printSuccess, type OutputOptions } from '../lib/output.js';\n\nexport interface AuthSwitchOptions extends OutputOptions {\n profile: string;\n}\n\nexport async function authSwitchCommand(\n opts: AuthSwitchOptions\n): Promise<{ activeProfile: string }> {\n const file = await loadCredentials();\n if (!file.profiles[opts.profile]) {\n const available = Object.keys(file.profiles).join(', ') || '(none)';\n throw new CliError('not_found', `Profile '${opts.profile}' not found. Available: ${available}`);\n }\n\n await saveCredentials({ ...file, activeProfile: opts.profile });\n printSuccess(`Active profile set to '${opts.profile}'.`, opts);\n return { activeProfile: opts.profile };\n}\n","import { loadCredentials, type CredentialProfile } from './credentials.js';\nimport { CliError } from './errors.js';\n\nexport interface ResolvedAuth {\n apiKey: string;\n /** Where the key came from, for `doctor` and debug output. */\n source: 'flag' | 'env' | 'file';\n /** Profile name if resolved from file; undefined otherwise. */\n profile?: string;\n fileProfile?: CredentialProfile;\n}\n\nexport interface ResolveAuthOptions {\n /** `--api-key` flag value. Highest precedence. */\n apiKey?: string;\n /** `--profile` flag value. When set, reads that profile instead of the active one. */\n profile?: string;\n env?: NodeJS.ProcessEnv;\n}\n\n/**\n * Resolve the API key following SPEC §7 auth priority:\n *\n * 1. `--api-key` flag\n * 2. `GARU_API_KEY` environment variable\n * 3. credentials file active profile (or profile selected with `--profile`)\n *\n * Throws {@link CliError} with code `auth_error` if no key is found. Never logs.\n */\nexport async function resolveAuth(opts: ResolveAuthOptions = {}): Promise<ResolvedAuth> {\n const env = opts.env ?? process.env;\n\n if (opts.apiKey) {\n return { apiKey: opts.apiKey, source: 'flag' };\n }\n\n if (env.GARU_API_KEY) {\n return { apiKey: env.GARU_API_KEY, source: 'env' };\n }\n\n const file = await loadCredentials(env);\n const profileName = opts.profile ?? file.activeProfile;\n const profile = file.profiles[profileName];\n if (profile && profile.apiKey) {\n return {\n apiKey: profile.apiKey,\n source: 'file',\n profile: profileName,\n fileProfile: profile\n };\n }\n\n throw new CliError('auth_error', 'No API key found. Run `garu login` or set GARU_API_KEY.');\n}\n\n/**\n * Same as {@link resolveAuth} but returns `null` instead of throwing when no\n * credentials are available. Used by `garu doctor`.\n */\nexport async function resolveAuthOptional(\n opts: ResolveAuthOptions = {}\n): Promise<ResolvedAuth | null> {\n try {\n return await resolveAuth(opts);\n } catch (err) {\n if (err instanceof CliError && err.code === 'auth_error') return null;\n throw err;\n }\n}\n","import { Garu } from '@garuhq/node';\n\nimport type { ResolvedAuth } from './auth.js';\n\nexport interface GaruClientOptions {\n auth: ResolvedAuth;\n baseUrl?: string;\n}\n\n/**\n * Construct a `Garu` SDK instance from resolved auth.\n *\n * The CLI dogfoods `@garuhq/node` — every HTTP call flows through the SDK we\n * shipped in Chunk 3. This keeps retries, idempotency, and error mapping\n * consistent between the CLI, MCP server, and any user-written integration.\n */\nexport function createGaruClient(opts: GaruClientOptions): Garu {\n return new Garu({\n apiKey: opts.auth.apiKey,\n baseUrl: opts.baseUrl\n });\n}\n","import type { Charge, Customer, Garu, PaymentMethod, RefundChargeParams } from '@garuhq/node';\n\nimport { resolveAuth } from '../lib/auth.js';\nimport { createGaruClient } from '../lib/client.js';\nimport { CliError } from '../lib/errors.js';\nimport { printResult, type OutputOptions } from '../lib/output.js';\n\nexport interface ChargesGlobalOptions extends OutputOptions {\n apiKey?: string;\n profile?: string;\n baseUrl?: string;\n /** Injectable for tests — bypass auth resolution + SDK construction. */\n garu?: Garu;\n}\n\nexport interface ChargesCreateOptions extends ChargesGlobalOptions {\n type: PaymentMethod;\n productId: string;\n customerName: string;\n customerEmail: string;\n customerDocument: string;\n customerPhone: string;\n cardNumber?: string;\n cardCvv?: string;\n cardExpiration?: string;\n cardHolder?: string;\n installments?: number;\n idempotencyKey?: string;\n additionalInfo?: string;\n}\n\nexport interface ChargesByIdOptions extends ChargesGlobalOptions {\n id: number;\n}\n\nexport interface ChargesRefundOptions extends ChargesByIdOptions {\n /** Amount in centavos. Omit for full refund. */\n amount?: number;\n reason?: string;\n idempotencyKey?: string;\n}\n\nasync function getClient(opts: ChargesGlobalOptions): Promise<Garu> {\n if (opts.garu) return opts.garu;\n const auth = await resolveAuth({\n ...(opts.apiKey !== undefined ? { apiKey: opts.apiKey } : {}),\n ...(opts.profile !== undefined ? { profile: opts.profile } : {})\n });\n return createGaruClient({\n auth,\n ...(opts.baseUrl !== undefined ? { baseUrl: opts.baseUrl } : {})\n });\n}\n\ntype ValidatedCardFields = ChargesCreateOptions & {\n cardNumber: string;\n cardCvv: string;\n cardExpiration: string;\n cardHolder: string;\n};\n\n/**\n * Assert that a credit-card charge request has every required card field.\n * Narrows the type so downstream code doesn't need `!` assertions.\n */\nfunction assertCardFieldsPresent(opts: ChargesCreateOptions): asserts opts is ValidatedCardFields {\n const missing: string[] = [];\n if (!opts.cardNumber) missing.push('--card-number');\n if (!opts.cardCvv) missing.push('--card-cvv');\n if (!opts.cardExpiration) missing.push('--card-expiration');\n if (!opts.cardHolder) missing.push('--card-holder');\n if (missing.length) {\n throw new CliError('invalid_input', `Credit-card charges require: ${missing.join(', ')}`);\n }\n}\n\nexport async function chargesCreateCommand(opts: ChargesCreateOptions): Promise<Charge> {\n const garu = await getClient(opts);\n\n const customer: Customer = {\n name: opts.customerName,\n email: opts.customerEmail,\n document: opts.customerDocument,\n phone: opts.customerPhone\n };\n\n const base = {\n productId: opts.productId,\n paymentMethod: opts.type,\n customer,\n additionalInfo: opts.additionalInfo,\n idempotencyKey: opts.idempotencyKey\n };\n\n let charge: Charge;\n if (opts.type === 'credit_card') {\n assertCardFieldsPresent(opts);\n charge = await garu.charges.create({\n ...base,\n cardInfo: {\n cardNumber: opts.cardNumber,\n cvv: opts.cardCvv,\n expirationDate: opts.cardExpiration,\n holderName: opts.cardHolder,\n installments: opts.installments ?? 1\n }\n });\n } else {\n charge = await garu.charges.create(base);\n }\n\n printResult(charge, { ...opts, prettyPrint: prettyCharge });\n return charge;\n}\n\nexport async function chargesGetCommand(opts: ChargesByIdOptions): Promise<Charge> {\n const garu = await getClient(opts);\n const charge = await garu.charges.get(opts.id);\n printResult(charge, { ...opts, prettyPrint: prettyCharge });\n return charge;\n}\n\nexport async function chargesRefundCommand(opts: ChargesRefundOptions): Promise<Charge> {\n const garu = await getClient(opts);\n const params: RefundChargeParams = {};\n if (opts.amount !== undefined) params.amount = opts.amount;\n if (opts.reason !== undefined) params.reason = opts.reason;\n if (opts.idempotencyKey !== undefined) params.idempotencyKey = opts.idempotencyKey;\n const charge = await garu.charges.refund(opts.id, params);\n printResult(charge, { ...opts, prettyPrint: prettyCharge });\n return charge;\n}\n\nfunction prettyCharge(charge: Charge): string {\n const lines = [\n `Charge ${charge.id}`,\n ` status: ${charge.status}`,\n ` amount: ${charge.amount}`,\n ` method: ${charge.paymentMethodId}`,\n ` date: ${charge.date}`\n ];\n if (charge.deadline) lines.push(` deadline: ${charge.deadline}`);\n return lines.join('\\n');\n}\n","import { existsSync } from 'node:fs';\nimport { homedir, platform } from 'node:os';\nimport { join } from 'node:path';\n\nimport { Garu } from '@garuhq/node';\n\nimport { resolveAuthOptional } from '../lib/auth.js';\nimport { credentialsFileMode, credentialsPath } from '../lib/credentials.js';\nimport { printResult, type OutputOptions } from '../lib/output.js';\nimport { CLI_VERSION } from '../version.js';\n\nexport interface DoctorReport {\n cli: { version: string };\n api: { reachable: boolean; url: string; version?: string; error?: string };\n credentials: {\n path: string;\n source: 'flag' | 'env' | 'file' | 'none';\n profile?: string;\n fileMode?: string;\n warning?: string;\n };\n agents: {\n claudeCode: boolean;\n cursor: boolean;\n codex: boolean;\n windsurf: boolean;\n claudeDesktop: boolean;\n vscodeMcpInCwd: boolean;\n };\n}\n\nexport interface DoctorOptions extends OutputOptions {\n apiKey?: string;\n profile?: string;\n baseUrl?: string;\n /** Injectable for tests — bypass the real HTTP call. */\n garu?: Garu;\n /** Injectable HOME, for tests. */\n home?: string;\n /** Injectable cwd, for tests. */\n cwd?: string;\n /** Injectable platform, for tests. */\n platform?: NodeJS.Platform;\n}\n\n/**\n * Run a full environment diagnostic.\n *\n * Never throws on expected failures — bad auth, unreachable API, missing\n * credentials all become structured report fields. Only genuinely unexpected\n * errors (programming bugs) bubble up.\n */\nexport async function doctorCommand(opts: DoctorOptions = {}): Promise<DoctorReport> {\n const home = opts.home ?? homedir();\n const cwd = opts.cwd ?? process.cwd();\n const plat = opts.platform ?? platform();\n\n const credentials = await reportCredentials(opts);\n const api = await reportApi(opts);\n const agents = detectAgents(home, cwd, plat);\n\n const report: DoctorReport = {\n cli: { version: CLI_VERSION },\n api,\n credentials,\n agents\n };\n\n printResult(report, { ...opts, prettyPrint: prettyDoctor });\n return report;\n}\n\nasync function reportCredentials(opts: DoctorOptions): Promise<DoctorReport['credentials']> {\n const path = credentialsPath();\n const resolved = await resolveAuthOptional({\n ...(opts.apiKey !== undefined ? { apiKey: opts.apiKey } : {}),\n ...(opts.profile !== undefined ? { profile: opts.profile } : {})\n });\n\n if (!resolved) {\n return { path, source: 'none' };\n }\n\n const out: DoctorReport['credentials'] = { path, source: resolved.source };\n if (resolved.profile) out.profile = resolved.profile;\n\n if (resolved.source === 'file') {\n const mode = await credentialsFileMode();\n if (mode !== null) {\n out.fileMode = `0${mode.toString(8)}`;\n if (mode !== 0o600) {\n out.warning = `credentials file mode is 0${mode.toString(8)}; expected 0600`;\n }\n }\n }\n\n return out;\n}\n\nasync function reportApi(opts: DoctorOptions): Promise<DoctorReport['api']> {\n const url = opts.baseUrl ?? 'https://garu.com.br';\n const garu =\n opts.garu ??\n new Garu({\n ...(opts.baseUrl !== undefined ? { baseUrl: opts.baseUrl } : {})\n });\n\n try {\n const meta = await garu.meta.get();\n return { reachable: true, url, version: meta.version };\n } catch (err) {\n return {\n reachable: false,\n url,\n error: err instanceof Error ? err.message : String(err)\n };\n }\n}\n\nfunction detectAgents(home: string, cwd: string, plat: NodeJS.Platform): DoctorReport['agents'] {\n return {\n claudeCode: existsSync(join(home, '.claude')),\n cursor: existsSync(join(home, '.cursor')),\n codex: existsSync(join(home, '.codex')),\n windsurf: existsSync(join(home, '.windsurf')),\n claudeDesktop: existsSync(claudeDesktopConfigPath(home, plat)),\n vscodeMcpInCwd: existsSync(join(cwd, '.vscode', 'mcp.json'))\n };\n}\n\nfunction claudeDesktopConfigPath(home: string, plat: NodeJS.Platform): string {\n if (plat === 'darwin') {\n return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');\n }\n if (plat === 'win32') {\n return join(home, 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json');\n }\n return join(home, '.config', 'Claude', 'claude_desktop_config.json');\n}\n\nfunction prettyDoctor(r: DoctorReport): string {\n const check = (ok: boolean) => (ok ? 'yes' : 'no ');\n const lines = [\n `CLI: garu ${r.cli.version}`,\n `API: ${r.api.reachable ? `reachable (${r.api.url}, backend ${r.api.version ?? '?'})` : `unreachable (${r.api.url})`}`,\n r.api.error ? ` ${r.api.error}` : undefined,\n `Credentials: source=${r.credentials.source}${r.credentials.profile ? ` profile=${r.credentials.profile}` : ''}${r.credentials.fileMode ? ` mode=${r.credentials.fileMode}` : ''}`,\n r.credentials.warning ? ` ⚠ ${r.credentials.warning}` : undefined,\n '',\n 'Detected agents:',\n ` Claude Code: ${check(r.agents.claudeCode)}`,\n ` Cursor: ${check(r.agents.cursor)}`,\n ` Codex: ${check(r.agents.codex)}`,\n ` Windsurf: ${check(r.agents.windsurf)}`,\n ` Claude Desktop: ${check(r.agents.claudeDesktop)}`,\n ` VS Code MCP: ${check(r.agents.vscodeMcpInCwd)} (.vscode/mcp.json in cwd)`\n ].filter((l): l is string => l !== undefined);\n return lines.join('\\n');\n}\n","import { Garu } from '@garuhq/node';\n\nimport { loadCredentials, saveCredentials, upsertProfile } from '../lib/credentials.js';\nimport { CliError } from '../lib/errors.js';\nimport { printStatus, printSuccess, type OutputOptions } from '../lib/output.js';\n\nexport interface LoginOptions extends OutputOptions {\n /** Profile name to create/update. Default: `default`. */\n profile?: string;\n /** Pre-supplied API key (for scripting). When set, no interactive prompt. */\n apiKey?: string;\n /** Override base URL (tests). */\n baseUrl?: string;\n}\n\nexport async function loginCommand(opts: LoginOptions = {}): Promise<{ profile: string }> {\n const profile = opts.profile ?? 'default';\n\n // `@inquirer/prompts` is ESM-only; we lazy-load it via dynamic import so the\n // tsup-built CJS entry works on Node 18 (where require-of-ESM is forbidden).\n const apiKey =\n opts.apiKey ??\n (await import('@inquirer/prompts')\n .then(({ password }) =>\n password({\n message: 'Paste your Garu API key (sk_live_... or sk_test_...)',\n mask: '*'\n })\n )\n .catch(() => {\n throw new CliError('user_cancelled', 'Login cancelled.');\n }));\n\n if (!apiKey || !/^sk_(live|test)_[A-Za-z0-9_]+$/.test(apiKey)) {\n throw new CliError('invalid_input', 'API key must look like `sk_live_...` or `sk_test_...`.');\n }\n\n printStatus('Checking connectivity to Garu...', opts);\n const garu = new Garu({ apiKey, baseUrl: opts.baseUrl });\n\n // We hit the unauthenticated `/api/meta` to verify the SDK can reach the\n // backend. We do NOT yet verify the key is accepted — that requires an\n // authenticated probe endpoint (tracked as a Chunk 2b backend follow-up:\n // expose `GET /api/v1/me`). Until then, a malformed-but-valid-shape key\n // will be saved and fail on the next real command.\n await garu.meta.get();\n\n const file = await loadCredentials();\n const updated = upsertProfile(file, profile, { apiKey });\n await saveCredentials(updated);\n\n printSuccess(`Saved profile '${profile}' to ~/.config/garu/credentials.json`, opts);\n return { profile };\n}\n","import { deleteCredentials, loadCredentials, saveCredentials } from '../lib/credentials.js';\nimport { CliError } from '../lib/errors.js';\nimport { printSuccess, type OutputOptions } from '../lib/output.js';\n\nexport interface LogoutOptions extends OutputOptions {\n /**\n * Profile to remove. If omitted, the entire credentials file is deleted.\n */\n profile?: string;\n}\n\nexport async function logoutCommand(opts: LogoutOptions = {}): Promise<{ cleared: string }> {\n if (!opts.profile) {\n await deleteCredentials();\n printSuccess('All saved credentials deleted.', opts);\n return { cleared: 'all' };\n }\n\n const file = await loadCredentials();\n if (!file.profiles[opts.profile]) {\n throw new CliError('not_found', `Profile '${opts.profile}' not found.`);\n }\n\n const { [opts.profile]: _removed, ...rest } = file.profiles;\n void _removed;\n\n // If this was the only profile, delete the file entirely instead of writing\n // back an orphaned activeProfile pointing at nothing. Matches what users\n // would expect from `logout` — no credentials left on disk.\n if (Object.keys(rest).length === 0) {\n await deleteCredentials();\n printSuccess(`Profile '${opts.profile}' removed (credentials file deleted).`, opts);\n return { cleared: opts.profile };\n }\n\n const nextActive =\n file.activeProfile === opts.profile ? Object.keys(rest)[0]! : file.activeProfile;\n\n await saveCredentials({ ...file, activeProfile: nextActive, profiles: rest });\n printSuccess(`Profile '${opts.profile}' removed.`, opts);\n return { cleared: opts.profile };\n}\n","import { Command, Option } from 'commander';\n\nimport { CLI_VERSION } from './version.js';\nimport { authSwitchCommand } from './commands/auth-switch.js';\nimport {\n chargesCreateCommand,\n chargesGetCommand,\n chargesRefundCommand\n} from './commands/charges.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { loginCommand } from './commands/login.js';\nimport { logoutCommand } from './commands/logout.js';\nimport type { PaymentMethod } from '@garuhq/node';\nimport { CliError } from './lib/errors.js';\nimport { printErrorAndExit, type OutputMode } from './lib/output.js';\n\ninterface GlobalFlags {\n apiKey?: string;\n profile?: string;\n json?: boolean;\n quiet?: boolean;\n}\n\ninterface CommandBaseOptions {\n apiKey?: string;\n profile?: string;\n mode?: OutputMode;\n quiet?: boolean;\n}\n\n/** Build the top-level command tree. Exposed so tests can exercise the router. */\nexport function buildCli(): Command {\n const program = new Command();\n\n program\n .name('garu')\n .description('Command-line interface for the Garu payment gateway.')\n .version(CLI_VERSION, '-v, --version')\n .addOption(new Option('--api-key <key>', 'Garu API key (overrides env and credentials file)'))\n .addOption(new Option('-p, --profile <name>', 'credentials profile name'))\n .addOption(new Option('--json', 'emit strict JSON on stdout (forced in pipes)'))\n .addOption(new Option('-q, --quiet', 'suppress status output; only print results and errors'))\n .showHelpAfterError();\n\n // login\n program\n .command('login')\n .description('Save a Garu API key to the credentials file')\n .option('--api-key <key>', 'pre-supply the key instead of prompting')\n .option('-p, --profile <name>', 'profile name to store under', 'default')\n .action(async (cmdOpts: { apiKey?: string; profile: string }) => {\n const base = toCommandOptions(program);\n await loginCommand({\n apiKey: cmdOpts.apiKey,\n profile: cmdOpts.profile,\n mode: base.mode,\n quiet: base.quiet\n }).catch((err) => printErrorAndExit(err, base));\n });\n\n // logout\n program\n .command('logout')\n .description('Remove saved credentials')\n .option('-p, --profile <name>', 'only remove this profile instead of the whole file')\n .action(async (cmdOpts: { profile?: string }) => {\n const base = toCommandOptions(program);\n await logoutCommand({\n profile: cmdOpts.profile,\n mode: base.mode,\n quiet: base.quiet\n }).catch((err) => printErrorAndExit(err, base));\n });\n\n // auth switch\n const auth = program.command('auth').description('Manage credentials profiles');\n auth\n .command('switch <profile>')\n .description('Set the active credentials profile')\n .action(async (profile: string) => {\n const base = toCommandOptions(program);\n await authSwitchCommand({ profile, mode: base.mode, quiet: base.quiet }).catch((err) =>\n printErrorAndExit(err, base)\n );\n });\n\n // charges\n const charges = program.command('charges').description('Create, fetch, and refund charges');\n\n charges\n .command('create')\n .description('Create a charge (PIX, credit card, or boleto)')\n .requiredOption('--type <type>', 'payment method: pix | credit_card | boleto')\n .requiredOption('--product-id <uuid>', 'product UUID')\n .requiredOption('--customer-name <name>', 'customer full name')\n .requiredOption('--customer-email <email>', 'customer email')\n .requiredOption(\n '--customer-document <document>',\n 'CPF (11 digits) or CNPJ (14 digits), digits only'\n )\n .requiredOption('--customer-phone <phone>', 'customer phone with area code, digits only')\n .option('--card-number <number>', 'credit-card number (required for credit_card)')\n .option('--card-cvv <cvv>', 'credit-card CVV')\n .option('--card-expiration <yyyy-mm>', 'credit-card expiration date (YYYY-MM)')\n .option('--card-holder <name>', 'credit-card holder name')\n .option('--installments <n>', 'number of installments (1-12)', (v) => parseInt(v, 10), 1)\n .option('--additional-info <text>', 'free-form metadata attached to the charge')\n .option('--idempotency-key <key>', 'idempotency key (auto-generated if omitted)')\n .action(async (cmdOpts) => {\n const base = toCommandOptions(program);\n await chargesCreateCommand({\n ...base,\n type: parsePaymentMethod(cmdOpts.type),\n productId: cmdOpts.productId,\n customerName: cmdOpts.customerName,\n customerEmail: cmdOpts.customerEmail,\n customerDocument: cmdOpts.customerDocument,\n customerPhone: cmdOpts.customerPhone,\n cardNumber: cmdOpts.cardNumber,\n cardCvv: cmdOpts.cardCvv,\n cardExpiration: cmdOpts.cardExpiration,\n cardHolder: cmdOpts.cardHolder,\n installments: cmdOpts.installments,\n additionalInfo: cmdOpts.additionalInfo,\n idempotencyKey: cmdOpts.idempotencyKey\n }).catch((err) => printErrorAndExit(err, base));\n });\n\n charges\n .command('get <id>')\n .description('Fetch a single charge by ID')\n .action(async (id: string) => {\n const base = toCommandOptions(program);\n await chargesGetCommand({ ...base, id: parseId(id) }).catch((err) =>\n printErrorAndExit(err, base)\n );\n });\n\n charges\n .command('refund <id>')\n .description('Refund a charge (full or partial)')\n .option('--amount <centavos>', 'partial refund amount in centavos', (v) => parseInt(v, 10))\n .option('--reason <text>', 'optional refund reason')\n .option('--idempotency-key <key>', 'idempotency key (auto-generated if omitted)')\n .action(async (id: string, cmdOpts) => {\n const base = toCommandOptions(program);\n await chargesRefundCommand({\n ...base,\n id: parseId(id),\n amount: cmdOpts.amount,\n reason: cmdOpts.reason,\n idempotencyKey: cmdOpts.idempotencyKey\n }).catch((err) => printErrorAndExit(err, base));\n });\n\n // doctor\n program\n .command('doctor')\n .description('Environment diagnostic')\n .action(async () => {\n const base = toCommandOptions(program);\n await doctorCommand(base).catch((err) => printErrorAndExit(err, base));\n });\n\n return program;\n}\n\n/**\n * Collapse the root-command's global flags into the shape every command takes.\n * Commander never passes `undefined` for unset flags — they're just absent — so\n * we can forward this object to command handlers via spread without polluting\n * their signatures with `undefined` props.\n */\nfunction toCommandOptions(program: Command): CommandBaseOptions {\n const g = program.opts<GlobalFlags>();\n const out: CommandBaseOptions = {};\n if (g.apiKey) out.apiKey = g.apiKey;\n if (g.profile) out.profile = g.profile;\n if (g.json) out.mode = 'json';\n if (g.quiet) out.quiet = true;\n return out;\n}\n\nfunction parsePaymentMethod(raw: string): PaymentMethod {\n if (raw === 'pix' || raw === 'credit_card' || raw === 'boleto') return raw;\n throw new CliError(\n 'invalid_input',\n `--type must be 'pix', 'credit_card', or 'boleto' (got '${raw}')`\n );\n}\n\nfunction parseId(raw: string): number {\n const id = Number.parseInt(raw, 10);\n if (!Number.isFinite(id) || id <= 0) {\n throw new CliError('invalid_input', `Charge ID must be a positive integer (got '${raw}')`);\n }\n return id;\n}\n\n/** Main entry invoked by `bin/garu.cjs` and the compiled binary. */\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const program = buildCli();\n await program.parseAsync(argv);\n}\n\n// This module is only ever loaded as the CLI entry point — either through the\n// `bin/garu.cjs` shim for npm installs or as the compiled binary produced by\n// `bun build --compile`. No test imports `src/index.ts`, so it's safe to call\n// `main()` unconditionally at module load time.\nmain().catch((err) => printErrorAndExit(err));\n"]}