brex-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/dist/main.js +2455 -0
  4. package/package.json +32 -0
package/dist/main.js ADDED
@@ -0,0 +1,2455 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // sources/config.ts
5
+ var {existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync} = (() => ({}));
6
+
7
+ // node:os
8
+ var homedir = function() {
9
+ return "/";
10
+ };
11
+
12
+ // node:path
13
+ function assertPath(path) {
14
+ if (typeof path !== "string")
15
+ throw TypeError("Path must be a string. Received " + JSON.stringify(path));
16
+ }
17
+ function normalizeStringPosix(path, allowAboveRoot) {
18
+ var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
19
+ for (var i = 0;i <= path.length; ++i) {
20
+ if (i < path.length)
21
+ code = path.charCodeAt(i);
22
+ else if (code === 47)
23
+ break;
24
+ else
25
+ code = 47;
26
+ if (code === 47) {
27
+ if (lastSlash === i - 1 || dots === 1)
28
+ ;
29
+ else if (lastSlash !== i - 1 && dots === 2) {
30
+ if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
31
+ if (res.length > 2) {
32
+ var lastSlashIndex = res.lastIndexOf("/");
33
+ if (lastSlashIndex !== res.length - 1) {
34
+ if (lastSlashIndex === -1)
35
+ res = "", lastSegmentLength = 0;
36
+ else
37
+ res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
38
+ lastSlash = i, dots = 0;
39
+ continue;
40
+ }
41
+ } else if (res.length === 2 || res.length === 1) {
42
+ res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
43
+ continue;
44
+ }
45
+ }
46
+ if (allowAboveRoot) {
47
+ if (res.length > 0)
48
+ res += "/..";
49
+ else
50
+ res = "..";
51
+ lastSegmentLength = 2;
52
+ }
53
+ } else {
54
+ if (res.length > 0)
55
+ res += "/" + path.slice(lastSlash + 1, i);
56
+ else
57
+ res = path.slice(lastSlash + 1, i);
58
+ lastSegmentLength = i - lastSlash - 1;
59
+ }
60
+ lastSlash = i, dots = 0;
61
+ } else if (code === 46 && dots !== -1)
62
+ ++dots;
63
+ else
64
+ dots = -1;
65
+ }
66
+ return res;
67
+ }
68
+ function _format(sep, pathObject) {
69
+ var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
70
+ if (!dir)
71
+ return base;
72
+ if (dir === pathObject.root)
73
+ return dir + base;
74
+ return dir + sep + base;
75
+ }
76
+ function resolve() {
77
+ var resolvedPath = "", resolvedAbsolute = false, cwd;
78
+ for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
79
+ var path;
80
+ if (i >= 0)
81
+ path = arguments[i];
82
+ else {
83
+ if (cwd === undefined)
84
+ cwd = process.cwd();
85
+ path = cwd;
86
+ }
87
+ if (assertPath(path), path.length === 0)
88
+ continue;
89
+ resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
90
+ }
91
+ if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
92
+ if (resolvedPath.length > 0)
93
+ return "/" + resolvedPath;
94
+ else
95
+ return "/";
96
+ else if (resolvedPath.length > 0)
97
+ return resolvedPath;
98
+ else
99
+ return ".";
100
+ }
101
+ function normalize(path) {
102
+ if (assertPath(path), path.length === 0)
103
+ return ".";
104
+ var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
105
+ if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
106
+ path = ".";
107
+ if (path.length > 0 && trailingSeparator)
108
+ path += "/";
109
+ if (isAbsolute)
110
+ return "/" + path;
111
+ return path;
112
+ }
113
+ function isAbsolute(path) {
114
+ return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
115
+ }
116
+ function join() {
117
+ if (arguments.length === 0)
118
+ return ".";
119
+ var joined;
120
+ for (var i = 0;i < arguments.length; ++i) {
121
+ var arg = arguments[i];
122
+ if (assertPath(arg), arg.length > 0)
123
+ if (joined === undefined)
124
+ joined = arg;
125
+ else
126
+ joined += "/" + arg;
127
+ }
128
+ if (joined === undefined)
129
+ return ".";
130
+ return normalize(joined);
131
+ }
132
+ function relative(from, to) {
133
+ if (assertPath(from), assertPath(to), from === to)
134
+ return "";
135
+ if (from = resolve(from), to = resolve(to), from === to)
136
+ return "";
137
+ var fromStart = 1;
138
+ for (;fromStart < from.length; ++fromStart)
139
+ if (from.charCodeAt(fromStart) !== 47)
140
+ break;
141
+ var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
142
+ for (;toStart < to.length; ++toStart)
143
+ if (to.charCodeAt(toStart) !== 47)
144
+ break;
145
+ var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
146
+ for (;i <= length; ++i) {
147
+ if (i === length) {
148
+ if (toLen > length) {
149
+ if (to.charCodeAt(toStart + i) === 47)
150
+ return to.slice(toStart + i + 1);
151
+ else if (i === 0)
152
+ return to.slice(toStart + i);
153
+ } else if (fromLen > length) {
154
+ if (from.charCodeAt(fromStart + i) === 47)
155
+ lastCommonSep = i;
156
+ else if (i === 0)
157
+ lastCommonSep = 0;
158
+ }
159
+ break;
160
+ }
161
+ var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
162
+ if (fromCode !== toCode)
163
+ break;
164
+ else if (fromCode === 47)
165
+ lastCommonSep = i;
166
+ }
167
+ var out = "";
168
+ for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
169
+ if (i === fromEnd || from.charCodeAt(i) === 47)
170
+ if (out.length === 0)
171
+ out += "..";
172
+ else
173
+ out += "/..";
174
+ if (out.length > 0)
175
+ return out + to.slice(toStart + lastCommonSep);
176
+ else {
177
+ if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
178
+ ++toStart;
179
+ return to.slice(toStart);
180
+ }
181
+ }
182
+ function _makeLong(path) {
183
+ return path;
184
+ }
185
+ function dirname(path) {
186
+ if (assertPath(path), path.length === 0)
187
+ return ".";
188
+ var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
189
+ for (var i = path.length - 1;i >= 1; --i)
190
+ if (code = path.charCodeAt(i), code === 47) {
191
+ if (!matchedSlash) {
192
+ end = i;
193
+ break;
194
+ }
195
+ } else
196
+ matchedSlash = false;
197
+ if (end === -1)
198
+ return hasRoot ? "/" : ".";
199
+ if (hasRoot && end === 1)
200
+ return "//";
201
+ return path.slice(0, end);
202
+ }
203
+ function basename(path, ext) {
204
+ if (ext !== undefined && typeof ext !== "string")
205
+ throw TypeError('"ext" argument must be a string');
206
+ assertPath(path);
207
+ var start = 0, end = -1, matchedSlash = true, i;
208
+ if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
209
+ if (ext.length === path.length && ext === path)
210
+ return "";
211
+ var extIdx = ext.length - 1, firstNonSlashEnd = -1;
212
+ for (i = path.length - 1;i >= 0; --i) {
213
+ var code = path.charCodeAt(i);
214
+ if (code === 47) {
215
+ if (!matchedSlash) {
216
+ start = i + 1;
217
+ break;
218
+ }
219
+ } else {
220
+ if (firstNonSlashEnd === -1)
221
+ matchedSlash = false, firstNonSlashEnd = i + 1;
222
+ if (extIdx >= 0)
223
+ if (code === ext.charCodeAt(extIdx)) {
224
+ if (--extIdx === -1)
225
+ end = i;
226
+ } else
227
+ extIdx = -1, end = firstNonSlashEnd;
228
+ }
229
+ }
230
+ if (start === end)
231
+ end = firstNonSlashEnd;
232
+ else if (end === -1)
233
+ end = path.length;
234
+ return path.slice(start, end);
235
+ } else {
236
+ for (i = path.length - 1;i >= 0; --i)
237
+ if (path.charCodeAt(i) === 47) {
238
+ if (!matchedSlash) {
239
+ start = i + 1;
240
+ break;
241
+ }
242
+ } else if (end === -1)
243
+ matchedSlash = false, end = i + 1;
244
+ if (end === -1)
245
+ return "";
246
+ return path.slice(start, end);
247
+ }
248
+ }
249
+ function extname(path) {
250
+ assertPath(path);
251
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
252
+ for (var i = path.length - 1;i >= 0; --i) {
253
+ var code = path.charCodeAt(i);
254
+ if (code === 47) {
255
+ if (!matchedSlash) {
256
+ startPart = i + 1;
257
+ break;
258
+ }
259
+ continue;
260
+ }
261
+ if (end === -1)
262
+ matchedSlash = false, end = i + 1;
263
+ if (code === 46) {
264
+ if (startDot === -1)
265
+ startDot = i;
266
+ else if (preDotState !== 1)
267
+ preDotState = 1;
268
+ } else if (startDot !== -1)
269
+ preDotState = -1;
270
+ }
271
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
272
+ return "";
273
+ return path.slice(startDot, end);
274
+ }
275
+ function format(pathObject) {
276
+ if (pathObject === null || typeof pathObject !== "object")
277
+ throw TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
278
+ return _format("/", pathObject);
279
+ }
280
+ function parse(path) {
281
+ assertPath(path);
282
+ var ret = { root: "", dir: "", base: "", ext: "", name: "" };
283
+ if (path.length === 0)
284
+ return ret;
285
+ var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
286
+ if (isAbsolute2)
287
+ ret.root = "/", start = 1;
288
+ else
289
+ start = 0;
290
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
291
+ for (;i >= start; --i) {
292
+ if (code = path.charCodeAt(i), code === 47) {
293
+ if (!matchedSlash) {
294
+ startPart = i + 1;
295
+ break;
296
+ }
297
+ continue;
298
+ }
299
+ if (end === -1)
300
+ matchedSlash = false, end = i + 1;
301
+ if (code === 46) {
302
+ if (startDot === -1)
303
+ startDot = i;
304
+ else if (preDotState !== 1)
305
+ preDotState = 1;
306
+ } else if (startDot !== -1)
307
+ preDotState = -1;
308
+ }
309
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
310
+ if (end !== -1)
311
+ if (startPart === 0 && isAbsolute2)
312
+ ret.base = ret.name = path.slice(1, end);
313
+ else
314
+ ret.base = ret.name = path.slice(startPart, end);
315
+ } else {
316
+ if (startPart === 0 && isAbsolute2)
317
+ ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
318
+ else
319
+ ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
320
+ ret.ext = path.slice(startDot, end);
321
+ }
322
+ if (startPart > 0)
323
+ ret.dir = path.slice(0, startPart - 1);
324
+ else if (isAbsolute2)
325
+ ret.dir = "/";
326
+ return ret;
327
+ }
328
+ var sep = "/";
329
+ var delimiter = ":";
330
+ var posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
331
+
332
+ // sources/config.ts
333
+ var CONFIG_DIR = join(homedir(), ".brex");
334
+ var TOKEN_PATH = join(CONFIG_DIR, "token");
335
+ var CONFIG_PATH = join(CONFIG_DIR, "config.json");
336
+ function ensureConfigDir() {
337
+ if (!existsSync(CONFIG_DIR)) {
338
+ mkdirSync(CONFIG_DIR, { mode: 448, recursive: true });
339
+ }
340
+ }
341
+ function loadToken() {
342
+ if (!existsSync(TOKEN_PATH)) {
343
+ return null;
344
+ }
345
+ try {
346
+ const value = readFileSync(TOKEN_PATH, "utf-8").trim();
347
+ return value.length > 0 ? value : null;
348
+ } catch {
349
+ return null;
350
+ }
351
+ }
352
+ function saveToken(token) {
353
+ ensureConfigDir();
354
+ writeFileSync(TOKEN_PATH, token.trim(), { mode: 384 });
355
+ }
356
+ function clearToken() {
357
+ if (existsSync(TOKEN_PATH)) {
358
+ unlinkSync(TOKEN_PATH);
359
+ }
360
+ }
361
+ function loadConfig() {
362
+ if (!existsSync(CONFIG_PATH)) {
363
+ return {};
364
+ }
365
+ try {
366
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
367
+ } catch {
368
+ return {};
369
+ }
370
+ }
371
+ function getApiBaseUrl() {
372
+ const config = loadConfig();
373
+ return config.apiBaseUrl ?? "https://platform.brexapis.com";
374
+ }
375
+
376
+ // sources/client.ts
377
+ class BrexApiError extends Error {
378
+ status;
379
+ body;
380
+ constructor(status, body) {
381
+ super(body.message ?? body.error ?? `HTTP ${status}`);
382
+ this.name = "BrexApiError";
383
+ this.status = status;
384
+ this.body = body;
385
+ }
386
+ }
387
+ function createBrexClient() {
388
+ const token = loadToken();
389
+ const baseUrl = getApiBaseUrl();
390
+ return {
391
+ baseUrl,
392
+ token,
393
+ fetch: async (path, init) => {
394
+ if (!token) {
395
+ throw new Error("Not authenticated. Run 'brex login' first.");
396
+ }
397
+ const url = path.startsWith("http") ? path : `${baseUrl}${path}`;
398
+ const response = await fetch(url, {
399
+ ...init,
400
+ headers: {
401
+ Authorization: `Bearer ${token}`,
402
+ "Content-Type": "application/json",
403
+ Accept: "application/json",
404
+ ...init?.headers
405
+ }
406
+ });
407
+ if (!response.ok) {
408
+ let body;
409
+ try {
410
+ body = await response.json();
411
+ } catch {
412
+ body = { error: `HTTP ${response.status}`, message: response.statusText };
413
+ }
414
+ throw new BrexApiError(response.status, body);
415
+ }
416
+ if (response.status === 204) {
417
+ return;
418
+ }
419
+ return response.json();
420
+ }
421
+ };
422
+ }
423
+
424
+ // sources/commands/login/index.ts
425
+ var USAGE = `brex login --token <API_TOKEN>
426
+ brex login --token-stdin`;
427
+ var loginCommand = {
428
+ name: "login",
429
+ description: "Authenticate with your Brex API token.",
430
+ usage: USAGE,
431
+ run: async (args) => {
432
+ const options = parseLoginArgs(args);
433
+ if (options.tokenStdin && options.token) {
434
+ throw new Error("Use either --token or --token-stdin, not both.");
435
+ }
436
+ let token = options.token;
437
+ if (options.tokenStdin) {
438
+ token = await readTokenFromStdin();
439
+ }
440
+ if (!token) {
441
+ const existingToken = loadToken();
442
+ if (existingToken) {
443
+ console.log("Already authenticated. Use 'brex logout' to disconnect.");
444
+ return;
445
+ }
446
+ throw new Error("Missing token. Use --token <TOKEN> or --token-stdin.");
447
+ }
448
+ token = token.trim();
449
+ if (!token) {
450
+ throw new Error("Token cannot be empty.");
451
+ }
452
+ saveToken(token);
453
+ console.log("Authenticated successfully. Token saved to ~/.brex/token");
454
+ }
455
+ };
456
+ function parseLoginArgs(args) {
457
+ let token;
458
+ let tokenStdin = false;
459
+ const positionals = [];
460
+ for (let i = 0;i < args.length; i += 1) {
461
+ const arg = args[i];
462
+ if (arg === undefined)
463
+ continue;
464
+ if (arg === "--token") {
465
+ const value = args[i + 1];
466
+ if (value === undefined) {
467
+ throw new Error("--token requires a value");
468
+ }
469
+ token = value;
470
+ i += 1;
471
+ continue;
472
+ }
473
+ if (arg === "--token-stdin") {
474
+ tokenStdin = true;
475
+ continue;
476
+ }
477
+ if (arg.startsWith("-")) {
478
+ throw new Error(`Unknown option: ${arg}`);
479
+ }
480
+ positionals.push(arg);
481
+ }
482
+ if (positionals.length > 0) {
483
+ throw new Error(`Unexpected arguments: ${positionals.join(" ")}`);
484
+ }
485
+ return { token, tokenStdin };
486
+ }
487
+ async function readTokenFromStdin() {
488
+ const chunks = [];
489
+ for await (const chunk of process.stdin) {
490
+ chunks.push(chunk);
491
+ }
492
+ return Buffer.concat(chunks).toString("utf-8").trim();
493
+ }
494
+
495
+ // sources/commands/logout/index.ts
496
+ var USAGE2 = "brex logout";
497
+ var logoutCommand = {
498
+ name: "logout",
499
+ description: "Remove stored authentication token.",
500
+ usage: USAGE2,
501
+ run: async () => {
502
+ const token = loadToken();
503
+ if (!token) {
504
+ console.log("Not currently authenticated.");
505
+ return;
506
+ }
507
+ clearToken();
508
+ console.log("Logged out. Token removed from ~/.brex/token");
509
+ }
510
+ };
511
+
512
+ // sources/commands/status/index.ts
513
+ var USAGE3 = "brex status";
514
+ var statusCommand = {
515
+ name: "status",
516
+ description: "Show current authentication and configuration status.",
517
+ usage: USAGE3,
518
+ run: async () => {
519
+ const token = loadToken();
520
+ const config = loadConfig();
521
+ const baseUrl = getApiBaseUrl();
522
+ console.log("Brex CLI Status");
523
+ console.log("──────────────────");
524
+ console.log(`Authenticated: ${token ? "Yes" : "No"}`);
525
+ if (token) {
526
+ const masked = token.slice(0, 10) + "..." + token.slice(-4);
527
+ console.log(`Token: ${masked}`);
528
+ }
529
+ console.log(`API Base URL: ${baseUrl}`);
530
+ if (config.defaultAccountId) {
531
+ console.log(`Default Account: ${config.defaultAccountId}`);
532
+ }
533
+ }
534
+ };
535
+
536
+ // sources/client.ts
537
+ class BrexApiError2 extends Error {
538
+ status;
539
+ body;
540
+ constructor(status, body) {
541
+ super(body.message ?? body.error ?? `HTTP ${status}`);
542
+ this.name = "BrexApiError";
543
+ this.status = status;
544
+ this.body = body;
545
+ }
546
+ }
547
+
548
+ // sources/output.ts
549
+ function parseOutputFlag(args) {
550
+ let format2 = "table";
551
+ const remaining = [];
552
+ for (const arg of args) {
553
+ if (arg === "--json") {
554
+ format2 = "json";
555
+ continue;
556
+ }
557
+ remaining.push(arg);
558
+ }
559
+ return { format: format2, args: remaining };
560
+ }
561
+ function printJson(data) {
562
+ console.log(JSON.stringify(data, null, 2));
563
+ }
564
+ function printTable(rows, columns) {
565
+ if (rows.length === 0) {
566
+ console.log("No results.");
567
+ return;
568
+ }
569
+ const widths = columns.map((col) => {
570
+ const headerWidth = col.header.length;
571
+ const maxDataWidth = rows.reduce((max, row) => {
572
+ const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? "");
573
+ return Math.max(max, value.length);
574
+ }, 0);
575
+ return col.width ?? Math.min(Math.max(headerWidth, maxDataWidth), 50);
576
+ });
577
+ const headerLine = columns.map((col, i) => col.header.padEnd(widths[i])).join(" ");
578
+ console.log(headerLine);
579
+ console.log(columns.map((_, i) => "─".repeat(widths[i])).join(" "));
580
+ for (const row of rows) {
581
+ const line = columns.map((col, i) => {
582
+ const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? "");
583
+ return value.slice(0, widths[i]).padEnd(widths[i]);
584
+ }).join(" ");
585
+ console.log(line);
586
+ }
587
+ }
588
+ function formatAmount(amount, currency = "USD") {
589
+ if (amount === null || amount === undefined)
590
+ return "-";
591
+ const numeric = typeof amount === "string" ? Number(amount) : amount;
592
+ if (!Number.isFinite(numeric)) {
593
+ return String(amount);
594
+ }
595
+ return new Intl.NumberFormat("en-US", {
596
+ style: "currency",
597
+ currency
598
+ }).format(numeric);
599
+ }
600
+ function formatDate(isoString) {
601
+ if (!isoString)
602
+ return "-";
603
+ const date = new Date(isoString);
604
+ return date.toLocaleDateString("en-US", {
605
+ year: "numeric",
606
+ month: "short",
607
+ day: "numeric"
608
+ });
609
+ }
610
+ function formatDateTime(isoString) {
611
+ if (!isoString)
612
+ return "-";
613
+ const date = new Date(isoString);
614
+ return date.toLocaleString("en-US", {
615
+ year: "numeric",
616
+ month: "short",
617
+ day: "numeric",
618
+ hour: "2-digit",
619
+ minute: "2-digit"
620
+ });
621
+ }
622
+ function truncate(str, maxLen) {
623
+ if (str.length <= maxLen)
624
+ return str;
625
+ return str.slice(0, maxLen - 3) + "...";
626
+ }
627
+
628
+ // sources/commands/accounts/index.ts
629
+ var USAGE4 = `brex accounts
630
+ brex accounts list [--type cash|card|all] [--cursor <cursor>]
631
+ brex accounts get <account-id> [--type cash|card]
632
+ brex accounts --json`;
633
+ var accountsCommand = {
634
+ name: "accounts",
635
+ description: "List and view Brex cash/card accounts.",
636
+ usage: USAGE4,
637
+ aliases: ["account", "acc"],
638
+ run: async (args, context) => {
639
+ const { format: format2, args: remaining } = parseOutputFlag(args);
640
+ const subcommand = remaining[0] ?? "list";
641
+ switch (subcommand) {
642
+ case "list":
643
+ await listAccounts(context, parseListOptions(remaining.slice(1)), format2);
644
+ return;
645
+ case "get": {
646
+ const accountId = remaining[1];
647
+ if (!accountId) {
648
+ throw new Error("Missing account ID. Usage: brex accounts get <account-id> [--type cash|card]");
649
+ }
650
+ await getAccount(context, accountId, parseGetOptions(remaining.slice(2)), format2);
651
+ return;
652
+ }
653
+ default:
654
+ throw new Error(`Unknown subcommand: ${subcommand}. Use 'list' or 'get'.`);
655
+ }
656
+ }
657
+ };
658
+ function parseListOptions(args) {
659
+ let type = "all";
660
+ let cursor;
661
+ for (let i = 0;i < args.length; i += 1) {
662
+ const arg = args[i];
663
+ if (!arg)
664
+ continue;
665
+ if (arg === "--type") {
666
+ const value = args[++i];
667
+ if (!value || value !== "cash" && value !== "card" && value !== "all") {
668
+ throw new Error("--type must be one of: cash, card, all");
669
+ }
670
+ type = value;
671
+ continue;
672
+ }
673
+ if (arg === "--cursor") {
674
+ const value = args[++i];
675
+ if (!value)
676
+ throw new Error("--cursor requires a value");
677
+ cursor = value;
678
+ continue;
679
+ }
680
+ if (arg.startsWith("-")) {
681
+ throw new Error(`Unknown option: ${arg}`);
682
+ }
683
+ }
684
+ if (type === "all" && cursor) {
685
+ throw new Error("--cursor can only be used with --type cash or --type card");
686
+ }
687
+ return { type, cursor };
688
+ }
689
+ function parseGetOptions(args) {
690
+ let type;
691
+ for (let i = 0;i < args.length; i += 1) {
692
+ const arg = args[i];
693
+ if (!arg)
694
+ continue;
695
+ if (arg === "--type") {
696
+ const value = args[++i];
697
+ if (!value || value !== "cash" && value !== "card") {
698
+ throw new Error("--type must be one of: cash, card");
699
+ }
700
+ type = value;
701
+ continue;
702
+ }
703
+ if (arg.startsWith("-")) {
704
+ throw new Error(`Unknown option: ${arg}`);
705
+ }
706
+ }
707
+ return { type };
708
+ }
709
+ async function listAccounts(context, options, format2) {
710
+ const cashPath = withCursor("/v2/accounts/cash", options.cursor);
711
+ const cardPath = withCursor("/v2/accounts/card", options.cursor);
712
+ if (options.type === "cash") {
713
+ const cashResponse2 = await context.client.fetch(cashPath);
714
+ const cashAccounts2 = extractItems(cashResponse2, ["items", "cash_accounts", "accounts"]);
715
+ if (format2 === "json") {
716
+ printJson({ items: cashAccounts2, nextCursor: cashResponse2.next_cursor ?? null });
717
+ return;
718
+ }
719
+ printAccountsTable(cashAccounts2.map((account) => toAccountRow(account, "cash")));
720
+ if (cashResponse2.next_cursor) {
721
+ console.log(`
722
+ Next cursor: ${cashResponse2.next_cursor}`);
723
+ }
724
+ return;
725
+ }
726
+ if (options.type === "card") {
727
+ const cardResponse2 = await context.client.fetch(cardPath);
728
+ const cardAccounts2 = extractItems(cardResponse2, ["items", "card_accounts", "accounts"]);
729
+ if (format2 === "json") {
730
+ printJson({ items: cardAccounts2, nextCursor: cardResponse2.next_cursor ?? null });
731
+ return;
732
+ }
733
+ printAccountsTable(cardAccounts2.map((account) => toAccountRow(account, "card")));
734
+ if (cardResponse2.next_cursor) {
735
+ console.log(`
736
+ Next cursor: ${cardResponse2.next_cursor}`);
737
+ }
738
+ return;
739
+ }
740
+ const [cashResponse, cardResponse] = await Promise.all([
741
+ context.client.fetch(cashPath),
742
+ context.client.fetch(cardPath)
743
+ ]);
744
+ const cashAccounts = extractItems(cashResponse, ["items", "cash_accounts", "accounts"]);
745
+ const cardAccounts = extractItems(cardResponse, ["items", "card_accounts", "accounts"]);
746
+ if (format2 === "json") {
747
+ printJson({
748
+ cash: { items: cashAccounts, nextCursor: cashResponse.next_cursor ?? null },
749
+ card: { items: cardAccounts, nextCursor: cardResponse.next_cursor ?? null }
750
+ });
751
+ return;
752
+ }
753
+ const rows = [
754
+ ...cashAccounts.map((account) => toAccountRow(account, "cash")),
755
+ ...cardAccounts.map((account) => toAccountRow(account, "card"))
756
+ ];
757
+ printAccountsTable(rows);
758
+ }
759
+ async function getAccount(context, accountId, options, format2) {
760
+ const fetchCash = async () => context.client.fetch(`/v2/accounts/cash/${accountId}`);
761
+ const fetchCard = async () => context.client.fetch(`/v2/accounts/card/${accountId}`);
762
+ if (options.type === "cash") {
763
+ const account = await fetchCash();
764
+ renderAccount(account, "cash", format2);
765
+ return;
766
+ }
767
+ if (options.type === "card") {
768
+ const account = await fetchCard();
769
+ renderAccount(account, "card", format2);
770
+ return;
771
+ }
772
+ try {
773
+ const account = await fetchCash();
774
+ renderAccount(account, "cash", format2);
775
+ return;
776
+ } catch (error) {
777
+ if (!(error instanceof BrexApiError2) || error.status !== 404) {
778
+ throw error;
779
+ }
780
+ }
781
+ const cardAccount = await fetchCard();
782
+ renderAccount(cardAccount, "card", format2);
783
+ }
784
+ function renderAccount(account, type, format2) {
785
+ if (format2 === "json") {
786
+ printJson(account);
787
+ return;
788
+ }
789
+ const row = toAccountRow(account, type);
790
+ console.log("Account Details");
791
+ console.log("───────────────");
792
+ console.log(`ID: ${row.id}`);
793
+ console.log(`Name: ${row.name}`);
794
+ console.log(`Type: ${row.type}`);
795
+ console.log(`Status: ${row.status}`);
796
+ if (row.accountNumber !== "-")
797
+ console.log(`Account Number: ${row.accountNumber}`);
798
+ if (row.routingNumber !== "-")
799
+ console.log(`Routing Number: ${row.routingNumber}`);
800
+ console.log(`Available: ${row.available}`);
801
+ console.log(`Current: ${row.current}`);
802
+ }
803
+ function toAccountRow(account, type) {
804
+ const availableBalance = "available_balance" in account ? account.available_balance : undefined;
805
+ const currentBalance = account.current_balance;
806
+ const status = account.status ?? "-";
807
+ const accountName = account.account_name ?? "-";
808
+ const accountType = account.account_type ?? type;
809
+ return {
810
+ id: account.id,
811
+ name: accountName,
812
+ type: accountType,
813
+ status,
814
+ accountNumber: "account_number" in account ? account.account_number ?? "-" : "-",
815
+ routingNumber: "routing_number" in account ? account.routing_number ?? "-" : "-",
816
+ available: formatMoney(availableBalance ?? currentBalance),
817
+ current: formatMoney(currentBalance)
818
+ };
819
+ }
820
+ function formatMoney(balance) {
821
+ if (!balance)
822
+ return "-";
823
+ return formatAmount(balance.amount, balance.currency);
824
+ }
825
+ function withCursor(path, cursor) {
826
+ if (!cursor)
827
+ return path;
828
+ return `${path}?cursor=${encodeURIComponent(cursor)}`;
829
+ }
830
+ function extractItems(response, keys) {
831
+ for (const key of keys) {
832
+ const value = response[key];
833
+ if (Array.isArray(value))
834
+ return value;
835
+ }
836
+ return [];
837
+ }
838
+ function printAccountsTable(rows) {
839
+ if (rows.length === 0) {
840
+ console.log("No accounts found.");
841
+ return;
842
+ }
843
+ printTable(rows, [
844
+ { key: "id", header: "ID", width: 36 },
845
+ { key: "name", header: "Name", width: 22 },
846
+ { key: "type", header: "Type", width: 12 },
847
+ { key: "status", header: "Status", width: 10 },
848
+ { key: "accountNumber", header: "Account #", width: 12 },
849
+ { key: "available", header: "Available", width: 14 },
850
+ { key: "current", header: "Current", width: 14 }
851
+ ]);
852
+ }
853
+
854
+ // sources/commands/transactions/index.ts
855
+ var USAGE5 = `brex transactions <account-id> [--type cash|card] [--limit <N>] [--cursor <cursor>] [--start-time <ISO>] [--end-time <ISO>]
856
+ brex transactions get <account-id> <transaction-id> [--type cash|card]
857
+ brex transactions --json`;
858
+ var transactionsCommand = {
859
+ name: "transactions",
860
+ description: "List and view Brex account transactions.",
861
+ usage: USAGE5,
862
+ aliases: ["tx", "txn"],
863
+ run: async (args, context) => {
864
+ const { format: format2, args: remaining } = parseOutputFlag(args);
865
+ if (remaining.length === 0) {
866
+ throw new Error("Missing account ID. Usage: brex transactions <account-id>");
867
+ }
868
+ const firstArg = remaining[0];
869
+ if (firstArg === "get") {
870
+ const accountId2 = remaining[1];
871
+ const transactionId = remaining[2];
872
+ if (!accountId2 || !transactionId) {
873
+ throw new Error("Usage: brex transactions get <account-id> <transaction-id> [--type cash|card]");
874
+ }
875
+ await getTransaction(context, accountId2, transactionId, parseGetOptions2(remaining.slice(3)), format2);
876
+ return;
877
+ }
878
+ if (firstArg === "send") {
879
+ throw new Error("Brex sends money via Transfers API. Use `brex transfer` instead.");
880
+ }
881
+ const accountId = firstArg;
882
+ const options = parseListOptions2(remaining.slice(1));
883
+ await listTransactions(context, accountId, options, format2);
884
+ }
885
+ };
886
+ function parseListOptions2(args) {
887
+ const options = { type: "cash" };
888
+ for (let i = 0;i < args.length; i += 1) {
889
+ const arg = args[i];
890
+ if (!arg)
891
+ continue;
892
+ if (arg === "--type") {
893
+ const value = args[++i];
894
+ if (!value || value !== "cash" && value !== "card") {
895
+ throw new Error("--type must be one of: cash, card");
896
+ }
897
+ options.type = value;
898
+ continue;
899
+ }
900
+ if (arg === "--limit") {
901
+ const value = args[++i];
902
+ if (!value)
903
+ throw new Error("--limit requires a value");
904
+ const parsed = parseInt(value, 10);
905
+ if (Number.isNaN(parsed) || parsed <= 0) {
906
+ throw new Error("--limit must be a positive integer");
907
+ }
908
+ options.limit = parsed;
909
+ continue;
910
+ }
911
+ if (arg === "--cursor") {
912
+ const value = args[++i];
913
+ if (!value)
914
+ throw new Error("--cursor requires a value");
915
+ options.cursor = value;
916
+ continue;
917
+ }
918
+ if (arg === "--start-time" || arg === "--start") {
919
+ const value = args[++i];
920
+ if (!value)
921
+ throw new Error(`${arg} requires a value`);
922
+ options.startTime = value;
923
+ continue;
924
+ }
925
+ if (arg === "--end-time" || arg === "--end") {
926
+ const value = args[++i];
927
+ if (!value)
928
+ throw new Error(`${arg} requires a value`);
929
+ options.endTime = value;
930
+ continue;
931
+ }
932
+ if (arg.startsWith("-")) {
933
+ throw new Error(`Unknown option: ${arg}`);
934
+ }
935
+ }
936
+ return options;
937
+ }
938
+ function parseGetOptions2(args) {
939
+ let type = "cash";
940
+ for (let i = 0;i < args.length; i += 1) {
941
+ const arg = args[i];
942
+ if (!arg)
943
+ continue;
944
+ if (arg === "--type") {
945
+ const value = args[++i];
946
+ if (!value || value !== "cash" && value !== "card") {
947
+ throw new Error("--type must be one of: cash, card");
948
+ }
949
+ type = value;
950
+ continue;
951
+ }
952
+ if (arg.startsWith("-")) {
953
+ throw new Error(`Unknown option: ${arg}`);
954
+ }
955
+ }
956
+ return { type };
957
+ }
958
+ async function listTransactions(context, accountId, options, format2) {
959
+ const pathBase = options.type === "cash" ? `/v2/accounts/cash/${accountId}/transactions` : `/v2/accounts/card/${accountId}/transactions`;
960
+ const path = withQuery(pathBase, options);
961
+ const response = await context.client.fetch(path);
962
+ const transactions = response.items ?? response.transactions ?? [];
963
+ if (format2 === "json") {
964
+ printJson({ items: transactions, nextCursor: response.next_cursor ?? null });
965
+ return;
966
+ }
967
+ if (transactions.length === 0) {
968
+ console.log("No transactions found.");
969
+ return;
970
+ }
971
+ printTable(transactions.map((tx) => toTableRow(tx)), [
972
+ { key: "id", header: "ID", width: 36 },
973
+ { key: "type", header: "Type", width: 16 },
974
+ { key: "status", header: "Status", width: 12 },
975
+ { key: "amount", header: "Amount", width: 14 },
976
+ { key: "counterparty", header: "Counterparty", width: 25 },
977
+ { key: "postedAt", header: "Posted", width: 20 }
978
+ ]);
979
+ if (response.next_cursor) {
980
+ console.log(`
981
+ Next cursor: ${response.next_cursor}`);
982
+ }
983
+ }
984
+ async function getTransaction(context, accountId, transactionId, options, format2) {
985
+ const path = options.type === "cash" ? `/v2/accounts/cash/${accountId}/transactions/${transactionId}` : `/v2/accounts/card/${accountId}/transactions/${transactionId}`;
986
+ const response = await context.client.fetch(path);
987
+ const transaction = response.cash_transaction ?? response.card_transaction ?? response.transaction ?? response.item;
988
+ if (!transaction) {
989
+ throw new Error("Brex API returned an empty transaction payload.");
990
+ }
991
+ if (format2 === "json") {
992
+ printJson(transaction);
993
+ return;
994
+ }
995
+ const amount = transaction.amount ? formatAmount(transaction.amount.amount, transaction.amount.currency) : "-";
996
+ console.log("Transaction Details");
997
+ console.log("───────────────────");
998
+ console.log(`ID: ${transaction.id}`);
999
+ console.log(`Type: ${transaction.transaction_type ?? "-"}`);
1000
+ console.log(`Source Type: ${transaction.transaction_source_type ?? "-"}`);
1001
+ console.log(`Status: ${transaction.status ?? "-"}`);
1002
+ console.log(`Amount: ${amount}`);
1003
+ console.log(`Counterparty: ${transaction.counterparty_name ?? transaction.merchant_name ?? "-"}`);
1004
+ console.log(`Description: ${transaction.description ?? "-"}`);
1005
+ console.log(`Memo: ${transaction.memo ?? "-"}`);
1006
+ console.log(`Initiated At: ${formatDateTime(transaction.initiated_at)}`);
1007
+ console.log(`Posted At: ${formatDateTime(transaction.posted_at)}`);
1008
+ }
1009
+ function withQuery(path, options) {
1010
+ const params = new URLSearchParams;
1011
+ if (options.limit)
1012
+ params.set("limit", String(options.limit));
1013
+ if (options.cursor)
1014
+ params.set("cursor", options.cursor);
1015
+ if (options.startTime)
1016
+ params.set("start_time", options.startTime);
1017
+ if (options.endTime)
1018
+ params.set("end_time", options.endTime);
1019
+ const query = params.toString();
1020
+ return query ? `${path}?${query}` : path;
1021
+ }
1022
+ function toTableRow(transaction) {
1023
+ return {
1024
+ id: transaction.id,
1025
+ type: truncate(transaction.transaction_type ?? "-", 16),
1026
+ status: transaction.status ?? "-",
1027
+ amount: transaction.amount ? formatAmount(transaction.amount.amount, transaction.amount.currency) : "-",
1028
+ counterparty: truncate(transaction.counterparty_name ?? transaction.merchant_name ?? "-", 25),
1029
+ postedAt: formatDateTime(transaction.posted_at ?? transaction.initiated_at)
1030
+ };
1031
+ }
1032
+
1033
+ // sources/commands/transfer/index.ts
1034
+ var USAGE6 = `brex transfer --from <cash-account-id> --to <counterparty-id> --amount <decimal> --idempotency-key <key> [--currency <code>]
1035
+ brex transfer get <transfer-id>
1036
+ brex transfer list [--cursor <cursor>] [--limit <N>] [--status <status>] [--from-account-id <id>] [--to-counterparty-id <id>]
1037
+ brex transfer --json`;
1038
+ var transferCommand = {
1039
+ name: "transfer",
1040
+ description: "Create and inspect transfers.",
1041
+ usage: USAGE6,
1042
+ run: async (args, context) => {
1043
+ const { format: format2, args: remaining } = parseOutputFlag(args);
1044
+ const subcommand = remaining[0];
1045
+ if (subcommand === "get") {
1046
+ const transferId = remaining[1];
1047
+ if (!transferId)
1048
+ throw new Error("Usage: brex transfer get <transfer-id>");
1049
+ await getTransfer(context, transferId, format2);
1050
+ return;
1051
+ }
1052
+ if (subcommand === "list") {
1053
+ await listTransfers(context, parseListTransferOptions(remaining.slice(1)), format2);
1054
+ return;
1055
+ }
1056
+ const options = parseCreateTransferOptions(remaining);
1057
+ await createTransfer(context, options, format2);
1058
+ }
1059
+ };
1060
+ function parseCreateTransferOptions(args) {
1061
+ let fromAccountId;
1062
+ let toCounterpartyId;
1063
+ let amount;
1064
+ let currency = "USD";
1065
+ let idempotencyKey;
1066
+ for (let i = 0;i < args.length; i += 1) {
1067
+ const arg = args[i];
1068
+ if (!arg)
1069
+ continue;
1070
+ if (arg === "--from") {
1071
+ const value = args[++i];
1072
+ if (!value)
1073
+ throw new Error("--from requires a value");
1074
+ fromAccountId = value;
1075
+ continue;
1076
+ }
1077
+ if (arg === "--to") {
1078
+ const value = args[++i];
1079
+ if (!value)
1080
+ throw new Error("--to requires a value");
1081
+ toCounterpartyId = value;
1082
+ continue;
1083
+ }
1084
+ if (arg === "--amount") {
1085
+ const value = args[++i];
1086
+ if (!value)
1087
+ throw new Error("--amount requires a value");
1088
+ const parsed = Number(value);
1089
+ if (!Number.isFinite(parsed) || parsed <= 0) {
1090
+ throw new Error("--amount must be a positive number (e.g. 125.50)");
1091
+ }
1092
+ amount = parsed.toFixed(2);
1093
+ continue;
1094
+ }
1095
+ if (arg === "--currency") {
1096
+ const value = args[++i];
1097
+ if (!value)
1098
+ throw new Error("--currency requires a value");
1099
+ currency = value.toUpperCase();
1100
+ continue;
1101
+ }
1102
+ if (arg === "--idempotency-key") {
1103
+ const value = args[++i];
1104
+ if (!value)
1105
+ throw new Error("--idempotency-key requires a value");
1106
+ idempotencyKey = value;
1107
+ continue;
1108
+ }
1109
+ if (arg.startsWith("-")) {
1110
+ throw new Error(`Unknown option: ${arg}`);
1111
+ }
1112
+ }
1113
+ if (!fromAccountId)
1114
+ throw new Error("Missing required --from");
1115
+ if (!toCounterpartyId)
1116
+ throw new Error("Missing required --to");
1117
+ if (!amount)
1118
+ throw new Error("Missing required --amount");
1119
+ if (!idempotencyKey)
1120
+ throw new Error("Missing required --idempotency-key");
1121
+ return { fromAccountId, toCounterpartyId, amount, currency, idempotencyKey };
1122
+ }
1123
+ function parseListTransferOptions(args) {
1124
+ const options = {};
1125
+ for (let i = 0;i < args.length; i += 1) {
1126
+ const arg = args[i];
1127
+ if (!arg)
1128
+ continue;
1129
+ if (arg === "--cursor") {
1130
+ const value = args[++i];
1131
+ if (!value)
1132
+ throw new Error("--cursor requires a value");
1133
+ options.cursor = value;
1134
+ continue;
1135
+ }
1136
+ if (arg === "--limit") {
1137
+ const value = args[++i];
1138
+ if (!value)
1139
+ throw new Error("--limit requires a value");
1140
+ const parsed = parseInt(value, 10);
1141
+ if (Number.isNaN(parsed) || parsed <= 0) {
1142
+ throw new Error("--limit must be a positive integer");
1143
+ }
1144
+ options.limit = parsed;
1145
+ continue;
1146
+ }
1147
+ if (arg === "--status") {
1148
+ const value = args[++i];
1149
+ if (!value)
1150
+ throw new Error("--status requires a value");
1151
+ options.status = value;
1152
+ continue;
1153
+ }
1154
+ if (arg === "--from-account-id") {
1155
+ const value = args[++i];
1156
+ if (!value)
1157
+ throw new Error("--from-account-id requires a value");
1158
+ options.fromAccountId = value;
1159
+ continue;
1160
+ }
1161
+ if (arg === "--to-counterparty-id") {
1162
+ const value = args[++i];
1163
+ if (!value)
1164
+ throw new Error("--to-counterparty-id requires a value");
1165
+ options.toCounterpartyId = value;
1166
+ continue;
1167
+ }
1168
+ if (arg.startsWith("-")) {
1169
+ throw new Error(`Unknown option: ${arg}`);
1170
+ }
1171
+ }
1172
+ return options;
1173
+ }
1174
+ async function createTransfer(context, options, format2) {
1175
+ const body = {
1176
+ from_account: {
1177
+ cash_account: {
1178
+ id: options.fromAccountId
1179
+ }
1180
+ },
1181
+ recipient: {
1182
+ payment_counterparty: {
1183
+ id: options.toCounterpartyId
1184
+ }
1185
+ },
1186
+ amount: {
1187
+ amount: options.amount,
1188
+ currency: options.currency
1189
+ },
1190
+ idempotency_key: options.idempotencyKey
1191
+ };
1192
+ const response = await context.client.fetch("/v1/transfers", {
1193
+ method: "POST",
1194
+ headers: {
1195
+ "Idempotency-Key": options.idempotencyKey
1196
+ },
1197
+ body: JSON.stringify(body)
1198
+ });
1199
+ const transfer = response.transfer ?? response.item ?? response;
1200
+ if (format2 === "json") {
1201
+ printJson(transfer);
1202
+ return;
1203
+ }
1204
+ printTransferDetails(transfer, "Transfer Created");
1205
+ }
1206
+ async function getTransfer(context, transferId, format2) {
1207
+ const response = await context.client.fetch(`/v1/transfers/${transferId}`);
1208
+ const transfer = response.transfer ?? response.item ?? response;
1209
+ if (format2 === "json") {
1210
+ printJson(transfer);
1211
+ return;
1212
+ }
1213
+ printTransferDetails(transfer, "Transfer Details");
1214
+ }
1215
+ async function listTransfers(context, options, format2) {
1216
+ const params = new URLSearchParams;
1217
+ if (options.cursor)
1218
+ params.set("cursor", options.cursor);
1219
+ if (options.limit)
1220
+ params.set("limit", String(options.limit));
1221
+ if (options.status)
1222
+ params.set("status", options.status);
1223
+ if (options.fromAccountId)
1224
+ params.set("from_account_id", options.fromAccountId);
1225
+ if (options.toCounterpartyId)
1226
+ params.set("to_counterparty_id", options.toCounterpartyId);
1227
+ const query = params.toString();
1228
+ const path = query ? `/v1/transfers?${query}` : "/v1/transfers";
1229
+ const response = await context.client.fetch(path);
1230
+ const transfers = response.items ?? response.transfers ?? [];
1231
+ if (format2 === "json") {
1232
+ printJson({ items: transfers, nextCursor: response.next_cursor ?? null });
1233
+ return;
1234
+ }
1235
+ if (transfers.length === 0) {
1236
+ console.log("No transfers found.");
1237
+ return;
1238
+ }
1239
+ printTable(transfers.map((transfer) => ({
1240
+ id: transfer.id,
1241
+ from: transfer.from_account?.cash_account?.id ?? "-",
1242
+ to: transfer.recipient?.payment_counterparty?.id ?? "-",
1243
+ amount: transfer.amount ? formatAmount(transfer.amount.amount, transfer.amount.currency) : "-",
1244
+ status: transfer.status ?? "-"
1245
+ })), [
1246
+ { key: "id", header: "Transfer ID", width: 36 },
1247
+ { key: "from", header: "From Account", width: 36 },
1248
+ { key: "to", header: "To Counterparty", width: 36 },
1249
+ { key: "amount", header: "Amount", width: 14 },
1250
+ { key: "status", header: "Status", width: 14 }
1251
+ ]);
1252
+ if (response.next_cursor) {
1253
+ console.log(`
1254
+ Next cursor: ${response.next_cursor}`);
1255
+ }
1256
+ }
1257
+ function printTransferDetails(transfer, title) {
1258
+ console.log(title);
1259
+ console.log("──────────────────");
1260
+ console.log(`ID: ${transfer.id}`);
1261
+ console.log(`From Account:${" "}${transfer.from_account?.cash_account?.id ?? "-"}`);
1262
+ console.log(`To Recipient:${" "}${transfer.recipient?.payment_counterparty?.id ?? "-"}`);
1263
+ console.log(`Amount: ${transfer.amount ? formatAmount(transfer.amount.amount, transfer.amount.currency) : "-"}`);
1264
+ console.log(`Status: ${transfer.status ?? "-"}`);
1265
+ if (transfer.idempotency_key) {
1266
+ console.log(`Idempotency: ${transfer.idempotency_key}`);
1267
+ }
1268
+ }
1269
+
1270
+ // sources/commands/recipients/index.ts
1271
+ var USAGE7 = `brex recipients
1272
+ brex recipients list [--limit <N>] [--cursor <cursor>] [--name <name>]
1273
+ brex recipients get <counterparty-id>
1274
+ brex recipients add --name <name> --account <number> --routing <number> [--account-type CHECKING|SAVINGS]
1275
+ brex recipients delete <counterparty-id>
1276
+ brex recipients --json`;
1277
+ var recipientsCommand = {
1278
+ name: "recipients",
1279
+ description: "Manage payment counterparties.",
1280
+ usage: USAGE7,
1281
+ aliases: ["recipient", "recip"],
1282
+ run: async (args, context) => {
1283
+ const { format: format2, args: remaining } = parseOutputFlag(args);
1284
+ const subcommand = remaining[0] ?? "list";
1285
+ switch (subcommand) {
1286
+ case "list":
1287
+ await listRecipients(context, parseListOptions3(remaining.slice(1)), format2);
1288
+ return;
1289
+ case "get": {
1290
+ const recipientId = remaining[1];
1291
+ if (!recipientId)
1292
+ throw new Error("Missing recipient ID. Usage: brex recipients get <counterparty-id>");
1293
+ await getRecipient(context, recipientId, format2);
1294
+ return;
1295
+ }
1296
+ case "add":
1297
+ await addRecipient(context, parseAddOptions(remaining.slice(1)), format2);
1298
+ return;
1299
+ case "delete": {
1300
+ const recipientId = remaining[1];
1301
+ if (!recipientId)
1302
+ throw new Error("Missing recipient ID. Usage: brex recipients delete <counterparty-id>");
1303
+ await deleteRecipient(context, recipientId);
1304
+ return;
1305
+ }
1306
+ default:
1307
+ throw new Error(`Unknown subcommand: ${subcommand}. Use 'list', 'get', 'add', or 'delete'.`);
1308
+ }
1309
+ }
1310
+ };
1311
+ function parseListOptions3(args) {
1312
+ const options = {};
1313
+ for (let i = 0;i < args.length; i += 1) {
1314
+ const arg = args[i];
1315
+ if (!arg)
1316
+ continue;
1317
+ if (arg === "--limit") {
1318
+ const value = args[++i];
1319
+ if (!value)
1320
+ throw new Error("--limit requires a value");
1321
+ const parsed = parseInt(value, 10);
1322
+ if (Number.isNaN(parsed) || parsed <= 0) {
1323
+ throw new Error("--limit must be a positive integer");
1324
+ }
1325
+ options.limit = parsed;
1326
+ continue;
1327
+ }
1328
+ if (arg === "--cursor") {
1329
+ const value = args[++i];
1330
+ if (!value)
1331
+ throw new Error("--cursor requires a value");
1332
+ options.cursor = value;
1333
+ continue;
1334
+ }
1335
+ if (arg === "--name") {
1336
+ const value = args[++i];
1337
+ if (!value)
1338
+ throw new Error("--name requires a value");
1339
+ options.name = value;
1340
+ continue;
1341
+ }
1342
+ if (arg.startsWith("-")) {
1343
+ throw new Error(`Unknown option: ${arg}`);
1344
+ }
1345
+ }
1346
+ return options;
1347
+ }
1348
+ function parseAddOptions(args) {
1349
+ let name;
1350
+ let accountNumber;
1351
+ let routingNumber;
1352
+ let accountType;
1353
+ let country;
1354
+ let currency;
1355
+ for (let i = 0;i < args.length; i += 1) {
1356
+ const arg = args[i];
1357
+ if (!arg)
1358
+ continue;
1359
+ if (arg === "--name") {
1360
+ const value = args[++i];
1361
+ if (!value)
1362
+ throw new Error("--name requires a value");
1363
+ name = value;
1364
+ continue;
1365
+ }
1366
+ if (arg === "--account") {
1367
+ const value = args[++i];
1368
+ if (!value)
1369
+ throw new Error("--account requires a value");
1370
+ accountNumber = value;
1371
+ continue;
1372
+ }
1373
+ if (arg === "--routing") {
1374
+ const value = args[++i];
1375
+ if (!value)
1376
+ throw new Error("--routing requires a value");
1377
+ routingNumber = value;
1378
+ continue;
1379
+ }
1380
+ if (arg === "--account-type") {
1381
+ const value = args[++i];
1382
+ if (!value || value !== "CHECKING" && value !== "SAVINGS") {
1383
+ throw new Error("--account-type must be CHECKING or SAVINGS");
1384
+ }
1385
+ accountType = value;
1386
+ continue;
1387
+ }
1388
+ if (arg === "--country") {
1389
+ const value = args[++i];
1390
+ if (!value)
1391
+ throw new Error("--country requires a value");
1392
+ country = value;
1393
+ continue;
1394
+ }
1395
+ if (arg === "--currency") {
1396
+ const value = args[++i];
1397
+ if (!value)
1398
+ throw new Error("--currency requires a value");
1399
+ currency = value;
1400
+ continue;
1401
+ }
1402
+ if (arg.startsWith("-")) {
1403
+ throw new Error(`Unknown option: ${arg}`);
1404
+ }
1405
+ }
1406
+ if (!name)
1407
+ throw new Error("Missing required --name");
1408
+ if (!accountNumber)
1409
+ throw new Error("Missing required --account");
1410
+ if (!routingNumber)
1411
+ throw new Error("Missing required --routing");
1412
+ return { name, accountNumber, routingNumber, accountType, country, currency };
1413
+ }
1414
+ async function listRecipients(context, options, format2) {
1415
+ const params = new URLSearchParams;
1416
+ if (options.limit)
1417
+ params.set("limit", String(options.limit));
1418
+ if (options.cursor)
1419
+ params.set("cursor", options.cursor);
1420
+ if (options.name)
1421
+ params.set("name", options.name);
1422
+ const query = params.toString();
1423
+ const path = query ? `/v1/payment_counterparties?${query}` : "/v1/payment_counterparties";
1424
+ const response = await context.client.fetch(path);
1425
+ const recipients = response.items ?? response.payment_counterparties ?? [];
1426
+ if (format2 === "json") {
1427
+ printJson({ items: recipients, nextCursor: response.next_cursor ?? null });
1428
+ return;
1429
+ }
1430
+ if (recipients.length === 0) {
1431
+ console.log("No recipients found.");
1432
+ return;
1433
+ }
1434
+ printTable(recipients.map((recipient) => {
1435
+ const bank = recipient.payment_instruments?.[0]?.bank_transfer;
1436
+ return {
1437
+ id: recipient.id,
1438
+ name: truncate(recipient.name ?? "-", 30),
1439
+ account: bank?.account_number ? `...${bank.account_number.slice(-4)}` : "-",
1440
+ routing: bank?.routing_number ?? "-",
1441
+ bank: truncate(bank?.bank_name ?? "-", 20)
1442
+ };
1443
+ }), [
1444
+ { key: "id", header: "ID", width: 36 },
1445
+ { key: "name", header: "Name", width: 30 },
1446
+ { key: "account", header: "Account", width: 12 },
1447
+ { key: "routing", header: "Routing", width: 12 },
1448
+ { key: "bank", header: "Bank", width: 20 }
1449
+ ]);
1450
+ if (response.next_cursor) {
1451
+ console.log(`
1452
+ Next cursor: ${response.next_cursor}`);
1453
+ }
1454
+ }
1455
+ async function getRecipient(context, recipientId, format2) {
1456
+ const response = await context.client.fetch(`/v1/payment_counterparties/${recipientId}`);
1457
+ const recipient = response.payment_counterparty ?? response.item ?? response;
1458
+ if (format2 === "json") {
1459
+ printJson(recipient);
1460
+ return;
1461
+ }
1462
+ const bank = recipient.payment_instruments?.[0]?.bank_transfer;
1463
+ console.log("Recipient Details");
1464
+ console.log("─────────────────");
1465
+ console.log(`ID: ${recipient.id}`);
1466
+ console.log(`Name: ${recipient.name ?? "-"}`);
1467
+ console.log(`Account Number: ${bank?.account_number ?? "-"}`);
1468
+ console.log(`Routing Number: ${bank?.routing_number ?? "-"}`);
1469
+ if (bank?.bank_name)
1470
+ console.log(`Bank Name: ${bank.bank_name}`);
1471
+ if (bank?.account_type)
1472
+ console.log(`Account Type: ${bank.account_type}`);
1473
+ if (bank?.country)
1474
+ console.log(`Country: ${bank.country}`);
1475
+ if (bank?.currency)
1476
+ console.log(`Currency: ${bank.currency}`);
1477
+ }
1478
+ async function addRecipient(context, options, format2) {
1479
+ const body = {
1480
+ name: options.name,
1481
+ payment_instrument: {
1482
+ bank_transfer: {
1483
+ account_number: options.accountNumber,
1484
+ routing_number: options.routingNumber,
1485
+ ...options.accountType ? { account_type: options.accountType } : {},
1486
+ ...options.country ? { country: options.country } : {},
1487
+ ...options.currency ? { currency: options.currency } : {}
1488
+ }
1489
+ }
1490
+ };
1491
+ const response = await context.client.fetch("/v1/payment_counterparties", {
1492
+ method: "POST",
1493
+ body: JSON.stringify(body)
1494
+ });
1495
+ const recipient = response.payment_counterparty ?? response.item ?? response;
1496
+ if (format2 === "json") {
1497
+ printJson(recipient);
1498
+ return;
1499
+ }
1500
+ console.log("Recipient Created");
1501
+ console.log("─────────────────");
1502
+ console.log(`ID: ${recipient.id}`);
1503
+ console.log(`Name: ${recipient.name ?? "-"}`);
1504
+ }
1505
+ async function deleteRecipient(context, recipientId) {
1506
+ await context.client.fetch(`/v1/payment_counterparties/${recipientId}`, {
1507
+ method: "DELETE"
1508
+ });
1509
+ console.log(`Recipient ${recipientId} deleted.`);
1510
+ }
1511
+
1512
+ // sources/commands/cards/index.ts
1513
+ var USAGE8 = `brex cards [list] [--user-id <user-id>] [--cursor <cursor>] [--limit <N>]
1514
+ brex cards get <card-id>
1515
+ brex cards --json`;
1516
+ var cardsCommand = {
1517
+ name: "cards",
1518
+ description: "List and view cards.",
1519
+ usage: USAGE8,
1520
+ aliases: ["card"],
1521
+ run: async (args, context) => {
1522
+ const { format: format2, args: remaining } = parseOutputFlag(args);
1523
+ const subcommand = remaining[0] ?? "list";
1524
+ if (subcommand === "get") {
1525
+ const cardId = remaining[1];
1526
+ if (!cardId) {
1527
+ throw new Error("Usage: brex cards get <card-id>");
1528
+ }
1529
+ await getCard(context, cardId, format2);
1530
+ return;
1531
+ }
1532
+ if (subcommand !== "list" && !subcommand.startsWith("-")) {
1533
+ await getCard(context, subcommand, format2);
1534
+ return;
1535
+ }
1536
+ const listArgs = subcommand === "list" ? remaining.slice(1) : remaining;
1537
+ await listCards(context, parseListOptions4(listArgs), format2);
1538
+ }
1539
+ };
1540
+ function parseListOptions4(args) {
1541
+ let userId;
1542
+ let cursor;
1543
+ let limit;
1544
+ for (let i = 0;i < args.length; i += 1) {
1545
+ const arg = args[i];
1546
+ if (!arg)
1547
+ continue;
1548
+ if (arg === "--user-id") {
1549
+ const value = args[++i];
1550
+ if (!value)
1551
+ throw new Error("--user-id requires a value");
1552
+ userId = value;
1553
+ continue;
1554
+ }
1555
+ if (arg === "--cursor") {
1556
+ const value = args[++i];
1557
+ if (!value)
1558
+ throw new Error("--cursor requires a value");
1559
+ cursor = value;
1560
+ continue;
1561
+ }
1562
+ if (arg === "--limit") {
1563
+ const value = args[++i];
1564
+ if (!value)
1565
+ throw new Error("--limit requires a value");
1566
+ const parsed = parseInt(value, 10);
1567
+ if (Number.isNaN(parsed) || parsed <= 0) {
1568
+ throw new Error("--limit must be a positive integer");
1569
+ }
1570
+ limit = parsed;
1571
+ continue;
1572
+ }
1573
+ if (arg.startsWith("-")) {
1574
+ throw new Error(`Unknown option: ${arg}`);
1575
+ }
1576
+ }
1577
+ return { userId, cursor, limit };
1578
+ }
1579
+ async function listCards(context, options, format2) {
1580
+ const params = new URLSearchParams;
1581
+ if (options.userId)
1582
+ params.set("user_id", options.userId);
1583
+ if (options.cursor)
1584
+ params.set("cursor", options.cursor);
1585
+ if (options.limit)
1586
+ params.set("limit", String(options.limit));
1587
+ const query = params.toString();
1588
+ const path = query ? `/v2/cards?${query}` : "/v2/cards";
1589
+ const response = await context.client.fetch(path);
1590
+ const cards = response.items ?? response.cards ?? [];
1591
+ if (format2 === "json") {
1592
+ printJson({ items: cards, nextCursor: response.next_cursor ?? null });
1593
+ return;
1594
+ }
1595
+ if (cards.length === 0) {
1596
+ console.log("No cards found.");
1597
+ return;
1598
+ }
1599
+ printTable(cards.map((card) => ({
1600
+ id: card.id,
1601
+ name: card.card_name ?? "-",
1602
+ last4: card.last_four ?? card.last_4 ?? "-",
1603
+ status: card.status ?? "-",
1604
+ expires: formatExpiration(card.expiration_month, card.expiration_year),
1605
+ userId: card.cardholder?.user_id ?? "-"
1606
+ })), [
1607
+ { key: "id", header: "Card ID", width: 36 },
1608
+ { key: "name", header: "Name", width: 22 },
1609
+ { key: "last4", header: "Last 4", width: 8 },
1610
+ { key: "status", header: "Status", width: 12 },
1611
+ { key: "expires", header: "Expires", width: 10 },
1612
+ { key: "userId", header: "User ID", width: 36 }
1613
+ ]);
1614
+ if (response.next_cursor) {
1615
+ console.log(`
1616
+ Next cursor: ${response.next_cursor}`);
1617
+ }
1618
+ }
1619
+ async function getCard(context, cardId, format2) {
1620
+ const response = await context.client.fetch(`/v2/cards/${cardId}`);
1621
+ const card = response.card ?? response.item ?? response;
1622
+ if (format2 === "json") {
1623
+ printJson(card);
1624
+ return;
1625
+ }
1626
+ console.log("Card Details");
1627
+ console.log("────────────");
1628
+ console.log(`ID: ${card.id}`);
1629
+ console.log(`Name: ${card.card_name ?? "-"}`);
1630
+ console.log(`Status: ${card.status ?? "-"}`);
1631
+ console.log(`Last 4: ${card.last_four ?? card.last_4 ?? "-"}`);
1632
+ console.log(`Expires: ${formatExpiration(card.expiration_month, card.expiration_year)}`);
1633
+ console.log(`User ID: ${card.cardholder?.user_id ?? "-"}`);
1634
+ }
1635
+ function formatExpiration(month, year) {
1636
+ if (!month || !year)
1637
+ return "-";
1638
+ const mm = String(month).padStart(2, "0");
1639
+ const yy = String(year);
1640
+ return `${mm}/${yy}`;
1641
+ }
1642
+
1643
+ // sources/commands/statements/index.ts
1644
+ var USAGE9 = `brex statements [--scope primary|additional] [--account-id <additional-card-account-id>] [--cursor <cursor>]
1645
+ brex statements get <statement-id> [--scope primary|additional] [--account-id <additional-card-account-id>]
1646
+ brex statements --json`;
1647
+ var statementsCommand = {
1648
+ name: "statements",
1649
+ description: "List and view card account statements.",
1650
+ usage: USAGE9,
1651
+ aliases: ["statement"],
1652
+ run: async (args, context) => {
1653
+ const { format: format2, args: remaining } = parseOutputFlag(args);
1654
+ const firstArg = remaining[0] ?? "list";
1655
+ if (firstArg === "get") {
1656
+ const statementId = remaining[1];
1657
+ if (!statementId) {
1658
+ throw new Error("Usage: brex statements get <statement-id> [--scope primary|additional] [--account-id <id>]");
1659
+ }
1660
+ const options2 = parseSharedOptions(remaining.slice(2));
1661
+ await getStatement(context, statementId, options2, format2);
1662
+ return;
1663
+ }
1664
+ const options = parseListOptions5(remaining.slice(firstArg === "list" ? 1 : 0));
1665
+ await listStatements(context, options, format2);
1666
+ }
1667
+ };
1668
+ function parseListOptions5(args) {
1669
+ const shared = parseSharedOptions(args);
1670
+ let cursor;
1671
+ for (let i = 0;i < args.length; i += 1) {
1672
+ const arg = args[i];
1673
+ if (!arg)
1674
+ continue;
1675
+ if (arg === "--cursor") {
1676
+ const value = args[++i];
1677
+ if (!value)
1678
+ throw new Error("--cursor requires a value");
1679
+ cursor = value;
1680
+ }
1681
+ }
1682
+ return { ...shared, cursor };
1683
+ }
1684
+ function parseSharedOptions(args) {
1685
+ let scope = "primary";
1686
+ let accountId;
1687
+ for (let i = 0;i < args.length; i += 1) {
1688
+ const arg = args[i];
1689
+ if (!arg)
1690
+ continue;
1691
+ if (arg === "--scope") {
1692
+ const value = args[++i];
1693
+ if (!value || value !== "primary" && value !== "additional") {
1694
+ throw new Error("--scope must be one of: primary, additional");
1695
+ }
1696
+ scope = value;
1697
+ continue;
1698
+ }
1699
+ if (arg === "--account-id") {
1700
+ const value = args[++i];
1701
+ if (!value)
1702
+ throw new Error("--account-id requires a value");
1703
+ accountId = value;
1704
+ continue;
1705
+ }
1706
+ if (arg === "--cursor") {
1707
+ i += 1;
1708
+ continue;
1709
+ }
1710
+ if (arg === "list") {
1711
+ continue;
1712
+ }
1713
+ if (arg.startsWith("-")) {
1714
+ throw new Error(`Unknown option: ${arg}`);
1715
+ }
1716
+ }
1717
+ if (scope === "additional" && !accountId) {
1718
+ throw new Error("--account-id is required when --scope additional");
1719
+ }
1720
+ return { scope, accountId };
1721
+ }
1722
+ async function listStatements(context, options, format2) {
1723
+ const path = options.scope === "primary" ? withCursor2("/v2/accounts/card/primary/statements", options.cursor) : withCursor2(`/v2/accounts/card/additional/${options.accountId}/statements`, options.cursor);
1724
+ const response = await context.client.fetch(path);
1725
+ const statements = response.items ?? response.statements ?? [];
1726
+ if (format2 === "json") {
1727
+ printJson({ items: statements, nextCursor: response.next_cursor ?? null });
1728
+ return;
1729
+ }
1730
+ if (statements.length === 0) {
1731
+ console.log("No statements found.");
1732
+ return;
1733
+ }
1734
+ printTable(statements.map((statement) => ({
1735
+ id: statement.id,
1736
+ status: statement.statement_status ?? "-",
1737
+ start: formatDate(statement.period_start_date),
1738
+ end: formatDate(statement.period_end_date),
1739
+ due: formatDate(statement.due_date),
1740
+ downloadUrl: statement.download_url ?? "-"
1741
+ })), [
1742
+ { key: "id", header: "Statement ID", width: 36 },
1743
+ { key: "status", header: "Status", width: 12 },
1744
+ { key: "start", header: "Start", width: 12 },
1745
+ { key: "end", header: "End", width: 12 },
1746
+ { key: "due", header: "Due", width: 12 },
1747
+ { key: "downloadUrl", header: "Download URL", width: 50 }
1748
+ ]);
1749
+ if (response.next_cursor) {
1750
+ console.log(`
1751
+ Next cursor: ${response.next_cursor}`);
1752
+ }
1753
+ }
1754
+ async function getStatement(context, statementId, options, format2) {
1755
+ const path = options.scope === "primary" ? `/v2/accounts/card/primary/statements/${statementId}` : `/v2/accounts/card/additional/${options.accountId}/statements/${statementId}`;
1756
+ const response = await context.client.fetch(path);
1757
+ const statement = response.account_statement ?? response.statement ?? response.item;
1758
+ if (!statement) {
1759
+ throw new Error("Brex API returned an empty statement payload.");
1760
+ }
1761
+ if (format2 === "json") {
1762
+ printJson(statement);
1763
+ return;
1764
+ }
1765
+ console.log("Statement Details");
1766
+ console.log("─────────────────");
1767
+ console.log(`ID: ${statement.id}`);
1768
+ console.log(`Status: ${statement.statement_status ?? "-"}`);
1769
+ console.log(`Period Start:${" "}${formatDate(statement.period_start_date)}`);
1770
+ console.log(`Period End: ${formatDate(statement.period_end_date)}`);
1771
+ console.log(`Due Date: ${formatDate(statement.due_date)}`);
1772
+ console.log(`Download: ${statement.download_url ?? "-"}`);
1773
+ }
1774
+ function withCursor2(path, cursor) {
1775
+ if (!cursor)
1776
+ return path;
1777
+ return `${path}?cursor=${encodeURIComponent(cursor)}`;
1778
+ }
1779
+
1780
+ // sources/commands/webhooks/index.ts
1781
+ var USAGE10 = `brex webhooks
1782
+ brex webhooks list [--cursor <cursor>] [--limit <N>]
1783
+ brex webhooks get <webhook-id>
1784
+ brex webhooks create --url <url> [--status <status>] [--events <event1,event2>]
1785
+ brex webhooks update <webhook-id> [--url <url>] [--status <status>] [--events <event1,event2>]
1786
+ brex webhooks delete <webhook-id>
1787
+ brex webhooks --json`;
1788
+ var webhooksCommand = {
1789
+ name: "webhooks",
1790
+ description: "Manage webhook endpoints.",
1791
+ usage: USAGE10,
1792
+ aliases: ["webhook", "wh"],
1793
+ run: async (args, context) => {
1794
+ const { format: format2, args: remaining } = parseOutputFlag(args);
1795
+ const subcommand = remaining[0] ?? "list";
1796
+ switch (subcommand) {
1797
+ case "list":
1798
+ await listWebhooks(context, parseListOptions6(remaining.slice(1)), format2);
1799
+ return;
1800
+ case "get": {
1801
+ const webhookId = remaining[1];
1802
+ if (!webhookId)
1803
+ throw new Error("Missing webhook ID. Usage: brex webhooks get <webhook-id>");
1804
+ await getWebhook(context, webhookId, format2);
1805
+ return;
1806
+ }
1807
+ case "create":
1808
+ await createWebhook(context, parseCreateOptions(remaining.slice(1)), format2);
1809
+ return;
1810
+ case "update": {
1811
+ const webhookId = remaining[1];
1812
+ if (!webhookId)
1813
+ throw new Error("Missing webhook ID. Usage: brex webhooks update <webhook-id> ...");
1814
+ await updateWebhook(context, webhookId, parseUpdateOptions(remaining.slice(2)), format2);
1815
+ return;
1816
+ }
1817
+ case "delete": {
1818
+ const webhookId = remaining[1];
1819
+ if (!webhookId)
1820
+ throw new Error("Missing webhook ID. Usage: brex webhooks delete <webhook-id>");
1821
+ await deleteWebhook(context, webhookId);
1822
+ return;
1823
+ }
1824
+ case "verify":
1825
+ throw new Error("`brex webhooks verify` is not available in the current Brex Webhooks API.");
1826
+ default:
1827
+ throw new Error(`Unknown subcommand: ${subcommand}`);
1828
+ }
1829
+ }
1830
+ };
1831
+ function parseListOptions6(args) {
1832
+ const options = {};
1833
+ for (let i = 0;i < args.length; i += 1) {
1834
+ const arg = args[i];
1835
+ if (!arg)
1836
+ continue;
1837
+ if (arg === "--cursor") {
1838
+ const value = args[++i];
1839
+ if (!value)
1840
+ throw new Error("--cursor requires a value");
1841
+ options.cursor = value;
1842
+ continue;
1843
+ }
1844
+ if (arg === "--limit") {
1845
+ const value = args[++i];
1846
+ if (!value)
1847
+ throw new Error("--limit requires a value");
1848
+ const parsed = parseInt(value, 10);
1849
+ if (Number.isNaN(parsed) || parsed <= 0) {
1850
+ throw new Error("--limit must be a positive integer");
1851
+ }
1852
+ options.limit = parsed;
1853
+ continue;
1854
+ }
1855
+ if (arg.startsWith("-")) {
1856
+ throw new Error(`Unknown option: ${arg}`);
1857
+ }
1858
+ }
1859
+ return options;
1860
+ }
1861
+ function parseCreateOptions(args) {
1862
+ let url;
1863
+ let status;
1864
+ let events;
1865
+ for (let i = 0;i < args.length; i += 1) {
1866
+ const arg = args[i];
1867
+ if (!arg)
1868
+ continue;
1869
+ if (arg === "--url") {
1870
+ const value = args[++i];
1871
+ if (!value)
1872
+ throw new Error("--url requires a value");
1873
+ url = value;
1874
+ continue;
1875
+ }
1876
+ if (arg === "--status") {
1877
+ const value = args[++i];
1878
+ if (!value)
1879
+ throw new Error("--status requires a value");
1880
+ status = value;
1881
+ continue;
1882
+ }
1883
+ if (arg === "--events") {
1884
+ const value = args[++i];
1885
+ if (!value)
1886
+ throw new Error("--events requires a value");
1887
+ events = value.split(",").map((eventType) => eventType.trim()).filter(Boolean);
1888
+ continue;
1889
+ }
1890
+ if (arg.startsWith("-")) {
1891
+ throw new Error(`Unknown option: ${arg}`);
1892
+ }
1893
+ }
1894
+ if (!url)
1895
+ throw new Error("Missing required --url");
1896
+ return { url, status, events };
1897
+ }
1898
+ function parseUpdateOptions(args) {
1899
+ const options = {};
1900
+ for (let i = 0;i < args.length; i += 1) {
1901
+ const arg = args[i];
1902
+ if (!arg)
1903
+ continue;
1904
+ if (arg === "--url") {
1905
+ const value = args[++i];
1906
+ if (!value)
1907
+ throw new Error("--url requires a value");
1908
+ options.url = value;
1909
+ continue;
1910
+ }
1911
+ if (arg === "--status") {
1912
+ const value = args[++i];
1913
+ if (!value)
1914
+ throw new Error("--status requires a value");
1915
+ options.status = value;
1916
+ continue;
1917
+ }
1918
+ if (arg === "--events") {
1919
+ const value = args[++i];
1920
+ if (!value)
1921
+ throw new Error("--events requires a value");
1922
+ options.events = value.split(",").map((eventType) => eventType.trim()).filter(Boolean);
1923
+ continue;
1924
+ }
1925
+ if (arg.startsWith("-")) {
1926
+ throw new Error(`Unknown option: ${arg}`);
1927
+ }
1928
+ }
1929
+ return options;
1930
+ }
1931
+ async function listWebhooks(context, options, format2) {
1932
+ const params = new URLSearchParams;
1933
+ if (options.cursor)
1934
+ params.set("cursor", options.cursor);
1935
+ if (options.limit)
1936
+ params.set("limit", String(options.limit));
1937
+ const query = params.toString();
1938
+ const path = query ? `/v1/webhooks?${query}` : "/v1/webhooks";
1939
+ const response = await context.client.fetch(path);
1940
+ const webhooks = response.items ?? response.webhooks ?? [];
1941
+ if (format2 === "json") {
1942
+ printJson({ items: webhooks, nextCursor: response.next_cursor ?? null });
1943
+ return;
1944
+ }
1945
+ if (webhooks.length === 0) {
1946
+ console.log("No webhooks configured.");
1947
+ return;
1948
+ }
1949
+ printTable(webhooks.map((webhook) => ({
1950
+ id: webhook.id,
1951
+ url: truncate(webhook.url ?? "-", 40),
1952
+ status: webhook.status ?? "-",
1953
+ events: truncate((webhook.subscriptions ?? []).map((subscription) => subscription.event_type).filter((eventType) => Boolean(eventType)).join(", ") || "-", 35)
1954
+ })), [
1955
+ { key: "id", header: "ID", width: 36 },
1956
+ { key: "url", header: "URL", width: 40 },
1957
+ { key: "status", header: "Status", width: 12 },
1958
+ { key: "events", header: "Events", width: 35 }
1959
+ ]);
1960
+ if (response.next_cursor) {
1961
+ console.log(`
1962
+ Next cursor: ${response.next_cursor}`);
1963
+ }
1964
+ }
1965
+ async function getWebhook(context, webhookId, format2) {
1966
+ const response = await context.client.fetch(`/v1/webhooks/${webhookId}`);
1967
+ const webhook = response.webhook ?? response.item ?? response;
1968
+ if (format2 === "json") {
1969
+ printJson(webhook);
1970
+ return;
1971
+ }
1972
+ const events = (webhook.subscriptions ?? []).map((subscription) => subscription.event_type).filter((eventType) => Boolean(eventType));
1973
+ console.log("Webhook Details");
1974
+ console.log("───────────────");
1975
+ console.log(`ID: ${webhook.id}`);
1976
+ console.log(`URL: ${webhook.url ?? "-"}`);
1977
+ console.log(`Status: ${webhook.status ?? "-"}`);
1978
+ console.log(`Events: ${events.length > 0 ? events.join(", ") : "-"}`);
1979
+ }
1980
+ async function createWebhook(context, options, format2) {
1981
+ const body = {
1982
+ url: options.url
1983
+ };
1984
+ if (options.status)
1985
+ body.status = options.status;
1986
+ if (options.events && options.events.length > 0) {
1987
+ body.subscriptions = options.events.map((eventType) => ({
1988
+ event_type: eventType,
1989
+ status: "ACTIVE"
1990
+ }));
1991
+ }
1992
+ const response = await context.client.fetch("/v1/webhooks", {
1993
+ method: "POST",
1994
+ body: JSON.stringify(body)
1995
+ });
1996
+ const webhook = response.webhook ?? response.item ?? response;
1997
+ if (format2 === "json") {
1998
+ printJson(webhook);
1999
+ return;
2000
+ }
2001
+ console.log("Webhook Created");
2002
+ console.log("───────────────");
2003
+ console.log(`ID: ${webhook.id}`);
2004
+ console.log(`URL: ${webhook.url ?? "-"}`);
2005
+ console.log(`Status: ${webhook.status ?? "-"}`);
2006
+ }
2007
+ async function updateWebhook(context, webhookId, options, format2) {
2008
+ const body = {};
2009
+ if (options.url)
2010
+ body.url = options.url;
2011
+ if (options.status)
2012
+ body.status = options.status;
2013
+ if (options.events && options.events.length > 0) {
2014
+ body.subscriptions = options.events.map((eventType) => ({
2015
+ event_type: eventType,
2016
+ status: "ACTIVE"
2017
+ }));
2018
+ }
2019
+ const response = await context.client.fetch(`/v1/webhooks/${webhookId}`, {
2020
+ method: "PUT",
2021
+ body: JSON.stringify(body)
2022
+ });
2023
+ const webhook = response.webhook ?? response.item ?? response;
2024
+ if (format2 === "json") {
2025
+ printJson(webhook);
2026
+ return;
2027
+ }
2028
+ console.log("Webhook Updated");
2029
+ console.log("───────────────");
2030
+ console.log(`ID: ${webhook.id}`);
2031
+ console.log(`URL: ${webhook.url ?? "-"}`);
2032
+ console.log(`Status: ${webhook.status ?? "-"}`);
2033
+ }
2034
+ async function deleteWebhook(context, webhookId) {
2035
+ await context.client.fetch(`/v1/webhooks/${webhookId}`, { method: "DELETE" });
2036
+ console.log(`Webhook ${webhookId} deleted.`);
2037
+ }
2038
+
2039
+ // sources/commands/events/index.ts
2040
+ var USAGE11 = `brex events
2041
+ brex events list [--event-type <type>] [--after-date <ISO>] [--before-date <ISO>] [--cursor <cursor>] [--limit <N>]
2042
+ brex events get <event-id>
2043
+ brex events --json`;
2044
+ var eventsCommand = {
2045
+ name: "events",
2046
+ description: "List and view webhook events.",
2047
+ usage: USAGE11,
2048
+ aliases: ["event"],
2049
+ run: async (args, context) => {
2050
+ const { format: format2, args: remaining } = parseOutputFlag(args);
2051
+ const subcommand = remaining[0] ?? "list";
2052
+ if (subcommand === "list") {
2053
+ await listEvents(context, parseListOptions7(remaining.slice(1)), format2);
2054
+ return;
2055
+ }
2056
+ if (subcommand === "get") {
2057
+ const eventId = remaining[1];
2058
+ if (!eventId)
2059
+ throw new Error("Missing event ID. Usage: brex events get <event-id>");
2060
+ await getEvent(context, eventId, format2);
2061
+ return;
2062
+ }
2063
+ if (!subcommand.startsWith("-")) {
2064
+ await getEvent(context, subcommand, format2);
2065
+ return;
2066
+ }
2067
+ throw new Error(`Unknown subcommand: ${subcommand}`);
2068
+ }
2069
+ };
2070
+ function parseListOptions7(args) {
2071
+ const options = {};
2072
+ for (let i = 0;i < args.length; i += 1) {
2073
+ const arg = args[i];
2074
+ if (!arg)
2075
+ continue;
2076
+ if (arg === "--event-type") {
2077
+ const value = args[++i];
2078
+ if (!value)
2079
+ throw new Error("--event-type requires a value");
2080
+ options.eventType = value;
2081
+ continue;
2082
+ }
2083
+ if (arg === "--after-date") {
2084
+ const value = args[++i];
2085
+ if (!value)
2086
+ throw new Error("--after-date requires a value");
2087
+ options.afterDate = value;
2088
+ continue;
2089
+ }
2090
+ if (arg === "--before-date") {
2091
+ const value = args[++i];
2092
+ if (!value)
2093
+ throw new Error("--before-date requires a value");
2094
+ options.beforeDate = value;
2095
+ continue;
2096
+ }
2097
+ if (arg === "--cursor") {
2098
+ const value = args[++i];
2099
+ if (!value)
2100
+ throw new Error("--cursor requires a value");
2101
+ options.cursor = value;
2102
+ continue;
2103
+ }
2104
+ if (arg === "--limit") {
2105
+ const value = args[++i];
2106
+ if (!value)
2107
+ throw new Error("--limit requires a value");
2108
+ const parsed = parseInt(value, 10);
2109
+ if (Number.isNaN(parsed) || parsed <= 0) {
2110
+ throw new Error("--limit must be a positive integer");
2111
+ }
2112
+ options.limit = parsed;
2113
+ continue;
2114
+ }
2115
+ if (arg.startsWith("-")) {
2116
+ throw new Error(`Unknown option: ${arg}`);
2117
+ }
2118
+ }
2119
+ return options;
2120
+ }
2121
+ async function listEvents(context, options, format2) {
2122
+ const params = new URLSearchParams;
2123
+ if (options.eventType)
2124
+ params.set("event_type", options.eventType);
2125
+ if (options.afterDate)
2126
+ params.set("after_date", options.afterDate);
2127
+ if (options.beforeDate)
2128
+ params.set("before_date", options.beforeDate);
2129
+ if (options.cursor)
2130
+ params.set("cursor", options.cursor);
2131
+ if (options.limit)
2132
+ params.set("limit", String(options.limit));
2133
+ const query = params.toString();
2134
+ const path = query ? `/v1/events?${query}` : "/v1/events";
2135
+ const response = await context.client.fetch(path);
2136
+ const events = response.items ?? response.events ?? [];
2137
+ if (format2 === "json") {
2138
+ printJson({ items: events, nextCursor: response.next_cursor ?? null });
2139
+ return;
2140
+ }
2141
+ if (events.length === 0) {
2142
+ console.log("No events found.");
2143
+ return;
2144
+ }
2145
+ printTable(events.map((event) => ({
2146
+ id: event.id,
2147
+ type: truncate(event.event_type ?? "-", 30),
2148
+ occurredAt: formatDateTime(event.occurred_at),
2149
+ webhookId: truncate(event.webhook_id ?? "-", 36)
2150
+ })), [
2151
+ { key: "id", header: "Event ID", width: 36 },
2152
+ { key: "type", header: "Type", width: 30 },
2153
+ { key: "occurredAt", header: "Occurred", width: 20 },
2154
+ { key: "webhookId", header: "Webhook ID", width: 36 }
2155
+ ]);
2156
+ if (response.next_cursor) {
2157
+ console.log(`
2158
+ Next cursor: ${response.next_cursor}`);
2159
+ }
2160
+ }
2161
+ async function getEvent(context, eventId, format2) {
2162
+ const response = await context.client.fetch(`/v1/events/${eventId}`);
2163
+ const event = response.event ?? response.item ?? response;
2164
+ if (format2 === "json") {
2165
+ printJson(event);
2166
+ return;
2167
+ }
2168
+ console.log("Event Details");
2169
+ console.log("─────────────");
2170
+ console.log(`ID: ${event.id}`);
2171
+ console.log(`Type: ${event.event_type ?? "-"}`);
2172
+ console.log(`Occurred: ${formatDateTime(event.occurred_at)}`);
2173
+ console.log(`Webhook ID: ${event.webhook_id ?? "-"}`);
2174
+ console.log("Payload:");
2175
+ console.log(JSON.stringify(event.payload ?? {}, null, 2));
2176
+ }
2177
+
2178
+ // sources/commands/organization/index.ts
2179
+ var USAGE12 = `brex organization
2180
+ brex org
2181
+ brex organization --json`;
2182
+ var organizationCommand = {
2183
+ name: "organization",
2184
+ description: "Get organization details.",
2185
+ usage: USAGE12,
2186
+ aliases: ["org"],
2187
+ run: async (args, context) => {
2188
+ const { format: format2 } = parseOutputFlag(args);
2189
+ const response = await context.client.fetch("/v2/company");
2190
+ const company = response.company ?? response.item ?? response;
2191
+ if (format2 === "json") {
2192
+ printJson(company);
2193
+ return;
2194
+ }
2195
+ const primaryLocation = company.location ?? company.locations?.[0];
2196
+ console.log("Organization Details");
2197
+ console.log("────────────────────");
2198
+ console.log(`ID: ${company.id ?? "-"}`);
2199
+ console.log(`Legal Name: ${company.legal_name ?? "-"}`);
2200
+ if (company.dba_name)
2201
+ console.log(`DBA Name: ${company.dba_name}`);
2202
+ if (company.tax_id)
2203
+ console.log(`Tax ID: ${company.tax_id}`);
2204
+ if (company.status)
2205
+ console.log(`Status: ${company.status}`);
2206
+ if (primaryLocation) {
2207
+ console.log(`Address: ${primaryLocation.address_line_1 ?? "-"}`);
2208
+ if (primaryLocation.address_line_2) {
2209
+ console.log(` ${primaryLocation.address_line_2}`);
2210
+ }
2211
+ const cityRegion = [primaryLocation.city, primaryLocation.state].filter(Boolean).join(", ");
2212
+ const postal = primaryLocation.postal_code ?? "";
2213
+ const firstLine = [cityRegion, postal].filter(Boolean).join(" ");
2214
+ if (firstLine)
2215
+ console.log(` ${firstLine}`);
2216
+ if (primaryLocation.country)
2217
+ console.log(` ${primaryLocation.country}`);
2218
+ }
2219
+ }
2220
+ };
2221
+
2222
+ // sources/commands/users/index.ts
2223
+ var USAGE13 = `brex users [list] [--cursor <cursor>] [--email <email>]
2224
+ brex users get <user-id>
2225
+ brex users --json`;
2226
+ var usersCommand = {
2227
+ name: "users",
2228
+ description: "List and view organization users.",
2229
+ usage: USAGE13,
2230
+ aliases: ["user"],
2231
+ run: async (args, context) => {
2232
+ const { format: format2, args: remaining } = parseOutputFlag(args);
2233
+ const subcommand = remaining[0] ?? "list";
2234
+ switch (subcommand) {
2235
+ case "list":
2236
+ await listUsers(context, parseListOptions8(remaining.slice(1)), format2);
2237
+ return;
2238
+ case "get": {
2239
+ const userId = remaining[1];
2240
+ if (!userId)
2241
+ throw new Error("Missing user ID. Usage: brex users get <user-id>");
2242
+ await getUser(context, userId, format2);
2243
+ return;
2244
+ }
2245
+ default:
2246
+ if (!subcommand.startsWith("-")) {
2247
+ await getUser(context, subcommand, format2);
2248
+ return;
2249
+ }
2250
+ throw new Error(`Unknown subcommand: ${subcommand}`);
2251
+ }
2252
+ }
2253
+ };
2254
+ function parseListOptions8(args) {
2255
+ let cursor;
2256
+ let email;
2257
+ for (let i = 0;i < args.length; i += 1) {
2258
+ const arg = args[i];
2259
+ if (!arg)
2260
+ continue;
2261
+ if (arg === "--cursor") {
2262
+ const value = args[++i];
2263
+ if (!value)
2264
+ throw new Error("--cursor requires a value");
2265
+ cursor = value;
2266
+ continue;
2267
+ }
2268
+ if (arg === "--email") {
2269
+ const value = args[++i];
2270
+ if (!value)
2271
+ throw new Error("--email requires a value");
2272
+ email = value;
2273
+ continue;
2274
+ }
2275
+ if (arg.startsWith("-")) {
2276
+ throw new Error(`Unknown option: ${arg}`);
2277
+ }
2278
+ }
2279
+ return { cursor, email };
2280
+ }
2281
+ async function listUsers(context, options, format2) {
2282
+ const params = new URLSearchParams;
2283
+ if (options.cursor)
2284
+ params.set("cursor", options.cursor);
2285
+ if (options.email)
2286
+ params.set("email", options.email);
2287
+ const query = params.toString();
2288
+ const path = query ? `/v2/users?${query}` : "/v2/users";
2289
+ const response = await context.client.fetch(path);
2290
+ const users = response.items ?? response.users ?? [];
2291
+ if (format2 === "json") {
2292
+ printJson({ items: users, nextCursor: response.next_cursor ?? null });
2293
+ return;
2294
+ }
2295
+ if (users.length === 0) {
2296
+ console.log("No users found.");
2297
+ return;
2298
+ }
2299
+ printTable(users.map((user) => ({
2300
+ id: user.id,
2301
+ firstName: user.first_name ?? "-",
2302
+ lastName: user.last_name ?? "-",
2303
+ email: user.email ?? "-",
2304
+ department: user.department ?? "-",
2305
+ status: user.status ?? "-"
2306
+ })), [
2307
+ { key: "id", header: "ID", width: 36 },
2308
+ { key: "firstName", header: "First Name", width: 14 },
2309
+ { key: "lastName", header: "Last Name", width: 14 },
2310
+ { key: "email", header: "Email", width: 30 },
2311
+ { key: "department", header: "Department", width: 15 },
2312
+ { key: "status", header: "Status", width: 10 }
2313
+ ]);
2314
+ if (response.next_cursor) {
2315
+ console.log(`
2316
+ Next cursor: ${response.next_cursor}`);
2317
+ }
2318
+ }
2319
+ async function getUser(context, userId, format2) {
2320
+ const response = await context.client.fetch(`/v2/users/${userId}`);
2321
+ const user = response.user ?? response.item ?? response;
2322
+ if (format2 === "json") {
2323
+ printJson(user);
2324
+ return;
2325
+ }
2326
+ console.log("User Details");
2327
+ console.log("────────────");
2328
+ console.log(`ID: ${user.id}`);
2329
+ console.log(`Name: ${user.first_name ?? "-"} ${user.last_name ?? "-"}`);
2330
+ console.log(`Email: ${user.email ?? "-"}`);
2331
+ console.log(`Department: ${user.department ?? "-"}`);
2332
+ console.log(`Status: ${user.status ?? "-"}`);
2333
+ if (user.manager_id) {
2334
+ console.log(`Manager ID: ${user.manager_id}`);
2335
+ }
2336
+ }
2337
+
2338
+ // sources/commands/categories/index.ts
2339
+ var USAGE14 = `brex categories`;
2340
+ var categoriesCommand = {
2341
+ name: "categories",
2342
+ description: "Not supported by Brex public APIs in this CLI.",
2343
+ usage: USAGE14,
2344
+ aliases: ["category", "cat"],
2345
+ run: async () => {
2346
+ throw new Error("The Brex APIs currently used by this CLI do not expose a direct transaction categories endpoint. See https://developer.brex.com/ for available resources.");
2347
+ }
2348
+ };
2349
+
2350
+ // sources/commands/version/index.ts
2351
+ var VERSION = "0.1.0";
2352
+ var versionCommand = {
2353
+ name: "version",
2354
+ description: "Show brex-cli version.",
2355
+ usage: "brex version",
2356
+ aliases: ["v"],
2357
+ run: async () => {
2358
+ console.log(`brex-cli v${VERSION}`);
2359
+ }
2360
+ };
2361
+
2362
+ // sources/main.ts
2363
+ var BIN = "brex";
2364
+ var commands = [
2365
+ loginCommand,
2366
+ logoutCommand,
2367
+ statusCommand,
2368
+ accountsCommand,
2369
+ transactionsCommand,
2370
+ transferCommand,
2371
+ recipientsCommand,
2372
+ cardsCommand,
2373
+ statementsCommand,
2374
+ webhooksCommand,
2375
+ eventsCommand,
2376
+ organizationCommand,
2377
+ usersCommand,
2378
+ categoriesCommand,
2379
+ versionCommand
2380
+ ];
2381
+ var commandIndex = new Map;
2382
+ for (const command of commands) {
2383
+ commandIndex.set(command.name, command);
2384
+ if (command.aliases) {
2385
+ for (const alias of command.aliases) {
2386
+ commandIndex.set(alias, command);
2387
+ }
2388
+ }
2389
+ }
2390
+ function isHelpFlag(value) {
2391
+ return value === "-h" || value === "--help";
2392
+ }
2393
+ function printHelp() {
2394
+ console.log(`${BIN} <command> [options]`);
2395
+ console.log("");
2396
+ console.log("Commands:");
2397
+ for (const command of commands) {
2398
+ const aliasText = command.aliases && command.aliases.length > 0 ? ` (${command.aliases.join(", ")})` : "";
2399
+ console.log(` ${command.name.padEnd(16)}${command.description}${aliasText}`);
2400
+ }
2401
+ console.log("");
2402
+ console.log("Global options:");
2403
+ console.log(" --json Output as JSON");
2404
+ console.log(" -h, --help Show help");
2405
+ console.log(" -v, --version Show version");
2406
+ console.log("");
2407
+ console.log(`Run "${BIN} <command> --help" for command-specific help.`);
2408
+ }
2409
+ function printCommandHelp(command) {
2410
+ console.log(command.usage);
2411
+ console.log("");
2412
+ console.log(command.description);
2413
+ }
2414
+ async function runCli() {
2415
+ const args = process.argv.slice(2);
2416
+ const firstArg = args[0];
2417
+ if (!firstArg || isHelpFlag(firstArg)) {
2418
+ printHelp();
2419
+ return;
2420
+ }
2421
+ if (firstArg === "--version" || firstArg === "-v") {
2422
+ await versionCommand.run([], createContext());
2423
+ return;
2424
+ }
2425
+ const commandName = firstArg;
2426
+ const command = commandIndex.get(commandName);
2427
+ if (!command) {
2428
+ console.error(`Unknown command: ${commandName}`);
2429
+ printHelp();
2430
+ process.exitCode = 1;
2431
+ return;
2432
+ }
2433
+ const commandArgs = args.slice(1);
2434
+ if (commandArgs.some(isHelpFlag)) {
2435
+ printCommandHelp(command);
2436
+ return;
2437
+ }
2438
+ try {
2439
+ const context = createContext();
2440
+ await command.run(commandArgs, context);
2441
+ } catch (error) {
2442
+ if (error instanceof Error) {
2443
+ console.error(`Error: ${error.message}`);
2444
+ } else {
2445
+ console.error("Unexpected error");
2446
+ }
2447
+ process.exitCode = 1;
2448
+ }
2449
+ }
2450
+ function createContext() {
2451
+ return {
2452
+ client: createBrexClient()
2453
+ };
2454
+ }
2455
+ runCli();