@stephendolan/ynab-cli 1.0.3 → 1.0.5
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/README.md +5 -3
- package/dist/cli.js +76 -59
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,9 +202,11 @@ Use the YNAB web or mobile app for these operations.
|
|
|
202
202
|
|
|
203
203
|
## API Rate Limits
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
The YNAB API enforces a rate limit of **200 requests per hour** per access token. When exceeded, the API returns HTTP 429 errors.
|
|
206
|
+
|
|
207
|
+
**If you hit the rate limit:**
|
|
208
|
+
- Wait 5-10 minutes before retrying (the limit uses a rolling 60-minute window)
|
|
209
|
+
- For batch operations, add delays between requests: `sleep 20` in shell loops ensures ~180 requests/hour
|
|
208
210
|
|
|
209
211
|
## References
|
|
210
212
|
|
package/dist/cli.js
CHANGED
|
@@ -15,24 +15,24 @@ function isInteractive() {
|
|
|
15
15
|
return process.stdin.isTTY === true;
|
|
16
16
|
}
|
|
17
17
|
function convertMilliunitsToAmounts(data) {
|
|
18
|
-
if (data === null || data === void 0)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} else {
|
|
30
|
-
converted[key] = convertMilliunitsToAmounts(value);
|
|
18
|
+
if (data === null || data === void 0) return data;
|
|
19
|
+
if (Array.isArray(data)) return data.map(convertMilliunitsToAmounts);
|
|
20
|
+
if (typeof data !== "object") return data;
|
|
21
|
+
const converted = {};
|
|
22
|
+
for (const [key, value] of Object.entries(data)) {
|
|
23
|
+
if (isAmountField(key) && typeof value === "number") {
|
|
24
|
+
converted[key] = milliunitsToAmount(value);
|
|
25
|
+
} else if (isDebtAmountMapField(key) && typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
26
|
+
const convertedMap = {};
|
|
27
|
+
for (const [dateKey, amountValue] of Object.entries(value)) {
|
|
28
|
+
convertedMap[dateKey] = typeof amountValue === "number" ? milliunitsToAmount(amountValue) : amountValue;
|
|
31
29
|
}
|
|
30
|
+
converted[key] = convertedMap;
|
|
31
|
+
} else {
|
|
32
|
+
converted[key] = convertMilliunitsToAmounts(value);
|
|
32
33
|
}
|
|
33
|
-
return converted;
|
|
34
34
|
}
|
|
35
|
-
return
|
|
35
|
+
return converted;
|
|
36
36
|
}
|
|
37
37
|
function isAmountField(fieldName) {
|
|
38
38
|
const amountFields = [
|
|
@@ -43,10 +43,24 @@ function isAmountField(fieldName) {
|
|
|
43
43
|
"budgeted",
|
|
44
44
|
"activity",
|
|
45
45
|
"available",
|
|
46
|
-
"goal_target"
|
|
46
|
+
"goal_target",
|
|
47
|
+
"goal_under_funded",
|
|
48
|
+
"goal_overall_funded",
|
|
49
|
+
"goal_overall_left",
|
|
50
|
+
"income",
|
|
51
|
+
"to_be_budgeted",
|
|
52
|
+
"debt_original_balance"
|
|
47
53
|
];
|
|
48
54
|
return amountFields.includes(fieldName) || fieldName.endsWith("_amount");
|
|
49
55
|
}
|
|
56
|
+
function isDebtAmountMapField(fieldName) {
|
|
57
|
+
const debtAmountMapFields = [
|
|
58
|
+
"debt_minimum_payments",
|
|
59
|
+
"debt_escrow_amounts",
|
|
60
|
+
"debt_interest_rates"
|
|
61
|
+
];
|
|
62
|
+
return debtAmountMapFields.includes(fieldName);
|
|
63
|
+
}
|
|
50
64
|
function parseApprovedFilter(value) {
|
|
51
65
|
const normalized = value.toLowerCase();
|
|
52
66
|
if (normalized !== "true" && normalized !== "false") {
|
|
@@ -113,9 +127,6 @@ function outputJson(data, options = {}) {
|
|
|
113
127
|
const jsonString = mergedOptions.compact ? JSON.stringify(convertedData) : JSON.stringify(convertedData, null, 2);
|
|
114
128
|
console.log(jsonString);
|
|
115
129
|
}
|
|
116
|
-
function outputSuccess(data, options = {}) {
|
|
117
|
-
outputJson(data, options);
|
|
118
|
-
}
|
|
119
130
|
|
|
120
131
|
// src/commands/auth.ts
|
|
121
132
|
import { Command } from "commander";
|
|
@@ -309,8 +320,14 @@ function sanitizeApiError(error) {
|
|
|
309
320
|
id: apiError.id
|
|
310
321
|
};
|
|
311
322
|
}
|
|
323
|
+
function enhanceRateLimitMessage(detail) {
|
|
324
|
+
return `${detail}
|
|
325
|
+
|
|
326
|
+
YNAB API limit: 200 requests/hour (rolling window). Wait a few minutes and retry.`;
|
|
327
|
+
}
|
|
312
328
|
function formatErrorResponse(name, detail, statusCode) {
|
|
313
|
-
|
|
329
|
+
const enhancedDetail = name === "too_many_requests" ? enhanceRateLimitMessage(detail) : detail;
|
|
330
|
+
outputJson({ error: { name, detail: enhancedDetail, statusCode } });
|
|
314
331
|
process.exit(1);
|
|
315
332
|
}
|
|
316
333
|
function handleYnabError(error) {
|
|
@@ -339,7 +356,7 @@ import dotenv from "dotenv";
|
|
|
339
356
|
dotenv.config();
|
|
340
357
|
var YnabClient = class {
|
|
341
358
|
api = null;
|
|
342
|
-
|
|
359
|
+
envVarWarningShown = false;
|
|
343
360
|
async getApi() {
|
|
344
361
|
if (this.api) {
|
|
345
362
|
return this.api;
|
|
@@ -352,11 +369,11 @@ var YnabClient = class {
|
|
|
352
369
|
401
|
|
353
370
|
);
|
|
354
371
|
}
|
|
355
|
-
if (!keychainToken && process.env.YNAB_API_KEY && !this.
|
|
372
|
+
if (!keychainToken && process.env.YNAB_API_KEY && !this.envVarWarningShown) {
|
|
356
373
|
console.warn(
|
|
357
374
|
"\x1B[33m\u26A0\uFE0F WARNING: Using YNAB_API_KEY environment variable.\nEnvironment variables may be visible to other processes.\nFor better security, use: ynab auth login\x1B[0m\n"
|
|
358
375
|
);
|
|
359
|
-
this.
|
|
376
|
+
this.envVarWarningShown = true;
|
|
360
377
|
}
|
|
361
378
|
this.api = new ynab.API(accessToken);
|
|
362
379
|
return this.api;
|
|
@@ -784,7 +801,7 @@ async function confirmDelete(itemType, skipConfirmation = false) {
|
|
|
784
801
|
`Are you sure you want to delete this ${itemType}?`
|
|
785
802
|
);
|
|
786
803
|
if (!confirmed) {
|
|
787
|
-
|
|
804
|
+
outputJson({ message: "Operation cancelled" });
|
|
788
805
|
return false;
|
|
789
806
|
}
|
|
790
807
|
return true;
|
|
@@ -808,7 +825,7 @@ function createAuthCommand() {
|
|
|
808
825
|
await auth.setAccessToken(token);
|
|
809
826
|
try {
|
|
810
827
|
const user = await client.getUser();
|
|
811
|
-
|
|
828
|
+
outputJson({
|
|
812
829
|
message: "Successfully authenticated",
|
|
813
830
|
user: { id: user?.id }
|
|
814
831
|
});
|
|
@@ -825,14 +842,14 @@ function createAuthCommand() {
|
|
|
825
842
|
}
|
|
826
843
|
try {
|
|
827
844
|
const user = await client.getUser();
|
|
828
|
-
|
|
845
|
+
outputJson({ authenticated: true, user: { id: user?.id } });
|
|
829
846
|
} catch (error) {
|
|
830
847
|
outputJson({ authenticated: false, message: "Token exists but is invalid" });
|
|
831
848
|
}
|
|
832
849
|
}));
|
|
833
850
|
cmd.command("logout").description("Remove stored credentials").action(withErrorHandling(async () => {
|
|
834
851
|
await auth.logout();
|
|
835
|
-
|
|
852
|
+
outputJson({ message: "Successfully logged out" });
|
|
836
853
|
}));
|
|
837
854
|
return cmd;
|
|
838
855
|
}
|
|
@@ -843,7 +860,7 @@ function createUserCommand() {
|
|
|
843
860
|
const cmd = new Command2("user").description("User information");
|
|
844
861
|
cmd.command("info").description("Get authenticated user information").action(withErrorHandling(async () => {
|
|
845
862
|
const user = await client.getUser();
|
|
846
|
-
|
|
863
|
+
outputJson(user);
|
|
847
864
|
}));
|
|
848
865
|
return cmd;
|
|
849
866
|
}
|
|
@@ -854,15 +871,15 @@ function createBudgetsCommand() {
|
|
|
854
871
|
const cmd = new Command3("budgets").description("Budget operations");
|
|
855
872
|
cmd.command("list").description("List all budgets").option("--include-accounts", "Include accounts in response").action(withErrorHandling(async (options) => {
|
|
856
873
|
const result = await client.getBudgets(options.includeAccounts);
|
|
857
|
-
|
|
874
|
+
outputJson(result?.budgets);
|
|
858
875
|
}));
|
|
859
876
|
cmd.command("view").description("View budget details (uses default if no id provided)").argument("[id]", "Budget ID").action(withErrorHandling(async (id) => {
|
|
860
877
|
const result = await client.getBudget(id);
|
|
861
|
-
|
|
878
|
+
outputJson(result?.budget);
|
|
862
879
|
}));
|
|
863
880
|
cmd.command("settings").description("View budget settings").argument("[id]", "Budget ID").action(withErrorHandling(async (id) => {
|
|
864
881
|
const settings = await client.getBudgetSettings(id);
|
|
865
|
-
|
|
882
|
+
outputJson(settings);
|
|
866
883
|
}));
|
|
867
884
|
cmd.command("set-default").description("Set default budget for commands").argument("<id>", "Budget ID").action(withErrorHandling(async (id) => {
|
|
868
885
|
const result = await client.getBudgets();
|
|
@@ -871,7 +888,7 @@ function createBudgetsCommand() {
|
|
|
871
888
|
throw new YnabCliError(`Budget with ID ${id} not found`, 404);
|
|
872
889
|
}
|
|
873
890
|
config.setDefaultBudget(id);
|
|
874
|
-
|
|
891
|
+
outputJson({
|
|
875
892
|
message: "Default budget set",
|
|
876
893
|
budget: { id: budget.id, name: budget.name }
|
|
877
894
|
});
|
|
@@ -885,11 +902,11 @@ function createAccountsCommand() {
|
|
|
885
902
|
const cmd = new Command4("accounts").description("Account operations");
|
|
886
903
|
cmd.command("list").description("List all accounts").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (options) => {
|
|
887
904
|
const result = await client.getAccounts(options.budget);
|
|
888
|
-
|
|
905
|
+
outputJson(result?.accounts);
|
|
889
906
|
}));
|
|
890
907
|
cmd.command("view").description("View account details").argument("<id>", "Account ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
891
908
|
const account = await client.getAccount(id, options.budget);
|
|
892
|
-
|
|
909
|
+
outputJson(account);
|
|
893
910
|
}));
|
|
894
911
|
cmd.command("transactions").description("List transactions for account").argument("<id>", "Account ID").option("-b, --budget <id>", "Budget ID").option("--since <date>", "Filter transactions since date (YYYY-MM-DD)").option("--type <type>", "Filter by transaction type").action(withErrorHandling(async (id, options) => {
|
|
895
912
|
const result = await client.getTransactionsByAccount(id, {
|
|
@@ -897,7 +914,7 @@ function createAccountsCommand() {
|
|
|
897
914
|
sinceDate: options.since,
|
|
898
915
|
type: options.type
|
|
899
916
|
});
|
|
900
|
-
|
|
917
|
+
outputJson(result?.transactions);
|
|
901
918
|
}));
|
|
902
919
|
return cmd;
|
|
903
920
|
}
|
|
@@ -908,13 +925,13 @@ function createCategoriesCommand() {
|
|
|
908
925
|
const cmd = new Command5("categories").description("Category operations");
|
|
909
926
|
cmd.command("list").description("List all categories").option("-b, --budget <id>", "Budget ID").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (options) => {
|
|
910
927
|
const result = await client.getCategories(options.budget, options.lastKnowledge);
|
|
911
|
-
|
|
928
|
+
outputJson(result?.category_groups);
|
|
912
929
|
}));
|
|
913
930
|
cmd.command("view").description("View category details").argument("<id>", "Category ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
914
931
|
const category = await client.getCategory(id, options.budget);
|
|
915
|
-
|
|
932
|
+
outputJson(category);
|
|
916
933
|
}));
|
|
917
|
-
cmd.command("budget").description("
|
|
934
|
+
cmd.command("budget").description("Set category budgeted amount for a month (overrides existing amount)").argument("<id>", "Category ID").requiredOption("--month <month>", "Month in YYYY-MM-DD format (e.g., 2025-07-01)").requiredOption("--amount <amount>", "Total budgeted amount to set (e.g., 100.50)", parseFloat).option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
918
935
|
if (isNaN(options.amount)) {
|
|
919
936
|
throw new YnabCliError("Amount must be a valid number", 400);
|
|
920
937
|
}
|
|
@@ -925,7 +942,7 @@ function createCategoriesCommand() {
|
|
|
925
942
|
{ category: { budgeted: milliunits } },
|
|
926
943
|
options.budget
|
|
927
944
|
);
|
|
928
|
-
|
|
945
|
+
outputJson(category);
|
|
929
946
|
}));
|
|
930
947
|
cmd.command("transactions").description("List transactions for category").argument("<id>", "Category ID").option("-b, --budget <id>", "Budget ID").option("--since <date>", "Filter transactions since date (YYYY-MM-DD)").option("--type <type>", "Filter by transaction type").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (id, options) => {
|
|
931
948
|
const result = await client.getTransactionsByCategory(id, {
|
|
@@ -934,7 +951,7 @@ function createCategoriesCommand() {
|
|
|
934
951
|
type: options.type,
|
|
935
952
|
lastKnowledgeOfServer: options.lastKnowledge
|
|
936
953
|
});
|
|
937
|
-
|
|
954
|
+
outputJson(result?.transactions);
|
|
938
955
|
}));
|
|
939
956
|
return cmd;
|
|
940
957
|
}
|
|
@@ -1003,11 +1020,11 @@ function createTransactionsCommand() {
|
|
|
1003
1020
|
maxAmount: options.maxAmount
|
|
1004
1021
|
});
|
|
1005
1022
|
const selected = applyFieldSelection(filtered, options.fields);
|
|
1006
|
-
|
|
1023
|
+
outputJson(selected);
|
|
1007
1024
|
}));
|
|
1008
1025
|
cmd.command("view").description("View single transaction").argument("<id>", "Transaction ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1009
1026
|
const transaction = await client.getTransaction(id, options.budget);
|
|
1010
|
-
|
|
1027
|
+
outputJson(transaction);
|
|
1011
1028
|
}));
|
|
1012
1029
|
cmd.command("create").description("Create transaction").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Account ID").option("--date <date>", "Date (YYYY-MM-DD)").option("--amount <amount>", "Amount in currency units (e.g., 10.50)", parseFloat).option("--payee-name <name>", "Payee name").option("--payee-id <id>", "Payee ID").option("--category-id <id>", "Category ID").option("--memo <memo>", "Memo").option("--cleared <status>", "Cleared status (cleared, uncleared, reconciled)").option("--approved", "Mark as approved").action(withErrorHandling(async (options) => {
|
|
1013
1030
|
const shouldPrompt = isInteractive() && !options.account && !options.amount;
|
|
@@ -1016,7 +1033,7 @@ function createTransactionsCommand() {
|
|
|
1016
1033
|
{ transaction: transactionData },
|
|
1017
1034
|
options.budget
|
|
1018
1035
|
);
|
|
1019
|
-
|
|
1036
|
+
outputJson(transaction);
|
|
1020
1037
|
}));
|
|
1021
1038
|
cmd.command("update").description("Update transaction").argument("<id>", "Transaction ID").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Account ID").option("--date <date>", "Date (YYYY-MM-DD)").option("--amount <amount>", "Amount in currency units", parseFloat).option("--payee-name <name>", "Payee name").option("--payee-id <id>", "Payee ID").option("--category-id <id>", "Category ID").option("--memo <memo>", "Memo").option("--cleared <status>", "Cleared status").option("--approved", "Mark as approved").action(withErrorHandling(async (id, options) => {
|
|
1022
1039
|
const transactionData = buildUpdateObject(options, {
|
|
@@ -1037,18 +1054,18 @@ function createTransactionsCommand() {
|
|
|
1037
1054
|
{ transaction: transactionData },
|
|
1038
1055
|
options.budget
|
|
1039
1056
|
);
|
|
1040
|
-
|
|
1057
|
+
outputJson(transaction);
|
|
1041
1058
|
}));
|
|
1042
1059
|
cmd.command("delete").description("Delete transaction").argument("<id>", "Transaction ID").option("-b, --budget <id>", "Budget ID").option("-y, --yes", "Skip confirmation").action(withErrorHandling(async (id, options) => {
|
|
1043
1060
|
if (!await confirmDelete("transaction", options.yes)) {
|
|
1044
1061
|
return;
|
|
1045
1062
|
}
|
|
1046
1063
|
const transaction = await client.deleteTransaction(id, options.budget);
|
|
1047
|
-
|
|
1064
|
+
outputJson({ message: "Transaction deleted", transaction });
|
|
1048
1065
|
}));
|
|
1049
1066
|
cmd.command("import").description("Import transactions").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (options) => {
|
|
1050
1067
|
const transactionIds = await client.importTransactions(options.budget);
|
|
1051
|
-
|
|
1068
|
+
outputJson({ transaction_ids: transactionIds });
|
|
1052
1069
|
}));
|
|
1053
1070
|
cmd.command("split").description("Split transaction into multiple categories").argument("<id>", "Transaction ID").requiredOption("--splits <json>", 'JSON array of splits: [{"amount": -21400, "category_id": "xxx", "memo": "..."}]').option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1054
1071
|
let parsedSplits;
|
|
@@ -1068,7 +1085,7 @@ function createTransactionsCommand() {
|
|
|
1068
1085
|
},
|
|
1069
1086
|
options.budget
|
|
1070
1087
|
);
|
|
1071
|
-
|
|
1088
|
+
outputJson(transaction);
|
|
1072
1089
|
}));
|
|
1073
1090
|
cmd.command("search").description("Search transactions").option("-b, --budget <id>", "Budget ID").option("--memo <text>", "Search in memo field").option("--payee-name <name>", "Search in payee name").option("--amount <amount>", "Search for exact amount in currency units", parseFloat).option("--since <date>", "Search transactions since date (YYYY-MM-DD)").option("--until <date>", "Search transactions until date (YYYY-MM-DD)").option("--approved <value>", "Filter by approval status: true or false").option("--status <statuses>", "Filter by cleared status: cleared, uncleared, reconciled (comma-separated)").option("--fields <fields>", "Comma-separated list of fields to include").action(withErrorHandling(async (options) => {
|
|
1074
1091
|
if (!options.memo && !options.payeeName && options.amount === void 0) {
|
|
@@ -1102,7 +1119,7 @@ function createTransactionsCommand() {
|
|
|
1102
1119
|
status: options.status
|
|
1103
1120
|
});
|
|
1104
1121
|
const filteredTransactions = applyFieldSelection(transactions, options.fields);
|
|
1105
|
-
|
|
1122
|
+
outputJson(filteredTransactions);
|
|
1106
1123
|
}));
|
|
1107
1124
|
return cmd;
|
|
1108
1125
|
}
|
|
@@ -1113,18 +1130,18 @@ function createScheduledCommand() {
|
|
|
1113
1130
|
const cmd = new Command7("scheduled").description("Scheduled transaction operations");
|
|
1114
1131
|
cmd.command("list").description("List all scheduled transactions").option("-b, --budget <id>", "Budget ID").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (options) => {
|
|
1115
1132
|
const result = await client.getScheduledTransactions(options.budget, options.lastKnowledge);
|
|
1116
|
-
|
|
1133
|
+
outputJson(result?.scheduled_transactions);
|
|
1117
1134
|
}));
|
|
1118
1135
|
cmd.command("view").description("View scheduled transaction").argument("<id>", "Scheduled transaction ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1119
1136
|
const scheduledTransaction = await client.getScheduledTransaction(id, options.budget);
|
|
1120
|
-
|
|
1137
|
+
outputJson(scheduledTransaction);
|
|
1121
1138
|
}));
|
|
1122
1139
|
cmd.command("delete").description("Delete scheduled transaction").argument("<id>", "Scheduled transaction ID").option("-b, --budget <id>", "Budget ID").option("-y, --yes", "Skip confirmation").action(withErrorHandling(async (id, options) => {
|
|
1123
1140
|
if (!await confirmDelete("scheduled transaction", options.yes)) {
|
|
1124
1141
|
return;
|
|
1125
1142
|
}
|
|
1126
1143
|
const scheduledTransaction = await client.deleteScheduledTransaction(id, options.budget);
|
|
1127
|
-
|
|
1144
|
+
outputJson({
|
|
1128
1145
|
message: "Scheduled transaction deleted",
|
|
1129
1146
|
scheduled_transaction: scheduledTransaction
|
|
1130
1147
|
});
|
|
@@ -1138,11 +1155,11 @@ function createPayeesCommand() {
|
|
|
1138
1155
|
const cmd = new Command8("payees").description("Payee operations");
|
|
1139
1156
|
cmd.command("list").description("List all payees").option("-b, --budget <id>", "Budget ID").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (options) => {
|
|
1140
1157
|
const result = await client.getPayees(options.budget, options.lastKnowledge);
|
|
1141
|
-
|
|
1158
|
+
outputJson(result?.payees);
|
|
1142
1159
|
}));
|
|
1143
1160
|
cmd.command("view").description("View payee details").argument("<id>", "Payee ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1144
1161
|
const payee = await client.getPayee(id, options.budget);
|
|
1145
|
-
|
|
1162
|
+
outputJson(payee);
|
|
1146
1163
|
}));
|
|
1147
1164
|
cmd.command("update").description("Rename payee").argument("<id>", "Payee ID").requiredOption("--name <name>", "New payee name").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1148
1165
|
if (!options.name?.trim()) {
|
|
@@ -1153,11 +1170,11 @@ function createPayeesCommand() {
|
|
|
1153
1170
|
{ payee: { name: options.name } },
|
|
1154
1171
|
options.budget
|
|
1155
1172
|
);
|
|
1156
|
-
|
|
1173
|
+
outputJson(payee);
|
|
1157
1174
|
}));
|
|
1158
1175
|
cmd.command("locations").description("List locations for payee").argument("<id>", "Payee ID").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (id, options) => {
|
|
1159
1176
|
const locations = await client.getPayeeLocationsByPayee(id, options.budget);
|
|
1160
|
-
|
|
1177
|
+
outputJson(locations);
|
|
1161
1178
|
}));
|
|
1162
1179
|
cmd.command("transactions").description("List transactions for payee").argument("<id>", "Payee ID").option("-b, --budget <id>", "Budget ID").option("--since <date>", "Filter transactions since date (YYYY-MM-DD)").option("--type <type>", "Filter by transaction type").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (id, options) => {
|
|
1163
1180
|
const result = await client.getTransactionsByPayee(id, {
|
|
@@ -1166,7 +1183,7 @@ function createPayeesCommand() {
|
|
|
1166
1183
|
type: options.type,
|
|
1167
1184
|
lastKnowledgeOfServer: options.lastKnowledge
|
|
1168
1185
|
});
|
|
1169
|
-
|
|
1186
|
+
outputJson(result?.transactions);
|
|
1170
1187
|
}));
|
|
1171
1188
|
return cmd;
|
|
1172
1189
|
}
|
|
@@ -1177,11 +1194,11 @@ function createMonthsCommand() {
|
|
|
1177
1194
|
const cmd = new Command9("months").description("Monthly budget operations");
|
|
1178
1195
|
cmd.command("list").description("List all budget months").option("-b, --budget <id>", "Budget ID").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(withErrorHandling(async (options) => {
|
|
1179
1196
|
const result = await client.getBudgetMonths(options.budget, options.lastKnowledge);
|
|
1180
|
-
|
|
1197
|
+
outputJson(result?.months);
|
|
1181
1198
|
}));
|
|
1182
|
-
cmd.command("view").description("View specific month details").argument("<month>", "Month in YYYY-MM format").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (month, options) => {
|
|
1199
|
+
cmd.command("view").description("View specific month details").argument("<month>", "Month in YYYY-MM-DD format (e.g., 2025-07-01)").option("-b, --budget <id>", "Budget ID").action(withErrorHandling(async (month, options) => {
|
|
1183
1200
|
const monthData = await client.getBudgetMonth(month, options.budget);
|
|
1184
|
-
|
|
1201
|
+
outputJson(monthData);
|
|
1185
1202
|
}));
|
|
1186
1203
|
return cmd;
|
|
1187
1204
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/lib/utils.ts","../src/lib/output.ts","../src/commands/auth.ts","../src/lib/config.ts","../src/lib/auth.ts","../src/lib/prompts.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/lib/command-utils.ts","../src/commands/user.ts","../src/commands/budgets.ts","../src/commands/accounts.ts","../src/commands/categories.ts","../src/commands/transactions.ts","../src/lib/schemas.ts","../src/commands/scheduled.ts","../src/commands/payees.ts","../src/commands/months.ts","../src/commands/api.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { setOutputOptions } from './lib/output.js';\nimport { createAuthCommand } from './commands/auth.js';\nimport { createUserCommand } from './commands/user.js';\nimport { createBudgetsCommand } from './commands/budgets.js';\nimport { createAccountsCommand } from './commands/accounts.js';\nimport { createCategoriesCommand } from './commands/categories.js';\nimport { createTransactionsCommand } from './commands/transactions.js';\nimport { createScheduledCommand } from './commands/scheduled.js';\nimport { createPayeesCommand } from './commands/payees.js';\nimport { createMonthsCommand } from './commands/months.js';\nimport { createApiCommand } from './commands/api.js';\n\nconst program = new Command();\n\nprogram\n .name('ynab')\n .description('A command-line interface for You Need a Budget (YNAB)')\n .version('1.0.0')\n .option('-c, --compact', 'Minified JSON output (single line)')\n .hook('preAction', (thisCommand) => {\n const options = thisCommand.opts();\n setOutputOptions({\n compact: options.compact,\n });\n });\n\nprogram.addCommand(createAuthCommand());\nprogram.addCommand(createUserCommand());\nprogram.addCommand(createBudgetsCommand());\nprogram.addCommand(createAccountsCommand());\nprogram.addCommand(createCategoriesCommand());\nprogram.addCommand(createTransactionsCommand());\nprogram.addCommand(createScheduledCommand());\nprogram.addCommand(createPayeesCommand());\nprogram.addCommand(createMonthsCommand());\nprogram.addCommand(createApiCommand());\n\nprogram.parse();\n","import { format, parseISO } from 'date-fns';\n\nexport function milliunitsToAmount(milliunits: number): number {\n return milliunits / 1000;\n}\n\nexport function amountToMilliunits(amount: number): number {\n return Math.round(amount * 1000);\n}\n\nexport function formatCurrency(milliunits: number, currencySymbol = '$'): string {\n const amount = milliunitsToAmount(milliunits);\n return `${currencySymbol}${amount.toFixed(2)}`;\n}\n\nexport function formatDate(isoDate: string, formatString = 'yyyy-MM-dd'): string {\n return format(parseISO(isoDate), formatString);\n}\n\nexport function parseDate(dateString: string): string {\n const date = parseISO(dateString);\n return format(date, 'yyyy-MM-dd');\n}\n\nexport function isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nexport function convertMilliunitsToAmounts(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n if (Array.isArray(data)) {\n return data.map(item => convertMilliunitsToAmounts(item));\n }\n\n if (typeof data === 'object') {\n const converted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (isAmountField(key) && typeof value === 'number') {\n converted[key] = milliunitsToAmount(value);\n } else {\n converted[key] = convertMilliunitsToAmounts(value);\n }\n }\n return converted;\n }\n\n return data;\n}\n\nfunction isAmountField(fieldName: string): boolean {\n const amountFields = [\n 'amount',\n 'balance',\n 'cleared_balance',\n 'uncleared_balance',\n 'budgeted',\n 'activity',\n 'available',\n 'goal_target',\n ];\n\n return amountFields.includes(fieldName) || fieldName.endsWith('_amount');\n}\n\nexport function parseApprovedFilter(value: string): boolean {\n const normalized = value.toLowerCase();\n if (normalized !== 'true' && normalized !== 'false') {\n throw new Error(`--approved must be 'true' or 'false', got '${value}'`);\n }\n return normalized === 'true';\n}\n\nexport function parseStatusFilter(value: string): string[] {\n const statuses = value.split(',').map(s => s.trim().toLowerCase());\n const validStatuses = ['cleared', 'uncleared', 'reconciled'];\n\n for (const status of statuses) {\n if (!validStatuses.includes(status)) {\n throw new Error(`Invalid status '${status}'. Must be one of: ${validStatuses.join(', ')}`);\n }\n }\n\n return statuses;\n}\n\nexport type TransactionLike = {\n date: string;\n amount: number;\n approved: boolean;\n cleared: string;\n};\n\nexport function applyTransactionFilters<T extends TransactionLike>(transactions: T[], filters: {\n until?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n}): T[] {\n let filtered = transactions;\n\n if (filters.until) {\n filtered = filtered.filter(t => t.date <= filters.until!);\n }\n\n if (filters.approved !== undefined) {\n const approvedValue = parseApprovedFilter(filters.approved);\n filtered = filtered.filter(t => t.approved === approvedValue);\n }\n\n if (filters.status) {\n const statuses = parseStatusFilter(filters.status);\n filtered = filtered.filter(t => statuses.includes(t.cleared.toLowerCase()));\n }\n\n if (filters.minAmount !== undefined) {\n const minMilliunits = amountToMilliunits(filters.minAmount);\n filtered = filtered.filter(t => t.amount >= minMilliunits);\n }\n\n if (filters.maxAmount !== undefined) {\n const maxMilliunits = amountToMilliunits(filters.maxAmount);\n filtered = filtered.filter(t => t.amount <= maxMilliunits);\n }\n\n return filtered;\n}\n\nexport function applyFieldSelection<T>(items: T[], fields?: string): Partial<T>[] {\n if (!fields) return items;\n\n const fieldList = fields.split(',').map(f => f.trim());\n return items.map(item => {\n const filtered: Partial<T> = {};\n const itemRecord = item as Record<string, unknown>;\n fieldList.forEach(field => {\n if (field in itemRecord) {\n (filtered as Record<string, unknown>)[field] = itemRecord[field];\n }\n });\n return filtered;\n });\n}\n","import type { OutputOptions } from '../types/index.js';\nimport { convertMilliunitsToAmounts } from './utils.js';\n\nlet globalOutputOptions: OutputOptions = {};\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOutputOptions = options;\n}\n\nexport function outputJson(data: unknown, options: OutputOptions = {}): void {\n const convertedData = convertMilliunitsToAmounts(data);\n\n const mergedOptions = { ...globalOutputOptions, ...options };\n const jsonString = mergedOptions.compact\n ? JSON.stringify(convertedData)\n : JSON.stringify(convertedData, null, 2);\n\n console.log(jsonString);\n}\n\nexport function outputSuccess(data: unknown, options: OutputOptions = {}): void {\n outputJson(data, options);\n}\n","import { Command } from 'commander';\nimport { auth } from '../lib/auth.js';\nimport { promptForAccessToken } from '../lib/prompts.js';\nimport { outputJson, outputSuccess } from '../lib/output.js';\nimport { client } from '../lib/api-client.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createAuthCommand(): Command {\n const cmd = new Command('auth').description('Authentication management');\n\n cmd\n .command('login')\n .description('Configure access token')\n .action(withErrorHandling(async () => {\n const token = await promptForAccessToken();\n await auth.setAccessToken(token);\n\n try {\n const user = await client.getUser();\n outputSuccess({\n message: 'Successfully authenticated',\n user: { id: user?.id },\n });\n } catch (error) {\n await auth.deleteAccessToken();\n throw error;\n }\n }));\n\n cmd\n .command('status')\n .description('Check authentication status')\n .action(withErrorHandling(async () => {\n const isAuthenticated = await auth.isAuthenticated();\n\n if (!isAuthenticated) {\n outputJson({ authenticated: false, message: 'Not authenticated' });\n return;\n }\n\n try {\n const user = await client.getUser();\n outputSuccess({ authenticated: true, user: { id: user?.id } });\n } catch (error) {\n outputJson({ authenticated: false, message: 'Token exists but is invalid' });\n }\n }));\n\n cmd\n .command('logout')\n .description('Remove stored credentials')\n .action(withErrorHandling(async () => {\n await auth.logout();\n outputSuccess({ message: 'Successfully logged out' });\n }));\n\n return cmd;\n}\n","import Conf from 'conf';\nimport type { Config } from '../types/index.js';\n\nclass ConfigManager {\n private conf: Conf<Config>;\n\n constructor() {\n this.conf = new Conf<Config>({\n projectName: 'ynab-cli',\n schema: {\n defaultBudget: { type: 'string' },\n version: { type: 'string', default: '1.0.0' },\n },\n defaults: { version: '1.0.0' },\n });\n }\n\n getDefaultBudget(): string | undefined {\n return this.conf.get('defaultBudget');\n }\n\n setDefaultBudget(budgetId: string): void {\n this.conf.set('defaultBudget', budgetId);\n }\n\n clearDefaultBudget(): void {\n this.conf.delete('defaultBudget');\n }\n\n clear(): void {\n this.conf.clear();\n }\n}\n\nexport const config = new ConfigManager();\n","import { config } from './config.js';\n\nconst SERVICE_NAME = 'ynab-cli';\nconst ACCOUNT_NAME = 'access-token';\n\nconst KEYTAR_UNAVAILABLE_ERROR =\n 'Keychain storage unavailable. Cannot store credentials securely.\\n' +\n 'On Linux, install libsecret: sudo apt-get install libsecret-1-dev\\n' +\n 'Then reinstall: npm install -g @stephendolan/ynab-cli\\n' +\n 'Alternatively, use the YNAB_API_KEY environment variable.';\n\nlet keytar: typeof import('keytar') | undefined;\n\ntry {\n keytar = await import('keytar');\n} catch (error) {\n if (process.env.NODE_ENV !== 'test') {\n console.error(\n 'Warning: Keychain storage unavailable. Credentials will not be stored securely.\\n' +\n 'On Linux, install libsecret: sudo apt-get install libsecret-1-dev\\n' +\n 'Falling back to environment variable only (YNAB_API_KEY).\\n'\n );\n }\n}\n\nexport class AuthManager {\n async getAccessToken(): Promise<string | null> {\n if (keytar) {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n }\n return null;\n }\n\n async setAccessToken(token: string): Promise<void> {\n if (keytar) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);\n } else {\n throw new Error(KEYTAR_UNAVAILABLE_ERROR);\n }\n }\n\n async deleteAccessToken(): Promise<boolean> {\n if (keytar) {\n return keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n }\n return false;\n }\n\n async isAuthenticated(): Promise<boolean> {\n return (await this.getAccessToken()) !== null;\n }\n\n async logout(): Promise<void> {\n await this.deleteAccessToken();\n config.clearDefaultBudget();\n }\n}\n\nexport const auth = new AuthManager();\n","import inquirer from 'inquirer';\nimport { amountToMilliunits } from './utils.js';\n\nexport async function promptForAccessToken(): Promise<string> {\n const { token } = await inquirer.prompt([\n {\n type: 'password',\n name: 'token',\n message: 'Enter your YNAB Personal Access Token:',\n validate: (input: string) => !!input.trim() || 'Access token is required',\n },\n ]);\n return token;\n}\n\nexport async function promptForBudget(\n budgets: Array<{ id: string; name: string }>,\n): Promise<string> {\n const { budgetId } = await inquirer.prompt([\n {\n type: 'list',\n name: 'budgetId',\n message: 'Select a budget:',\n choices: budgets.map((b) => ({ name: b.name, value: b.id })),\n },\n ]);\n return budgetId;\n}\n\nexport async function promptForConfirmation(message: string): Promise<boolean> {\n const { confirmed } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'confirmed',\n message,\n default: false,\n },\n ]);\n return confirmed;\n}\n\nexport async function promptForTransaction(): Promise<Record<string, unknown>> {\n const answers = await inquirer.prompt([\n {\n type: 'input',\n name: 'date',\n message: 'Date (YYYY-MM-DD):',\n default: new Date().toISOString().split('T')[0],\n },\n {\n type: 'input',\n name: 'amount',\n message: 'Amount (in currency units, e.g., 10.50):',\n validate: (input: string) => !isNaN(parseFloat(input)) || 'Amount must be a valid number',\n },\n {\n type: 'input',\n name: 'payee_name',\n message: 'Payee name (optional):',\n },\n {\n type: 'input',\n name: 'memo',\n message: 'Memo (optional):',\n },\n ]);\n\n return {\n date: answers.date,\n amount: amountToMilliunits(parseFloat(answers.amount)),\n payee_name: answers.payee_name || undefined,\n memo: answers.memo || undefined,\n };\n}\n","import * as ynab from 'ynab';\nimport { config } from './config.js';\nimport { YnabCliError, handleYnabError, sanitizeApiError } from './errors.js';\nimport { auth } from './auth.js';\nimport dotenv from 'dotenv';\n\ndotenv.config();\n\ntype TransactionTypeFilter = 'uncategorized' | 'unapproved' | undefined;\n\nexport class YnabClient {\n private api: ynab.API | null = null;\n private hasShownEnvVarWarning = false;\n\n async getApi(): Promise<ynab.API> {\n if (this.api) {\n return this.api;\n }\n\n const keychainToken = await auth.getAccessToken();\n const accessToken = keychainToken || process.env.YNAB_API_KEY || null;\n\n if (!accessToken) {\n throw new YnabCliError(\n 'Not authenticated. Please run: ynab auth login or set YNAB_API_KEY environment variable',\n 401,\n );\n }\n\n if (!keychainToken && process.env.YNAB_API_KEY && !this.hasShownEnvVarWarning) {\n console.warn(\n '\\x1b[33m⚠️ WARNING: Using YNAB_API_KEY environment variable.\\n' +\n 'Environment variables may be visible to other processes.\\n' +\n 'For better security, use: ynab auth login\\x1b[0m\\n'\n );\n this.hasShownEnvVarWarning = true;\n }\n\n this.api = new ynab.API(accessToken);\n return this.api;\n }\n\n async getBudgetId(budgetIdOrDefault?: string): Promise<string> {\n const budgetId =\n budgetIdOrDefault || config.getDefaultBudget() || process.env.YNAB_BUDGET_ID;\n\n if (!budgetId) {\n throw new YnabCliError(\n 'No budget specified. Use --budget flag, set default with \"ynab budgets set-default\", or set YNAB_BUDGET_ID environment variable',\n 400,\n );\n }\n\n return budgetId;\n }\n\n private async withErrorHandling<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n handleYnabError(error);\n }\n }\n\n async getUser() {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const response = await api.user.getUser();\n return response.data.user;\n });\n }\n\n async getBudgets(includeAccounts = false) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const response = await api.budgets.getBudgets(includeAccounts);\n return {\n budgets: response.data.budgets,\n server_knowledge: 0,\n };\n });\n }\n\n async getBudget(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.budgets.getBudgetById(id, lastKnowledgeOfServer);\n return {\n budget: response.data.budget,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getBudgetSettings(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.budgets.getBudgetSettingsById(id);\n return response.data.settings;\n });\n }\n\n async getAccounts(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.getAccounts(id, lastKnowledgeOfServer);\n return {\n accounts: response.data.accounts,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getAccount(accountId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.getAccountById(id, accountId);\n return response.data.account;\n });\n }\n\n async createAccount(accountData: ynab.PostAccountWrapper, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.createAccount(id, accountData);\n return response.data.account;\n });\n }\n\n async getCategories(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getCategories(id, lastKnowledgeOfServer);\n return {\n category_groups: response.data.category_groups,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getCategory(categoryId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getCategoryById(id, categoryId);\n return response.data.category;\n });\n }\n\n async updateCategory(\n categoryId: string,\n data: ynab.PatchCategoryWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.updateCategory(id, categoryId, data);\n return response.data.category;\n });\n }\n\n async getMonthCategory(month: string, categoryId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getMonthCategoryById(id, month, categoryId);\n return response.data.category;\n });\n }\n\n async updateMonthCategory(\n month: string,\n categoryId: string,\n data: ynab.PatchMonthCategoryWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.updateMonthCategory(id, month, categoryId, data);\n return response.data.category;\n });\n }\n\n async getPayees(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.getPayees(id, lastKnowledgeOfServer);\n return {\n payees: response.data.payees,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getPayee(payeeId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.getPayeeById(id, payeeId);\n return response.data.payee;\n });\n }\n\n async updatePayee(payeeId: string, data: ynab.PatchPayeeWrapper, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.updatePayee(id, payeeId, data);\n return response.data.payee;\n });\n }\n\n async getPayeeLocations(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocations(id);\n return response.data.payee_locations;\n });\n }\n\n async getPayeeLocation(payeeLocationId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocationById(id, payeeLocationId);\n return response.data.payee_location;\n });\n }\n\n async getPayeeLocationsByPayee(payeeId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocationsByPayee(id, payeeId);\n return response.data.payee_locations;\n });\n }\n\n async getBudgetMonths(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.months.getBudgetMonths(id, lastKnowledgeOfServer);\n return {\n months: response.data.months,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getBudgetMonth(month: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.months.getBudgetMonth(id, month);\n return response.data.month;\n });\n }\n\n async getTransactions(params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactions(\n id,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByAccount(accountId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByAccount(\n id,\n accountId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByCategory(categoryId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByCategory(\n id,\n categoryId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByPayee(payeeId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByPayee(\n id,\n payeeId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransaction(transactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.getTransactionById(id, transactionId);\n return response.data.transaction;\n });\n }\n\n async createTransaction(\n transactionData: ynab.PutTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.createTransaction(id, transactionData);\n return response.data.transaction;\n });\n }\n\n async createTransactions(\n transactionsData: ynab.PostTransactionsWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.createTransactions(id, transactionsData);\n return response.data;\n });\n }\n\n async updateTransaction(\n transactionId: string,\n transactionData: ynab.PutTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.updateTransaction(\n id,\n transactionId,\n transactionData,\n );\n return response.data.transaction;\n });\n }\n\n async updateTransactions(\n transactionsData: ynab.PatchTransactionsWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.updateTransactions(id, transactionsData);\n return response.data;\n });\n }\n\n async deleteTransaction(transactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.deleteTransaction(id, transactionId);\n return response.data.transaction;\n });\n }\n\n async importTransactions(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.importTransactions(id);\n return response.data.transaction_ids;\n });\n }\n\n async getScheduledTransactions(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.getScheduledTransactions(\n id,\n lastKnowledgeOfServer,\n );\n return {\n scheduled_transactions: response.data.scheduled_transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getScheduledTransaction(scheduledTransactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.getScheduledTransactionById(\n id,\n scheduledTransactionId,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async createScheduledTransaction(\n data: ynab.PostScheduledTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.createScheduledTransaction(id, data);\n return response.data.scheduled_transaction;\n });\n }\n\n async updateScheduledTransaction(\n scheduledTransactionId: string,\n data: ynab.PutScheduledTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.updateScheduledTransaction(\n id,\n scheduledTransactionId,\n data,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async deleteScheduledTransaction(scheduledTransactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.deleteScheduledTransaction(\n id,\n scheduledTransactionId,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async rawApiCall(method: string, path: string, data?: unknown, budgetId?: string) {\n return this.withErrorHandling(async () => {\n await this.getApi();\n\n const fullPath = path.includes('{budget_id}')\n ? path.replace('{budget_id}', await this.getBudgetId(budgetId))\n : path;\n\n const url = `https://api.ynab.com/v1${fullPath}`;\n const headers = {\n Authorization: `Bearer ${await auth.getAccessToken()}`,\n 'Content-Type': 'application/json',\n };\n\n const httpMethod = method.toUpperCase();\n const hasBody = ['POST', 'PUT', 'PATCH'].includes(httpMethod);\n\n if (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(httpMethod)) {\n throw new YnabCliError(`Unsupported HTTP method: ${method}`, 400);\n }\n\n const response = await fetch(url, {\n method: httpMethod,\n headers,\n ...(hasBody && { body: JSON.stringify(data) }),\n });\n\n if (!response.ok) {\n const errorData = await response.json() as Record<string, unknown>;\n throw { error: sanitizeApiError(errorData.error || errorData) };\n }\n\n return await response.json();\n });\n }\n}\n\nexport const client = new YnabClient();\n","import type { YnabError } from '../types/index.js';\nimport { outputJson } from './output.js';\n\nexport class YnabCliError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = 'YnabCliError';\n }\n}\n\nconst ERROR_STATUS_CODES: Record<string, number> = {\n bad_request: 400,\n not_authorized: 401,\n subscription_lapsed: 403,\n trial_expired: 403,\n unauthorized_scope: 403,\n data_limit_reached: 403,\n not_found: 404,\n resource_not_found: 404,\n conflict: 409,\n too_many_requests: 429,\n internal_server_error: 500,\n service_unavailable: 503,\n};\n\nexport function sanitizeErrorMessage(message: string): string {\n const sensitivePatterns = [\n /Bearer\\s+[\\w\\-._~+/]+=*/gi,\n /token[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /api[_-]?key[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /authorization:\\s*bearer\\s+[\\w\\-._~+/]+=*/gi,\n ];\n\n let sanitized = message;\n for (const pattern of sensitivePatterns) {\n sanitized = sanitized.replace(pattern, '[REDACTED]');\n }\n\n return sanitized.length > 500 ? sanitized.substring(0, 500) + '...' : sanitized;\n}\n\ninterface YnabApiError {\n name?: string;\n detail?: string;\n message?: string;\n id?: string;\n}\n\nfunction isErrorObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function sanitizeApiError(error: unknown): YnabError {\n if (!isErrorObject(error)) {\n return {\n name: 'api_error',\n detail: 'An error occurred',\n id: undefined,\n };\n }\n\n const apiError = error as YnabApiError;\n const detail = sanitizeErrorMessage(\n String(apiError.detail || apiError.message || 'An error occurred')\n );\n\n return {\n name: apiError.name || 'api_error',\n detail,\n id: apiError.id,\n };\n}\n\nfunction formatErrorResponse(name: string, detail: string, statusCode: number): never {\n outputJson({ error: { name, detail, statusCode } });\n process.exit(1);\n}\n\nexport function handleYnabError(error: unknown): never {\n if (!isErrorObject(error)) {\n formatErrorResponse('unknown_error', 'An unexpected error occurred', 1);\n }\n\n const errorObj = error as { error?: unknown; message?: string };\n\n if (errorObj.error) {\n const ynabError: YnabError = sanitizeApiError(errorObj.error);\n formatErrorResponse(\n ynabError.name,\n ynabError.detail,\n ERROR_STATUS_CODES[ynabError.name] || 500,\n );\n }\n\n if (error instanceof YnabCliError) {\n const sanitized = sanitizeErrorMessage(error.message);\n formatErrorResponse('cli_error', sanitized, error.statusCode || 1);\n }\n\n const sanitized = sanitizeErrorMessage(errorObj.message || 'An unexpected error occurred');\n formatErrorResponse('unknown_error', sanitized, 1);\n}\n","import { handleYnabError } from './errors.js';\nimport { promptForConfirmation } from './prompts.js';\nimport { isInteractive } from './utils.js';\nimport { outputSuccess } from './output.js';\n\nexport function withErrorHandling<TArgs extends unknown[], R>(\n fn: (...args: TArgs) => Promise<R>,\n): (...args: TArgs) => Promise<void> {\n return async (...args: TArgs) => {\n try {\n await fn(...args);\n } catch (error) {\n handleYnabError(error);\n }\n };\n}\n\nexport async function confirmDelete(\n itemType: string,\n skipConfirmation: boolean = false,\n): Promise<boolean> {\n if (skipConfirmation || !isInteractive()) {\n return true;\n }\n\n const confirmed = await promptForConfirmation(\n `Are you sure you want to delete this ${itemType}?`,\n );\n\n if (!confirmed) {\n outputSuccess({ message: 'Operation cancelled' });\n return false;\n }\n\n return true;\n}\n\nexport function buildUpdateObject<T>(\n options: T,\n mapping: Record<string, string>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const optionsRecord = options as Record<string, unknown>;\n\n for (const [optionKey, targetKey] of Object.entries(mapping)) {\n if (optionsRecord[optionKey] !== undefined) {\n result[targetKey] = optionsRecord[optionKey];\n }\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createUserCommand(): Command {\n const cmd = new Command('user').description('User information');\n\n cmd\n .command('info')\n .description('Get authenticated user information')\n .action(withErrorHandling(async () => {\n const user = await client.getUser();\n outputSuccess(user);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createBudgetsCommand(): Command {\n const cmd = new Command('budgets').description('Budget operations');\n\n cmd\n .command('list')\n .description('List all budgets')\n .option('--include-accounts', 'Include accounts in response')\n .action(withErrorHandling(async (options: { includeAccounts?: boolean }) => {\n const result = await client.getBudgets(options.includeAccounts);\n outputSuccess(result?.budgets);\n }));\n\n cmd\n .command('view')\n .description('View budget details (uses default if no id provided)')\n .argument('[id]', 'Budget ID')\n .action(withErrorHandling(async (id: string | undefined) => {\n const result = await client.getBudget(id);\n outputSuccess(result?.budget);\n }));\n\n cmd\n .command('settings')\n .description('View budget settings')\n .argument('[id]', 'Budget ID')\n .action(withErrorHandling(async (id: string | undefined) => {\n const settings = await client.getBudgetSettings(id);\n outputSuccess(settings);\n }));\n\n cmd\n .command('set-default')\n .description('Set default budget for commands')\n .argument('<id>', 'Budget ID')\n .action(withErrorHandling(async (id: string) => {\n const result = await client.getBudgets();\n const budget = result?.budgets.find((b) => b.id === id);\n\n if (!budget) {\n throw new YnabCliError(`Budget with ID ${id} not found`, 404);\n }\n\n config.setDefaultBudget(id);\n outputSuccess({\n message: 'Default budget set',\n budget: { id: budget.id, name: budget.name },\n });\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createAccountsCommand(): Command {\n const cmd = new Command('accounts').description('Account operations');\n\n cmd\n .command('list')\n .description('List all accounts')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (options: CommandOptions) => {\n const result = await client.getAccounts(options.budget);\n outputSuccess(result?.accounts);\n }));\n\n cmd\n .command('view')\n .description('View account details')\n .argument('<id>', 'Account ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const account = await client.getAccount(id, options.budget);\n outputSuccess(account);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for account')\n .argument('<id>', 'Account ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByAccount(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n });\n outputSuccess(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { amountToMilliunits } from '../lib/utils.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createCategoriesCommand(): Command {\n const cmd = new Command('categories').description('Category operations');\n\n cmd\n .command('list')\n .description('List all categories')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getCategories(options.budget, options.lastKnowledge);\n outputSuccess(result?.category_groups);\n }));\n\n cmd\n .command('view')\n .description('View category details')\n .argument('<id>', 'Category ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const category = await client.getCategory(id, options.budget);\n outputSuccess(category);\n }));\n\n cmd\n .command('budget')\n .description('Update category budget for a month')\n .argument('<id>', 'Category ID')\n .requiredOption('--month <month>', 'Month in YYYY-MM format')\n .requiredOption('--amount <amount>', 'Budget amount in currency units (e.g., 100.50)', parseFloat)\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (\n id: string,\n options: {\n month: string;\n amount: number;\n budget?: string;\n } & CommandOptions,\n ) => {\n if (isNaN(options.amount)) {\n throw new YnabCliError('Amount must be a valid number', 400);\n }\n\n const milliunits = amountToMilliunits(options.amount);\n const category = await client.updateMonthCategory(\n options.month,\n id,\n { category: { budgeted: milliunits } },\n options.budget,\n );\n outputSuccess(category);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for category')\n .argument('<id>', 'Category ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n lastKnowledge?: number;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByCategory(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputSuccess(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { promptForTransaction } from '../lib/prompts.js';\nimport { isInteractive, amountToMilliunits, applyTransactionFilters, applyFieldSelection, type TransactionLike } from '../lib/utils.js';\nimport { withErrorHandling, confirmDelete, buildUpdateObject } from '../lib/command-utils.js';\nimport { validateJson, TransactionSplitSchema } from '../lib/schemas.js';\nimport type { CommandOptions } from '../types/index.js';\n\ninterface TransactionOptions {\n account?: string;\n date?: string;\n amount?: number;\n payeeName?: string;\n payeeId?: string;\n categoryId?: string;\n memo?: string;\n cleared?: string;\n approved?: boolean;\n}\n\nfunction buildTransactionData(options: TransactionOptions): Record<string, unknown> {\n if (!options.account) {\n throw new YnabCliError('--account is required in non-interactive mode', 400);\n }\n if (options.amount === undefined) {\n throw new YnabCliError('--amount is required in non-interactive mode', 400);\n }\n\n return {\n account_id: options.account,\n date: options.date || new Date().toISOString().split('T')[0],\n amount: amountToMilliunits(options.amount),\n payee_name: options.payeeName,\n payee_id: options.payeeId,\n category_id: options.categoryId,\n memo: options.memo,\n cleared: options.cleared,\n approved: options.approved,\n };\n}\n\nexport function createTransactionsCommand(): Command {\n const cmd = new Command('transactions').description('Transaction operations');\n\n cmd\n .command('list')\n .description('List transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Filter by account ID')\n .option('--category <id>', 'Filter by category ID')\n .option('--payee <id>', 'Filter by payee ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--until <date>', 'Filter transactions until date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option('--status <statuses>', 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated for multiple)')\n .option('--min-amount <amount>', 'Minimum amount in currency units (e.g., 10.50)', parseFloat)\n .option('--max-amount <amount>', 'Maximum amount in currency units (e.g., 100.00)', parseFloat)\n .option('--fields <fields>', 'Comma-separated list of fields to include (e.g., id,date,amount,memo)')\n .action(withErrorHandling(async (options: {\n budget?: string;\n account?: string;\n category?: string;\n payee?: string;\n since?: string;\n until?: string;\n type?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n fields?: string;\n } & CommandOptions) => {\n const params = {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n };\n\n const result = options.account\n ? await client.getTransactionsByAccount(options.account, params)\n : options.category\n ? await client.getTransactionsByCategory(options.category, params)\n : options.payee\n ? await client.getTransactionsByPayee(options.payee, params)\n : await client.getTransactions(params);\n\n const transactions = result?.transactions || [];\n\n const filtered = applyTransactionFilters(transactions as TransactionLike[], {\n until: options.until,\n approved: options.approved,\n status: options.status,\n minAmount: options.minAmount,\n maxAmount: options.maxAmount,\n });\n\n const selected = applyFieldSelection(filtered, options.fields);\n\n outputSuccess(selected);\n }));\n\n cmd\n .command('view')\n .description('View single transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const transaction = await client.getTransaction(id, options.budget);\n outputSuccess(transaction);\n }));\n\n cmd\n .command('create')\n .description('Create transaction')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Account ID')\n .option('--date <date>', 'Date (YYYY-MM-DD)')\n .option('--amount <amount>', 'Amount in currency units (e.g., 10.50)', parseFloat)\n .option('--payee-name <name>', 'Payee name')\n .option('--payee-id <id>', 'Payee ID')\n .option('--category-id <id>', 'Category ID')\n .option('--memo <memo>', 'Memo')\n .option('--cleared <status>', 'Cleared status (cleared, uncleared, reconciled)')\n .option('--approved', 'Mark as approved')\n .action(withErrorHandling(async (options: {\n budget?: string;\n account?: string;\n date?: string;\n amount?: number;\n payeeName?: string;\n payeeId?: string;\n categoryId?: string;\n memo?: string;\n cleared?: string;\n approved?: boolean;\n } & CommandOptions) => {\n const shouldPrompt = isInteractive() && !options.account && !options.amount;\n const transactionData = shouldPrompt\n ? await promptForTransaction()\n : buildTransactionData(options);\n\n const transaction = await client.createTransaction(\n { transaction: transactionData },\n options.budget,\n );\n outputSuccess(transaction);\n }));\n\n cmd\n .command('update')\n .description('Update transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Account ID')\n .option('--date <date>', 'Date (YYYY-MM-DD)')\n .option('--amount <amount>', 'Amount in currency units', parseFloat)\n .option('--payee-name <name>', 'Payee name')\n .option('--payee-id <id>', 'Payee ID')\n .option('--category-id <id>', 'Category ID')\n .option('--memo <memo>', 'Memo')\n .option('--cleared <status>', 'Cleared status')\n .option('--approved', 'Mark as approved')\n .action(withErrorHandling(async (\n id: string,\n options: TransactionOptions & { budget?: string } & CommandOptions,\n ) => {\n const transactionData = buildUpdateObject(options, {\n account: 'account_id',\n date: 'date',\n payeeName: 'payee_name',\n payeeId: 'payee_id',\n categoryId: 'category_id',\n memo: 'memo',\n cleared: 'cleared',\n approved: 'approved',\n });\n\n if (options.amount !== undefined) {\n transactionData.amount = amountToMilliunits(options.amount);\n }\n\n const transaction = await client.updateTransaction(\n id,\n { transaction: transactionData },\n options.budget,\n );\n outputSuccess(transaction);\n }));\n\n cmd\n .command('delete')\n .description('Delete transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('-y, --yes', 'Skip confirmation')\n .action(withErrorHandling(async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n if (!await confirmDelete('transaction', options.yes)) {\n return;\n }\n\n const transaction = await client.deleteTransaction(id, options.budget);\n outputSuccess({ message: 'Transaction deleted', transaction });\n }));\n\n cmd\n .command('import')\n .description('Import transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (options: CommandOptions) => {\n const transactionIds = await client.importTransactions(options.budget);\n outputSuccess({ transaction_ids: transactionIds });\n }));\n\n cmd\n .command('split')\n .description('Split transaction into multiple categories')\n .argument('<id>', 'Transaction ID')\n .requiredOption('--splits <json>', 'JSON array of splits: [{\"amount\": -21400, \"category_id\": \"xxx\", \"memo\": \"...\"}]')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (\n id: string,\n options: { splits: string; budget?: string } & CommandOptions,\n ) => {\n let parsedSplits;\n try {\n parsedSplits = JSON.parse(options.splits);\n } catch (error) {\n throw new YnabCliError('Invalid JSON in --splits parameter', 400);\n }\n\n const splits = validateJson(parsedSplits, TransactionSplitSchema, 'transaction splits');\n\n const transaction = await client.updateTransaction(\n id,\n {\n transaction: {\n category_id: null,\n subtransactions: splits,\n },\n },\n options.budget,\n );\n outputSuccess(transaction);\n }));\n\n cmd\n .command('search')\n .description('Search transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--memo <text>', 'Search in memo field')\n .option('--payee-name <name>', 'Search in payee name')\n .option('--amount <amount>', 'Search for exact amount in currency units', parseFloat)\n .option('--since <date>', 'Search transactions since date (YYYY-MM-DD)')\n .option('--until <date>', 'Search transactions until date (YYYY-MM-DD)')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option('--status <statuses>', 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated)')\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .action(withErrorHandling(async (options: {\n budget?: string;\n memo?: string;\n payeeName?: string;\n amount?: number;\n since?: string;\n until?: string;\n approved?: string;\n status?: string;\n fields?: string;\n } & CommandOptions) => {\n if (!options.memo && !options.payeeName && options.amount === undefined) {\n throw new YnabCliError('At least one search criteria required: --memo, --payee-name, or --amount', 400);\n }\n\n const params = {\n budgetId: options.budget,\n sinceDate: options.since,\n };\n\n const result = await client.getTransactions(params);\n let transactions = result?.transactions || [];\n\n if (options.memo) {\n const searchTerm = options.memo.toLowerCase();\n transactions = transactions.filter(t =>\n t.memo?.toLowerCase().includes(searchTerm)\n );\n }\n\n if (options.payeeName) {\n const searchTerm = options.payeeName.toLowerCase();\n transactions = transactions.filter(t =>\n t.payee_name?.toLowerCase().includes(searchTerm)\n );\n }\n\n if (options.amount !== undefined) {\n const amountMilliunits = amountToMilliunits(options.amount);\n transactions = transactions.filter(t => t.amount === amountMilliunits);\n }\n\n transactions = applyTransactionFilters(transactions, {\n until: options.until,\n approved: options.approved,\n status: options.status,\n });\n\n const filteredTransactions = applyFieldSelection(transactions, options.fields);\n\n outputSuccess(filteredTransactions);\n }));\n\n return cmd;\n}\n","import { z } from 'zod';\nimport { YnabCliError } from './errors.js';\n\nexport const TransactionSplitSchema = z.array(\n z.object({\n amount: z.number(),\n category_id: z.string().nullable().optional(),\n memo: z.string().optional(),\n payee_id: z.string().optional(),\n })\n);\n\nexport const ApiDataSchema = z.record(z.any());\n\nexport function validateJson<T>(\n data: unknown,\n schema: z.ZodSchema<T>,\n fieldName: string\n): T {\n try {\n return schema.parse(data);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = error.issues\n .map(i => `${i.path.join('.')}: ${i.message}`)\n .join(', ');\n throw new YnabCliError(`Invalid ${fieldName}: ${issues}`, 400);\n }\n throw error;\n }\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { withErrorHandling, confirmDelete } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createScheduledCommand(): Command {\n const cmd = new Command('scheduled').description('Scheduled transaction operations');\n\n cmd\n .command('list')\n .description('List all scheduled transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getScheduledTransactions(options.budget, options.lastKnowledge);\n outputSuccess(result?.scheduled_transactions);\n }));\n\n cmd\n .command('view')\n .description('View scheduled transaction')\n .argument('<id>', 'Scheduled transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const scheduledTransaction = await client.getScheduledTransaction(id, options.budget);\n outputSuccess(scheduledTransaction);\n }));\n\n cmd\n .command('delete')\n .description('Delete scheduled transaction')\n .argument('<id>', 'Scheduled transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('-y, --yes', 'Skip confirmation')\n .action(withErrorHandling(async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n if (!await confirmDelete('scheduled transaction', options.yes)) {\n return;\n }\n\n const scheduledTransaction = await client.deleteScheduledTransaction(id, options.budget);\n outputSuccess({\n message: 'Scheduled transaction deleted',\n scheduled_transaction: scheduledTransaction,\n });\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createPayeesCommand(): Command {\n const cmd = new Command('payees').description('Payee operations');\n\n cmd\n .command('list')\n .description('List all payees')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getPayees(options.budget, options.lastKnowledge);\n outputSuccess(result?.payees);\n }));\n\n cmd\n .command('view')\n .description('View payee details')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const payee = await client.getPayee(id, options.budget);\n outputSuccess(payee);\n }));\n\n cmd\n .command('update')\n .description('Rename payee')\n .argument('<id>', 'Payee ID')\n .requiredOption('--name <name>', 'New payee name')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: { name: string; budget?: string } & CommandOptions) => {\n if (!options.name?.trim()) {\n throw new YnabCliError('Name cannot be empty', 400);\n }\n\n const payee = await client.updatePayee(\n id,\n { payee: { name: options.name } },\n options.budget,\n );\n outputSuccess(payee);\n }));\n\n cmd\n .command('locations')\n .description('List locations for payee')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const locations = await client.getPayeeLocationsByPayee(id, options.budget);\n outputSuccess(locations);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for payee')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n lastKnowledge?: number;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByPayee(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputSuccess(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputSuccess } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createMonthsCommand(): Command {\n const cmd = new Command('months').description('Monthly budget operations');\n\n cmd\n .command('list')\n .description('List all budget months')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getBudgetMonths(options.budget, options.lastKnowledge);\n outputSuccess(result?.months);\n }));\n\n cmd\n .command('view')\n .description('View specific month details')\n .argument('<month>', 'Month in YYYY-MM format')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (month: string, options: CommandOptions) => {\n const monthData = await client.getBudgetMonth(month, options.budget);\n outputSuccess(monthData);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { validateJson, ApiDataSchema } from '../lib/schemas.js';\nimport type { CommandOptions } from '../types/index.js';\n\nconst VALID_HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\n\nexport function createApiCommand(): Command {\n const cmd = new Command('api').description('Raw API access');\n\n cmd\n .argument('<method>', 'HTTP method (GET, POST, PUT, PATCH, DELETE)')\n .argument('<path>', 'API path (e.g., /budgets or /budgets/{budget_id}/transactions)')\n .option('-b, --budget <id>', 'Budget ID (used to replace {budget_id} in path)')\n .option('--data <json>', 'JSON data for POST/PUT/PATCH requests')\n .description('Make raw API calls to YNAB')\n .action(withErrorHandling(async (\n method: string,\n path: string,\n options: { budget?: string; data?: string } & CommandOptions,\n ) => {\n const upperMethod = method.toUpperCase();\n\n if (!VALID_HTTP_METHODS.includes(upperMethod)) {\n throw new YnabCliError(\n `Invalid HTTP method: ${method}. Must be one of: ${VALID_HTTP_METHODS.join(', ')}`,\n 400,\n );\n }\n\n let data: Record<string, unknown> | undefined;\n if (options.data) {\n try {\n const parsedData = JSON.parse(options.data);\n data = validateJson(parsedData, ApiDataSchema, 'API data');\n } catch (error) {\n throw new YnabCliError('Invalid JSON in --data parameter', 400);\n }\n }\n\n const result = await client.rawApiCall(upperMethod, path, data, options.budget);\n outputJson(result);\n }));\n\n return cmd;\n}\n"],"mappings":"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","names":["Command","sanitized","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/lib/utils.ts","../src/lib/output.ts","../src/commands/auth.ts","../src/lib/config.ts","../src/lib/auth.ts","../src/lib/prompts.ts","../src/lib/api-client.ts","../src/lib/errors.ts","../src/lib/command-utils.ts","../src/commands/user.ts","../src/commands/budgets.ts","../src/commands/accounts.ts","../src/commands/categories.ts","../src/commands/transactions.ts","../src/lib/schemas.ts","../src/commands/scheduled.ts","../src/commands/payees.ts","../src/commands/months.ts","../src/commands/api.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { setOutputOptions } from './lib/output.js';\nimport { createAuthCommand } from './commands/auth.js';\nimport { createUserCommand } from './commands/user.js';\nimport { createBudgetsCommand } from './commands/budgets.js';\nimport { createAccountsCommand } from './commands/accounts.js';\nimport { createCategoriesCommand } from './commands/categories.js';\nimport { createTransactionsCommand } from './commands/transactions.js';\nimport { createScheduledCommand } from './commands/scheduled.js';\nimport { createPayeesCommand } from './commands/payees.js';\nimport { createMonthsCommand } from './commands/months.js';\nimport { createApiCommand } from './commands/api.js';\n\nconst program = new Command();\n\nprogram\n .name('ynab')\n .description('A command-line interface for You Need a Budget (YNAB)')\n .version('1.0.0')\n .option('-c, --compact', 'Minified JSON output (single line)')\n .hook('preAction', (thisCommand) => {\n const options = thisCommand.opts();\n setOutputOptions({\n compact: options.compact,\n });\n });\n\nprogram.addCommand(createAuthCommand());\nprogram.addCommand(createUserCommand());\nprogram.addCommand(createBudgetsCommand());\nprogram.addCommand(createAccountsCommand());\nprogram.addCommand(createCategoriesCommand());\nprogram.addCommand(createTransactionsCommand());\nprogram.addCommand(createScheduledCommand());\nprogram.addCommand(createPayeesCommand());\nprogram.addCommand(createMonthsCommand());\nprogram.addCommand(createApiCommand());\n\nprogram.parse();\n","import { format, parseISO } from 'date-fns';\n\nexport function milliunitsToAmount(milliunits: number): number {\n return milliunits / 1000;\n}\n\nexport function amountToMilliunits(amount: number): number {\n return Math.round(amount * 1000);\n}\n\nexport function formatCurrency(milliunits: number, currencySymbol = '$'): string {\n const amount = milliunitsToAmount(milliunits);\n return `${currencySymbol}${amount.toFixed(2)}`;\n}\n\nexport function formatDate(isoDate: string, formatString = 'yyyy-MM-dd'): string {\n return format(parseISO(isoDate), formatString);\n}\n\nexport function parseDate(dateString: string): string {\n const date = parseISO(dateString);\n return format(date, 'yyyy-MM-dd');\n}\n\nexport function isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nexport function convertMilliunitsToAmounts(data: unknown): unknown {\n if (data === null || data === undefined) return data;\n if (Array.isArray(data)) return data.map(convertMilliunitsToAmounts);\n if (typeof data !== 'object') return data;\n\n const converted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (isAmountField(key) && typeof value === 'number') {\n converted[key] = milliunitsToAmount(value);\n } else if (isDebtAmountMapField(key) && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const convertedMap: Record<string, unknown> = {};\n for (const [dateKey, amountValue] of Object.entries(value)) {\n convertedMap[dateKey] = typeof amountValue === 'number' ? milliunitsToAmount(amountValue) : amountValue;\n }\n converted[key] = convertedMap;\n } else {\n converted[key] = convertMilliunitsToAmounts(value);\n }\n }\n return converted;\n}\n\nfunction isAmountField(fieldName: string): boolean {\n const amountFields = [\n 'amount',\n 'balance',\n 'cleared_balance',\n 'uncleared_balance',\n 'budgeted',\n 'activity',\n 'available',\n 'goal_target',\n 'goal_under_funded',\n 'goal_overall_funded',\n 'goal_overall_left',\n 'income',\n 'to_be_budgeted',\n 'debt_original_balance',\n ];\n\n return amountFields.includes(fieldName) || fieldName.endsWith('_amount');\n}\n\nfunction isDebtAmountMapField(fieldName: string): boolean {\n const debtAmountMapFields = [\n 'debt_minimum_payments',\n 'debt_escrow_amounts',\n 'debt_interest_rates',\n ];\n\n return debtAmountMapFields.includes(fieldName);\n}\n\nexport function parseApprovedFilter(value: string): boolean {\n const normalized = value.toLowerCase();\n if (normalized !== 'true' && normalized !== 'false') {\n throw new Error(`--approved must be 'true' or 'false', got '${value}'`);\n }\n return normalized === 'true';\n}\n\nexport function parseStatusFilter(value: string): string[] {\n const statuses = value.split(',').map(s => s.trim().toLowerCase());\n const validStatuses = ['cleared', 'uncleared', 'reconciled'];\n\n for (const status of statuses) {\n if (!validStatuses.includes(status)) {\n throw new Error(`Invalid status '${status}'. Must be one of: ${validStatuses.join(', ')}`);\n }\n }\n\n return statuses;\n}\n\nexport type TransactionLike = {\n date: string;\n amount: number;\n approved: boolean;\n cleared: string;\n};\n\nexport function applyTransactionFilters<T extends TransactionLike>(transactions: T[], filters: {\n until?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n}): T[] {\n let filtered = transactions;\n\n if (filters.until) {\n filtered = filtered.filter(t => t.date <= filters.until!);\n }\n\n if (filters.approved !== undefined) {\n const approvedValue = parseApprovedFilter(filters.approved);\n filtered = filtered.filter(t => t.approved === approvedValue);\n }\n\n if (filters.status) {\n const statuses = parseStatusFilter(filters.status);\n filtered = filtered.filter(t => statuses.includes(t.cleared.toLowerCase()));\n }\n\n if (filters.minAmount !== undefined) {\n const minMilliunits = amountToMilliunits(filters.minAmount);\n filtered = filtered.filter(t => t.amount >= minMilliunits);\n }\n\n if (filters.maxAmount !== undefined) {\n const maxMilliunits = amountToMilliunits(filters.maxAmount);\n filtered = filtered.filter(t => t.amount <= maxMilliunits);\n }\n\n return filtered;\n}\n\nexport function applyFieldSelection<T>(items: T[], fields?: string): Partial<T>[] {\n if (!fields) return items;\n\n const fieldList = fields.split(',').map(f => f.trim());\n return items.map(item => {\n const filtered: Partial<T> = {};\n const itemRecord = item as Record<string, unknown>;\n fieldList.forEach(field => {\n if (field in itemRecord) {\n (filtered as Record<string, unknown>)[field] = itemRecord[field];\n }\n });\n return filtered;\n });\n}\n","import type { OutputOptions } from '../types/index.js';\nimport { convertMilliunitsToAmounts } from './utils.js';\n\nlet globalOutputOptions: OutputOptions = {};\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOutputOptions = options;\n}\n\nexport function outputJson(data: unknown, options: OutputOptions = {}): void {\n const convertedData = convertMilliunitsToAmounts(data);\n const mergedOptions = { ...globalOutputOptions, ...options };\n const jsonString = mergedOptions.compact\n ? JSON.stringify(convertedData)\n : JSON.stringify(convertedData, null, 2);\n\n console.log(jsonString);\n}\n","import { Command } from 'commander';\nimport { auth } from '../lib/auth.js';\nimport { promptForAccessToken } from '../lib/prompts.js';\nimport { outputJson } from '../lib/output.js';\nimport { client } from '../lib/api-client.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createAuthCommand(): Command {\n const cmd = new Command('auth').description('Authentication management');\n\n cmd\n .command('login')\n .description('Configure access token')\n .action(withErrorHandling(async () => {\n const token = await promptForAccessToken();\n await auth.setAccessToken(token);\n\n try {\n const user = await client.getUser();\n outputJson({\n message: 'Successfully authenticated',\n user: { id: user?.id },\n });\n } catch (error) {\n await auth.deleteAccessToken();\n throw error;\n }\n }));\n\n cmd\n .command('status')\n .description('Check authentication status')\n .action(withErrorHandling(async () => {\n const isAuthenticated = await auth.isAuthenticated();\n\n if (!isAuthenticated) {\n outputJson({ authenticated: false, message: 'Not authenticated' });\n return;\n }\n\n try {\n const user = await client.getUser();\n outputJson({ authenticated: true, user: { id: user?.id } });\n } catch (error) {\n outputJson({ authenticated: false, message: 'Token exists but is invalid' });\n }\n }));\n\n cmd\n .command('logout')\n .description('Remove stored credentials')\n .action(withErrorHandling(async () => {\n await auth.logout();\n outputJson({ message: 'Successfully logged out' });\n }));\n\n return cmd;\n}\n","import Conf from 'conf';\nimport type { Config } from '../types/index.js';\n\nclass ConfigManager {\n private conf: Conf<Config>;\n\n constructor() {\n this.conf = new Conf<Config>({\n projectName: 'ynab-cli',\n schema: {\n defaultBudget: { type: 'string' },\n version: { type: 'string', default: '1.0.0' },\n },\n defaults: { version: '1.0.0' },\n });\n }\n\n getDefaultBudget(): string | undefined {\n return this.conf.get('defaultBudget');\n }\n\n setDefaultBudget(budgetId: string): void {\n this.conf.set('defaultBudget', budgetId);\n }\n\n clearDefaultBudget(): void {\n this.conf.delete('defaultBudget');\n }\n\n clear(): void {\n this.conf.clear();\n }\n}\n\nexport const config = new ConfigManager();\n","import { config } from './config.js';\n\nconst SERVICE_NAME = 'ynab-cli';\nconst ACCOUNT_NAME = 'access-token';\n\nconst KEYTAR_UNAVAILABLE_ERROR =\n 'Keychain storage unavailable. Cannot store credentials securely.\\n' +\n 'On Linux, install libsecret: sudo apt-get install libsecret-1-dev\\n' +\n 'Then reinstall: npm install -g @stephendolan/ynab-cli\\n' +\n 'Alternatively, use the YNAB_API_KEY environment variable.';\n\nlet keytar: typeof import('keytar') | undefined;\n\ntry {\n keytar = await import('keytar');\n} catch (error) {\n if (process.env.NODE_ENV !== 'test') {\n console.error(\n 'Warning: Keychain storage unavailable. Credentials will not be stored securely.\\n' +\n 'On Linux, install libsecret: sudo apt-get install libsecret-1-dev\\n' +\n 'Falling back to environment variable only (YNAB_API_KEY).\\n'\n );\n }\n}\n\nexport class AuthManager {\n async getAccessToken(): Promise<string | null> {\n if (keytar) {\n return keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n }\n return null;\n }\n\n async setAccessToken(token: string): Promise<void> {\n if (keytar) {\n await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);\n } else {\n throw new Error(KEYTAR_UNAVAILABLE_ERROR);\n }\n }\n\n async deleteAccessToken(): Promise<boolean> {\n if (keytar) {\n return keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n }\n return false;\n }\n\n async isAuthenticated(): Promise<boolean> {\n return (await this.getAccessToken()) !== null;\n }\n\n async logout(): Promise<void> {\n await this.deleteAccessToken();\n config.clearDefaultBudget();\n }\n}\n\nexport const auth = new AuthManager();\n","import inquirer from 'inquirer';\nimport { amountToMilliunits } from './utils.js';\n\nexport async function promptForAccessToken(): Promise<string> {\n const { token } = await inquirer.prompt([\n {\n type: 'password',\n name: 'token',\n message: 'Enter your YNAB Personal Access Token:',\n validate: (input: string) => !!input.trim() || 'Access token is required',\n },\n ]);\n return token;\n}\n\nexport async function promptForBudget(\n budgets: Array<{ id: string; name: string }>,\n): Promise<string> {\n const { budgetId } = await inquirer.prompt([\n {\n type: 'list',\n name: 'budgetId',\n message: 'Select a budget:',\n choices: budgets.map((b) => ({ name: b.name, value: b.id })),\n },\n ]);\n return budgetId;\n}\n\nexport async function promptForConfirmation(message: string): Promise<boolean> {\n const { confirmed } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'confirmed',\n message,\n default: false,\n },\n ]);\n return confirmed;\n}\n\nexport async function promptForTransaction(): Promise<Record<string, unknown>> {\n const answers = await inquirer.prompt([\n {\n type: 'input',\n name: 'date',\n message: 'Date (YYYY-MM-DD):',\n default: new Date().toISOString().split('T')[0],\n },\n {\n type: 'input',\n name: 'amount',\n message: 'Amount (in currency units, e.g., 10.50):',\n validate: (input: string) => !isNaN(parseFloat(input)) || 'Amount must be a valid number',\n },\n {\n type: 'input',\n name: 'payee_name',\n message: 'Payee name (optional):',\n },\n {\n type: 'input',\n name: 'memo',\n message: 'Memo (optional):',\n },\n ]);\n\n return {\n date: answers.date,\n amount: amountToMilliunits(parseFloat(answers.amount)),\n payee_name: answers.payee_name || undefined,\n memo: answers.memo || undefined,\n };\n}\n","import * as ynab from 'ynab';\nimport { config } from './config.js';\nimport { YnabCliError, handleYnabError, sanitizeApiError } from './errors.js';\nimport { auth } from './auth.js';\nimport dotenv from 'dotenv';\n\ndotenv.config();\n\ntype TransactionTypeFilter = 'uncategorized' | 'unapproved' | undefined;\n\nexport class YnabClient {\n private api: ynab.API | null = null;\n private envVarWarningShown = false;\n\n async getApi(): Promise<ynab.API> {\n if (this.api) {\n return this.api;\n }\n\n const keychainToken = await auth.getAccessToken();\n const accessToken = keychainToken || process.env.YNAB_API_KEY || null;\n\n if (!accessToken) {\n throw new YnabCliError(\n 'Not authenticated. Please run: ynab auth login or set YNAB_API_KEY environment variable',\n 401,\n );\n }\n\n if (!keychainToken && process.env.YNAB_API_KEY && !this.envVarWarningShown) {\n console.warn(\n '\\x1b[33m⚠️ WARNING: Using YNAB_API_KEY environment variable.\\n' +\n 'Environment variables may be visible to other processes.\\n' +\n 'For better security, use: ynab auth login\\x1b[0m\\n'\n );\n this.envVarWarningShown = true;\n }\n\n this.api = new ynab.API(accessToken);\n return this.api;\n }\n\n async getBudgetId(budgetIdOrDefault?: string): Promise<string> {\n const budgetId =\n budgetIdOrDefault || config.getDefaultBudget() || process.env.YNAB_BUDGET_ID;\n\n if (!budgetId) {\n throw new YnabCliError(\n 'No budget specified. Use --budget flag, set default with \"ynab budgets set-default\", or set YNAB_BUDGET_ID environment variable',\n 400,\n );\n }\n\n return budgetId;\n }\n\n private async withErrorHandling<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n handleYnabError(error);\n }\n }\n\n async getUser() {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const response = await api.user.getUser();\n return response.data.user;\n });\n }\n\n async getBudgets(includeAccounts = false) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const response = await api.budgets.getBudgets(includeAccounts);\n return {\n budgets: response.data.budgets,\n server_knowledge: 0,\n };\n });\n }\n\n async getBudget(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.budgets.getBudgetById(id, lastKnowledgeOfServer);\n return {\n budget: response.data.budget,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getBudgetSettings(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.budgets.getBudgetSettingsById(id);\n return response.data.settings;\n });\n }\n\n async getAccounts(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.getAccounts(id, lastKnowledgeOfServer);\n return {\n accounts: response.data.accounts,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getAccount(accountId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.getAccountById(id, accountId);\n return response.data.account;\n });\n }\n\n async createAccount(accountData: ynab.PostAccountWrapper, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.accounts.createAccount(id, accountData);\n return response.data.account;\n });\n }\n\n async getCategories(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getCategories(id, lastKnowledgeOfServer);\n return {\n category_groups: response.data.category_groups,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getCategory(categoryId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getCategoryById(id, categoryId);\n return response.data.category;\n });\n }\n\n async updateCategory(\n categoryId: string,\n data: ynab.PatchCategoryWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.updateCategory(id, categoryId, data);\n return response.data.category;\n });\n }\n\n async getMonthCategory(month: string, categoryId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.getMonthCategoryById(id, month, categoryId);\n return response.data.category;\n });\n }\n\n async updateMonthCategory(\n month: string,\n categoryId: string,\n data: ynab.PatchMonthCategoryWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.categories.updateMonthCategory(id, month, categoryId, data);\n return response.data.category;\n });\n }\n\n async getPayees(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.getPayees(id, lastKnowledgeOfServer);\n return {\n payees: response.data.payees,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getPayee(payeeId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.getPayeeById(id, payeeId);\n return response.data.payee;\n });\n }\n\n async updatePayee(payeeId: string, data: ynab.PatchPayeeWrapper, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payees.updatePayee(id, payeeId, data);\n return response.data.payee;\n });\n }\n\n async getPayeeLocations(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocations(id);\n return response.data.payee_locations;\n });\n }\n\n async getPayeeLocation(payeeLocationId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocationById(id, payeeLocationId);\n return response.data.payee_location;\n });\n }\n\n async getPayeeLocationsByPayee(payeeId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.payeeLocations.getPayeeLocationsByPayee(id, payeeId);\n return response.data.payee_locations;\n });\n }\n\n async getBudgetMonths(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.months.getBudgetMonths(id, lastKnowledgeOfServer);\n return {\n months: response.data.months,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getBudgetMonth(month: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.months.getBudgetMonth(id, month);\n return response.data.month;\n });\n }\n\n async getTransactions(params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactions(\n id,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByAccount(accountId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByAccount(\n id,\n accountId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByCategory(categoryId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByCategory(\n id,\n categoryId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransactionsByPayee(payeeId: string, params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(params.budgetId);\n const response = await api.transactions.getTransactionsByPayee(\n id,\n payeeId,\n params.sinceDate,\n params.type as TransactionTypeFilter,\n params.lastKnowledgeOfServer,\n );\n return {\n transactions: response.data.transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getTransaction(transactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.getTransactionById(id, transactionId);\n return response.data.transaction;\n });\n }\n\n async createTransaction(\n transactionData: ynab.PutTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.createTransaction(id, transactionData);\n return response.data.transaction;\n });\n }\n\n async createTransactions(\n transactionsData: ynab.PostTransactionsWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.createTransactions(id, transactionsData);\n return response.data;\n });\n }\n\n async updateTransaction(\n transactionId: string,\n transactionData: ynab.PutTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.updateTransaction(\n id,\n transactionId,\n transactionData,\n );\n return response.data.transaction;\n });\n }\n\n async updateTransactions(\n transactionsData: ynab.PatchTransactionsWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.updateTransactions(id, transactionsData);\n return response.data;\n });\n }\n\n async deleteTransaction(transactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.deleteTransaction(id, transactionId);\n return response.data.transaction;\n });\n }\n\n async importTransactions(budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.transactions.importTransactions(id);\n return response.data.transaction_ids;\n });\n }\n\n async getScheduledTransactions(budgetId?: string, lastKnowledgeOfServer?: number) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.getScheduledTransactions(\n id,\n lastKnowledgeOfServer,\n );\n return {\n scheduled_transactions: response.data.scheduled_transactions,\n server_knowledge: response.data.server_knowledge,\n };\n });\n }\n\n async getScheduledTransaction(scheduledTransactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.getScheduledTransactionById(\n id,\n scheduledTransactionId,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async createScheduledTransaction(\n data: ynab.PostScheduledTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.createScheduledTransaction(id, data);\n return response.data.scheduled_transaction;\n });\n }\n\n async updateScheduledTransaction(\n scheduledTransactionId: string,\n data: ynab.PutScheduledTransactionWrapper,\n budgetId?: string,\n ) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.updateScheduledTransaction(\n id,\n scheduledTransactionId,\n data,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async deleteScheduledTransaction(scheduledTransactionId: string, budgetId?: string) {\n return this.withErrorHandling(async () => {\n const api = await this.getApi();\n const id = await this.getBudgetId(budgetId);\n const response = await api.scheduledTransactions.deleteScheduledTransaction(\n id,\n scheduledTransactionId,\n );\n return response.data.scheduled_transaction;\n });\n }\n\n async rawApiCall(method: string, path: string, data?: unknown, budgetId?: string) {\n return this.withErrorHandling(async () => {\n await this.getApi();\n\n const fullPath = path.includes('{budget_id}')\n ? path.replace('{budget_id}', await this.getBudgetId(budgetId))\n : path;\n\n const url = `https://api.ynab.com/v1${fullPath}`;\n const headers = {\n Authorization: `Bearer ${await auth.getAccessToken()}`,\n 'Content-Type': 'application/json',\n };\n\n const httpMethod = method.toUpperCase();\n const hasBody = ['POST', 'PUT', 'PATCH'].includes(httpMethod);\n\n if (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(httpMethod)) {\n throw new YnabCliError(`Unsupported HTTP method: ${method}`, 400);\n }\n\n const response = await fetch(url, {\n method: httpMethod,\n headers,\n ...(hasBody && { body: JSON.stringify(data) }),\n });\n\n if (!response.ok) {\n const errorData = await response.json() as Record<string, unknown>;\n throw { error: sanitizeApiError(errorData.error || errorData) };\n }\n\n return await response.json();\n });\n }\n}\n\nexport const client = new YnabClient();\n","import type { YnabError } from '../types/index.js';\nimport { outputJson } from './output.js';\n\nexport class YnabCliError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = 'YnabCliError';\n }\n}\n\nconst ERROR_STATUS_CODES: Record<string, number> = {\n bad_request: 400,\n not_authorized: 401,\n subscription_lapsed: 403,\n trial_expired: 403,\n unauthorized_scope: 403,\n data_limit_reached: 403,\n not_found: 404,\n resource_not_found: 404,\n conflict: 409,\n too_many_requests: 429,\n internal_server_error: 500,\n service_unavailable: 503,\n};\n\nexport function sanitizeErrorMessage(message: string): string {\n const sensitivePatterns = [\n /Bearer\\s+[\\w\\-._~+/]+=*/gi,\n /token[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /api[_-]?key[=:]\\s*[\\w\\-._~+/]+=*/gi,\n /authorization:\\s*bearer\\s+[\\w\\-._~+/]+=*/gi,\n ];\n\n let sanitized = message;\n for (const pattern of sensitivePatterns) {\n sanitized = sanitized.replace(pattern, '[REDACTED]');\n }\n\n return sanitized.length > 500 ? sanitized.substring(0, 500) + '...' : sanitized;\n}\n\ninterface YnabApiError {\n name?: string;\n detail?: string;\n message?: string;\n id?: string;\n}\n\nfunction isErrorObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function sanitizeApiError(error: unknown): YnabError {\n if (!isErrorObject(error)) {\n return {\n name: 'api_error',\n detail: 'An error occurred',\n id: undefined,\n };\n }\n\n const apiError = error as YnabApiError;\n const detail = sanitizeErrorMessage(\n String(apiError.detail || apiError.message || 'An error occurred')\n );\n\n return {\n name: apiError.name || 'api_error',\n detail,\n id: apiError.id,\n };\n}\n\nfunction enhanceRateLimitMessage(detail: string): string {\n return `${detail}\\n\\nYNAB API limit: 200 requests/hour (rolling window). Wait a few minutes and retry.`;\n}\n\nfunction formatErrorResponse(name: string, detail: string, statusCode: number): never {\n const enhancedDetail = name === 'too_many_requests'\n ? enhanceRateLimitMessage(detail)\n : detail;\n\n outputJson({ error: { name, detail: enhancedDetail, statusCode } });\n process.exit(1);\n}\n\nexport function handleYnabError(error: unknown): never {\n if (!isErrorObject(error)) {\n formatErrorResponse('unknown_error', 'An unexpected error occurred', 1);\n }\n\n const errorObj = error as { error?: unknown; message?: string };\n\n if (errorObj.error) {\n const ynabError: YnabError = sanitizeApiError(errorObj.error);\n formatErrorResponse(\n ynabError.name,\n ynabError.detail,\n ERROR_STATUS_CODES[ynabError.name] || 500,\n );\n }\n\n if (error instanceof YnabCliError) {\n const sanitized = sanitizeErrorMessage(error.message);\n formatErrorResponse('cli_error', sanitized, error.statusCode || 1);\n }\n\n const sanitized = sanitizeErrorMessage(errorObj.message || 'An unexpected error occurred');\n formatErrorResponse('unknown_error', sanitized, 1);\n}\n","import { handleYnabError } from './errors.js';\nimport { promptForConfirmation } from './prompts.js';\nimport { isInteractive } from './utils.js';\nimport { outputJson } from './output.js';\n\nexport function withErrorHandling<TArgs extends unknown[], R>(\n fn: (...args: TArgs) => Promise<R>,\n): (...args: TArgs) => Promise<void> {\n return async (...args: TArgs) => {\n try {\n await fn(...args);\n } catch (error) {\n handleYnabError(error);\n }\n };\n}\n\nexport async function confirmDelete(\n itemType: string,\n skipConfirmation: boolean = false,\n): Promise<boolean> {\n if (skipConfirmation || !isInteractive()) {\n return true;\n }\n\n const confirmed = await promptForConfirmation(\n `Are you sure you want to delete this ${itemType}?`,\n );\n\n if (!confirmed) {\n outputJson({ message: 'Operation cancelled' });\n return false;\n }\n\n return true;\n}\n\nexport function buildUpdateObject<T>(\n options: T,\n mapping: Record<string, string>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const optionsRecord = options as Record<string, unknown>;\n\n for (const [optionKey, targetKey] of Object.entries(mapping)) {\n if (optionsRecord[optionKey] !== undefined) {\n result[targetKey] = optionsRecord[optionKey];\n }\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createUserCommand(): Command {\n const cmd = new Command('user').description('User information');\n\n cmd\n .command('info')\n .description('Get authenticated user information')\n .action(withErrorHandling(async () => {\n const user = await client.getUser();\n outputJson(user);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { config } from '../lib/config.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\n\nexport function createBudgetsCommand(): Command {\n const cmd = new Command('budgets').description('Budget operations');\n\n cmd\n .command('list')\n .description('List all budgets')\n .option('--include-accounts', 'Include accounts in response')\n .action(withErrorHandling(async (options: { includeAccounts?: boolean }) => {\n const result = await client.getBudgets(options.includeAccounts);\n outputJson(result?.budgets);\n }));\n\n cmd\n .command('view')\n .description('View budget details (uses default if no id provided)')\n .argument('[id]', 'Budget ID')\n .action(withErrorHandling(async (id: string | undefined) => {\n const result = await client.getBudget(id);\n outputJson(result?.budget);\n }));\n\n cmd\n .command('settings')\n .description('View budget settings')\n .argument('[id]', 'Budget ID')\n .action(withErrorHandling(async (id: string | undefined) => {\n const settings = await client.getBudgetSettings(id);\n outputJson(settings);\n }));\n\n cmd\n .command('set-default')\n .description('Set default budget for commands')\n .argument('<id>', 'Budget ID')\n .action(withErrorHandling(async (id: string) => {\n const result = await client.getBudgets();\n const budget = result?.budgets.find((b) => b.id === id);\n\n if (!budget) {\n throw new YnabCliError(`Budget with ID ${id} not found`, 404);\n }\n\n config.setDefaultBudget(id);\n outputJson({\n message: 'Default budget set',\n budget: { id: budget.id, name: budget.name },\n });\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createAccountsCommand(): Command {\n const cmd = new Command('accounts').description('Account operations');\n\n cmd\n .command('list')\n .description('List all accounts')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (options: CommandOptions) => {\n const result = await client.getAccounts(options.budget);\n outputJson(result?.accounts);\n }));\n\n cmd\n .command('view')\n .description('View account details')\n .argument('<id>', 'Account ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const account = await client.getAccount(id, options.budget);\n outputJson(account);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for account')\n .argument('<id>', 'Account ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByAccount(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n });\n outputJson(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { amountToMilliunits } from '../lib/utils.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createCategoriesCommand(): Command {\n const cmd = new Command('categories').description('Category operations');\n\n cmd\n .command('list')\n .description('List all categories')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getCategories(options.budget, options.lastKnowledge);\n outputJson(result?.category_groups);\n }));\n\n cmd\n .command('view')\n .description('View category details')\n .argument('<id>', 'Category ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const category = await client.getCategory(id, options.budget);\n outputJson(category);\n }));\n\n cmd\n .command('budget')\n .description('Set category budgeted amount for a month (overrides existing amount)')\n .argument('<id>', 'Category ID')\n .requiredOption('--month <month>', 'Month in YYYY-MM-DD format (e.g., 2025-07-01)')\n .requiredOption('--amount <amount>', 'Total budgeted amount to set (e.g., 100.50)', parseFloat)\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (\n id: string,\n options: {\n month: string;\n amount: number;\n budget?: string;\n } & CommandOptions,\n ) => {\n if (isNaN(options.amount)) {\n throw new YnabCliError('Amount must be a valid number', 400);\n }\n\n const milliunits = amountToMilliunits(options.amount);\n const category = await client.updateMonthCategory(\n options.month,\n id,\n { category: { budgeted: milliunits } },\n options.budget,\n );\n outputJson(category);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for category')\n .argument('<id>', 'Category ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n lastKnowledge?: number;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByCategory(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputJson(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { promptForTransaction } from '../lib/prompts.js';\nimport { isInteractive, amountToMilliunits, applyTransactionFilters, applyFieldSelection, type TransactionLike } from '../lib/utils.js';\nimport { withErrorHandling, confirmDelete, buildUpdateObject } from '../lib/command-utils.js';\nimport { validateJson, TransactionSplitSchema } from '../lib/schemas.js';\nimport type { CommandOptions } from '../types/index.js';\n\ninterface TransactionOptions {\n account?: string;\n date?: string;\n amount?: number;\n payeeName?: string;\n payeeId?: string;\n categoryId?: string;\n memo?: string;\n cleared?: string;\n approved?: boolean;\n}\n\nfunction buildTransactionData(options: TransactionOptions): Record<string, unknown> {\n if (!options.account) {\n throw new YnabCliError('--account is required in non-interactive mode', 400);\n }\n if (options.amount === undefined) {\n throw new YnabCliError('--amount is required in non-interactive mode', 400);\n }\n\n return {\n account_id: options.account,\n date: options.date || new Date().toISOString().split('T')[0],\n amount: amountToMilliunits(options.amount),\n payee_name: options.payeeName,\n payee_id: options.payeeId,\n category_id: options.categoryId,\n memo: options.memo,\n cleared: options.cleared,\n approved: options.approved,\n };\n}\n\nexport function createTransactionsCommand(): Command {\n const cmd = new Command('transactions').description('Transaction operations');\n\n cmd\n .command('list')\n .description('List transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Filter by account ID')\n .option('--category <id>', 'Filter by category ID')\n .option('--payee <id>', 'Filter by payee ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--until <date>', 'Filter transactions until date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option('--status <statuses>', 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated for multiple)')\n .option('--min-amount <amount>', 'Minimum amount in currency units (e.g., 10.50)', parseFloat)\n .option('--max-amount <amount>', 'Maximum amount in currency units (e.g., 100.00)', parseFloat)\n .option('--fields <fields>', 'Comma-separated list of fields to include (e.g., id,date,amount,memo)')\n .action(withErrorHandling(async (options: {\n budget?: string;\n account?: string;\n category?: string;\n payee?: string;\n since?: string;\n until?: string;\n type?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n fields?: string;\n } & CommandOptions) => {\n const params = {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n };\n\n const result = options.account\n ? await client.getTransactionsByAccount(options.account, params)\n : options.category\n ? await client.getTransactionsByCategory(options.category, params)\n : options.payee\n ? await client.getTransactionsByPayee(options.payee, params)\n : await client.getTransactions(params);\n\n const transactions = result?.transactions || [];\n\n const filtered = applyTransactionFilters(transactions as TransactionLike[], {\n until: options.until,\n approved: options.approved,\n status: options.status,\n minAmount: options.minAmount,\n maxAmount: options.maxAmount,\n });\n\n const selected = applyFieldSelection(filtered, options.fields);\n\n outputJson(selected);\n }));\n\n cmd\n .command('view')\n .description('View single transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const transaction = await client.getTransaction(id, options.budget);\n outputJson(transaction);\n }));\n\n cmd\n .command('create')\n .description('Create transaction')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Account ID')\n .option('--date <date>', 'Date (YYYY-MM-DD)')\n .option('--amount <amount>', 'Amount in currency units (e.g., 10.50)', parseFloat)\n .option('--payee-name <name>', 'Payee name')\n .option('--payee-id <id>', 'Payee ID')\n .option('--category-id <id>', 'Category ID')\n .option('--memo <memo>', 'Memo')\n .option('--cleared <status>', 'Cleared status (cleared, uncleared, reconciled)')\n .option('--approved', 'Mark as approved')\n .action(withErrorHandling(async (options: {\n budget?: string;\n account?: string;\n date?: string;\n amount?: number;\n payeeName?: string;\n payeeId?: string;\n categoryId?: string;\n memo?: string;\n cleared?: string;\n approved?: boolean;\n } & CommandOptions) => {\n const shouldPrompt = isInteractive() && !options.account && !options.amount;\n const transactionData = shouldPrompt\n ? await promptForTransaction()\n : buildTransactionData(options);\n\n const transaction = await client.createTransaction(\n { transaction: transactionData },\n options.budget,\n );\n outputJson(transaction);\n }));\n\n cmd\n .command('update')\n .description('Update transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--account <id>', 'Account ID')\n .option('--date <date>', 'Date (YYYY-MM-DD)')\n .option('--amount <amount>', 'Amount in currency units', parseFloat)\n .option('--payee-name <name>', 'Payee name')\n .option('--payee-id <id>', 'Payee ID')\n .option('--category-id <id>', 'Category ID')\n .option('--memo <memo>', 'Memo')\n .option('--cleared <status>', 'Cleared status')\n .option('--approved', 'Mark as approved')\n .action(withErrorHandling(async (\n id: string,\n options: TransactionOptions & { budget?: string } & CommandOptions,\n ) => {\n const transactionData = buildUpdateObject(options, {\n account: 'account_id',\n date: 'date',\n payeeName: 'payee_name',\n payeeId: 'payee_id',\n categoryId: 'category_id',\n memo: 'memo',\n cleared: 'cleared',\n approved: 'approved',\n });\n\n if (options.amount !== undefined) {\n transactionData.amount = amountToMilliunits(options.amount);\n }\n\n const transaction = await client.updateTransaction(\n id,\n { transaction: transactionData },\n options.budget,\n );\n outputJson(transaction);\n }));\n\n cmd\n .command('delete')\n .description('Delete transaction')\n .argument('<id>', 'Transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('-y, --yes', 'Skip confirmation')\n .action(withErrorHandling(async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n if (!await confirmDelete('transaction', options.yes)) {\n return;\n }\n\n const transaction = await client.deleteTransaction(id, options.budget);\n outputJson({ message: 'Transaction deleted', transaction });\n }));\n\n cmd\n .command('import')\n .description('Import transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (options: CommandOptions) => {\n const transactionIds = await client.importTransactions(options.budget);\n outputJson({ transaction_ids: transactionIds });\n }));\n\n cmd\n .command('split')\n .description('Split transaction into multiple categories')\n .argument('<id>', 'Transaction ID')\n .requiredOption('--splits <json>', 'JSON array of splits: [{\"amount\": -21400, \"category_id\": \"xxx\", \"memo\": \"...\"}]')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (\n id: string,\n options: { splits: string; budget?: string } & CommandOptions,\n ) => {\n let parsedSplits;\n try {\n parsedSplits = JSON.parse(options.splits);\n } catch (error) {\n throw new YnabCliError('Invalid JSON in --splits parameter', 400);\n }\n\n const splits = validateJson(parsedSplits, TransactionSplitSchema, 'transaction splits');\n\n const transaction = await client.updateTransaction(\n id,\n {\n transaction: {\n category_id: null,\n subtransactions: splits,\n },\n },\n options.budget,\n );\n outputJson(transaction);\n }));\n\n cmd\n .command('search')\n .description('Search transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--memo <text>', 'Search in memo field')\n .option('--payee-name <name>', 'Search in payee name')\n .option('--amount <amount>', 'Search for exact amount in currency units', parseFloat)\n .option('--since <date>', 'Search transactions since date (YYYY-MM-DD)')\n .option('--until <date>', 'Search transactions until date (YYYY-MM-DD)')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option('--status <statuses>', 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated)')\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .action(withErrorHandling(async (options: {\n budget?: string;\n memo?: string;\n payeeName?: string;\n amount?: number;\n since?: string;\n until?: string;\n approved?: string;\n status?: string;\n fields?: string;\n } & CommandOptions) => {\n if (!options.memo && !options.payeeName && options.amount === undefined) {\n throw new YnabCliError('At least one search criteria required: --memo, --payee-name, or --amount', 400);\n }\n\n const params = {\n budgetId: options.budget,\n sinceDate: options.since,\n };\n\n const result = await client.getTransactions(params);\n let transactions = result?.transactions || [];\n\n if (options.memo) {\n const searchTerm = options.memo.toLowerCase();\n transactions = transactions.filter(t =>\n t.memo?.toLowerCase().includes(searchTerm)\n );\n }\n\n if (options.payeeName) {\n const searchTerm = options.payeeName.toLowerCase();\n transactions = transactions.filter(t =>\n t.payee_name?.toLowerCase().includes(searchTerm)\n );\n }\n\n if (options.amount !== undefined) {\n const amountMilliunits = amountToMilliunits(options.amount);\n transactions = transactions.filter(t => t.amount === amountMilliunits);\n }\n\n transactions = applyTransactionFilters(transactions, {\n until: options.until,\n approved: options.approved,\n status: options.status,\n });\n\n const filteredTransactions = applyFieldSelection(transactions, options.fields);\n\n outputJson(filteredTransactions);\n }));\n\n return cmd;\n}\n","import { z } from 'zod';\nimport { YnabCliError } from './errors.js';\n\nexport const TransactionSplitSchema = z.array(\n z.object({\n amount: z.number(),\n category_id: z.string().nullable().optional(),\n memo: z.string().optional(),\n payee_id: z.string().optional(),\n })\n);\n\nexport const ApiDataSchema = z.record(z.any());\n\nexport function validateJson<T>(\n data: unknown,\n schema: z.ZodSchema<T>,\n fieldName: string\n): T {\n try {\n return schema.parse(data);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = error.issues\n .map(i => `${i.path.join('.')}: ${i.message}`)\n .join(', ');\n throw new YnabCliError(`Invalid ${fieldName}: ${issues}`, 400);\n }\n throw error;\n }\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling, confirmDelete } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createScheduledCommand(): Command {\n const cmd = new Command('scheduled').description('Scheduled transaction operations');\n\n cmd\n .command('list')\n .description('List all scheduled transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getScheduledTransactions(options.budget, options.lastKnowledge);\n outputJson(result?.scheduled_transactions);\n }));\n\n cmd\n .command('view')\n .description('View scheduled transaction')\n .argument('<id>', 'Scheduled transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const scheduledTransaction = await client.getScheduledTransaction(id, options.budget);\n outputJson(scheduledTransaction);\n }));\n\n cmd\n .command('delete')\n .description('Delete scheduled transaction')\n .argument('<id>', 'Scheduled transaction ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('-y, --yes', 'Skip confirmation')\n .action(withErrorHandling(async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n if (!await confirmDelete('scheduled transaction', options.yes)) {\n return;\n }\n\n const scheduledTransaction = await client.deleteScheduledTransaction(id, options.budget);\n outputJson({\n message: 'Scheduled transaction deleted',\n scheduled_transaction: scheduledTransaction,\n });\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createPayeesCommand(): Command {\n const cmd = new Command('payees').description('Payee operations');\n\n cmd\n .command('list')\n .description('List all payees')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getPayees(options.budget, options.lastKnowledge);\n outputJson(result?.payees);\n }));\n\n cmd\n .command('view')\n .description('View payee details')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const payee = await client.getPayee(id, options.budget);\n outputJson(payee);\n }));\n\n cmd\n .command('update')\n .description('Rename payee')\n .argument('<id>', 'Payee ID')\n .requiredOption('--name <name>', 'New payee name')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: { name: string; budget?: string } & CommandOptions) => {\n if (!options.name?.trim()) {\n throw new YnabCliError('Name cannot be empty', 400);\n }\n\n const payee = await client.updatePayee(\n id,\n { payee: { name: options.name } },\n options.budget,\n );\n outputJson(payee);\n }));\n\n cmd\n .command('locations')\n .description('List locations for payee')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (id: string, options: CommandOptions) => {\n const locations = await client.getPayeeLocationsByPayee(id, options.budget);\n outputJson(locations);\n }));\n\n cmd\n .command('transactions')\n .description('List transactions for payee')\n .argument('<id>', 'Payee ID')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--since <date>', 'Filter transactions since date (YYYY-MM-DD)')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (\n id: string,\n options: {\n budget?: string;\n since?: string;\n type?: string;\n lastKnowledge?: number;\n } & CommandOptions,\n ) => {\n const result = await client.getTransactionsByPayee(id, {\n budgetId: options.budget,\n sinceDate: options.since,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputJson(result?.transactions);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport type { CommandOptions } from '../types/index.js';\n\nexport function createMonthsCommand(): Command {\n const cmd = new Command('months').description('Monthly budget operations');\n\n cmd\n .command('list')\n .description('List all budget months')\n .option('-b, --budget <id>', 'Budget ID')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(withErrorHandling(async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getBudgetMonths(options.budget, options.lastKnowledge);\n outputJson(result?.months);\n }));\n\n cmd\n .command('view')\n .description('View specific month details')\n .argument('<month>', 'Month in YYYY-MM-DD format (e.g., 2025-07-01)')\n .option('-b, --budget <id>', 'Budget ID')\n .action(withErrorHandling(async (month: string, options: CommandOptions) => {\n const monthData = await client.getBudgetMonth(month, options.budget);\n outputJson(monthData);\n }));\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { YnabCliError } from '../lib/errors.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { validateJson, ApiDataSchema } from '../lib/schemas.js';\nimport type { CommandOptions } from '../types/index.js';\n\nconst VALID_HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];\n\nexport function createApiCommand(): Command {\n const cmd = new Command('api').description('Raw API access');\n\n cmd\n .argument('<method>', 'HTTP method (GET, POST, PUT, PATCH, DELETE)')\n .argument('<path>', 'API path (e.g., /budgets or /budgets/{budget_id}/transactions)')\n .option('-b, --budget <id>', 'Budget ID (used to replace {budget_id} in path)')\n .option('--data <json>', 'JSON data for POST/PUT/PATCH requests')\n .description('Make raw API calls to YNAB')\n .action(withErrorHandling(async (\n method: string,\n path: string,\n options: { budget?: string; data?: string } & CommandOptions,\n ) => {\n const upperMethod = method.toUpperCase();\n\n if (!VALID_HTTP_METHODS.includes(upperMethod)) {\n throw new YnabCliError(\n `Invalid HTTP method: ${method}. Must be one of: ${VALID_HTTP_METHODS.join(', ')}`,\n 400,\n );\n }\n\n let data: Record<string, unknown> | undefined;\n if (options.data) {\n try {\n const parsedData = JSON.parse(options.data);\n data = validateJson(parsedData, ApiDataSchema, 'API data');\n } catch (error) {\n throw new YnabCliError('Invalid JSON in --data parameter', 400);\n }\n }\n\n const result = await client.rawApiCall(upperMethod, path, data, options.budget);\n outputJson(result);\n }));\n\n return cmd;\n}\n"],"mappings":"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","names":["Command","sanitized","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
|