@actual-app/api 26.6.0 → 26.7.0-nightly.20260602

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/index.js CHANGED
@@ -17806,6 +17806,7 @@ var schema = {
17806
17806
  show_hidden: f("integer", { default: 0 }),
17807
17807
  show_uncategorized: f("integer", { default: 0 }),
17808
17808
  trim_intervals: f("integer", { default: 0 }),
17809
+ show_trend_lines: f("integer", { default: 0 }),
17809
17810
  include_current: f("integer", { default: 0 }),
17810
17811
  graph_type: f("string", { default: "BarGraph" }),
17811
17812
  conditions: f("json"),
@@ -18983,6 +18984,14 @@ var currencies = [
18983
18984
  numberFormat: "comma-dot-in",
18984
18985
  symbolFirst: true
18985
18986
  },
18987
+ {
18988
+ code: "IRR",
18989
+ name: "Iranian Rial",
18990
+ symbol: "﷼",
18991
+ decimalPlaces: 0,
18992
+ numberFormat: "comma-dot",
18993
+ symbolFirst: false
18994
+ },
18986
18995
  {
18987
18996
  code: "JMD",
18988
18997
  name: "Jamaican Dollar",
@@ -19039,6 +19048,14 @@ var currencies = [
19039
19048
  numberFormat: "comma-dot",
19040
19049
  symbolFirst: true
19041
19050
  },
19051
+ {
19052
+ code: "PKR",
19053
+ name: "Pakistani Rupee",
19054
+ symbol: "Rs.",
19055
+ decimalPlaces: 2,
19056
+ numberFormat: "comma-dot",
19057
+ symbolFirst: true
19058
+ },
19042
19059
  {
19043
19060
  code: "PLN",
19044
19061
  name: "Polish Złoty",
@@ -107616,7 +107633,8 @@ var TYPE_INFO = {
107616
107633
  "isNot",
107617
107634
  "doesNotContain",
107618
107635
  "notOneOf",
107619
- "hasTags"
107636
+ "hasTags",
107637
+ "hasAnyTag"
107620
107638
  ],
107621
107639
  nullable: true
107622
107640
  },
@@ -107640,7 +107658,7 @@ var TYPE_INFO = {
107640
107658
  var FIELD_INFO = {
107641
107659
  imported_payee: {
107642
107660
  type: "string",
107643
- disallowedOps: new Set(["hasTags"])
107661
+ disallowedOps: new Set(["hasTags", "hasAnyTag"])
107644
107662
  },
107645
107663
  payee: {
107646
107664
  type: "id",
@@ -111005,6 +111023,7 @@ var OP_SCORES = {
111005
111023
  doesNotContain: 0,
111006
111024
  matches: 0,
111007
111025
  hasTags: 0,
111026
+ hasAnyTag: 0,
111008
111027
  onBudget: 0,
111009
111028
  offBudget: 0
111010
111029
  };
@@ -111397,6 +111416,21 @@ var Action = class {
111397
111416
  }
111398
111417
  };
111399
111418
  //#endregion
111419
+ //#region ../loot-core/src/shared/tags.ts
111420
+ function extractTagsForFilter(value) {
111421
+ if (!value) return [];
111422
+ const tagValues = [];
111423
+ const seenTags = /* @__PURE__ */ new Set();
111424
+ for (const [_, tag] of value.matchAll(/#*([^#\s]+)/g)) {
111425
+ const tagWithHash = "#" + tag;
111426
+ if (!seenTags.has(tagWithHash)) {
111427
+ seenTags.add(tagWithHash);
111428
+ tagValues.push(tagWithHash);
111429
+ }
111430
+ }
111431
+ return tagValues;
111432
+ }
111433
+ //#endregion
111400
111434
  //#region ../loot-core/src/server/rules/condition.ts
111401
111435
  var CONDITION_TYPES = {
111402
111436
  date: {
@@ -111448,7 +111482,8 @@ var CONDITION_TYPES = {
111448
111482
  "isNot",
111449
111483
  "doesNotContain",
111450
111484
  "notOneOf",
111451
- "hasTags"
111485
+ "hasTags",
111486
+ "hasAnyTag"
111452
111487
  ],
111453
111488
  nullable: true,
111454
111489
  parse(op, value, fieldName) {
@@ -111457,8 +111492,8 @@ var CONDITION_TYPES = {
111457
111492
  return value.filter(Boolean).map((val) => val.toLowerCase());
111458
111493
  }
111459
111494
  assert(typeof value === "string", "not-string", `Invalid string value (field: ${fieldName})`);
111460
- if (op === "contains" || op === "matches" || op === "doesNotContain" || op === "hasTags") assert(value.length > 0, "no-empty-string", `${op} must have non-empty string (field: ${fieldName})`);
111461
- if (op === "hasTags") return value;
111495
+ if (op === "contains" || op === "matches" || op === "doesNotContain" || op === "hasTags" || op === "hasAnyTag") assert(value.length > 0, "no-empty-string", `${op} must have non-empty string (field: ${fieldName})`);
111496
+ if (op === "hasTags" || op === "hasAnyTag") return value;
111462
111497
  return value.toLowerCase();
111463
111498
  }
111464
111499
  },
@@ -111582,7 +111617,19 @@ var Condition = class {
111582
111617
  return this.value.indexOf(fieldValue) !== -1;
111583
111618
  case "hasTags":
111584
111619
  if (fieldValue === null) return false;
111585
- return String(fieldValue).indexOf(this.value) !== -1;
111620
+ const normalizedFieldValue = String(fieldValue);
111621
+ return !extractTagsForFilter(this.value).some((tag) => {
111622
+ const escapedTag = tag.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
111623
+ return !new RegExp(`(?<!#)${escapedTag}([\\s#]|$)`).test(normalizedFieldValue);
111624
+ });
111625
+ case "hasAnyTag": {
111626
+ if (fieldValue === null) return false;
111627
+ const normalizedFieldValue = String(fieldValue);
111628
+ return extractTagsForFilter(this.value).some((tag) => {
111629
+ const escapedTag = tag.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
111630
+ return new RegExp(`(?<!#)${escapedTag}([\\s#]|$)`).test(normalizedFieldValue);
111631
+ });
111632
+ }
111586
111633
  case "notOneOf":
111587
111634
  if (fieldValue === null) return false;
111588
111635
  return this.value.indexOf(fieldValue) === -1;
@@ -112355,7 +112402,7 @@ function conditionsToAQL(conditions, { recurDateBounds = 100, applySpecialCases
112355
112402
  }
112356
112403
  return { amount: { [aqlOp]: value } };
112357
112404
  } else if (type === "string") return { [field]: {
112358
- $transform: op !== "hasTags" ? "$lower" : void 0,
112405
+ $transform: !["hasTags", "hasAnyTag"].includes(op) ? "$lower" : void 0,
112359
112406
  [aqlOp]: value
112360
112407
  } };
112361
112408
  else if (type === "date") return { [field]: { [aqlOp]: value.date } };
@@ -112409,18 +112456,17 @@ function conditionsToAQL(conditions, { recurDateBounds = 100, applySpecialCases
112409
112456
  if (values.length === 0) return { id: null };
112410
112457
  return { $or: values.map((v) => apply(field, "$eq", v)) };
112411
112458
  case "hasTags": {
112412
- const tagValues = [];
112413
- const seenTags = /* @__PURE__ */ new Set();
112414
- for (const [_, tag] of value.matchAll(/(?<!#)(#[^#\s]+)/g)) if (!seenTags.has(tag)) {
112415
- seenTags.add(tag);
112416
- tagValues.push(tag);
112417
- }
112459
+ const tagValues = extractTagsForFilter(value);
112418
112460
  if (tagValues.length === 0) return { id: null };
112419
112461
  return { $and: tagValues.map((v) => {
112420
112462
  const pattern = `(?<!#)${v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\$/g, "[$]")}([\\s#]|$)`;
112421
112463
  return apply(field, "$regexp", pattern);
112422
112464
  }) };
112423
112465
  }
112466
+ case "hasAnyTag": return { $or: extractTagsForFilter(value).map((v) => {
112467
+ const pattern = `(?<!#)${v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\$/g, "[$]")}([\\s#]|$)`;
112468
+ return apply(field, "$regexp", pattern);
112469
+ }) };
112424
112470
  case "notOneOf":
112425
112471
  const notValues = value;
112426
112472
  if (notValues.length === 0) return { id: null };
@@ -116811,6 +116857,9 @@ async function checkIfScheduleExists(name, scheduleId) {
116811
116857
  if (scheduleId) return idForName["id"] !== scheduleId;
116812
116858
  return true;
116813
116859
  }
116860
+ function normalizeScheduleName(name) {
116861
+ return name?.trim() || null;
116862
+ }
116814
116863
  async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116815
116864
  const scheduleId = schedule?.id || v4();
116816
116865
  const { date: dateCond } = extractScheduleConds(conditions);
@@ -116818,9 +116867,15 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116818
116867
  if (dateCond.value == null) throw new Error("Date is required");
116819
116868
  const nextDate = getNextDate(dateCond);
116820
116869
  const nextDateRepr = nextDate ? toDateRepr(nextDate) : null;
116821
- if (schedule) if (schedule.name) {
116822
- if (await checkIfScheduleExists(schedule.name, scheduleId)) throw new Error("Cannot create schedules with the same name");
116823
- } else schedule.name = null;
116870
+ const scheduleFields = schedule && {
116871
+ ...schedule,
116872
+ name: normalizeScheduleName(schedule.name)
116873
+ };
116874
+ if (scheduleFields) {
116875
+ if (scheduleFields.name) {
116876
+ if (await checkIfScheduleExists(scheduleFields.name, scheduleId)) throw new Error("Cannot create schedules with the same name");
116877
+ }
116878
+ }
116824
116879
  const ruleId = await insertRule({
116825
116880
  stage: null,
116826
116881
  conditionsOp: "and",
@@ -116839,7 +116894,7 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116839
116894
  base_next_date_ts: now
116840
116895
  });
116841
116896
  await insertWithSchema("schedules", {
116842
- ...schedule,
116897
+ ...scheduleFields,
116843
116898
  id: scheduleId,
116844
116899
  rule: ruleId
116845
116900
  });
@@ -116847,6 +116902,11 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116847
116902
  }
116848
116903
  async function updateSchedule$1({ schedule, conditions, resetNextDate }) {
116849
116904
  if (schedule.rule) throw new Error("You cannot change the rule of a schedule");
116905
+ const scheduleFields = { ...schedule };
116906
+ if ("name" in scheduleFields) {
116907
+ scheduleFields.name = normalizeScheduleName(scheduleFields.name);
116908
+ if (scheduleFields.name && await checkIfScheduleExists(scheduleFields.name, scheduleFields.id)) throw new Error("Cannot update schedules with the same name");
116909
+ }
116850
116910
  let rule;
116851
116911
  if (conditions) {
116852
116912
  const { date: dateCond } = extractScheduleConds(conditions);
@@ -116872,9 +116932,9 @@ async function updateSchedule$1({ schedule, conditions, resetNextDate }) {
116872
116932
  id: schedule.id,
116873
116933
  reset: true
116874
116934
  });
116875
- await updateWithSchema("schedules", schedule);
116935
+ await updateWithSchema("schedules", scheduleFields);
116876
116936
  });
116877
- return schedule.id;
116937
+ return scheduleFields.id;
116878
116938
  }
116879
116939
  async function deleteSchedule$1({ id }) {
116880
116940
  const { data: ruleId } = await aqlQuery$1(q$1("schedules").filter({ id }).calculate("rule"));
@@ -125515,6 +125575,7 @@ var reportModel = {
125515
125575
  showHiddenCategories: row.show_hidden === 1,
125516
125576
  showUncategorized: row.show_uncategorized === 1,
125517
125577
  trimIntervals: row.trim_intervals === 1,
125578
+ showTrendLines: row.show_trend_lines === 1,
125518
125579
  includeCurrentInterval: row.include_current === 1,
125519
125580
  graphType: row.graph_type,
125520
125581
  conditions: row.conditions ?? [],
@@ -125540,6 +125601,7 @@ var reportModel = {
125540
125601
  show_hidden: report.showHiddenCategories ? 1 : 0,
125541
125602
  show_uncategorized: report.showUncategorized ? 1 : 0,
125542
125603
  trim_intervals: report.trimIntervals ? 1 : 0,
125604
+ show_trend_lines: report.showTrendLines ? 1 : 0,
125543
125605
  include_current: report.includeCurrentInterval ? 1 : 0,
125544
125606
  graph_type: report.graphType,
125545
125607
  conditions: report.conditions,