@stephendolan/ynab-cli 2.0.0 → 2.1.1

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/dist/cli.js CHANGED
@@ -97,9 +97,6 @@ function milliunitsToAmount(milliunits) {
97
97
  function amountToMilliunits(amount) {
98
98
  return Math.round(amount * 1e3);
99
99
  }
100
- function isInteractive() {
101
- return process.stdin.isTTY === true;
102
- }
103
100
  function convertMilliunitsToAmounts(data) {
104
101
  if (data === null || data === void 0) return data;
105
102
  if (Array.isArray(data)) return data.map(convertMilliunitsToAmounts);
@@ -314,67 +311,8 @@ Or use the YNAB_API_KEY environment variable instead.`
314
311
  };
315
312
  var auth = new AuthManager();
316
313
 
317
- // src/lib/prompts.ts
318
- import inquirer from "inquirer";
319
- async function promptForAccessToken() {
320
- const { token } = await inquirer.prompt([
321
- {
322
- type: "password",
323
- name: "token",
324
- message: "Enter your YNAB Personal Access Token:",
325
- validate: (input) => !!input.trim() || "Access token is required"
326
- }
327
- ]);
328
- return token.trim();
329
- }
330
- async function promptForConfirmation(message) {
331
- const { confirmed } = await inquirer.prompt([
332
- {
333
- type: "confirm",
334
- name: "confirmed",
335
- message,
336
- default: false
337
- }
338
- ]);
339
- return confirmed;
340
- }
341
- async function promptForTransaction() {
342
- const answers = await inquirer.prompt([
343
- {
344
- type: "input",
345
- name: "date",
346
- message: "Date (YYYY-MM-DD):",
347
- default: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
348
- },
349
- {
350
- type: "input",
351
- name: "amount",
352
- message: "Amount (in currency units, e.g., 10.50):",
353
- validate: (input) => !isNaN(parseFloat(input)) || "Amount must be a valid number"
354
- },
355
- {
356
- type: "input",
357
- name: "payee_name",
358
- message: "Payee name (optional):"
359
- },
360
- {
361
- type: "input",
362
- name: "memo",
363
- message: "Memo (optional):"
364
- }
365
- ]);
366
- return {
367
- date: answers.date,
368
- amount: amountToMilliunits(parseFloat(answers.amount)),
369
- payee_name: answers.payee_name || void 0,
370
- memo: answers.memo || void 0
371
- };
372
- }
373
-
374
314
  // src/lib/api-client.ts
375
315
  import * as ynab from "ynab";
376
- import dotenv from "dotenv";
377
- dotenv.config();
378
316
  var YnabClient = class {
379
317
  api = null;
380
318
  envVarWarningShown = false;
@@ -739,18 +677,13 @@ function withErrorHandling(fn) {
739
677
  }
740
678
  };
741
679
  }
742
- async function confirmDelete(itemType, skipConfirmation = false) {
743
- if (skipConfirmation || !isInteractive()) {
744
- return true;
745
- }
746
- const confirmed = await promptForConfirmation(
747
- `Are you sure you want to delete this ${itemType}?`
748
- );
680
+ function requireConfirmation(itemType, confirmed = false) {
749
681
  if (!confirmed) {
750
- outputJson({ message: "Operation cancelled" });
751
- return false;
682
+ throw new YnabCliError(
683
+ `Deleting ${itemType} requires --yes flag to confirm`,
684
+ 400
685
+ );
752
686
  }
753
- return true;
754
687
  }
755
688
  function buildUpdateObject(options, mapping) {
756
689
  const result = {};
@@ -766,9 +699,12 @@ function buildUpdateObject(options, mapping) {
766
699
  // src/commands/auth.ts
767
700
  function createAuthCommand() {
768
701
  const cmd = new Command("auth").description("Authentication management");
769
- cmd.command("login").description("Configure access token").action(
770
- withErrorHandling(async () => {
771
- const token = await promptForAccessToken();
702
+ cmd.command("login").description("Configure access token").requiredOption("-t, --token <token>", "YNAB Personal Access Token").action(
703
+ withErrorHandling(async (options) => {
704
+ const token = options.token.trim();
705
+ if (!token) {
706
+ throw new YnabCliError("Access token cannot be empty", 400);
707
+ }
772
708
  await auth.setAccessToken(token);
773
709
  client.clearApi();
774
710
  try {
@@ -863,6 +799,21 @@ function createBudgetsCommand() {
863
799
 
864
800
  // src/commands/accounts.ts
865
801
  import { Command as Command4 } from "commander";
802
+
803
+ // src/lib/dates.ts
804
+ import dayjs from "dayjs";
805
+ function parseDate(input) {
806
+ const d = dayjs(input);
807
+ if (!d.isValid()) {
808
+ throw new YnabCliError(`Invalid date: ${input}`, 400);
809
+ }
810
+ return d.format("YYYY-MM-DD");
811
+ }
812
+ function todayDate() {
813
+ return dayjs().format("YYYY-MM-DD");
814
+ }
815
+
816
+ // src/commands/accounts.ts
866
817
  function createAccountsCommand() {
867
818
  const cmd = new Command4("accounts").description("Account operations");
868
819
  cmd.command("list").description("List all accounts").option("-b, --budget <id>", "Budget ID").action(
@@ -877,12 +828,12 @@ function createAccountsCommand() {
877
828
  outputJson(account);
878
829
  })
879
830
  );
880
- 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(
831
+ 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").option("--type <type>", "Filter by transaction type").action(
881
832
  withErrorHandling(
882
833
  async (id, options) => {
883
834
  const result = await client.getTransactionsByAccount(id, {
884
835
  budgetId: options.budget,
885
- sinceDate: options.since,
836
+ sinceDate: options.since ? parseDate(options.since) : void 0,
886
837
  type: options.type
887
838
  });
888
839
  outputJson(result?.transactions);
@@ -910,7 +861,7 @@ function createCategoriesCommand() {
910
861
  outputJson(category);
911
862
  })
912
863
  );
913
- 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(
864
+ cmd.command("budget").description("Set category budgeted amount for a month (overrides existing amount)").argument("<id>", "Category ID").requiredOption("--month <month>", "Budget month (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(
914
865
  withErrorHandling(
915
866
  async (id, options) => {
916
867
  if (isNaN(options.amount)) {
@@ -918,7 +869,7 @@ function createCategoriesCommand() {
918
869
  }
919
870
  const milliunits = amountToMilliunits(options.amount);
920
871
  const category = await client.updateMonthCategory(
921
- options.month,
872
+ parseDate(options.month),
922
873
  id,
923
874
  { category: { budgeted: milliunits } },
924
875
  options.budget
@@ -927,12 +878,12 @@ function createCategoriesCommand() {
927
878
  }
928
879
  )
929
880
  );
930
- 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(
881
+ 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").option("--type <type>", "Filter by transaction type").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(
931
882
  withErrorHandling(
932
883
  async (id, options) => {
933
884
  const result = await client.getTransactionsByCategory(id, {
934
885
  budgetId: options.budget,
935
- sinceDate: options.since,
886
+ sinceDate: options.since ? parseDate(options.since) : void 0,
936
887
  type: options.type,
937
888
  lastKnowledgeOfServer: options.lastKnowledge
938
889
  });
@@ -947,26 +898,31 @@ function createCategoriesCommand() {
947
898
  import { Command as Command6 } from "commander";
948
899
 
949
900
  // src/lib/schemas.ts
950
- import { z } from "zod";
951
- var TransactionSplitSchema = z.array(
952
- z.object({
953
- amount: z.number(),
954
- category_id: z.string().nullable().optional(),
955
- memo: z.string().optional(),
956
- payee_id: z.string().optional()
957
- })
958
- );
959
- var ApiDataSchema = z.record(z.any());
960
- function validateJson(data, schema, fieldName) {
961
- try {
962
- return schema.parse(data);
963
- } catch (error) {
964
- if (error instanceof z.ZodError) {
965
- const issues = error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
966
- throw new YnabCliError(`Invalid ${fieldName}: ${issues}`, 400);
901
+ function validateTransactionSplits(data) {
902
+ if (!Array.isArray(data)) {
903
+ throw new YnabCliError("Transaction splits must be an array", 400);
904
+ }
905
+ return data.map((item, index) => {
906
+ if (typeof item !== "object" || item === null) {
907
+ throw new YnabCliError(`Split at index ${index} must be an object`, 400);
908
+ }
909
+ const split = item;
910
+ if (typeof split.amount !== "number") {
911
+ throw new YnabCliError(`Split at index ${index} must have a numeric amount`, 400);
967
912
  }
968
- throw error;
913
+ return {
914
+ amount: split.amount,
915
+ category_id: split.category_id,
916
+ memo: split.memo,
917
+ payee_id: split.payee_id
918
+ };
919
+ });
920
+ }
921
+ function validateApiData(data) {
922
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
923
+ throw new YnabCliError("API data must be an object", 400);
969
924
  }
925
+ return data;
970
926
  }
971
927
 
972
928
  // src/commands/transactions.ts
@@ -979,7 +935,7 @@ function buildTransactionData(options) {
979
935
  }
980
936
  return {
981
937
  account_id: options.account,
982
- date: options.date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
938
+ date: options.date ? parseDate(options.date) : todayDate(),
983
939
  amount: amountToMilliunits(options.amount),
984
940
  payee_name: options.payeeName,
985
941
  payee_id: options.payeeId,
@@ -991,7 +947,7 @@ function buildTransactionData(options) {
991
947
  }
992
948
  function createTransactionsCommand() {
993
949
  const cmd = new Command6("transactions").description("Transaction operations");
994
- cmd.command("list").description("List transactions").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Filter by account ID").option("--category <id>", "Filter by category ID").option("--payee <id>", "Filter by payee ID").option("--since <date>", "Filter transactions since date (YYYY-MM-DD)").option("--until <date>", "Filter transactions until date (YYYY-MM-DD)").option("--type <type>", "Filter by transaction type").option("--approved <value>", "Filter by approval status: true or false").option(
950
+ cmd.command("list").description("List transactions").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Filter by account ID").option("--category <id>", "Filter by category ID").option("--payee <id>", "Filter by payee ID").option("--since <date>", "Filter transactions since date").option("--until <date>", "Filter transactions until date").option("--type <type>", "Filter by transaction type").option("--approved <value>", "Filter by approval status: true or false").option(
995
951
  "--status <statuses>",
996
952
  "Filter by cleared status: cleared, uncleared, reconciled (comma-separated for multiple)"
997
953
  ).option("--min-amount <amount>", "Minimum amount in currency units (e.g., 10.50)", parseFloat).option("--max-amount <amount>", "Maximum amount in currency units (e.g., 100.00)", parseFloat).option(
@@ -1002,13 +958,13 @@ function createTransactionsCommand() {
1002
958
  async (options) => {
1003
959
  const params = {
1004
960
  budgetId: options.budget,
1005
- sinceDate: options.since,
961
+ sinceDate: options.since ? parseDate(options.since) : void 0,
1006
962
  type: options.type
1007
963
  };
1008
964
  const result = options.account ? await client.getTransactionsByAccount(options.account, params) : options.category ? await client.getTransactionsByCategory(options.category, params) : options.payee ? await client.getTransactionsByPayee(options.payee, params) : await client.getTransactions(params);
1009
965
  const transactions = result?.transactions || [];
1010
966
  const filtered = applyTransactionFilters(transactions, {
1011
- until: options.until,
967
+ until: options.until ? parseDate(options.until) : void 0,
1012
968
  approved: options.approved,
1013
969
  status: options.status,
1014
970
  minAmount: options.minAmount,
@@ -1025,17 +981,10 @@ function createTransactionsCommand() {
1025
981
  outputJson(transaction);
1026
982
  })
1027
983
  );
1028
- 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(
984
+ cmd.command("create").description("Create transaction").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Account ID").option("--date <date>", "Transaction date").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(
1029
985
  withErrorHandling(
1030
986
  async (options) => {
1031
- const shouldPrompt = isInteractive() && !options.amount;
1032
- if (shouldPrompt && !options.account) {
1033
- throw new YnabCliError(
1034
- "--account is required. Interactive mode cannot auto-select an account.",
1035
- 400
1036
- );
1037
- }
1038
- const transactionData = shouldPrompt ? { ...await promptForTransaction(), account_id: options.account } : buildTransactionData(options);
987
+ const transactionData = buildTransactionData(options);
1039
988
  const transaction = await client.createTransaction(
1040
989
  { transaction: transactionData },
1041
990
  options.budget
@@ -1044,7 +993,7 @@ function createTransactionsCommand() {
1044
993
  }
1045
994
  )
1046
995
  );
1047
- 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(
996
+ cmd.command("update").description("Update transaction").argument("<id>", "Transaction ID").option("-b, --budget <id>", "Budget ID").option("--account <id>", "Account ID").option("--date <date>", "Transaction date").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(
1048
997
  withErrorHandling(
1049
998
  async (id, options) => {
1050
999
  const transactionData = buildUpdateObject(options, {
@@ -1072,9 +1021,7 @@ function createTransactionsCommand() {
1072
1021
  cmd.command("delete").description("Delete transaction").argument("<id>", "Transaction ID").option("-b, --budget <id>", "Budget ID").option("-y, --yes", "Skip confirmation").action(
1073
1022
  withErrorHandling(
1074
1023
  async (id, options) => {
1075
- if (!await confirmDelete("transaction", options.yes)) {
1076
- return;
1077
- }
1024
+ requireConfirmation("transaction", options.yes);
1078
1025
  const transaction = await client.deleteTransaction(id, options.budget);
1079
1026
  outputJson({ message: "Transaction deleted", transaction });
1080
1027
  }
@@ -1100,7 +1047,7 @@ function createTransactionsCommand() {
1100
1047
  } catch {
1101
1048
  throw new YnabCliError("Invalid JSON in --splits parameter", 400);
1102
1049
  }
1103
- const splits = validateJson(parsedSplits, TransactionSplitSchema, "transaction splits");
1050
+ const splits = validateTransactionSplits(parsedSplits);
1104
1051
  const splitsInMilliunits = splits.map((split) => ({
1105
1052
  ...split,
1106
1053
  amount: amountToMilliunits(split.amount)
@@ -1150,7 +1097,7 @@ function createTransactionsCommand() {
1150
1097
  }
1151
1098
  )
1152
1099
  );
1153
- 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(
1100
+ 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").option("--until <date>", "Search transactions until date").option("--approved <value>", "Filter by approval status: true or false").option(
1154
1101
  "--status <statuses>",
1155
1102
  "Filter by cleared status: cleared, uncleared, reconciled (comma-separated)"
1156
1103
  ).option("--fields <fields>", "Comma-separated list of fields to include").action(
@@ -1164,7 +1111,7 @@ function createTransactionsCommand() {
1164
1111
  }
1165
1112
  const params = {
1166
1113
  budgetId: options.budget,
1167
- sinceDate: options.since
1114
+ sinceDate: options.since ? parseDate(options.since) : void 0
1168
1115
  };
1169
1116
  const result = await client.getTransactions(params);
1170
1117
  let transactions = result?.transactions || [];
@@ -1183,7 +1130,7 @@ function createTransactionsCommand() {
1183
1130
  transactions = transactions.filter((t) => t.amount === amountMilliunits);
1184
1131
  }
1185
1132
  transactions = applyTransactionFilters(transactions, {
1186
- until: options.until,
1133
+ until: options.until ? parseDate(options.until) : void 0,
1187
1134
  approved: options.approved,
1188
1135
  status: options.status
1189
1136
  });
@@ -1219,9 +1166,7 @@ function createScheduledCommand() {
1219
1166
  cmd.command("delete").description("Delete scheduled transaction").argument("<id>", "Scheduled transaction ID").option("-b, --budget <id>", "Budget ID").option("-y, --yes", "Skip confirmation").action(
1220
1167
  withErrorHandling(
1221
1168
  async (id, options) => {
1222
- if (!await confirmDelete("scheduled transaction", options.yes)) {
1223
- return;
1224
- }
1169
+ requireConfirmation("scheduled transaction", options.yes);
1225
1170
  const scheduledTransaction = await client.deleteScheduledTransaction(id, options.budget);
1226
1171
  outputJson({
1227
1172
  message: "Scheduled transaction deleted",
@@ -1272,12 +1217,12 @@ function createPayeesCommand() {
1272
1217
  outputJson(locations);
1273
1218
  })
1274
1219
  );
1275
- 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(
1220
+ 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").option("--type <type>", "Filter by transaction type").option("--last-knowledge <number>", "Last knowledge of server", parseInt).action(
1276
1221
  withErrorHandling(
1277
1222
  async (id, options) => {
1278
1223
  const result = await client.getTransactionsByPayee(id, {
1279
1224
  budgetId: options.budget,
1280
- sinceDate: options.since,
1225
+ sinceDate: options.since ? parseDate(options.since) : void 0,
1281
1226
  type: options.type,
1282
1227
  lastKnowledgeOfServer: options.lastKnowledge
1283
1228
  });
@@ -1300,9 +1245,9 @@ function createMonthsCommand() {
1300
1245
  }
1301
1246
  )
1302
1247
  );
1303
- 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(
1248
+ cmd.command("view").description("View specific month details").argument("<month>", "Budget month (e.g., 2025-07-01)").option("-b, --budget <id>", "Budget ID").action(
1304
1249
  withErrorHandling(async (month, options) => {
1305
- const monthData = await client.getBudgetMonth(month, options.budget);
1250
+ const monthData = await client.getBudgetMonth(parseDate(month), options.budget);
1306
1251
  outputJson(monthData);
1307
1252
  })
1308
1253
  );
@@ -1326,12 +1271,13 @@ function createApiCommand() {
1326
1271
  }
1327
1272
  let data;
1328
1273
  if (options.data) {
1274
+ let parsedData;
1329
1275
  try {
1330
- const parsedData = JSON.parse(options.data);
1331
- data = validateJson(parsedData, ApiDataSchema, "API data");
1276
+ parsedData = JSON.parse(options.data);
1332
1277
  } catch {
1333
1278
  throw new YnabCliError("Invalid JSON in --data parameter", 400);
1334
1279
  }
1280
+ data = validateApiData(parsedData);
1335
1281
  }
1336
1282
  const result = await client.rawApiCall(upperMethod, path, data, options.budget);
1337
1283
  outputJson(result);
@@ -1343,7 +1289,7 @@ function createApiCommand() {
1343
1289
 
1344
1290
  // src/cli.ts
1345
1291
  var program = new Command11();
1346
- program.name("ynab").description("A command-line interface for You Need a Budget (YNAB)").version("2.0.0").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
1292
+ program.name("ynab").description("A command-line interface for You Need a Budget (YNAB)").version("2.1.1").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
1347
1293
  const options = thisCommand.opts();
1348
1294
  setOutputOptions({
1349
1295
  compact: options.compact
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/lib/errors.ts","../src/lib/utils.ts","../src/lib/output.ts","../src/commands/auth.ts","../src/lib/auth.ts","../src/lib/config.ts","../src/lib/prompts.ts","../src/lib/api-client.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 bun\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\ndeclare const __VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('ynab')\n .description('A command-line interface for You Need a Budget (YNAB)')\n .version(__VERSION__)\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 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' ? enhanceRateLimitMessage(detail) : 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 { YnabCliError } from './errors.js';\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 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 (\n isDebtAmountMapField(key) &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n ) {\n const convertedMap: Record<string, unknown> = {};\n for (const [dateKey, amountValue] of Object.entries(value)) {\n convertedMap[dateKey] =\n 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 YnabCliError(`--approved must be 'true' or 'false', got '${value}'`, 400);\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 YnabCliError(\n `Invalid status '${status}'. Must be one of: ${validStatuses.join(', ')}`,\n 400\n );\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>(\n transactions: T[],\n filters: {\n until?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n }\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 for (const field of fieldList) {\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(\n withErrorHandling(async () => {\n const token = await promptForAccessToken();\n await auth.setAccessToken(token);\n client.clearApi();\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 client.clearApi();\n throw error;\n }\n })\n );\n\n cmd\n .command('status')\n .description('Check authentication status')\n .action(\n 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 {\n outputJson({ authenticated: false, message: 'Token exists but is invalid' });\n }\n })\n );\n\n cmd\n .command('logout')\n .description('Remove stored credentials')\n .action(\n withErrorHandling(async () => {\n await auth.logout();\n client.clearApi();\n outputJson({ message: 'Successfully logged out' });\n })\n );\n\n return cmd;\n}\n","import { Entry } from '@napi-rs/keyring';\nimport { config } from './config.js';\n\nconst SERVICE_NAME = 'ynab-cli';\nconst ACCOUNT_NAME = 'access-token';\n\nconst KEYRING_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: bun install -g @stephendolan/ynab-cli\\n' +\n 'Alternatively, use the YNAB_API_KEY environment variable.';\n\nlet keyring: Entry | null | undefined = undefined;\n\nfunction getKeyring(): Entry | null {\n if (keyring !== undefined) {\n return keyring;\n }\n try {\n keyring = new Entry(SERVICE_NAME, ACCOUNT_NAME);\n } catch {\n keyring = null;\n }\n return keyring;\n}\n\nexport function resetKeyringForTesting(): void {\n keyring = undefined;\n}\n\nexport class AuthManager {\n async getAccessToken(): Promise<string | null> {\n const entry = getKeyring();\n if (entry) {\n try {\n return entry.getPassword();\n } catch {\n return null;\n }\n }\n return null;\n }\n\n async setAccessToken(token: string): Promise<void> {\n const entry = getKeyring();\n if (!entry) {\n throw new Error(KEYRING_UNAVAILABLE_ERROR);\n }\n try {\n entry.setPassword(token);\n } catch (error) {\n throw new Error(\n `Failed to store token in keychain: ${error instanceof Error ? error.message : error}\\n\\n` +\n 'On Linux, ensure the Secret Service is running and unlocked.\\n' +\n 'Try: gnome-keyring-daemon --unlock\\n' +\n 'Or use the YNAB_API_KEY environment variable instead.'\n );\n }\n }\n\n async deleteAccessToken(): Promise<boolean> {\n const entry = getKeyring();\n if (entry) {\n return entry.deletePassword();\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 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 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.trim();\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 clearApi(): void {\n this.api = null;\n this.envVarWarningShown = false;\n }\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 = 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 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 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 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(\n accountId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(\n categoryId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(\n payeeId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(transactionData: ynab.PostTransactionsWrapper, 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.createTransaction(id, transactionData);\n return response.data.transaction;\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(id, transactionId, transactionData);\n return response.data.transaction;\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 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 accessToken = (await auth.getAccessToken()) || process.env.YNAB_API_KEY;\n const headers = {\n Authorization: `Bearer ${accessToken}`,\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 { 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(\n withErrorHandling(async () => {\n const user = await client.getUser();\n outputJson(user);\n })\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(\n withErrorHandling(async (options: { includeAccounts?: boolean }) => {\n const result = await client.getBudgets(options.includeAccounts);\n outputJson(result?.budgets);\n })\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(\n withErrorHandling(async (id: string | undefined) => {\n const result = await client.getBudget(id);\n outputJson(result?.budget);\n })\n );\n\n cmd\n .command('settings')\n .description('View budget settings')\n .argument('[id]', 'Budget ID')\n .action(\n withErrorHandling(async (id: string | undefined) => {\n const settings = await client.getBudgetSettings(id);\n outputJson(settings);\n })\n );\n\n cmd\n .command('set-default')\n .description('Set default budget for commands')\n .argument('<id>', 'Budget ID')\n .action(\n 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\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(\n withErrorHandling(async (options: CommandOptions) => {\n const result = await client.getAccounts(options.budget);\n outputJson(result?.accounts);\n })\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const account = await client.getAccount(id, options.budget);\n outputJson(account);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const category = await client.getCategory(id, options.budget);\n outputJson(category);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(\n 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 );\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 {\n isInteractive,\n amountToMilliunits,\n applyTransactionFilters,\n applyFieldSelection,\n type TransactionLike,\n} 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(\n '--status <statuses>',\n 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated for multiple)'\n )\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(\n '--fields <fields>',\n 'Comma-separated list of fields to include (e.g., id,date,amount,memo)'\n )\n .action(\n withErrorHandling(\n async (\n 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 ) => {\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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const transaction = await client.getTransaction(id, options.budget);\n outputJson(transaction);\n })\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(\n withErrorHandling(\n async (\n 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 ) => {\n const shouldPrompt = isInteractive() && !options.amount;\n if (shouldPrompt && !options.account) {\n throw new YnabCliError(\n '--account is required. Interactive mode cannot auto-select an account.',\n 400\n );\n }\n const transactionData = shouldPrompt\n ? { ...(await promptForTransaction()), account_id: options.account }\n : buildTransactionData(options);\n\n const transaction = await client.createTransaction(\n { transaction: transactionData },\n options.budget\n );\n outputJson(transaction);\n }\n )\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(\n withErrorHandling(\n async (id: string, options: TransactionOptions & { budget?: string } & CommandOptions) => {\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 );\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(\n withErrorHandling(\n 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 );\n\n cmd\n .command('import')\n .description('Import transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .action(\n withErrorHandling(async (options: CommandOptions) => {\n const transactionIds = await client.importTransactions(options.budget);\n outputJson({ transaction_ids: transactionIds });\n })\n );\n\n cmd\n .command('split')\n .description(\n 'Split transaction into multiple categories. Amounts should be in dollars (e.g., 10.50).'\n )\n .argument('<id>', 'Transaction ID')\n .requiredOption(\n '--splits <json>',\n 'JSON array of splits with dollar amounts: [{\"amount\": -21.40, \"category_id\": \"xxx\", \"memo\": \"...\"}]'\n )\n .option('-b, --budget <id>', 'Budget ID')\n .option('-f, --force', 'Force update of already-split transactions by deleting and recreating')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: { splits: string; budget?: string; force?: boolean } & CommandOptions\n ) => {\n let parsedSplits;\n try {\n parsedSplits = JSON.parse(options.splits);\n } catch {\n throw new YnabCliError('Invalid JSON in --splits parameter', 400);\n }\n\n const splits = validateJson(parsedSplits, TransactionSplitSchema, 'transaction splits');\n\n const splitsInMilliunits = splits.map((split) => ({\n ...split,\n amount: amountToMilliunits(split.amount),\n }));\n\n const existingTransaction = await client.getTransaction(id, options.budget);\n const isAlreadySplit =\n existingTransaction.subtransactions && existingTransaction.subtransactions.length > 0;\n\n if (isAlreadySplit && !options.force) {\n throw new YnabCliError(\n 'Transaction is already split. YNAB API does not support updating split transactions. ' +\n 'Use --force to delete and recreate the transaction with new splits.',\n 400\n );\n }\n\n if (isAlreadySplit) {\n await client.deleteTransaction(id, options.budget);\n\n const recreatedTransaction = await client.createTransaction(\n {\n transaction: {\n account_id: existingTransaction.account_id,\n date: existingTransaction.date,\n amount: existingTransaction.amount,\n payee_id: existingTransaction.payee_id,\n payee_name: existingTransaction.payee_name,\n category_id: null,\n memo: existingTransaction.memo,\n cleared: existingTransaction.cleared,\n approved: existingTransaction.approved,\n flag_color: existingTransaction.flag_color,\n subtransactions: splitsInMilliunits,\n },\n },\n options.budget\n );\n outputJson(recreatedTransaction);\n } else {\n const transaction = await client.updateTransaction(\n id,\n {\n transaction: {\n category_id: null,\n subtransactions: splitsInMilliunits,\n },\n },\n options.budget\n );\n outputJson(transaction);\n }\n }\n )\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(\n '--status <statuses>',\n 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated)'\n )\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .action(\n withErrorHandling(\n async (\n 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 ) => {\n if (!options.memo && !options.payeeName && options.amount === undefined) {\n throw new YnabCliError(\n 'At least one search criteria required: --memo, --payee-name, or --amount',\n 400\n );\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) => t.memo?.toLowerCase().includes(searchTerm));\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 );\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>(data: unknown, schema: z.ZodSchema<T>, fieldName: string): T {\n try {\n return schema.parse(data);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getScheduledTransactions(\n options.budget,\n options.lastKnowledge\n );\n outputJson(result?.scheduled_transactions);\n }\n )\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const scheduledTransaction = await client.getScheduledTransaction(id, options.budget);\n outputJson(scheduledTransaction);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getPayees(options.budget, options.lastKnowledge);\n outputJson(result?.payees);\n }\n )\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const payee = await client.getPayee(id, options.budget);\n outputJson(payee);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const locations = await client.getPayeeLocationsByPayee(id, options.budget);\n outputJson(locations);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getBudgetMonths(options.budget, options.lastKnowledge);\n outputJson(result?.months);\n }\n )\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(\n withErrorHandling(async (month: string, options: CommandOptions) => {\n const monthData = await client.getBudgetMonth(month, options.budget);\n outputJson(monthData);\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 { 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(\n withErrorHandling(\n 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 {\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 );\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/errors.ts","../src/lib/utils.ts","../src/lib/output.ts","../src/commands/auth.ts","../src/lib/auth.ts","../src/lib/config.ts","../src/lib/api-client.ts","../src/lib/command-utils.ts","../src/commands/user.ts","../src/commands/budgets.ts","../src/commands/accounts.ts","../src/lib/dates.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 bun\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\ndeclare const __VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('ynab')\n .description('A command-line interface for You Need a Budget (YNAB)')\n .version(__VERSION__)\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 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' ? enhanceRateLimitMessage(detail) : 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 { YnabCliError } from './errors.js';\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 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 (\n isDebtAmountMapField(key) &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value)\n ) {\n const convertedMap: Record<string, unknown> = {};\n for (const [dateKey, amountValue] of Object.entries(value)) {\n convertedMap[dateKey] =\n 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 YnabCliError(`--approved must be 'true' or 'false', got '${value}'`, 400);\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 YnabCliError(\n `Invalid status '${status}'. Must be one of: ${validStatuses.join(', ')}`,\n 400\n );\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>(\n transactions: T[],\n filters: {\n until?: string;\n approved?: string;\n status?: string;\n minAmount?: number;\n maxAmount?: number;\n }\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 for (const field of fieldList) {\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 { outputJson } from '../lib/output.js';\nimport { client } from '../lib/api-client.js';\nimport { withErrorHandling } from '../lib/command-utils.js';\nimport { YnabCliError } from '../lib/errors.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 .requiredOption('-t, --token <token>', 'YNAB Personal Access Token')\n .action(\n withErrorHandling(async (options: { token: string }) => {\n const token = options.token.trim();\n if (!token) {\n throw new YnabCliError('Access token cannot be empty', 400);\n }\n await auth.setAccessToken(token);\n client.clearApi();\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 client.clearApi();\n throw error;\n }\n })\n );\n\n cmd\n .command('status')\n .description('Check authentication status')\n .action(\n 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 {\n outputJson({ authenticated: false, message: 'Token exists but is invalid' });\n }\n })\n );\n\n cmd\n .command('logout')\n .description('Remove stored credentials')\n .action(\n withErrorHandling(async () => {\n await auth.logout();\n client.clearApi();\n outputJson({ message: 'Successfully logged out' });\n })\n );\n\n return cmd;\n}\n","import { Entry } from '@napi-rs/keyring';\nimport { config } from './config.js';\n\nconst SERVICE_NAME = 'ynab-cli';\nconst ACCOUNT_NAME = 'access-token';\n\nconst KEYRING_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: bun install -g @stephendolan/ynab-cli\\n' +\n 'Alternatively, use the YNAB_API_KEY environment variable.';\n\nlet keyring: Entry | null | undefined = undefined;\n\nfunction getKeyring(): Entry | null {\n if (keyring !== undefined) {\n return keyring;\n }\n try {\n keyring = new Entry(SERVICE_NAME, ACCOUNT_NAME);\n } catch {\n keyring = null;\n }\n return keyring;\n}\n\nexport function resetKeyringForTesting(): void {\n keyring = undefined;\n}\n\nexport class AuthManager {\n async getAccessToken(): Promise<string | null> {\n const entry = getKeyring();\n if (entry) {\n try {\n return entry.getPassword();\n } catch {\n return null;\n }\n }\n return null;\n }\n\n async setAccessToken(token: string): Promise<void> {\n const entry = getKeyring();\n if (!entry) {\n throw new Error(KEYRING_UNAVAILABLE_ERROR);\n }\n try {\n entry.setPassword(token);\n } catch (error) {\n throw new Error(\n `Failed to store token in keychain: ${error instanceof Error ? error.message : error}\\n\\n` +\n 'On Linux, ensure the Secret Service is running and unlocked.\\n' +\n 'Try: gnome-keyring-daemon --unlock\\n' +\n 'Or use the YNAB_API_KEY environment variable instead.'\n );\n }\n }\n\n async deleteAccessToken(): Promise<boolean> {\n const entry = getKeyring();\n if (entry) {\n return entry.deletePassword();\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 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 * as ynab from 'ynab';\nimport { config } from './config.js';\nimport { YnabCliError, handleYnabError, sanitizeApiError } from './errors.js';\nimport { auth } from './auth.js';\n\ntype TransactionTypeFilter = 'uncategorized' | 'unapproved' | undefined;\n\nexport class YnabClient {\n private api: ynab.API | null = null;\n private envVarWarningShown = false;\n\n clearApi(): void {\n this.api = null;\n this.envVarWarningShown = false;\n }\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 = 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 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 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 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(\n accountId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(\n categoryId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(\n payeeId: string,\n params: {\n budgetId?: string;\n sinceDate?: string;\n type?: string;\n lastKnowledgeOfServer?: number;\n }\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(transactionData: ynab.PostTransactionsWrapper, 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.createTransaction(id, transactionData);\n return response.data.transaction;\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(id, transactionId, transactionData);\n return response.data.transaction;\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 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 accessToken = (await auth.getAccessToken()) || process.env.YNAB_API_KEY;\n const headers = {\n Authorization: `Bearer ${accessToken}`,\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 { handleYnabError, YnabCliError } from './errors.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 function requireConfirmation(itemType: string, confirmed: boolean = false): void {\n if (!confirmed) {\n throw new YnabCliError(\n `Deleting ${itemType} requires --yes flag to confirm`,\n 400\n );\n }\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(\n withErrorHandling(async () => {\n const user = await client.getUser();\n outputJson(user);\n })\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(\n withErrorHandling(async (options: { includeAccounts?: boolean }) => {\n const result = await client.getBudgets(options.includeAccounts);\n outputJson(result?.budgets);\n })\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(\n withErrorHandling(async (id: string | undefined) => {\n const result = await client.getBudget(id);\n outputJson(result?.budget);\n })\n );\n\n cmd\n .command('settings')\n .description('View budget settings')\n .argument('[id]', 'Budget ID')\n .action(\n withErrorHandling(async (id: string | undefined) => {\n const settings = await client.getBudgetSettings(id);\n outputJson(settings);\n })\n );\n\n cmd\n .command('set-default')\n .description('Set default budget for commands')\n .argument('<id>', 'Budget ID')\n .action(\n 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\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 { parseDate } from '../lib/dates.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(\n withErrorHandling(async (options: CommandOptions) => {\n const result = await client.getAccounts(options.budget);\n outputJson(result?.accounts);\n })\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const account = await client.getAccount(id, options.budget);\n outputJson(account);\n })\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')\n .option('--type <type>', 'Filter by transaction type')\n .action(\n withErrorHandling(\n 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 ? parseDate(options.since) : undefined,\n type: options.type,\n });\n outputJson(result?.transactions);\n }\n )\n );\n\n return cmd;\n}\n","import dayjs from 'dayjs';\nimport { YnabCliError } from './errors.js';\n\nexport function parseDate(input: string): string {\n const d = dayjs(input);\n if (!d.isValid()) {\n throw new YnabCliError(`Invalid date: ${input}`, 400);\n }\n return d.format('YYYY-MM-DD');\n}\n\nexport function todayDate(): string {\n return dayjs().format('YYYY-MM-DD');\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 { parseDate } from '../lib/dates.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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const category = await client.getCategory(id, options.budget);\n outputJson(category);\n })\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>', 'Budget month (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(\n withErrorHandling(\n 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 parseDate(options.month),\n id,\n { category: { budgeted: milliunits } },\n options.budget\n );\n outputJson(category);\n }\n )\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')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(\n withErrorHandling(\n 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 ? parseDate(options.since) : undefined,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputJson(result?.transactions);\n }\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 {\n amountToMilliunits,\n applyTransactionFilters,\n applyFieldSelection,\n type TransactionLike,\n} from '../lib/utils.js';\nimport { withErrorHandling, requireConfirmation, buildUpdateObject } from '../lib/command-utils.js';\nimport { validateTransactionSplits } from '../lib/schemas.js';\nimport { parseDate, todayDate } from '../lib/dates.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 ? parseDate(options.date) : todayDate(),\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')\n .option('--until <date>', 'Filter transactions until date')\n .option('--type <type>', 'Filter by transaction type')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option(\n '--status <statuses>',\n 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated for multiple)'\n )\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(\n '--fields <fields>',\n 'Comma-separated list of fields to include (e.g., id,date,amount,memo)'\n )\n .action(\n withErrorHandling(\n async (\n 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 ) => {\n const params = {\n budgetId: options.budget,\n sinceDate: options.since ? parseDate(options.since) : undefined,\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 ? parseDate(options.until) : undefined,\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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const transaction = await client.getTransaction(id, options.budget);\n outputJson(transaction);\n })\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>', 'Transaction date')\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(\n withErrorHandling(\n async (\n 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 ) => {\n const transactionData = buildTransactionData(options);\n const transaction = await client.createTransaction(\n { transaction: transactionData },\n options.budget\n );\n outputJson(transaction);\n }\n )\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>', 'Transaction date')\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(\n withErrorHandling(\n async (id: string, options: TransactionOptions & { budget?: string } & CommandOptions) => {\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 );\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(\n withErrorHandling(\n async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n requireConfirmation('transaction', options.yes);\n const transaction = await client.deleteTransaction(id, options.budget);\n outputJson({ message: 'Transaction deleted', transaction });\n }\n )\n );\n\n cmd\n .command('import')\n .description('Import transactions')\n .option('-b, --budget <id>', 'Budget ID')\n .action(\n withErrorHandling(async (options: CommandOptions) => {\n const transactionIds = await client.importTransactions(options.budget);\n outputJson({ transaction_ids: transactionIds });\n })\n );\n\n cmd\n .command('split')\n .description(\n 'Split transaction into multiple categories. Amounts should be in dollars (e.g., 10.50).'\n )\n .argument('<id>', 'Transaction ID')\n .requiredOption(\n '--splits <json>',\n 'JSON array of splits with dollar amounts: [{\"amount\": -21.40, \"category_id\": \"xxx\", \"memo\": \"...\"}]'\n )\n .option('-b, --budget <id>', 'Budget ID')\n .option('-f, --force', 'Force update of already-split transactions by deleting and recreating')\n .action(\n withErrorHandling(\n async (\n id: string,\n options: { splits: string; budget?: string; force?: boolean } & CommandOptions\n ) => {\n let parsedSplits;\n try {\n parsedSplits = JSON.parse(options.splits);\n } catch {\n throw new YnabCliError('Invalid JSON in --splits parameter', 400);\n }\n\n const splits = validateTransactionSplits(parsedSplits);\n\n const splitsInMilliunits = splits.map((split) => ({\n ...split,\n amount: amountToMilliunits(split.amount),\n }));\n\n const existingTransaction = await client.getTransaction(id, options.budget);\n const isAlreadySplit =\n existingTransaction.subtransactions && existingTransaction.subtransactions.length > 0;\n\n if (isAlreadySplit && !options.force) {\n throw new YnabCliError(\n 'Transaction is already split. YNAB API does not support updating split transactions. ' +\n 'Use --force to delete and recreate the transaction with new splits.',\n 400\n );\n }\n\n if (isAlreadySplit) {\n await client.deleteTransaction(id, options.budget);\n\n const recreatedTransaction = await client.createTransaction(\n {\n transaction: {\n account_id: existingTransaction.account_id,\n date: existingTransaction.date,\n amount: existingTransaction.amount,\n payee_id: existingTransaction.payee_id,\n payee_name: existingTransaction.payee_name,\n category_id: null,\n memo: existingTransaction.memo,\n cleared: existingTransaction.cleared,\n approved: existingTransaction.approved,\n flag_color: existingTransaction.flag_color,\n subtransactions: splitsInMilliunits,\n },\n },\n options.budget\n );\n outputJson(recreatedTransaction);\n } else {\n const transaction = await client.updateTransaction(\n id,\n {\n transaction: {\n category_id: null,\n subtransactions: splitsInMilliunits,\n },\n },\n options.budget\n );\n outputJson(transaction);\n }\n }\n )\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')\n .option('--until <date>', 'Search transactions until date')\n .option('--approved <value>', 'Filter by approval status: true or false')\n .option(\n '--status <statuses>',\n 'Filter by cleared status: cleared, uncleared, reconciled (comma-separated)'\n )\n .option('--fields <fields>', 'Comma-separated list of fields to include')\n .action(\n withErrorHandling(\n async (\n 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 ) => {\n if (!options.memo && !options.payeeName && options.amount === undefined) {\n throw new YnabCliError(\n 'At least one search criteria required: --memo, --payee-name, or --amount',\n 400\n );\n }\n\n const params = {\n budgetId: options.budget,\n sinceDate: options.since ? parseDate(options.since) : undefined,\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) => t.memo?.toLowerCase().includes(searchTerm));\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 ? parseDate(options.until) : undefined,\n approved: options.approved,\n status: options.status,\n });\n\n const filteredTransactions = applyFieldSelection(transactions, options.fields);\n\n outputJson(filteredTransactions);\n }\n )\n );\n\n return cmd;\n}\n","import { YnabCliError } from './errors.js';\n\nexport interface TransactionSplit {\n amount: number;\n category_id?: string | null;\n memo?: string;\n payee_id?: string;\n}\n\nexport function validateTransactionSplits(data: unknown): TransactionSplit[] {\n if (!Array.isArray(data)) {\n throw new YnabCliError('Transaction splits must be an array', 400);\n }\n\n return data.map((item, index) => {\n if (typeof item !== 'object' || item === null) {\n throw new YnabCliError(`Split at index ${index} must be an object`, 400);\n }\n\n const split = item as Record<string, unknown>;\n\n if (typeof split.amount !== 'number') {\n throw new YnabCliError(`Split at index ${index} must have a numeric amount`, 400);\n }\n\n return {\n amount: split.amount,\n category_id: split.category_id as string | null | undefined,\n memo: split.memo as string | undefined,\n payee_id: split.payee_id as string | undefined,\n };\n });\n}\n\nexport function validateApiData(data: unknown): Record<string, unknown> {\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n throw new YnabCliError('API data must be an object', 400);\n }\n return data as Record<string, unknown>;\n}\n","import { Command } from 'commander';\nimport { client } from '../lib/api-client.js';\nimport { outputJson } from '../lib/output.js';\nimport { withErrorHandling, requireConfirmation } 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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getScheduledTransactions(\n options.budget,\n options.lastKnowledge\n );\n outputJson(result?.scheduled_transactions);\n }\n )\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const scheduledTransaction = await client.getScheduledTransaction(id, options.budget);\n outputJson(scheduledTransaction);\n })\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(\n withErrorHandling(\n async (id: string, options: { budget?: string; yes?: boolean } & CommandOptions) => {\n requireConfirmation('scheduled transaction', options.yes);\n const scheduledTransaction = await client.deleteScheduledTransaction(id, options.budget);\n outputJson({\n message: 'Scheduled transaction deleted',\n scheduled_transaction: scheduledTransaction,\n });\n }\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 { parseDate } from '../lib/dates.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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getPayees(options.budget, options.lastKnowledge);\n outputJson(result?.payees);\n }\n )\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const payee = await client.getPayee(id, options.budget);\n outputJson(payee);\n })\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(\n withErrorHandling(\n 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 );\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(\n withErrorHandling(async (id: string, options: CommandOptions) => {\n const locations = await client.getPayeeLocationsByPayee(id, options.budget);\n outputJson(locations);\n })\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')\n .option('--type <type>', 'Filter by transaction type')\n .option('--last-knowledge <number>', 'Last knowledge of server', parseInt)\n .action(\n withErrorHandling(\n 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 ? parseDate(options.since) : undefined,\n type: options.type,\n lastKnowledgeOfServer: options.lastKnowledge,\n });\n outputJson(result?.transactions);\n }\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 { parseDate } from '../lib/dates.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(\n withErrorHandling(\n async (options: { budget?: string; lastKnowledge?: number } & CommandOptions) => {\n const result = await client.getBudgetMonths(options.budget, options.lastKnowledge);\n outputJson(result?.months);\n }\n )\n );\n\n cmd\n .command('view')\n .description('View specific month details')\n .argument('<month>', 'Budget month (e.g., 2025-07-01)')\n .option('-b, --budget <id>', 'Budget ID')\n .action(\n withErrorHandling(async (month: string, options: CommandOptions) => {\n const monthData = await client.getBudgetMonth(parseDate(month), options.budget);\n outputJson(monthData);\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 { validateApiData } 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(\n withErrorHandling(\n 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 let parsedData: unknown;\n try {\n parsedData = JSON.parse(options.data);\n } catch {\n throw new YnabCliError('Invalid JSON in --data parameter', 400);\n }\n data = validateApiData(parsedData);\n }\n\n const result = await client.rawApiCall(upperMethod, path, data, options.budget);\n outputJson(result);\n }\n )\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stephendolan/ynab-cli",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "A command-line interface for You Need a Budget (YNAB)",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -46,18 +46,13 @@
46
46
  ],
47
47
  "dependencies": {
48
48
  "@napi-rs/keyring": "^1.2.0",
49
- "chalk": "^5.3.0",
50
49
  "commander": "^12.0.0",
51
50
  "conf": "^12.0.0",
52
- "date-fns": "^3.0.0",
53
- "dotenv": "^16.4.0",
54
- "inquirer": "^9.2.0",
55
- "ynab": "^2.10.0",
56
- "zod": "^3.22.0"
51
+ "dayjs": "^1.11.19",
52
+ "ynab": "^2.10.0"
57
53
  },
58
54
  "devDependencies": {
59
55
  "@biomejs/biome": "^1.9.4",
60
- "@types/inquirer": "^9.0.0",
61
56
  "@types/node": "^20.0.0",
62
57
  "oxlint": "^0.16.0",
63
58
  "tsup": "^8.0.0",