@actual-app/api 6.7.0 → 6.7.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.
@@ -12133,6 +12133,66 @@
12133
12133
  }
12134
12134
  /***/
12135
12135
  }),
12136
+ /***/ "./node_modules/date-fns/esm/endOfWeek/index.js":
12137
+ /*!******************************************************!*\
12138
+ !*** ./node_modules/date-fns/esm/endOfWeek/index.js ***!
12139
+ \******************************************************/
12140
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12141
+ "use strict";
12142
+ __webpack_require__.r(__webpack_exports__);
12143
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
12144
+ /* harmony export */ "default": () => ( /* binding */endOfWeek)
12145
+ /* harmony export */
12146
+ });
12147
+ /* harmony import */ var _lib_defaultOptions_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../_lib/defaultOptions/index.js */ "./node_modules/date-fns/esm/_lib/defaultOptions/index.js");
12148
+ /* harmony import */ var _toDate_index_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../toDate/index.js */ "./node_modules/date-fns/esm/toDate/index.js");
12149
+ /* harmony import */ var _lib_toInteger_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../_lib/toInteger/index.js */ "./node_modules/date-fns/esm/_lib/toInteger/index.js");
12150
+ /* harmony import */ var _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../_lib/requiredArgs/index.js */ "./node_modules/date-fns/esm/_lib/requiredArgs/index.js");
12151
+ /**
12152
+ * @name endOfWeek
12153
+ * @category Week Helpers
12154
+ * @summary Return the end of a week for the given date.
12155
+ *
12156
+ * @description
12157
+ * Return the end of a week for the given date.
12158
+ * The result will be in the local timezone.
12159
+ *
12160
+ * @param {Date|Number} date - the original date
12161
+ * @param {Object} [options] - an object with options.
12162
+ * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
12163
+ * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
12164
+ * @returns {Date} the end of a week
12165
+ * @throws {TypeError} 1 argument required
12166
+ * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
12167
+ *
12168
+ * @example
12169
+ * // The end of a week for 2 September 2014 11:55:00:
12170
+ * const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0))
12171
+ * //=> Sat Sep 06 2014 23:59:59.999
12172
+ *
12173
+ * @example
12174
+ * // If the week starts on Monday, the end of the week for 2 September 2014 11:55:00:
12175
+ * const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
12176
+ * //=> Sun Sep 07 2014 23:59:59.999
12177
+ */
12178
+ function endOfWeek(dirtyDate, options) {
12179
+ var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;
12180
+ (0, _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__["default"])(1, arguments);
12181
+ var defaultOptions = (0, _lib_defaultOptions_index_js__WEBPACK_IMPORTED_MODULE_1__.getDefaultOptions)();
12182
+ var weekStartsOn = (0, _lib_toInteger_index_js__WEBPACK_IMPORTED_MODULE_2__["default"])((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0);
12183
+ // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
12184
+ if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
12185
+ throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
12186
+ }
12187
+ var date = (0, _toDate_index_js__WEBPACK_IMPORTED_MODULE_3__["default"])(dirtyDate);
12188
+ var day = date.getDay();
12189
+ var diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
12190
+ date.setDate(date.getDate() + diff);
12191
+ date.setHours(23, 59, 59, 999);
12192
+ return date;
12193
+ }
12194
+ /***/
12195
+ }),
12136
12196
  /***/ "./node_modules/date-fns/esm/format/index.js":
12137
12197
  /*!***************************************************!*\
12138
12198
  !*** ./node_modules/date-fns/esm/format/index.js ***!
@@ -17359,6 +17419,66 @@
17359
17419
  }
17360
17420
  /***/
17361
17421
  }),
17422
+ /***/ "./node_modules/date-fns/esm/startOfWeek/index.js":
17423
+ /*!********************************************************!*\
17424
+ !*** ./node_modules/date-fns/esm/startOfWeek/index.js ***!
17425
+ \********************************************************/
17426
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
17427
+ "use strict";
17428
+ __webpack_require__.r(__webpack_exports__);
17429
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
17430
+ /* harmony export */ "default": () => ( /* binding */startOfWeek)
17431
+ /* harmony export */
17432
+ });
17433
+ /* harmony import */ var _toDate_index_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../toDate/index.js */ "./node_modules/date-fns/esm/toDate/index.js");
17434
+ /* harmony import */ var _lib_toInteger_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../_lib/toInteger/index.js */ "./node_modules/date-fns/esm/_lib/toInteger/index.js");
17435
+ /* harmony import */ var _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../_lib/requiredArgs/index.js */ "./node_modules/date-fns/esm/_lib/requiredArgs/index.js");
17436
+ /* harmony import */ var _lib_defaultOptions_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../_lib/defaultOptions/index.js */ "./node_modules/date-fns/esm/_lib/defaultOptions/index.js");
17437
+ /**
17438
+ * @name startOfWeek
17439
+ * @category Week Helpers
17440
+ * @summary Return the start of a week for the given date.
17441
+ *
17442
+ * @description
17443
+ * Return the start of a week for the given date.
17444
+ * The result will be in the local timezone.
17445
+ *
17446
+ * @param {Date|Number} date - the original date
17447
+ * @param {Object} [options] - an object with options.
17448
+ * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
17449
+ * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
17450
+ * @returns {Date} the start of a week
17451
+ * @throws {TypeError} 1 argument required
17452
+ * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
17453
+ *
17454
+ * @example
17455
+ * // The start of a week for 2 September 2014 11:55:00:
17456
+ * const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0))
17457
+ * //=> Sun Aug 31 2014 00:00:00
17458
+ *
17459
+ * @example
17460
+ * // If the week starts on Monday, the start of the week for 2 September 2014 11:55:00:
17461
+ * const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
17462
+ * //=> Mon Sep 01 2014 00:00:00
17463
+ */
17464
+ function startOfWeek(dirtyDate, options) {
17465
+ var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;
17466
+ (0, _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__["default"])(1, arguments);
17467
+ var defaultOptions = (0, _lib_defaultOptions_index_js__WEBPACK_IMPORTED_MODULE_1__.getDefaultOptions)();
17468
+ var weekStartsOn = (0, _lib_toInteger_index_js__WEBPACK_IMPORTED_MODULE_2__["default"])((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0);
17469
+ // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
17470
+ if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
17471
+ throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
17472
+ }
17473
+ var date = (0, _toDate_index_js__WEBPACK_IMPORTED_MODULE_3__["default"])(dirtyDate);
17474
+ var day = date.getDay();
17475
+ var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
17476
+ date.setDate(date.getDate() - diff);
17477
+ date.setHours(0, 0, 0, 0);
17478
+ return date;
17479
+ }
17480
+ /***/
17481
+ }),
17362
17482
  /***/ "./node_modules/date-fns/esm/subDays/index.js":
17363
17483
  /*!****************************************************!*\
17364
17484
  !*** ./node_modules/date-fns/esm/subDays/index.js ***!
@@ -31226,124 +31346,27 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31226
31346
  "use strict";
31227
31347
  __webpack_require__.r(__webpack_exports__);
31228
31348
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
31229
- /* harmony export */ addAccounts: () => ( /* binding */addAccounts),
31230
- /* harmony export */ addGoCardlessAccounts: () => ( /* binding */addGoCardlessAccounts),
31231
- /* harmony export */ findOrCreateBank: () => ( /* binding */findOrCreateBank),
31232
- /* harmony export */ handoffPublicToken: () => ( /* binding */handoffPublicToken)
31349
+ /* harmony export */ findOrCreateBank: () => ( /* binding */findOrCreateBank)
31233
31350
  /* harmony export */
31234
31351
  });
31235
- /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
31236
- /* harmony import */ var _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../platform/server/asyncStorage */ "./packages/loot-core/src/platform/server/asyncStorage/index.electron.ts");
31237
- /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
31238
- /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
31239
- /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
31240
- /* harmony import */ var _post__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../post */ "./packages/loot-core/src/server/post.ts");
31241
- /* harmony import */ var _server_config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../server-config */ "./packages/loot-core/src/server/server-config.ts");
31242
- /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./sync */ "./packages/loot-core/src/server/accounts/sync.ts");
31352
+ /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
31353
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
31243
31354
  // @ts-strict-ignore
31244
- async function handoffPublicToken(institution, publicToken) {
31245
- const [[, userId], [, key]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.multiGet([
31246
- 'user-id',
31247
- 'user-key'
31248
- ]);
31249
- if (institution == null || !institution.institution_id || !institution.name) {
31250
- throw new Error('Invalid institution object');
31251
- }
31252
- const id = (0, uuid__WEBPACK_IMPORTED_MODULE_7__["default"])();
31253
- // Make sure to generate an access token first before inserting it
31254
- // into our local database in case it fails
31255
- await (0, _post__WEBPACK_IMPORTED_MODULE_4__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_5__.getServer)().PLAID_SERVER + '/handoff_public_token', {
31256
- userId,
31257
- key,
31258
- item_id: id,
31259
- public_token: publicToken
31260
- });
31261
- await (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.runMutator)(() => _db__WEBPACK_IMPORTED_MODULE_2__.insertWithUUID('banks', {
31262
- id,
31263
- bank_id: institution.institution_id,
31264
- name: institution.name
31265
- }));
31266
- return id;
31267
- }
31268
31355
  async function findOrCreateBank(institution, requisitionId) {
31269
- const bank = await _db__WEBPACK_IMPORTED_MODULE_2__.first('SELECT id, bank_id, name FROM banks WHERE bank_id = ?', [
31356
+ const bank = await _db__WEBPACK_IMPORTED_MODULE_0__.first('SELECT id, bank_id, name FROM banks WHERE bank_id = ?', [
31270
31357
  requisitionId
31271
31358
  ]);
31272
31359
  if (bank) {
31273
31360
  return bank;
31274
31361
  }
31275
31362
  const bankData = {
31276
- id: (0, uuid__WEBPACK_IMPORTED_MODULE_7__["default"])(),
31363
+ id: (0, uuid__WEBPACK_IMPORTED_MODULE_1__["default"])(),
31277
31364
  bank_id: requisitionId,
31278
31365
  name: institution.name
31279
31366
  };
31280
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertWithUUID('banks', bankData);
31367
+ await _db__WEBPACK_IMPORTED_MODULE_0__.insertWithUUID('banks', bankData);
31281
31368
  return bankData;
31282
31369
  }
31283
- async function addAccounts(bankId, accountIds, offbudgetIds = []) {
31284
- const [[, userId], [, userKey]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.multiGet([
31285
- 'user-id',
31286
- 'user-key'
31287
- ]);
31288
- // Get all the available accounts
31289
- let accounts = await _sync__WEBPACK_IMPORTED_MODULE_6__.getAccounts(userId, userKey, bankId);
31290
- // Only add the selected accounts
31291
- accounts = accounts.filter((acct) => accountIds.includes(acct.account_id));
31292
- return Promise.all(accounts.map(async (acct) => {
31293
- const id = await (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.runMutator)(async () => {
31294
- const id = await _db__WEBPACK_IMPORTED_MODULE_2__.insertAccount({
31295
- account_id: acct.account_id,
31296
- name: acct.name,
31297
- official_name: acct.official_name,
31298
- balance_current: (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(acct.balances.current),
31299
- mask: acct.mask,
31300
- bank: bankId,
31301
- offbudget: offbudgetIds.includes(acct.account_id) ? 1 : 0
31302
- });
31303
- // Create a transfer payee
31304
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertPayee({
31305
- name: '',
31306
- transfer_acct: id
31307
- });
31308
- return id;
31309
- });
31310
- // Do an initial sync
31311
- await _sync__WEBPACK_IMPORTED_MODULE_6__.syncAccount(userId, userKey, id, acct.account_id, bankId);
31312
- return id;
31313
- }));
31314
- }
31315
- async function addGoCardlessAccounts(bankId, accountIds, offbudgetIds = []) {
31316
- const [[, userId], [, userKey]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.multiGet([
31317
- 'user-id',
31318
- 'user-key'
31319
- ]);
31320
- // Get all the available accounts
31321
- let accounts = await _sync__WEBPACK_IMPORTED_MODULE_6__.getGoCardlessAccounts(userId, userKey, bankId);
31322
- // Only add the selected accounts
31323
- accounts = accounts.filter((acct) => accountIds.includes(acct.account_id));
31324
- return Promise.all(accounts.map(async (acct) => {
31325
- const id = await (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.runMutator)(async () => {
31326
- const id = await _db__WEBPACK_IMPORTED_MODULE_2__.insertAccount({
31327
- account_id: acct.account_id,
31328
- name: acct.name,
31329
- official_name: acct.official_name,
31330
- balance_current: (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(acct.balances.current),
31331
- mask: acct.mask,
31332
- bank: bankId,
31333
- offbudget: offbudgetIds.includes(acct.account_id) ? 1 : 0
31334
- });
31335
- // Create a transfer payee
31336
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertPayee({
31337
- name: '',
31338
- transfer_acct: id
31339
- });
31340
- return id;
31341
- });
31342
- // Do an initial sync
31343
- await _sync__WEBPACK_IMPORTED_MODULE_6__.syncExternalAccount(userId, userKey, id, acct.account_id, bankId);
31344
- return id;
31345
- }));
31346
- }
31347
31370
  /***/
31348
31371
  }),
31349
31372
  /***/ "./packages/loot-core/src/server/accounts/ofx2json.ts":
@@ -31583,7 +31606,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31583
31606
  payee_name: trans.payee,
31584
31607
  imported_payee: trans.payee,
31585
31608
  notes: trans.memo || null
31586
- }))
31609
+ })).filter((trans) => trans.date != null && trans.amount != null)
31587
31610
  };
31588
31611
  }
31589
31612
  async function parseOFX(filepath, options) {
@@ -32284,7 +32307,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32284
32307
  update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(update);
32285
32308
  }
32286
32309
  }
32287
- // The split index 0 is reserved for "Before split" actions.
32310
+ // The split index 0 is reserved for "Apply to all" actions.
32288
32311
  // Remove that entry from the subtransactions.
32289
32312
  update.subtransactions = update.subtransactions.slice(1);
32290
32313
  return update;
@@ -32595,19 +32618,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32595
32618
  __webpack_require__.r(__webpack_exports__);
32596
32619
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
32597
32620
  /* harmony export */ addTransactions: () => ( /* binding */addTransactions),
32598
- /* harmony export */ fromPlaid: () => ( /* binding */fromPlaid),
32599
- /* harmony export */ getAccounts: () => ( /* binding */getAccounts),
32600
32621
  /* harmony export */ getGoCardlessAccounts: () => ( /* binding */getGoCardlessAccounts),
32601
- /* harmony export */ reconcileExternalTransactions: () => ( /* binding */reconcileExternalTransactions),
32602
32622
  /* harmony export */ reconcileTransactions: () => ( /* binding */reconcileTransactions),
32603
- /* harmony export */ syncAccount: () => ( /* binding */syncAccount),
32604
- /* harmony export */ syncExternalAccount: () => ( /* binding */syncExternalAccount)
32623
+ /* harmony export */ syncAccount: () => ( /* binding */syncAccount)
32605
32624
  /* harmony export */
32606
32625
  });
32607
32626
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInMilliseconds/index.js");
32608
32627
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
32609
32628
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/max/index.js");
32610
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/format/index.js");
32611
32629
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
32612
32630
  /* harmony import */ var _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../platform/server/asyncStorage */ "./packages/loot-core/src/platform/server/asyncStorage/index.electron.ts");
32613
32631
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
@@ -32623,8 +32641,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32623
32641
  /* harmony import */ var _transaction_rules__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./transaction-rules */ "./packages/loot-core/src/server/accounts/transaction-rules.ts");
32624
32642
  /* harmony import */ var _transactions__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./transactions */ "./packages/loot-core/src/server/accounts/transactions.ts");
32625
32643
  // @ts-strict-ignore
32626
- // Plaid article about API options:
32627
- // https://support.plaid.com/customer/en/portal/articles/2612155-transactions-returned-per-request
32628
32644
  function BankSyncError(type, code) {
32629
32645
  return {
32630
32646
  type: 'BankSyncError',
@@ -32663,18 +32679,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32663
32679
  id
32664
32680
  ]);
32665
32681
  }
32666
- async function getAccounts(userId, userKey, id) {
32667
- const res = await (0, _post__WEBPACK_IMPORTED_MODULE_6__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_7__.getServer)().PLAID_SERVER + '/accounts', {
32668
- userId,
32669
- key: userKey,
32670
- item_id: id
32671
- });
32672
- const { accounts } = res;
32673
- accounts.forEach((acct) => {
32674
- acct.balances.current = getAccountBalance(acct);
32675
- });
32676
- return accounts;
32677
- }
32678
32682
  async function getGoCardlessAccounts(userId, userKey, id) {
32679
32683
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.getItem('user-token');
32680
32684
  if (!userToken)
@@ -32692,55 +32696,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32692
32696
  });
32693
32697
  return accounts;
32694
32698
  }
32695
- function fromPlaid(trans) {
32696
- return {
32697
- imported_id: trans.transaction_id,
32698
- payee_name: trans.name,
32699
- imported_payee: trans.name,
32700
- amount: -(0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.amountToInteger)(trans.amount),
32701
- date: trans.date
32702
- };
32703
- }
32704
- async function downloadTransactions(userId, userKey, acctId, bankId, since, count) {
32705
- let allTransactions = [];
32706
- let accountBalance = null;
32707
- const pageSize = 100;
32708
- let offset = 0;
32709
- let numDownloaded = 0;
32710
- while (1) {
32711
- const endDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay();
32712
- const res = await (0, _post__WEBPACK_IMPORTED_MODULE_6__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_7__.getServer)().PLAID_SERVER + '/transactions', {
32713
- userId,
32714
- key: userKey,
32715
- item_id: '' + bankId,
32716
- account_id: acctId,
32717
- start_date: since,
32718
- end_date: endDate,
32719
- count: pageSize,
32720
- offset
32721
- });
32722
- if (res.error_code) {
32723
- throw BankSyncError(res.error_type, res.error_code);
32724
- }
32725
- if (res.transactions.length === 0) {
32726
- break;
32727
- }
32728
- numDownloaded += res.transactions.length;
32729
- // Remove pending transactions for now - we will handle them in
32730
- // the future.
32731
- allTransactions = allTransactions.concat(res.transactions.filter((t) => !t.pending));
32732
- accountBalance = getAccountBalance(res.accounts[0]);
32733
- if (numDownloaded === res.total_transactions || count != null && allTransactions.length >= count) {
32734
- break;
32735
- }
32736
- offset += pageSize;
32737
- }
32738
- allTransactions = count != null ? allTransactions.slice(0, count) : allTransactions;
32739
- return {
32740
- transactions: allTransactions.map(fromPlaid),
32741
- accountBalance
32742
- };
32743
- }
32744
32699
  async function downloadGoCardlessTransactions(userId, userKey, acctId, bankId, since) {
32745
32700
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.getItem('user-token');
32746
32701
  if (!userToken)
@@ -32854,7 +32809,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32854
32809
  payeesToCreate
32855
32810
  };
32856
32811
  }
32857
- async function normalizeExternalTransactions(transactions, acctId) {
32812
+ async function normalizeBankSyncTransactions(transactions, acctId) {
32858
32813
  const payeesToCreate = new Map();
32859
32814
  const normalized = [];
32860
32815
  for (const trans of transactions) {
@@ -32932,12 +32887,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32932
32887
  }
32933
32888
  });
32934
32889
  }
32935
- async function reconcileExternalTransactions(acctId, transactions) {
32890
+ async function reconcileTransactions(acctId, transactions, isBankSyncAccount = false) {
32936
32891
  console.log('Performing transaction reconciliation');
32937
32892
  const hasMatched = new Set();
32938
32893
  const updated = [];
32939
32894
  const added = [];
32940
- const { normalized, payeesToCreate } = await normalizeExternalTransactions(transactions, acctId);
32895
+ const transactionNormalization = isBankSyncAccount ? normalizeBankSyncTransactions : normalizeTransactions;
32896
+ const { normalized, payeesToCreate } = await transactionNormalization(transactions, acctId);
32941
32897
  // The first pass runs the rules, and preps data for fuzzy matching
32942
32898
  const transactionsStep1 = [];
32943
32899
  for (const { payee_name, trans: originalTrans, subtransactions } of normalized) {
@@ -33039,6 +32995,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33039
32995
  };
33040
32996
  // Update the transaction
33041
32997
  const updates = {
32998
+ ...isBankSyncAccount ? {} : {
32999
+ date: trans.date
33000
+ },
33042
33001
  imported_id: trans.imported_id || null,
33043
33002
  payee: existing.payee || trans.payee || null,
33044
33003
  category: existing.category || trans.category || null,
@@ -33100,167 +33059,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33100
33059
  updated: updated.map((trans) => trans.id)
33101
33060
  };
33102
33061
  }
33103
- async function reconcileTransactions(acctId, transactions) {
33104
- const hasMatched = new Set();
33105
- const updated = [];
33106
- const added = [];
33107
- const { normalized, payeesToCreate } = await normalizeTransactions(transactions, acctId);
33108
- // The first pass runs the rules, and preps data for fuzzy matching
33109
- const transactionsStep1 = [];
33110
- for (const { payee_name, trans: originalTrans, subtransactions } of normalized) {
33111
- // Run the rules
33112
- const trans = (0, _transaction_rules__WEBPACK_IMPORTED_MODULE_11__.runRules)(originalTrans);
33113
- let match = null;
33114
- let fuzzyDataset = null;
33115
- // First, match with an existing transaction's imported_id. This
33116
- // is the highest fidelity match and should always be attempted
33117
- // first.
33118
- if (trans.imported_id) {
33119
- match = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT * FROM v_transactions WHERE imported_id = ? AND account = ?', [
33120
- trans.imported_id,
33121
- acctId
33122
- ]);
33123
- if (match) {
33124
- hasMatched.add(match.id);
33125
- }
33126
- }
33127
- // If it didn't match, query data needed for fuzzy matching
33128
- if (!match) {
33129
- // Look 7 days ahead and 7 days back when fuzzy matching. This
33130
- // needs to select all fields that need to be read from the
33131
- // matched transaction. See the final pass below for the needed
33132
- // fields.
33133
- fuzzyDataset = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`SELECT id, is_parent, date, imported_id, payee, category, notes, reconciled FROM v_transactions
33134
- WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
33135
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
33136
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
33137
- trans.amount || 0,
33138
- acctId
33139
- ]);
33140
- // Sort the matched transactions according to the distance from the original
33141
- // transactions date. i.e. if the original transaction is in 21-02-2024 and
33142
- // the matched transactions are: 20-02-2024, 21-02-2024, 29-02-2024 then
33143
- // the resulting data-set should be: 21-02-2024, 20-02-2024, 29-02-2024.
33144
- fuzzyDataset = fuzzyDataset.sort((a, b) => {
33145
- const aDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(a.date))));
33146
- const bDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(b.date))));
33147
- return aDistance > bDistance ? 1 : -1;
33148
- });
33149
- }
33150
- transactionsStep1.push({
33151
- payee_name,
33152
- trans,
33153
- subtransactions: trans.subtransactions || subtransactions,
33154
- match,
33155
- fuzzyDataset
33156
- });
33157
- }
33158
- // Next, do the fuzzy matching. This first pass matches based on the
33159
- // payee id. We do this in multiple passes so that higher fidelity
33160
- // matching always happens first, i.e. a transaction should match
33161
- // match with low fidelity if a later transaction is going to match
33162
- // the same one with high fidelity.
33163
- const transactionsStep2 = transactionsStep1.map((data) => {
33164
- if (!data.match && data.fuzzyDataset) {
33165
- // Try to find one where the payees match.
33166
- const match = data.fuzzyDataset.find((row) => !hasMatched.has(row.id) && data.trans.payee === row.payee);
33167
- if (match) {
33168
- hasMatched.add(match.id);
33169
- return {
33170
- ...data,
33171
- match
33172
- };
33173
- }
33174
- }
33175
- return data;
33176
- });
33177
- // The final fuzzy matching pass. This is the lowest fidelity
33178
- // matching: it just find the first transaction that hasn't been
33179
- // matched yet. Remember the dataset only contains transactions
33180
- // around the same date with the same amount.
33181
- const transactionsStep3 = transactionsStep2.map((data) => {
33182
- if (!data.match && data.fuzzyDataset) {
33183
- const match = data.fuzzyDataset.find((row) => !hasMatched.has(row.id));
33184
- if (match) {
33185
- hasMatched.add(match.id);
33186
- return {
33187
- ...data,
33188
- match
33189
- };
33190
- }
33191
- }
33192
- return data;
33193
- });
33194
- // Finally, generate & commit the changes
33195
- for (const { trans, subtransactions, match } of transactionsStep3) {
33196
- if (match) {
33197
- // Skip updating already reconciled (locked) transactions
33198
- if (match.reconciled) {
33199
- continue;
33200
- }
33201
- // TODO: change the above sql query to use aql
33202
- const existing = {
33203
- ...match,
33204
- cleared: match.cleared === 1,
33205
- date: _db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(match.date)
33206
- };
33207
- // Update the transaction
33208
- const updates = {
33209
- date: trans.date,
33210
- imported_id: trans.imported_id || null,
33211
- payee: existing.payee || trans.payee || null,
33212
- category: existing.category || trans.category || null,
33213
- imported_payee: trans.imported_payee || null,
33214
- notes: existing.notes || trans.notes || null,
33215
- cleared: trans.cleared != null ? trans.cleared : true
33216
- };
33217
- if ((0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.hasFieldsChanged)(existing, updates, Object.keys(updates))) {
33218
- updated.push({
33219
- id: existing.id,
33220
- ...updates
33221
- });
33222
- }
33223
- if (existing.is_parent && existing.cleared !== updates.cleared) {
33224
- const children = await _db__WEBPACK_IMPORTED_MODULE_4__.all('SELECT id FROM v_transactions WHERE parent_id = ?', [
33225
- existing.id
33226
- ]);
33227
- for (const child of children) {
33228
- updated.push({
33229
- id: child.id,
33230
- cleared: updates.cleared
33231
- });
33232
- }
33233
- }
33234
- }
33235
- else {
33236
- // Insert a new transaction
33237
- const finalTransaction = {
33238
- ...trans,
33239
- id: (0, uuid__WEBPACK_IMPORTED_MODULE_13__["default"])(),
33240
- category: trans.category || null,
33241
- cleared: trans.cleared != null ? trans.cleared : true
33242
- };
33243
- if (subtransactions && subtransactions.length > 0) {
33244
- added.push(...makeSplitTransaction(finalTransaction, subtransactions));
33245
- }
33246
- else {
33247
- added.push(finalTransaction);
33248
- }
33249
- }
33250
- }
33251
- await createNewPayees(payeesToCreate, [
33252
- ...added,
33253
- ...updated
33254
- ]);
33255
- await (0, _transactions__WEBPACK_IMPORTED_MODULE_12__.batchUpdateTransactions)({
33256
- added,
33257
- updated
33258
- });
33259
- return {
33260
- added: added.map((trans) => trans.id),
33261
- updated: updated.map((trans) => trans.id)
33262
- };
33263
- }
33264
33062
  // This is similar to `reconcileTransactions` except much simpler: it
33265
33063
  // does not try to match any transactions. It just adds them
33266
33064
  async function addTransactions(acctId, transactions, { runTransfers = true, learnCategories = false } = {}) {
@@ -33303,7 +33101,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33303
33101
  }
33304
33102
  return newTransactions;
33305
33103
  }
33306
- async function syncExternalAccount(userId, userKey, id, acctId, bankId) {
33104
+ async function syncAccount(userId, userKey, id, acctId, bankId) {
33307
33105
  // TODO: Handle the case where transactions exist in the future
33308
33106
  // (that will make start date after end date)
33309
33107
  const latestTransaction = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT * FROM v_transactions WHERE account = ? ORDER BY date DESC LIMIT 1', [
@@ -33314,13 +33112,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33314
33112
  const startingTransaction = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT date FROM v_transactions WHERE account = ? ORDER BY date ASC LIMIT 1', [
33315
33113
  id
33316
33114
  ]);
33317
- const startingDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.parseDate(_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(startingTransaction.date));
33115
+ const startingDate = _db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(startingTransaction.date);
33116
+ // assert(startingTransaction)
33318
33117
  const startDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.dayFromDate(date_fns__WEBPACK_IMPORTED_MODULE_16__["default"]([
33319
33118
  // Many GoCardless integrations do not support getting more than 90 days
33320
33119
  // worth of data, so make that the earliest possible limit.
33321
33120
  _shared_months__WEBPACK_IMPORTED_MODULE_1__.parseDate(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay(), 90)),
33322
33121
  // Never download transactions before the starting date.
33323
- startingDate
33122
+ _shared_months__WEBPACK_IMPORTED_MODULE_1__.parseDate(startingDate)
33324
33123
  ]));
33325
33124
  let download;
33326
33125
  if (acctRow.account_sync_source === 'simpleFin') {
@@ -33329,6 +33128,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33329
33128
  else if (acctRow.account_sync_source === 'goCardless') {
33330
33129
  download = await downloadGoCardlessTransactions(userId, userKey, acctId, bankId, startDate);
33331
33130
  }
33131
+ else {
33132
+ throw new Error(`Unrecognized bank-sync provider: ${acctRow.account_sync_source}`);
33133
+ }
33332
33134
  const { transactions: originalTransactions, accountBalance } = download;
33333
33135
  if (originalTransactions.length === 0) {
33334
33136
  return {
@@ -33341,25 +33143,25 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33341
33143
  account: id
33342
33144
  }));
33343
33145
  return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
33344
- const result = await reconcileExternalTransactions(id, transactions);
33146
+ const result = await reconcileTransactions(id, transactions, true);
33345
33147
  await updateAccountBalance(id, accountBalance);
33346
33148
  return result;
33347
33149
  });
33348
33150
  }
33349
33151
  else {
33152
+ let download;
33350
33153
  // Otherwise, download transaction for the past 90 days
33351
33154
  const startingDay = _shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay(), 90);
33352
- let download;
33353
33155
  if (acctRow.account_sync_source === 'simpleFin') {
33354
33156
  download = await downloadSimpleFinTransactions(acctId, startingDay);
33355
33157
  }
33356
33158
  else if (acctRow.account_sync_source === 'goCardless') {
33357
33159
  download = await downloadGoCardlessTransactions(userId, userKey, acctId, bankId, startingDay);
33358
33160
  }
33359
- const { transactions, startingBalance } = download;
33360
- let balanceToUse = startingBalance;
33161
+ const { transactions } = download;
33162
+ let balanceToUse = download.startingBalance;
33361
33163
  if (acctRow.account_sync_source === 'simpleFin') {
33362
- const currentBalance = startingBalance;
33164
+ const currentBalance = download.startingBalance;
33363
33165
  const previousBalance = transactions.reduce((total, trans) => {
33364
33166
  return total - parseInt(trans.transactionAmount.amount.replace('.', ''));
33365
33167
  }, currentBalance);
@@ -33378,86 +33180,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33378
33180
  cleared: true,
33379
33181
  starting_balance_flag: true
33380
33182
  });
33381
- const result = await reconcileExternalTransactions(id, transactions);
33382
- return {
33383
- ...result,
33384
- added: [
33385
- initialId,
33386
- ...result.added
33387
- ]
33388
- };
33389
- });
33390
- }
33391
- }
33392
- async function syncAccount(userId, userKey, id, acctId, bankId) {
33393
- // TODO: Handle the case where transactions exist in the future
33394
- // (that will make start date after end date)
33395
- const latestTransaction = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT * FROM v_transactions WHERE account = ? ORDER BY date DESC LIMIT 1', [
33396
- id
33397
- ]);
33398
- if (latestTransaction) {
33399
- const startingTransaction = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT date FROM v_transactions WHERE account = ? ORDER BY date ASC LIMIT 1', [
33400
- id
33401
- ]);
33402
- const startingDate = _db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(startingTransaction.date);
33403
- // assert(startingTransaction)
33404
- // Get all transactions since the latest transaction, plus any 5
33405
- // days before the latest transaction. This gives us a chance to
33406
- // resolve any transactions that were entered manually.
33407
- //
33408
- // TODO: What this really should do is query the last imported_id
33409
- // and since then
33410
- let date = _shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(latestTransaction.date), 31);
33411
- // Never download transactions before the starting date. This was
33412
- // when the account was added to the system.
33413
- if (date < startingDate) {
33414
- date = startingDate;
33415
- }
33416
- const { transactions: originalTransactions, accountBalance } = await downloadTransactions(userId, userKey, acctId, bankId, date);
33417
- if (originalTransactions.length === 0) {
33418
- return {
33419
- added: [],
33420
- updated: []
33421
- };
33422
- }
33423
- const transactions = originalTransactions.map((trans) => ({
33424
- ...trans,
33425
- account: id
33426
- }));
33427
- return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
33428
- const result = await reconcileTransactions(id, transactions);
33429
- await updateAccountBalance(id, accountBalance);
33430
- return result;
33431
- });
33432
- }
33433
- else {
33434
- const acctRow = await _db__WEBPACK_IMPORTED_MODULE_4__.select('accounts', id);
33435
- // Otherwise, download transaction for the last few days if it's an
33436
- // on-budget account, or for the past 30 days if off-budget
33437
- const startingDay = _shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay(), acctRow.offbudget === 0 ? 1 : 30);
33438
- const { transactions } = await downloadTransactions(userId, userKey, acctId, bankId, date_fns__WEBPACK_IMPORTED_MODULE_17__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](startingDay), 'yyyy-MM-dd'));
33439
- // We need to add a transaction that represents the starting
33440
- // balance for everything to balance out. In order to get balance
33441
- // before the first imported transaction, we need to get the
33442
- // current balance from the accounts table and subtract all the
33443
- // imported transactions.
33444
- const currentBalance = acctRow.balance_current;
33445
- const previousBalance = transactions.reduce((total, trans) => {
33446
- return total - trans.amount;
33447
- }, currentBalance);
33448
- const oldestDate = transactions.length > 0 ? transactions[transactions.length - 1].date : _shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay();
33449
- const payee = await (0, _payees__WEBPACK_IMPORTED_MODULE_9__.getStartingBalancePayee)();
33450
- return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
33451
- const initialId = await _db__WEBPACK_IMPORTED_MODULE_4__.insertTransaction({
33452
- account: id,
33453
- amount: previousBalance,
33454
- category: acctRow.offbudget === 0 ? payee.category : null,
33455
- payee: payee.id,
33456
- date: oldestDate,
33457
- cleared: true,
33458
- starting_balance_flag: true
33459
- });
33460
- const result = await reconcileTransactions(id, transactions);
33183
+ const result = await reconcileTransactions(id, transactions, true);
33461
33184
  return {
33462
33185
  ...result,
33463
33186
  added: [
@@ -36057,6 +35780,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36057
35780
  return typed(val(state, args[0]), args[0].type);
36058
35781
  }
36059
35782
  // date functions
35783
+ case '$day':
35784
+ {
35785
+ validateArgLength(args, 1);
35786
+ return castInput(state, args[0], 'date');
35787
+ }
36060
35788
  case '$month':
36061
35789
  {
36062
35790
  validateArgLength(args, 1);
@@ -38589,6 +38317,83 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38589
38317
  function cleanupTemplate({ month }) {
38590
38318
  return processCleanup(month);
38591
38319
  }
38320
+ async function applyGroupCleanups(month, sourceGroups, sinkGroups, generalGroups) {
38321
+ const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
38322
+ const warnings = [];
38323
+ const db_month = parseInt(month.replace('-', ''));
38324
+ let groupLength = sourceGroups.length;
38325
+ while (groupLength > 0) {
38326
+ //function for each unique group
38327
+ const groupName = sourceGroups[0].group;
38328
+ const tempSourceGroups = sourceGroups.filter((c) => c.group === groupName);
38329
+ const sinkGroup = sinkGroups.filter((c) => c.group === groupName);
38330
+ const generalGroup = generalGroups.filter((c) => c.group === groupName);
38331
+ let total_weight = 0;
38332
+ if (sinkGroup.length > 0 || generalGroup.length > 0) {
38333
+ //only return group source funds to To Budget if there are corresponding sinking groups or underfunded included groups
38334
+ for (let ii = 0; ii < tempSourceGroups.length; ii++) {
38335
+ const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${tempSourceGroups[ii].category}`);
38336
+ const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${tempSourceGroups[ii].category}`);
38337
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38338
+ category: tempSourceGroups[ii].category,
38339
+ month,
38340
+ amount: budgeted - balance
38341
+ });
38342
+ }
38343
+ //calculate total weight for sinking funds
38344
+ for (let ii = 0; ii < sinkGroup.length; ii++) {
38345
+ total_weight += sinkGroup[ii].weight;
38346
+ }
38347
+ //fill underfunded categories within the group first
38348
+ for (let ii = 0; ii < generalGroup.length; ii++) {
38349
+ const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38350
+ const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${generalGroup[ii].category}`);
38351
+ const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${generalGroup[ii].category}`);
38352
+ const to_budget = budgeted + Math.abs(balance);
38353
+ const categoryId = generalGroup[ii].category;
38354
+ let carryover = await _db__WEBPACK_IMPORTED_MODULE_1__.first(`SELECT carryover FROM zero_budgets WHERE month = ? and category = ?`, [
38355
+ db_month,
38356
+ categoryId
38357
+ ]);
38358
+ if (carryover === null) {
38359
+ carryover = {
38360
+ carryover: 0
38361
+ };
38362
+ }
38363
+ if (balance < 0 && Math.abs(balance) <= budgetAvailable && !generalGroup[ii].category.is_income && carryover.carryover === 0) {
38364
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38365
+ category: generalGroup[ii].category,
38366
+ month,
38367
+ amount: to_budget
38368
+ });
38369
+ }
38370
+ else if (balance < 0 && !generalGroup[ii].category.is_income && carryover.carryover === 0 && Math.abs(balance) > budgetAvailable) {
38371
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38372
+ category: generalGroup[ii].category,
38373
+ month,
38374
+ amount: budgeted + budgetAvailable
38375
+ });
38376
+ }
38377
+ }
38378
+ const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38379
+ for (let ii = 0; ii < sinkGroup.length; ii++) {
38380
+ const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${sinkGroup[ii].category}`);
38381
+ const to_budget = budgeted + Math.round(sinkGroup[ii].weight / total_weight * budgetAvailable);
38382
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38383
+ category: sinkGroup[ii].category,
38384
+ month,
38385
+ amount: to_budget
38386
+ });
38387
+ }
38388
+ }
38389
+ else {
38390
+ warnings.push(groupName + ' has no matching sink categories.');
38391
+ }
38392
+ sourceGroups = sourceGroups.filter((c) => c.group !== groupName);
38393
+ groupLength = sourceGroups.length;
38394
+ }
38395
+ return warnings;
38396
+ }
38592
38397
  async function processCleanup(month) {
38593
38398
  let num_sources = 0;
38594
38399
  let num_sinks = 0;
@@ -38601,15 +38406,52 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38601
38406
  const category_templates = await getCategoryTemplates();
38602
38407
  const categories = await _db__WEBPACK_IMPORTED_MODULE_1__.all('SELECT * FROM v_categories WHERE tombstone = 0');
38603
38408
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
38409
+ const groupSource = [];
38410
+ const groupSink = [];
38411
+ const groupGeneral = [];
38412
+ //filter out category groups
38413
+ for (let c = 0; c < categories.length; c++) {
38414
+ const category = categories[c];
38415
+ const template = category_templates[category.id];
38416
+ //filter out source and sink groups for processing
38417
+ if (template) {
38418
+ if (template.filter((t) => t.type === 'source' && t.group !== null).length > 0) {
38419
+ groupSource.push({
38420
+ category: category.id,
38421
+ group: template.filter((t) => t.type === 'source' && t.group !== null)[0].group
38422
+ });
38423
+ }
38424
+ if (template.filter((t) => t.type === 'sink' && t.group !== null).length > 0) {
38425
+ //only supports 1 sink reference per category. Need more?
38426
+ groupSink.push({
38427
+ category: category.id,
38428
+ group: template.filter((t) => t.type === 'sink' && t.group !== null)[0].group,
38429
+ weight: template.filter((t) => t.type === 'sink' && t.group !== null)[0].weight
38430
+ });
38431
+ }
38432
+ if (template.filter((t) => t.type === null && t.group !== null).length > 0) {
38433
+ groupGeneral.push({
38434
+ category: category.id,
38435
+ group: template[0].group
38436
+ });
38437
+ }
38438
+ }
38439
+ }
38440
+ //run category groups
38441
+ const newWarnings = await applyGroupCleanups(month, groupSource, groupSink, groupGeneral);
38442
+ warnings.splice(1, 0, ...newWarnings);
38604
38443
  for (let c = 0; c < categories.length; c++) {
38605
38444
  const category = categories[c];
38606
38445
  const template = category_templates[category.id];
38607
38446
  if (template) {
38608
- if (template.filter((t) => t.type === 'source').length > 0) {
38447
+ if (template.filter((t) => t.type === 'source' && t.group === null).length > 0) {
38609
38448
  const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${category.id}`);
38610
38449
  const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${category.id}`);
38611
38450
  if (balance >= 0) {
38612
- const spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `sum-amount-${category.id}`);
38451
+ // const spent = await getSheetValue(
38452
+ // sheetName,
38453
+ // `sum-amount-${category.id}`,
38454
+ // );
38613
38455
  await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38614
38456
  category: category.id,
38615
38457
  month,
@@ -38618,7 +38460,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38618
38460
  await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setGoal)({
38619
38461
  category: category.id,
38620
38462
  month,
38621
- goal: -spent
38463
+ goal: budgeted - balance
38622
38464
  });
38623
38465
  num_sources += 1;
38624
38466
  }
@@ -38639,7 +38481,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38639
38481
  }
38640
38482
  }
38641
38483
  }
38642
- if (template.filter((t) => t.type === 'sink').length > 0) {
38484
+ if (template.filter((t) => t.type === 'sink' && t.group === null).length > 0) {
38643
38485
  sinkCategory.push({
38644
38486
  cat: category,
38645
38487
  temp: template
@@ -38683,8 +38525,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38683
38525
  }
38684
38526
  const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38685
38527
  if (budgetAvailable <= 0) {
38686
- warnings.push('No funds are available to reallocate.');
38528
+ warnings.push('Global: No funds are available to reallocate.');
38687
38529
  }
38530
+ //fill sinking categories
38688
38531
  for (let c = 0; c < sinkCategory.length; c++) {
38689
38532
  const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${sinkCategory[c].cat.id}`);
38690
38533
  const categoryId = sinkCategory[c].cat.id;
@@ -38714,7 +38557,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38714
38557
  else if (warnings.length) {
38715
38558
  return {
38716
38559
  type: 'warning',
38717
- message: 'Funds not available:',
38560
+ message: 'Global: Funds not available:',
38718
38561
  pre: warnings.join('\n\n')
38719
38562
  };
38720
38563
  }
@@ -38734,6 +38577,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38734
38577
  pre: errors.join('\n\n')
38735
38578
  };
38736
38579
  }
38580
+ else if (warnings.length) {
38581
+ return {
38582
+ type: 'warning',
38583
+ message: 'Global: Funds not available:',
38584
+ pre: warnings.join('\n\n')
38585
+ };
38586
+ }
38737
38587
  else {
38738
38588
  return {
38739
38589
  type: 'message',
@@ -38774,6 +38624,47 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38774
38624
  }
38775
38625
  /***/
38776
38626
  }),
38627
+ /***/ "./packages/loot-core/src/server/budget/goals/goalsAverage.ts":
38628
+ /*!********************************************************************!*\
38629
+ !*** ./packages/loot-core/src/server/budget/goals/goalsAverage.ts ***!
38630
+ \********************************************************************/
38631
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
38632
+ "use strict";
38633
+ __webpack_require__.r(__webpack_exports__);
38634
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
38635
+ /* harmony export */ goalsAverage: () => ( /* binding */goalsAverage)
38636
+ /* harmony export */
38637
+ });
38638
+ /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../shared/months */ "./packages/loot-core/src/shared/months.ts");
38639
+ /* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../actions */ "./packages/loot-core/src/server/budget/actions.ts");
38640
+ // @ts-strict-ignore
38641
+ async function goalsAverage(template, month, category, errors, to_budget) {
38642
+ // simple has an 'amount' param
38643
+ let increment = 0;
38644
+ if (template.amount) {
38645
+ let sum = 0;
38646
+ for (let i = 1; i <= template.amount; i++) {
38647
+ // add up other months
38648
+ const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.subMonths(month, i));
38649
+ sum += await (0, _actions__WEBPACK_IMPORTED_MODULE_1__.getSheetValue)(sheetName, `sum-amount-${category.id}`);
38650
+ }
38651
+ increment = sum / template.amount;
38652
+ }
38653
+ else {
38654
+ errors.push('Number of months to average is not valid');
38655
+ return {
38656
+ to_budget,
38657
+ errors
38658
+ };
38659
+ }
38660
+ to_budget += -Math.round(increment);
38661
+ return {
38662
+ to_budget,
38663
+ errors
38664
+ };
38665
+ }
38666
+ /***/
38667
+ }),
38777
38668
  /***/ "./packages/loot-core/src/server/budget/goals/goalsBy.ts":
38778
38669
  /*!***************************************************************!*\
38779
38670
  !*** ./packages/loot-core/src/server/budget/goals/goalsBy.ts ***!
@@ -39108,7 +38999,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39108
38999
  });
39109
39000
  /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../shared/util */ "./packages/loot-core/src/shared/util.ts");
39110
39001
  // @ts-strict-ignore
39111
- async function goalsSimple(template, limitCheck, errors, limit, hold, to_budget) {
39002
+ async function goalsSimple(template, limitCheck, errors, limit, hold, to_budget, last_month_balance) {
39112
39003
  // simple has 'monthly' and/or 'limit' params
39113
39004
  if (template.limit != null) {
39114
39005
  if (limitCheck) {
@@ -39133,7 +39024,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39133
39024
  increment = monthly;
39134
39025
  }
39135
39026
  else {
39136
- increment = limit;
39027
+ increment = limit - last_month_balance;
39137
39028
  }
39138
39029
  to_budget += increment;
39139
39030
  return {
@@ -39278,13 +39169,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39278
39169
  /* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./actions */ "./packages/loot-core/src/server/budget/actions.ts");
39279
39170
  /* harmony import */ var _goal_template_pegjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./goal-template.pegjs */ "./packages/loot-core/src/server/budget/goal-template.pegjs");
39280
39171
  /* harmony import */ var _goal_template_pegjs__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/ __webpack_require__.n(_goal_template_pegjs__WEBPACK_IMPORTED_MODULE_5__);
39281
- /* harmony import */ var _goals_goalsBy__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./goals/goalsBy */ "./packages/loot-core/src/server/budget/goals/goalsBy.ts");
39282
- /* harmony import */ var _goals_goalsPercentage__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./goals/goalsPercentage */ "./packages/loot-core/src/server/budget/goals/goalsPercentage.ts");
39283
- /* harmony import */ var _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./goals/goalsRemainder */ "./packages/loot-core/src/server/budget/goals/goalsRemainder.ts");
39284
- /* harmony import */ var _goals_goalsSchedule__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./goals/goalsSchedule */ "./packages/loot-core/src/server/budget/goals/goalsSchedule.ts");
39285
- /* harmony import */ var _goals_goalsSimple__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./goals/goalsSimple */ "./packages/loot-core/src/server/budget/goals/goalsSimple.ts");
39286
- /* harmony import */ var _goals_goalsSpend__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./goals/goalsSpend */ "./packages/loot-core/src/server/budget/goals/goalsSpend.ts");
39287
- /* harmony import */ var _goals_goalsWeek__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./goals/goalsWeek */ "./packages/loot-core/src/server/budget/goals/goalsWeek.ts");
39172
+ /* harmony import */ var _goals_goalsAverage__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./goals/goalsAverage */ "./packages/loot-core/src/server/budget/goals/goalsAverage.ts");
39173
+ /* harmony import */ var _goals_goalsBy__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./goals/goalsBy */ "./packages/loot-core/src/server/budget/goals/goalsBy.ts");
39174
+ /* harmony import */ var _goals_goalsPercentage__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./goals/goalsPercentage */ "./packages/loot-core/src/server/budget/goals/goalsPercentage.ts");
39175
+ /* harmony import */ var _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./goals/goalsRemainder */ "./packages/loot-core/src/server/budget/goals/goalsRemainder.ts");
39176
+ /* harmony import */ var _goals_goalsSchedule__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./goals/goalsSchedule */ "./packages/loot-core/src/server/budget/goals/goalsSchedule.ts");
39177
+ /* harmony import */ var _goals_goalsSimple__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./goals/goalsSimple */ "./packages/loot-core/src/server/budget/goals/goalsSimple.ts");
39178
+ /* harmony import */ var _goals_goalsSpend__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./goals/goalsSpend */ "./packages/loot-core/src/server/budget/goals/goalsSpend.ts");
39179
+ /* harmony import */ var _goals_goalsWeek__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./goals/goalsWeek */ "./packages/loot-core/src/server/budget/goals/goalsWeek.ts");
39288
39180
  // @ts-strict-ignore
39289
39181
  async function applyTemplate({ month }) {
39290
39182
  await storeTemplates();
@@ -39472,7 +39364,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39472
39364
  priority_list = priority_list.sort(function (a, b) {
39473
39365
  return a - b;
39474
39366
  }).filter((item, index, curr) => curr.indexOf(item) === index);
39475
- const { remainder_found, remainder_priority, remainder_weight_total } = (0, _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_8__.findRemainder)(priority_list, categories, category_templates);
39367
+ const { remainder_found, remainder_priority, remainder_weight_total } = (0, _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_9__.findRemainder)(priority_list, categories, category_templates);
39476
39368
  if (remainder_found)
39477
39369
  priority_list.push(remainder_priority);
39478
39370
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
@@ -39700,7 +39592,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39700
39592
  switch (template.type) {
39701
39593
  case 'simple':
39702
39594
  {
39703
- const goalsReturn = await (0, _goals_goalsSimple__WEBPACK_IMPORTED_MODULE_10__.goalsSimple)(template, limitCheck, errors, limit, hold, to_budget);
39595
+ const goalsReturn = await (0, _goals_goalsSimple__WEBPACK_IMPORTED_MODULE_11__.goalsSimple)(template, limitCheck, errors, limit, hold, to_budget, last_month_balance);
39704
39596
  to_budget = goalsReturn.to_budget;
39705
39597
  errors = goalsReturn.errors;
39706
39598
  limit = goalsReturn.limit;
@@ -39710,7 +39602,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39710
39602
  }
39711
39603
  case 'by':
39712
39604
  {
39713
- const goalsReturn = await (0, _goals_goalsBy__WEBPACK_IMPORTED_MODULE_6__.goalsBy)(template_lines, current_month, template, l, remainder, last_month_balance, to_budget, errors);
39605
+ const goalsReturn = await (0, _goals_goalsBy__WEBPACK_IMPORTED_MODULE_7__.goalsBy)(template_lines, current_month, template, l, remainder, last_month_balance, to_budget, errors);
39714
39606
  to_budget = goalsReturn.to_budget;
39715
39607
  errors = goalsReturn.errors;
39716
39608
  remainder = goalsReturn.remainder;
@@ -39718,7 +39610,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39718
39610
  }
39719
39611
  case 'week':
39720
39612
  {
39721
- const goalsReturn = await (0, _goals_goalsWeek__WEBPACK_IMPORTED_MODULE_12__.goalsWeek)(template, limit, limitCheck, hold, current_month, to_budget, errors);
39613
+ const goalsReturn = await (0, _goals_goalsWeek__WEBPACK_IMPORTED_MODULE_13__.goalsWeek)(template, limit, limitCheck, hold, current_month, to_budget, errors);
39722
39614
  to_budget = goalsReturn.to_budget;
39723
39615
  errors = goalsReturn.errors;
39724
39616
  limit = goalsReturn.limit;
@@ -39728,21 +39620,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39728
39620
  }
39729
39621
  case 'spend':
39730
39622
  {
39731
- const goalsReturn = await (0, _goals_goalsSpend__WEBPACK_IMPORTED_MODULE_11__.goalsSpend)(template, last_month_balance, current_month, to_budget, errors, category);
39623
+ const goalsReturn = await (0, _goals_goalsSpend__WEBPACK_IMPORTED_MODULE_12__.goalsSpend)(template, last_month_balance, current_month, to_budget, errors, category);
39732
39624
  to_budget = goalsReturn.to_budget;
39733
39625
  errors = goalsReturn.errors;
39734
39626
  break;
39735
39627
  }
39736
39628
  case 'percentage':
39737
39629
  {
39738
- const goalsReturn = await (0, _goals_goalsPercentage__WEBPACK_IMPORTED_MODULE_7__.goalsPercentage)(template, month, available_start, sheetName, to_budget, errors);
39630
+ const goalsReturn = await (0, _goals_goalsPercentage__WEBPACK_IMPORTED_MODULE_8__.goalsPercentage)(template, month, available_start, sheetName, to_budget, errors);
39739
39631
  to_budget = goalsReturn.to_budget;
39740
39632
  errors = goalsReturn.errors;
39741
39633
  break;
39742
39634
  }
39743
39635
  case 'schedule':
39744
39636
  {
39745
- const goalsReturn = await (0, _goals_goalsSchedule__WEBPACK_IMPORTED_MODULE_9__.goalsSchedule)(scheduleFlag, template_lines, current_month, balance, remainder, last_month_balance, to_budget, errors, category);
39637
+ const goalsReturn = await (0, _goals_goalsSchedule__WEBPACK_IMPORTED_MODULE_10__.goalsSchedule)(scheduleFlag, template_lines, current_month, balance, remainder, last_month_balance, to_budget, errors, category);
39746
39638
  to_budget = goalsReturn.to_budget;
39747
39639
  errors = goalsReturn.errors;
39748
39640
  remainder = goalsReturn.remainder;
@@ -39751,10 +39643,17 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39751
39643
  }
39752
39644
  case 'remainder':
39753
39645
  {
39754
- const goalsReturn = await (0, _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_8__.goalsRemainder)(template, budgetAvailable, remainder_scale, to_budget);
39646
+ const goalsReturn = await (0, _goals_goalsRemainder__WEBPACK_IMPORTED_MODULE_9__.goalsRemainder)(template, budgetAvailable, remainder_scale, to_budget);
39755
39647
  to_budget = goalsReturn.to_budget;
39756
39648
  break;
39757
39649
  }
39650
+ case 'average':
39651
+ {
39652
+ const goalsReturn = await (0, _goals_goalsAverage__WEBPACK_IMPORTED_MODULE_6__.goalsAverage)(template, current_month, category, errors, to_budget);
39653
+ to_budget = goalsReturn.to_budget;
39654
+ errors = goalsReturn.errors;
39655
+ break;
39656
+ }
39758
39657
  case 'error':
39759
39658
  return {
39760
39659
  errors
@@ -39784,16 +39683,24 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39784
39683
  const category_templates = await getCategoryTemplates(null);
39785
39684
  const errors = [];
39786
39685
  const categories = await _db__WEBPACK_IMPORTED_MODULE_2__.all('SELECT * FROM v_categories WHERE tombstone = 0');
39686
+ let all_schedule_names = await _db__WEBPACK_IMPORTED_MODULE_2__.all('SELECT name from schedules WHERE name NOT NULL AND tombstone = 0');
39687
+ all_schedule_names = all_schedule_names.map((v) => v.name);
39787
39688
  // run through each line and see if its an error
39788
39689
  for (let c = 0; c < categories.length; c++) {
39789
39690
  const category = categories[c];
39790
39691
  const template = category_templates[category.id];
39791
39692
  if (template) {
39792
39693
  for (let l = 0; l < template.length; l++) {
39694
+ //check for basic error
39793
39695
  if (template[l].type === 'error') {
39794
- //return { type: 'message', message: "found a bad one",};
39795
39696
  errors.push(category.name + ': ' + template[l].line);
39796
39697
  }
39698
+ // check schedule name error
39699
+ if (template[l].type === 'schedule') {
39700
+ if (!all_schedule_names.includes(template[l].name)) {
39701
+ errors.push(category.name + ': Schedule “' + template[l].name + '” does not exist');
39702
+ }
39703
+ }
39797
39704
  }
39798
39705
  }
39799
39706
  }
@@ -42298,14 +42205,121 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42298
42205
  payee
42299
42206
  ]);
42300
42207
  const payeeTransferAcctHashMap = new Map(payeesByTransferAcct);
42208
+ const orphanTransferMap = new Map();
42209
+ const orphanSubtransfer = [];
42210
+ const orphanSubtransferTrxId = [];
42211
+ const orphanSubtransferAcctIdByTrxIdMap = new Map();
42212
+ const orphanSubtransferDateByTrxIdMap = new Map();
42301
42213
  // Go ahead and generate ids for all of the transactions so we can
42302
42214
  // reliably resolve transfers
42303
- for (const transaction of data.transactions) {
42215
+ // Also identify orphan transfer transactions and subtransactions.
42216
+ for (const transaction of data.subtransactions) {
42304
42217
  entityIdMap.set(transaction.id, (0, uuid__WEBPACK_IMPORTED_MODULE_3__["default"])());
42218
+ if (transaction.transfer_account_id) {
42219
+ orphanSubtransfer.push(transaction);
42220
+ orphanSubtransferTrxId.push(transaction.transaction_id);
42221
+ }
42305
42222
  }
42306
- for (const transaction of data.subtransactions) {
42223
+ for (const transaction of data.transactions) {
42307
42224
  entityIdMap.set(transaction.id, (0, uuid__WEBPACK_IMPORTED_MODULE_3__["default"])());
42225
+ if (transaction.transfer_account_id && !transaction.transfer_transaction_id) {
42226
+ const key = transaction.account_id + '#' + transaction.transfer_account_id;
42227
+ if (!orphanTransferMap.has(key)) {
42228
+ orphanTransferMap.set(key, [
42229
+ transaction
42230
+ ]);
42231
+ }
42232
+ else {
42233
+ orphanTransferMap.get(key).push(transaction);
42234
+ }
42235
+ }
42236
+ if (orphanSubtransferTrxId.includes(transaction.id)) {
42237
+ orphanSubtransferAcctIdByTrxIdMap.set(transaction.id, transaction.account_id);
42238
+ orphanSubtransferDateByTrxIdMap.set(transaction.id, transaction.date);
42239
+ }
42308
42240
  }
42241
+ // Compute link between subtransaction transfers and orphaned transaction
42242
+ // transfers. The goal is to match each transfer subtransaction to the related
42243
+ // transfer transaction according to the accounts, date, amount and memo.
42244
+ const orphanSubtransferMap = orphanSubtransfer.reduce((map, subtransaction) => {
42245
+ const key = subtransaction.transfer_account_id + '#' + orphanSubtransferAcctIdByTrxIdMap.get(subtransaction.transaction_id);
42246
+ if (!map.has(key)) {
42247
+ map.set(key, [
42248
+ subtransaction
42249
+ ]);
42250
+ }
42251
+ else {
42252
+ map.get(key).push(subtransaction);
42253
+ }
42254
+ return map;
42255
+ }, new Map());
42256
+ // The comparator will be used to order transfer transactions and their
42257
+ // corresponding tranfer subtransaction in two aligned list. Hopefully
42258
+ // for every list index in the transactions list, the related subtransaction
42259
+ // will be at the same index.
42260
+ const orphanTransferComparator = (a, b) => {
42261
+ // a and b can be a YNAB5.Transaction (having a date attribute) or a
42262
+ // YNAB5.Subtransaction (missing that date attribute)
42263
+ const date_a = 'date' in a ? a.date : orphanSubtransferDateByTrxIdMap.get(a.transaction_id);
42264
+ const date_b = 'date' in b ? b.date : orphanSubtransferDateByTrxIdMap.get(b.transaction_id);
42265
+ // A transaction and the related subtransaction have inverted amounts.
42266
+ // To have those in the same order, the subtransaction has to be reversed
42267
+ // to have the same amount.
42268
+ const amount_a = 'date' in a ? a.amount : -a.amount;
42269
+ const amount_b = 'date' in b ? b.amount : -b.amount;
42270
+ // Transaction are ordered first by date, then by amount, and lastly by memo
42271
+ if (date_a > date_b)
42272
+ return 1;
42273
+ if (date_a < date_b)
42274
+ return -1;
42275
+ if (amount_a > amount_b)
42276
+ return 1;
42277
+ if (amount_a < amount_b)
42278
+ return -1;
42279
+ if (a.memo > b.memo)
42280
+ return 1;
42281
+ if (a.memo < b.memo)
42282
+ return -1;
42283
+ return 0;
42284
+ };
42285
+ const orphanTrxIdSubtrxIdMap = new Map();
42286
+ orphanTransferMap.forEach((transactions, key) => {
42287
+ const subtransactions = orphanSubtransferMap.get(key);
42288
+ if (subtransactions) {
42289
+ transactions.sort(orphanTransferComparator);
42290
+ subtransactions.sort(orphanTransferComparator);
42291
+ // Iterate on the two sorted lists transactions and subtransactions and
42292
+ // find matching data to identify the related transaction ids.
42293
+ let transactionIdx = 0;
42294
+ let subtransactionIdx = 0;
42295
+ do {
42296
+ switch (orphanTransferComparator(transactions[transactionIdx], subtransactions[subtransactionIdx])) {
42297
+ case 0:
42298
+ // The current list indexes are matching: the transaction and
42299
+ // subtransaction are related (same date, amount and memo)
42300
+ orphanTrxIdSubtrxIdMap.set(transactions[transactionIdx].id, entityIdMap.get(subtransactions[subtransactionIdx].id));
42301
+ orphanTrxIdSubtrxIdMap.set(subtransactions[subtransactionIdx].id, entityIdMap.get(transactions[transactionIdx].id));
42302
+ transactionIdx++;
42303
+ subtransactionIdx++;
42304
+ break;
42305
+ case -1:
42306
+ // The current list indexes are not matching:
42307
+ // The current transaction is "smaller" than the current subtransaction
42308
+ // (earlier date, smaller amount, memo value sorted before)
42309
+ // So we advance to the next transaction and see if it match with
42310
+ // the current subtransaction
42311
+ transactionIdx++;
42312
+ break;
42313
+ case 1:
42314
+ // Inverse of the previous case:
42315
+ // The current subtransaction is "smaller" than the current transaction
42316
+ // So we advance to the next subtransaction
42317
+ subtransactionIdx++;
42318
+ break;
42319
+ }
42320
+ } while (transactionIdx < transactions.length && subtransactionIdx < subtransactions.length);
42321
+ }
42322
+ });
42309
42323
  await Promise.all([
42310
42324
  ...transactionsGrouped.keys()
42311
42325
  ].map(async (accountId) => {
@@ -42329,31 +42343,38 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42329
42343
  reconciled: transaction.cleared === 'reconciled',
42330
42344
  notes: transaction.memo || null,
42331
42345
  imported_id: transaction.import_id || null,
42332
- transfer_id: entityIdMap.get(transaction.transfer_transaction_id) || null,
42346
+ transfer_id: entityIdMap.get(transaction.transfer_transaction_id) || orphanTrxIdSubtrxIdMap.get(transaction.id) || null,
42333
42347
  subtransactions: subtransactions ? subtransactions.map((subtrans) => {
42334
- let payee = null;
42335
- if (subtrans.transfer_account_id) {
42336
- const mappedTransferAccountId = entityIdMap.get(subtrans.transfer_account_id);
42337
- payee = payeeTransferAcctHashMap.get(mappedTransferAccountId)?.id;
42338
- }
42339
42348
  return {
42340
42349
  id: entityIdMap.get(subtrans.id),
42341
42350
  amount: amountFromYnab(subtrans.amount),
42342
42351
  category: entityIdMap.get(subtrans.category_id) || null,
42343
42352
  notes: subtrans.memo,
42344
- payee
42353
+ transfer_id: orphanTrxIdSubtrxIdMap.get(subtrans.id) || null,
42354
+ payee: null,
42355
+ imported_payee: null
42345
42356
  };
42346
42357
  }) : null,
42347
42358
  payee: null,
42348
42359
  imported_payee: null
42349
42360
  };
42350
- // Handle transfer payee
42351
- if (transaction.transfer_account_id) {
42352
- newTransaction.payee = payees.find((p) => p.transfer_acct === entityIdMap.get(transaction.transfer_account_id)).id;
42353
- }
42354
- else {
42355
- newTransaction.payee = entityIdMap.get(transaction.payee_id);
42356
- newTransaction.imported_payee = data.payees.find((p) => !p.deleted && p.id === transaction.payee_id)?.name;
42361
+ // Handle transactions and subtransactions payee
42362
+ const transactionPayeeUpdate = (trx, newTrx) => {
42363
+ if (trx.transfer_account_id) {
42364
+ const mappedTransferAccountId = entityIdMap.get(trx.transfer_account_id);
42365
+ newTrx.payee = payeeTransferAcctHashMap.get(mappedTransferAccountId)?.id;
42366
+ }
42367
+ else {
42368
+ newTrx.payee = entityIdMap.get(trx.payee_id);
42369
+ newTrx.imported_payee = data.payees.find((p) => !p.deleted && p.id === trx.payee_id)?.name;
42370
+ }
42371
+ };
42372
+ transactionPayeeUpdate(transaction, newTransaction);
42373
+ if (newTransaction.subtransactions) {
42374
+ subtransactions.forEach((subtrans) => {
42375
+ const newSubtransaction = newTransaction.subtransactions.find((newSubtrans) => newSubtrans.id === entityIdMap.get(subtrans.id));
42376
+ transactionPayeeUpdate(subtrans, newSubtransaction);
42377
+ });
42357
42378
  }
42358
42379
  // Handle starting balances
42359
42380
  if (transaction.payee_id === startingPayeeYNAB && entityIdMap.get(transaction.category_id) === incomeCatId) {
@@ -42959,21 +42980,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42959
42980
  }
42960
42981
  return (0, _aql__WEBPACK_IMPORTED_MODULE_22__.runQuery)(query);
42961
42982
  };
42962
- handlers['bank-delete'] = async function ({ id }) {
42963
- const accts = await _db__WEBPACK_IMPORTED_MODULE_27__.runQuery('SELECT * FROM accounts WHERE bank = ?', [
42964
- id
42965
- ], true);
42966
- await _db__WEBPACK_IMPORTED_MODULE_27__.delete_('banks', id);
42967
- await Promise.all(accts.map(async (acct) => {
42968
- // TODO: This will not sync across devices because we are bypassing
42969
- // the "recorded" functions
42970
- await _db__WEBPACK_IMPORTED_MODULE_27__.runQuery('DELETE FROM transactions WHERE acct = ?', [
42971
- acct.id
42972
- ]);
42973
- await _db__WEBPACK_IMPORTED_MODULE_27__.delete_('accounts', acct.id);
42974
- }));
42975
- return 'ok';
42976
- };
42977
42983
  handlers['account-update'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.mutator)(async function ({ id, name }) {
42978
42984
  return (0, _undo__WEBPACK_IMPORTED_MODULE_48__.withUndo)(async () => {
42979
42985
  await _db__WEBPACK_IMPORTED_MODULE_27__.update('accounts', {
@@ -42998,34 +43004,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42998
43004
  numTransactions: count
42999
43005
  };
43000
43006
  };
43001
- handlers['accounts-link'] = async function ({ institution, publicToken, accountId, upgradingId }) {
43002
- const bankId = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.handoffPublicToken(institution, publicToken);
43003
- const [[, userId], [, userKey]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.multiGet([
43004
- 'user-id',
43005
- 'user-key'
43006
- ]);
43007
- // Get all the available accounts and find the selected one
43008
- const accounts = await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.getGoCardlessAccounts(userId, userKey, bankId);
43009
- const account = accounts.find((acct) => acct.account_id === accountId);
43010
- await _db__WEBPACK_IMPORTED_MODULE_27__.update('accounts', {
43011
- id: upgradingId,
43012
- account_id: account.account_id,
43013
- official_name: account.official_name,
43014
- balance_current: (0, _shared_util__WEBPACK_IMPORTED_MODULE_13__.amountToInteger)(account.balances.current),
43015
- balance_available: (0, _shared_util__WEBPACK_IMPORTED_MODULE_13__.amountToInteger)(account.balances.available),
43016
- balance_limit: (0, _shared_util__WEBPACK_IMPORTED_MODULE_13__.amountToInteger)(account.balances.limit),
43017
- mask: account.mask,
43018
- bank: bankId
43019
- });
43020
- await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncAccount(userId, userKey, upgradingId, account.account_id, bankId);
43021
- _platform_server_connection__WEBPACK_IMPORTED_MODULE_6__.send('sync-event', {
43022
- type: 'success',
43023
- tables: [
43024
- 'transactions'
43025
- ]
43026
- });
43027
- return 'ok';
43028
- };
43029
43007
  handlers['gocardless-accounts-link'] = async function ({ requisitionId, account, upgradingId }) {
43030
43008
  let id;
43031
43009
  const bank = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.findOrCreateBank(account.institution, requisitionId);
@@ -43057,7 +43035,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43057
43035
  transfer_acct: id
43058
43036
  });
43059
43037
  }
43060
- await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncExternalAccount(undefined, undefined, id, account.account_id, bank.bank_id);
43038
+ await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncAccount(undefined, undefined, id, account.account_id, bank.bank_id);
43061
43039
  _platform_server_connection__WEBPACK_IMPORTED_MODULE_6__.send('sync-event', {
43062
43040
  type: 'success',
43063
43041
  tables: [
@@ -43099,7 +43077,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43099
43077
  transfer_acct: id
43100
43078
  });
43101
43079
  }
43102
- await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncExternalAccount(undefined, undefined, id, externalAccount.account_id, bank.bank_id);
43080
+ await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncAccount(undefined, undefined, id, externalAccount.account_id, bank.bank_id);
43103
43081
  await _platform_server_connection__WEBPACK_IMPORTED_MODULE_6__.send('sync-event', {
43104
43082
  type: 'success',
43105
43083
  tables: [
@@ -43108,16 +43086,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43108
43086
  });
43109
43087
  return 'ok';
43110
43088
  };
43111
- handlers['accounts-connect'] = async function ({ institution, publicToken, accountIds, offbudgetIds }) {
43112
- const bankId = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.handoffPublicToken(institution, publicToken);
43113
- const ids = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.addAccounts(bankId, accountIds, offbudgetIds);
43114
- return ids;
43115
- };
43116
- handlers['gocardless-accounts-connect'] = async function ({ institution, publicToken, accountIds, offbudgetIds }) {
43117
- const bankId = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.handoffPublicToken(institution, publicToken);
43118
- const ids = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.addGoCardlessAccounts(bankId, accountIds, offbudgetIds);
43119
- return ids;
43120
- };
43121
43089
  handlers['account-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.mutator)(async function ({ name, balance, offBudget, closed }) {
43122
43090
  return (0, _undo__WEBPACK_IMPORTED_MODULE_48__.withUndo)(async () => {
43123
43091
  const id = await _db__WEBPACK_IMPORTED_MODULE_27__.insertAccount({
@@ -43145,8 +43113,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43145
43113
  });
43146
43114
  });
43147
43115
  handlers['account-close'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.mutator)(async function ({ id, transferAccountId, categoryId, forced }) {
43148
- // Unlink the account if it's linked. This makes sure to remove it
43149
- // from Plaid. (This should not be undo-able, as it mutates the
43116
+ // Unlink the account if it's linked. This makes sure to remove it from
43117
+ // bank-sync providers. (This should not be undo-able, as it mutates the
43150
43118
  // remote server and the user will have to link the account again)
43151
43119
  await handlers['account-unlink']({
43152
43120
  id
@@ -43243,127 +43211,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43243
43211
  });
43244
43212
  });
43245
43213
  let stopPolling = false;
43246
- handlers['poll-web-token'] = async function ({ token }) {
43247
- const [[, userId], [, key]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.multiGet([
43248
- 'user-id',
43249
- 'user-key'
43250
- ]);
43251
- const startTime = Date.now();
43252
- stopPolling = false;
43253
- async function getData(cb) {
43254
- if (stopPolling) {
43255
- return;
43256
- }
43257
- if (Date.now() - startTime >= 1000 * 60 * 10) {
43258
- cb('timeout');
43259
- return;
43260
- }
43261
- const data = await (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().PLAID_SERVER + '/get-web-token-contents', {
43262
- userId,
43263
- key,
43264
- token
43265
- });
43266
- if (data) {
43267
- if (data.error) {
43268
- cb('unknown');
43269
- }
43270
- else {
43271
- cb(null, data);
43272
- }
43273
- }
43274
- else {
43275
- setTimeout(() => getData(cb), 3000);
43276
- }
43277
- }
43278
- return new Promise((resolve) => {
43279
- getData((error, data) => {
43280
- if (error) {
43281
- resolve({
43282
- error
43283
- });
43284
- }
43285
- else {
43286
- resolve({
43287
- data
43288
- });
43289
- }
43290
- });
43291
- });
43292
- };
43293
- handlers['poll-web-token-stop'] = async function () {
43294
- stopPolling = true;
43295
- return 'ok';
43296
- };
43297
- handlers['accounts-sync'] = async function ({ id }) {
43298
- const [[, userId], [, userKey]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.multiGet([
43299
- 'user-id',
43300
- 'user-key'
43301
- ]);
43302
- let accounts = await _db__WEBPACK_IMPORTED_MODULE_27__.runQuery(`SELECT a.*, b.id as bankId FROM accounts a
43303
- LEFT JOIN banks b ON a.bank = b.id
43304
- WHERE a.tombstone = 0 AND a.closed = 0`, [], true);
43305
- if (id) {
43306
- accounts = accounts.filter((acct) => acct.id === id);
43307
- }
43308
- const errors = [];
43309
- let newTransactions = [];
43310
- let matchedTransactions = [];
43311
- let updatedAccounts = [];
43312
- for (let i = 0; i < accounts.length; i++) {
43313
- const acct = accounts[i];
43314
- if (acct.bankId) {
43315
- try {
43316
- const res = await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncAccount(userId, userKey, acct.id, acct.account_id, acct.bankId);
43317
- const { added, updated } = res;
43318
- newTransactions = newTransactions.concat(added);
43319
- matchedTransactions = matchedTransactions.concat(updated);
43320
- if (added.length > 0 || updated.length > 0) {
43321
- updatedAccounts = updatedAccounts.concat(acct.id);
43322
- }
43323
- }
43324
- catch (err) {
43325
- if (err.type === 'BankSyncError') {
43326
- errors.push({
43327
- type: 'SyncError',
43328
- accountId: acct.id,
43329
- message: 'Failed syncing account “' + acct.name + '.”',
43330
- category: err.category,
43331
- code: err.code
43332
- });
43333
- }
43334
- else if (err instanceof _errors__WEBPACK_IMPORTED_MODULE_30__.PostError && err.reason !== 'internal') {
43335
- errors.push({
43336
- accountId: acct.id,
43337
- message: `Account “${acct.name}” is not linked properly. Please link it again`
43338
- });
43339
- }
43340
- else {
43341
- errors.push({
43342
- accountId: acct.id,
43343
- message: 'There was an internal error. Please get in touch https://actualbudget.org/contact for support.',
43344
- internal: err.stack
43345
- });
43346
- err.message = 'Failed syncing account: ' + err.message;
43347
- (0, _platform_exceptions__WEBPACK_IMPORTED_MODULE_4__.captureException)(err);
43348
- }
43349
- }
43350
- }
43351
- }
43352
- if (updatedAccounts.length > 0) {
43353
- _platform_server_connection__WEBPACK_IMPORTED_MODULE_6__.send('sync-event', {
43354
- type: 'success',
43355
- tables: [
43356
- 'transactions'
43357
- ]
43358
- });
43359
- }
43360
- return {
43361
- errors,
43362
- newTransactions,
43363
- matchedTransactions,
43364
- updatedAccounts
43365
- };
43366
- };
43367
43214
  handlers['secret-set'] = async function ({ name, value }) {
43368
43215
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.getItem('user-token');
43369
43216
  if (!userToken) {
@@ -43547,7 +43394,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43547
43394
  if (acct.bankId) {
43548
43395
  try {
43549
43396
  console.group('Bank Sync operation');
43550
- const res = await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncExternalAccount(userId, userKey, acct.id, acct.account_id, acct.bankId);
43397
+ const res = await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncAccount(userId, userKey, acct.id, acct.account_id, acct.bankId);
43551
43398
  console.groupEnd();
43552
43399
  const { added, updated } = res;
43553
43400
  newTransactions = newTransactions.concat(added);
@@ -43674,27 +43521,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43674
43521
  }
43675
43522
  return 'ok';
43676
43523
  });
43677
- handlers['make-plaid-public-token'] = async function ({ bankId }) {
43678
- const [[, userId], [, userKey]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.multiGet([
43679
- 'user-id',
43680
- 'user-key'
43681
- ]);
43682
- const data = await (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().PLAID_SERVER + '/make-public-token', {
43683
- userId,
43684
- key: userKey,
43685
- item_id: '' + bankId
43686
- });
43687
- if (data.error_code) {
43688
- return {
43689
- error: '',
43690
- code: data.error_code,
43691
- type: data.error_type
43692
- };
43693
- }
43694
- return {
43695
- linkToken: data.link_token
43696
- };
43697
- };
43698
43524
  handlers['save-global-prefs'] = async function (prefs) {
43699
43525
  if ('maxMonths' in prefs) {
43700
43526
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.setItem('max-months', '' + prefs.maxMonths);
@@ -43734,7 +43560,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43734
43560
  autoUpdate: autoUpdate == null || autoUpdate === 'true' ? true : false,
43735
43561
  documentDir: documentDir || getDefaultDocumentDir(),
43736
43562
  keyId: encryptKey && JSON.parse(encryptKey).id,
43737
- theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'light'
43563
+ theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'auto'
43738
43564
  };
43739
43565
  };
43740
43566
  handlers['save-prefs'] = async function (prefsToSet) {
@@ -43980,16 +43806,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43980
43806
  return {};
43981
43807
  };
43982
43808
  handlers['subscribe-sign-in'] = async function ({ password }) {
43983
- const res = await (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().SIGNUP_SERVER + '/login', {
43984
- password
43985
- });
43986
- if (res.token) {
43987
- await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.setItem('user-token', res.token);
43988
- return {};
43809
+ let res;
43810
+ try {
43811
+ res = await (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().SIGNUP_SERVER + '/login', {
43812
+ password
43813
+ });
43989
43814
  }
43990
- return {
43991
- error: 'invalid-password'
43992
- };
43815
+ catch (err) {
43816
+ return {
43817
+ error: err.reason || 'network-failure'
43818
+ };
43819
+ }
43820
+ if (!res.token) {
43821
+ throw new Error('login: User token not set');
43822
+ }
43823
+ await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.setItem('user-token', res.token);
43824
+ return {};
43993
43825
  };
43994
43826
  handlers['subscribe-sign-out'] = async function () {
43995
43827
  _encryption__WEBPACK_IMPORTED_MODULE_29__.unloadAllKeys();
@@ -44071,8 +43903,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44071
43903
  if (name !== DEMO_BUDGET_ID) {
44072
43904
  return {
44073
43905
  id: name,
44074
- cloudFileId: prefs.cloudFileId,
44075
- groupId: prefs.groupId,
43906
+ ...prefs.cloudFileId ? {
43907
+ cloudFileId: prefs.cloudFileId
43908
+ } : {},
43909
+ ...prefs.groupId ? {
43910
+ groupId: prefs.groupId
43911
+ } : {},
44076
43912
  name: prefs.budgetName || '(no name)'
44077
43913
  };
44078
43914
  }
@@ -46366,7 +46202,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
46366
46202
  BASE_SERVER: url,
46367
46203
  SYNC_SERVER: joinURL(url, '/sync'),
46368
46204
  SIGNUP_SERVER: joinURL(url, '/account'),
46369
- PLAID_SERVER: joinURL(url, '/plaid'),
46370
46205
  GOCARDLESS_SERVER: joinURL(url, '/gocardless'),
46371
46206
  SIMPLEFIN_SERVER: joinURL(url, '/simplefin')
46372
46207
  };
@@ -48789,6 +48624,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48789
48624
  "use strict";
48790
48625
  __webpack_require__.r(__webpack_exports__);
48791
48626
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
48627
+ /* harmony export */ LazyLoadFailedError: () => ( /* binding */LazyLoadFailedError),
48792
48628
  /* harmony export */ getCreateKeyError: () => ( /* binding */getCreateKeyError),
48793
48629
  /* harmony export */ getDownloadError: () => ( /* binding */getDownloadError),
48794
48630
  /* harmony export */ getSyncError: () => ( /* binding */getSyncError),
@@ -48863,6 +48699,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48863
48699
  return `We had an unknown problem opening “${id}”.`;
48864
48700
  }
48865
48701
  }
48702
+ class LazyLoadFailedError extends Error {
48703
+ constructor(name) {
48704
+ super(`Error: failed loading lazy-loaded module ${name}`);
48705
+ this.type = 'app-init-failure';
48706
+ this.meta = {};
48707
+ this.meta = {
48708
+ name
48709
+ };
48710
+ }
48711
+ }
48866
48712
  /***/
48867
48713
  }),
48868
48714
  /***/ "./packages/loot-core/src/shared/months.ts":
@@ -48876,13 +48722,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48876
48722
  /* harmony export */ _dayRange: () => ( /* binding */_dayRange),
48877
48723
  /* harmony export */ _parse: () => ( /* binding */_parse),
48878
48724
  /* harmony export */ _range: () => ( /* binding */_range),
48725
+ /* harmony export */ _weekRange: () => ( /* binding */_weekRange),
48726
+ /* harmony export */ _yearRange: () => ( /* binding */_yearRange),
48879
48727
  /* harmony export */ addDays: () => ( /* binding */addDays),
48880
48728
  /* harmony export */ addMonths: () => ( /* binding */addMonths),
48881
48729
  /* harmony export */ addWeeks: () => ( /* binding */addWeeks),
48730
+ /* harmony export */ addYears: () => ( /* binding */addYears),
48882
48731
  /* harmony export */ bounds: () => ( /* binding */bounds),
48883
48732
  /* harmony export */ currentDate: () => ( /* binding */currentDate),
48884
48733
  /* harmony export */ currentDay: () => ( /* binding */currentDay),
48885
48734
  /* harmony export */ currentMonth: () => ( /* binding */currentMonth),
48735
+ /* harmony export */ currentWeek: () => ( /* binding */currentWeek),
48736
+ /* harmony export */ currentYear: () => ( /* binding */currentYear),
48886
48737
  /* harmony export */ dayFromDate: () => ( /* binding */dayFromDate),
48887
48738
  /* harmony export */ dayRange: () => ( /* binding */dayRange),
48888
48739
  /* harmony export */ dayRangeInclusive: () => ( /* binding */dayRangeInclusive),
@@ -48890,15 +48741,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48890
48741
  /* harmony export */ differenceInCalendarMonths: () => ( /* binding */differenceInCalendarMonths),
48891
48742
  /* harmony export */ format: () => ( /* binding */format),
48892
48743
  /* harmony export */ getDateFormatRegex: () => ( /* binding */getDateFormatRegex),
48744
+ /* harmony export */ getDay: () => ( /* binding */getDay),
48893
48745
  /* harmony export */ getDayMonthFormat: () => ( /* binding */getDayMonthFormat),
48894
48746
  /* harmony export */ getDayMonthRegex: () => ( /* binding */getDayMonthRegex),
48895
48747
  /* harmony export */ getMonth: () => ( /* binding */getMonth),
48748
+ /* harmony export */ getMonthEnd: () => ( /* binding */getMonthEnd),
48896
48749
  /* harmony export */ getMonthFromIndex: () => ( /* binding */getMonthFromIndex),
48897
48750
  /* harmony export */ getMonthIndex: () => ( /* binding */getMonthIndex),
48898
48751
  /* harmony export */ getMonthYearFormat: () => ( /* binding */getMonthYearFormat),
48899
48752
  /* harmony export */ getMonthYearRegex: () => ( /* binding */getMonthYearRegex),
48900
48753
  /* harmony export */ getShortYearFormat: () => ( /* binding */getShortYearFormat),
48901
48754
  /* harmony export */ getShortYearRegex: () => ( /* binding */getShortYearRegex),
48755
+ /* harmony export */ getWeekEnd: () => ( /* binding */getWeekEnd),
48902
48756
  /* harmony export */ getYear: () => ( /* binding */getYear),
48903
48757
  /* harmony export */ getYearEnd: () => ( /* binding */getYearEnd),
48904
48758
  /* harmony export */ getYearStart: () => ( /* binding */getYearStart),
@@ -48915,23 +48769,33 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48915
48769
  /* harmony export */ sheetForMonth: () => ( /* binding */sheetForMonth),
48916
48770
  /* harmony export */ subDays: () => ( /* binding */subDays),
48917
48771
  /* harmony export */ subMonths: () => ( /* binding */subMonths),
48918
- /* harmony export */ yearFromDate: () => ( /* binding */yearFromDate)
48772
+ /* harmony export */ subWeeks: () => ( /* binding */subWeeks),
48773
+ /* harmony export */ subYears: () => ( /* binding */subYears),
48774
+ /* harmony export */ weekFromDate: () => ( /* binding */weekFromDate),
48775
+ /* harmony export */ weekRangeInclusive: () => ( /* binding */weekRangeInclusive),
48776
+ /* harmony export */ yearFromDate: () => ( /* binding */yearFromDate),
48777
+ /* harmony export */ yearRangeInclusive: () => ( /* binding */yearRangeInclusive)
48919
48778
  /* harmony export */
48920
48779
  });
48921
48780
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/format/index.js");
48922
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parse/index.js");
48923
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addMonths/index.js");
48924
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subMonths/index.js");
48925
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addWeeks/index.js");
48926
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarMonths/index.js");
48927
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarDays/index.js");
48928
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
48929
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
48930
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isBefore/index.js");
48931
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isAfter/index.js");
48932
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfMonth/index.js");
48933
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfMonth/index.js");
48934
- /* harmony import */ var memoize_one__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! memoize-one */ "./node_modules/memoize-one/dist/memoize-one.esm.js");
48781
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfWeek/index.js");
48782
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parse/index.js");
48783
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addMonths/index.js");
48784
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subMonths/index.js");
48785
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addYears/index.js");
48786
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addWeeks/index.js");
48787
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarMonths/index.js");
48788
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarDays/index.js");
48789
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subWeeks/index.js");
48790
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subYears/index.js");
48791
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
48792
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
48793
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isBefore/index.js");
48794
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isAfter/index.js");
48795
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfMonth/index.js");
48796
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfMonth/index.js");
48797
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfWeek/index.js");
48798
+ /* harmony import */ var memoize_one__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! memoize-one */ "./node_modules/memoize-one/dist/memoize-one.esm.js");
48935
48799
  /* harmony import */ var _client_platform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../client/platform */ "./packages/loot-core/src/client/platform.electron.ts");
48936
48800
  // @ts-strict-ignore
48937
48801
  function _parse(value) {
@@ -49012,6 +48876,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49012
48876
  function monthFromDate(date) {
49013
48877
  return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date), 'yyyy-MM');
49014
48878
  }
48879
+ function weekFromDate(date, firstDayOfWeekIdx) {
48880
+ const converted = parseInt(firstDayOfWeekIdx || '0');
48881
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date_fns__WEBPACK_IMPORTED_MODULE_2__["default"](_parse(date), {
48882
+ weekStartsOn: converted
48883
+ })), 'yyyy-MM-dd');
48884
+ }
49015
48885
  function dayFromDate(date) {
49016
48886
  return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date), 'yyyy-MM-dd');
49017
48887
  }
@@ -49023,9 +48893,28 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49023
48893
  return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](new Date(), 'yyyy-MM');
49024
48894
  }
49025
48895
  }
48896
+ function currentWeek(firstDayOfWeekIdx) {
48897
+ if (global.IS_TESTING || _client_platform__WEBPACK_IMPORTED_MODULE_0__.isPlaywright) {
48898
+ return global.currentWeek || '2017-01-01';
48899
+ }
48900
+ else {
48901
+ const converted = parseInt(firstDayOfWeekIdx || '0');
48902
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date_fns__WEBPACK_IMPORTED_MODULE_2__["default"](new Date(), {
48903
+ weekStartsOn: converted
48904
+ })), 'yyyy-MM-dd');
48905
+ }
48906
+ }
48907
+ function currentYear() {
48908
+ if (global.IS_TESTING || _client_platform__WEBPACK_IMPORTED_MODULE_0__.isPlaywright) {
48909
+ return global.currentMonth || '2017';
48910
+ }
48911
+ else {
48912
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](new Date(), 'yyyy');
48913
+ }
48914
+ }
49026
48915
  function currentDate() {
49027
48916
  if (global.IS_TESTING || _client_platform__WEBPACK_IMPORTED_MODULE_0__.isPlaywright) {
49028
- return date_fns__WEBPACK_IMPORTED_MODULE_2__["default"](currentDay(), 'yyyy-MM-dd', new Date());
48917
+ return date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](currentDay(), 'yyyy-MM-dd', new Date());
49029
48918
  }
49030
48919
  return new Date();
49031
48920
  }
@@ -49038,53 +48927,92 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49038
48927
  }
49039
48928
  }
49040
48929
  function nextMonth(month) {
49041
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](_parse(month), 1), 'yyyy-MM');
48930
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), 1), 'yyyy-MM');
49042
48931
  }
49043
48932
  function prevYear(month) {
49044
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), 12), 'yyyy-MM');
48933
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), 12), 'yyyy-MM');
49045
48934
  }
49046
48935
  function prevMonth(month) {
49047
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), 1), 'yyyy-MM');
48936
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), 1), 'yyyy-MM');
48937
+ }
48938
+ function addYears(year, n) {
48939
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](_parse(year), n), 'yyyy');
49048
48940
  }
49049
48941
  function addMonths(month, n) {
49050
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](_parse(month), n), 'yyyy-MM');
48942
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), n), 'yyyy-MM');
49051
48943
  }
49052
48944
  function addWeeks(date, n) {
49053
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(date), n), 'yyyy-MM-dd');
48945
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(date), n), 'yyyy-MM-dd');
49054
48946
  }
49055
48947
  function differenceInCalendarMonths(month1, month2) {
49056
- return date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](_parse(month1), _parse(month2));
48948
+ return date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](_parse(month1), _parse(month2));
49057
48949
  }
49058
48950
  function differenceInCalendarDays(month1, month2) {
49059
- return date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(month1), _parse(month2));
48951
+ return date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](_parse(month1), _parse(month2));
49060
48952
  }
49061
48953
  function subMonths(month, n) {
49062
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), n), 'yyyy-MM');
48954
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), n), 'yyyy-MM');
48955
+ }
48956
+ function subWeeks(date, n) {
48957
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(date), n), 'yyyy-MM-dd');
48958
+ }
48959
+ function subYears(year, n) {
48960
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](_parse(year), n), 'yyyy');
49063
48961
  }
49064
48962
  function addDays(day, n) {
49065
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](_parse(day), n), 'yyyy-MM-dd');
48963
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_12__["default"](_parse(day), n), 'yyyy-MM-dd');
49066
48964
  }
49067
48965
  function subDays(day, n) {
49068
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](_parse(day), n), 'yyyy-MM-dd');
48966
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_13__["default"](_parse(day), n), 'yyyy-MM-dd');
49069
48967
  }
49070
48968
  function isBefore(month1, month2) {
49071
- return date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(month1), _parse(month2));
48969
+ return date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month1), _parse(month2));
49072
48970
  }
49073
48971
  function isAfter(month1, month2) {
49074
- return date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](_parse(month1), _parse(month2));
48972
+ return date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_parse(month1), _parse(month2));
49075
48973
  }
49076
48974
  // TODO: This doesn't really fit in this module anymore, should
49077
48975
  // probably live elsewhere
49078
48976
  function bounds(month) {
49079
48977
  return {
49080
- start: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_12__["default"](_parse(month)), 'yyyyMMdd')),
49081
- end: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_13__["default"](_parse(month)), 'yyyyMMdd'))
48978
+ start: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(month)), 'yyyyMMdd')),
48979
+ end: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_17__["default"](_parse(month)), 'yyyyMMdd'))
49082
48980
  };
49083
48981
  }
48982
+ function _yearRange(start, end, inclusive = false) {
48983
+ const years = [];
48984
+ let year = yearFromDate(start);
48985
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(year), _parse(end))) {
48986
+ years.push(year);
48987
+ year = addYears(year, 1);
48988
+ }
48989
+ if (inclusive) {
48990
+ years.push(year);
48991
+ }
48992
+ return years;
48993
+ }
48994
+ function yearRangeInclusive(start, end) {
48995
+ return _yearRange(start, end, true);
48996
+ }
48997
+ function _weekRange(start, end, inclusive = false, firstDayOfWeekIdx) {
48998
+ const weeks = [];
48999
+ let week = weekFromDate(start, firstDayOfWeekIdx);
49000
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(week), _parse(end))) {
49001
+ weeks.push(week);
49002
+ week = addWeeks(week, 1);
49003
+ }
49004
+ if (inclusive) {
49005
+ weeks.push(week);
49006
+ }
49007
+ return weeks;
49008
+ }
49009
+ function weekRangeInclusive(start, end, firstDayOfWeekIdx) {
49010
+ return _weekRange(start, end, true, firstDayOfWeekIdx);
49011
+ }
49084
49012
  function _range(start, end, inclusive = false) {
49085
49013
  const months = [];
49086
49014
  let month = monthFromDate(start);
49087
- while (date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(month), _parse(end))) {
49015
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month), _parse(end))) {
49088
49016
  months.push(month);
49089
49017
  month = addMonths(month, 1);
49090
49018
  }
@@ -49102,7 +49030,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49102
49030
  function _dayRange(start, end, inclusive = false) {
49103
49031
  const days = [];
49104
49032
  let day = start;
49105
- while (date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(day), _parse(end))) {
49033
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(day), _parse(end))) {
49106
49034
  days.push(dayFromDate(day));
49107
49035
  day = addDays(day, 1);
49108
49036
  }
@@ -49130,6 +49058,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49130
49058
  function getMonth(day) {
49131
49059
  return day.slice(0, 7);
49132
49060
  }
49061
+ function getDay(day) {
49062
+ return Number(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(day), 'dd'));
49063
+ }
49064
+ function getMonthEnd(day) {
49065
+ return subDays(nextMonth(day.slice(0, 7)) + '-01', 1);
49066
+ }
49067
+ function getWeekEnd(date, firstDayOfWeekIdx) {
49068
+ const converted = parseInt(firstDayOfWeekIdx || '0');
49069
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date_fns__WEBPACK_IMPORTED_MODULE_18__["default"](_parse(date), {
49070
+ weekStartsOn: converted
49071
+ })), 'yyyy-MM-dd');
49072
+ }
49133
49073
  function getYearStart(month) {
49134
49074
  return getYear(month) + '-01';
49135
49075
  }
@@ -49140,33 +49080,32 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49140
49080
  return 'budget' + month.replace('-', '');
49141
49081
  }
49142
49082
  function nameForMonth(month) {
49143
- // eslint-disable-next-line rulesdir/typography
49144
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(month), "MMMM 'yy");
49083
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(month), 'MMMM ‘yy');
49145
49084
  }
49146
49085
  function format(month, str) {
49147
49086
  return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(month), str);
49148
49087
  }
49149
- const getDateFormatRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49088
+ const getDateFormatRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49150
49089
  return new RegExp(format.replace(/d+/g, '\\d{1,2}').replace(/M+/g, '\\d{1,2}').replace(/y+/g, '\\d{4}'));
49151
49090
  });
49152
- const getDayMonthFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49091
+ const getDayMonthFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49153
49092
  return format.replace(/y+/g, '').replace(/[^\w]$/, '').replace(/^[^\w]/, '');
49154
49093
  });
49155
- const getDayMonthRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49094
+ const getDayMonthRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49156
49095
  const regex = format.replace(/y+/g, '').replace(/[^\w]$/, '').replace(/^[^\w]/, '').replace(/d+/g, '\\d{1,2}').replace(/M+/g, '\\d{1,2}');
49157
49096
  return new RegExp('^' + regex + '$');
49158
49097
  });
49159
- const getMonthYearFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49098
+ const getMonthYearFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49160
49099
  return format.replace(/d+/g, '').replace(/[^\w]$/, '').replace(/^[^\w]/, '').replace(/\/\//, '/').replace(/\.\./, '.').replace(/--/, '-');
49161
49100
  });
49162
- const getMonthYearRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49101
+ const getMonthYearRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49163
49102
  const regex = format.replace(/d+/g, '').replace(/[^\w]$/, '').replace(/^[^\w]/, '').replace(/\/\//, '/').replace(/M+/g, '\\d{1,2}').replace(/y+/g, '\\d{2,4}');
49164
49103
  return new RegExp('^' + regex + '$');
49165
49104
  });
49166
- const getShortYearFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49105
+ const getShortYearFormat = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49167
49106
  return format.replace(/y+/g, 'yy');
49168
49107
  });
49169
- const getShortYearRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_14__["default"])((format) => {
49108
+ const getShortYearRegex = (0, memoize_one__WEBPACK_IMPORTED_MODULE_19__["default"])((format) => {
49170
49109
  const regex = format.replace(/[^\w]$/, '').replace(/^[^\w]/, '').replace(/d+/g, '\\d{1,2}').replace(/M+/g, '\\d{1,2}').replace(/y+/g, '\\d{2}');
49171
49110
  return new RegExp('^' + regex + '$');
49172
49111
  });
@@ -50013,11 +49952,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50013
49952
  return {
50014
49953
  amount: 0,
50015
49954
  ...data,
49955
+ category: 'category' in data ? data.category : parent.category,
50016
49956
  payee: 'payee' in data ? data.payee : parent.payee,
50017
49957
  id: 'id' in data ? data.id : prefix + (0, uuid__WEBPACK_IMPORTED_MODULE_1__["default"])(),
50018
49958
  account: parent.account,
50019
49959
  date: parent.date,
50020
49960
  cleared: parent.cleared != null ? parent.cleared : null,
49961
+ reconciled: 'reconciled' in data ? data.reconciled : parent.reconciled,
50021
49962
  starting_balance_flag: parent.starting_balance_flag != null ? parent.starting_balance_flag : null,
50022
49963
  is_child: true,
50023
49964
  parent_id: parent.id,
@@ -50612,7 +50553,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50612
50553
  if (amount.startsWith('(') && amount.endsWith(')')) {
50613
50554
  amount = amount.replace('(', '-').replace(')', '');
50614
50555
  }
50615
- const m = amount.match(/[.,][^.,]{1,2}$/);
50556
+ //look for a decimal marker, then look for either 5 or 1-2 decimal places.
50557
+ // This avoids matching against 3 places which may not actually be decimal
50558
+ const m = amount.match(/[.,]([^.,]{5}|[^.,]{1,2})$/);
50616
50559
  if (!m || m.index === undefined || m.index === 0) {
50617
50560
  return safeNumber(parseFloat(extractNumbers(amount)));
50618
50561
  }
@@ -55580,6 +55523,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55580
55523
  var peg$c0 = "source";
55581
55524
  var peg$c1 = "sink";
55582
55525
  var peg$c2 = " ";
55526
+ var peg$c3 = " source";
55527
+ var peg$c4 = " sink";
55583
55528
  var peg$r0 = /^[0-9]/;
55584
55529
  var peg$e0 = peg$literalExpectation("source", false);
55585
55530
  var peg$e1 = peg$literalExpectation("sink", false);
@@ -55588,9 +55533,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55588
55533
  var peg$e4 = peg$otherExpectation("digit");
55589
55534
  var peg$e5 = peg$classExpectation([["0", "9"]], false, false);
55590
55535
  var peg$e6 = peg$otherExpectation("weight");
55591
- var peg$f0 = function () { return { type: 'source' }; };
55592
- var peg$f1 = function (weight) { return { type: 'sink', weight: +weight || 1 }; };
55593
- var peg$f2 = function (weight) { return +weight; };
55536
+ var peg$e7 = peg$otherExpectation("Name");
55537
+ var peg$e8 = peg$literalExpectation(" source", false);
55538
+ var peg$e9 = peg$anyExpectation();
55539
+ var peg$e10 = peg$literalExpectation(" sink", false);
55540
+ var peg$f0 = function () { return { group: null, type: 'source' }; };
55541
+ var peg$f1 = function (weight) { return { type: 'sink', weight: +weight || 1, group: null }; };
55542
+ var peg$f2 = function (group) { return { group: group || null, type: 'source' }; };
55543
+ var peg$f3 = function (group, weight) { return { type: 'sink', weight: +weight || 1, group: group || null }; };
55544
+ var peg$f4 = function (group) { return { group: group, type: null }; };
55545
+ var peg$f5 = function (weight) { return +weight; };
55594
55546
  var peg$currPos = 0;
55595
55547
  var peg$savedPos = 0;
55596
55548
  var peg$posDetailsCache = [{ line: 1, column: 1 }];
@@ -55716,7 +55668,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55716
55668
  return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location);
55717
55669
  }
55718
55670
  function peg$parseexpr() {
55719
- var s0, s1, s2, s3;
55671
+ var s0, s1, s2, s3, s4, s5;
55720
55672
  s0 = peg$currPos;
55721
55673
  s1 = peg$parsesource();
55722
55674
  if (s1 !== peg$FAILED) {
@@ -55743,6 +55695,55 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55743
55695
  peg$currPos = s0;
55744
55696
  s0 = peg$FAILED;
55745
55697
  }
55698
+ if (s0 === peg$FAILED) {
55699
+ s0 = peg$currPos;
55700
+ s1 = peg$parsesourcegroup();
55701
+ s2 = peg$parse_();
55702
+ if (s2 === peg$FAILED) {
55703
+ s2 = null;
55704
+ }
55705
+ s3 = peg$parsesource();
55706
+ if (s3 !== peg$FAILED) {
55707
+ peg$savedPos = s0;
55708
+ s0 = peg$f2(s1);
55709
+ }
55710
+ else {
55711
+ peg$currPos = s0;
55712
+ s0 = peg$FAILED;
55713
+ }
55714
+ if (s0 === peg$FAILED) {
55715
+ s0 = peg$currPos;
55716
+ s1 = peg$parsesinkgroup();
55717
+ s2 = peg$parse_();
55718
+ if (s2 === peg$FAILED) {
55719
+ s2 = null;
55720
+ }
55721
+ s3 = peg$parsesink();
55722
+ if (s3 !== peg$FAILED) {
55723
+ s4 = peg$parse_();
55724
+ if (s4 === peg$FAILED) {
55725
+ s4 = null;
55726
+ }
55727
+ s5 = peg$parseweight();
55728
+ if (s5 === peg$FAILED) {
55729
+ s5 = null;
55730
+ }
55731
+ peg$savedPos = s0;
55732
+ s0 = peg$f3(s1, s5);
55733
+ }
55734
+ else {
55735
+ peg$currPos = s0;
55736
+ s0 = peg$FAILED;
55737
+ }
55738
+ if (s0 === peg$FAILED) {
55739
+ s0 = peg$currPos;
55740
+ s1 = peg$parsesourcegroup();
55741
+ peg$savedPos = s0;
55742
+ s1 = peg$f4(s1);
55743
+ s0 = s1;
55744
+ }
55745
+ }
55746
+ }
55746
55747
  }
55747
55748
  return s0;
55748
55749
  }
@@ -55861,7 +55862,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55861
55862
  }
55862
55863
  if (s1 !== peg$FAILED) {
55863
55864
  peg$savedPos = s0;
55864
- s1 = peg$f2(s1);
55865
+ s1 = peg$f5(s1);
55865
55866
  }
55866
55867
  s0 = s1;
55867
55868
  peg$silentFails--;
@@ -55873,6 +55874,218 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
55873
55874
  }
55874
55875
  return s0;
55875
55876
  }
55877
+ function peg$parsesourcegroup() {
55878
+ var s0, s1, s2, s3, s4;
55879
+ peg$silentFails++;
55880
+ s0 = peg$currPos;
55881
+ s1 = [];
55882
+ s2 = peg$currPos;
55883
+ s3 = peg$currPos;
55884
+ peg$silentFails++;
55885
+ if (input.substr(peg$currPos, 7) === peg$c3) {
55886
+ s4 = peg$c3;
55887
+ peg$currPos += 7;
55888
+ }
55889
+ else {
55890
+ s4 = peg$FAILED;
55891
+ if (peg$silentFails === 0) {
55892
+ peg$fail(peg$e8);
55893
+ }
55894
+ }
55895
+ peg$silentFails--;
55896
+ if (s4 === peg$FAILED) {
55897
+ s3 = undefined;
55898
+ }
55899
+ else {
55900
+ peg$currPos = s3;
55901
+ s3 = peg$FAILED;
55902
+ }
55903
+ if (s3 !== peg$FAILED) {
55904
+ if (input.length > peg$currPos) {
55905
+ s4 = input.charAt(peg$currPos);
55906
+ peg$currPos++;
55907
+ }
55908
+ else {
55909
+ s4 = peg$FAILED;
55910
+ if (peg$silentFails === 0) {
55911
+ peg$fail(peg$e9);
55912
+ }
55913
+ }
55914
+ if (s4 !== peg$FAILED) {
55915
+ s3 = [s3, s4];
55916
+ s2 = s3;
55917
+ }
55918
+ else {
55919
+ peg$currPos = s2;
55920
+ s2 = peg$FAILED;
55921
+ }
55922
+ }
55923
+ else {
55924
+ peg$currPos = s2;
55925
+ s2 = peg$FAILED;
55926
+ }
55927
+ while (s2 !== peg$FAILED) {
55928
+ s1.push(s2);
55929
+ s2 = peg$currPos;
55930
+ s3 = peg$currPos;
55931
+ peg$silentFails++;
55932
+ if (input.substr(peg$currPos, 7) === peg$c3) {
55933
+ s4 = peg$c3;
55934
+ peg$currPos += 7;
55935
+ }
55936
+ else {
55937
+ s4 = peg$FAILED;
55938
+ if (peg$silentFails === 0) {
55939
+ peg$fail(peg$e8);
55940
+ }
55941
+ }
55942
+ peg$silentFails--;
55943
+ if (s4 === peg$FAILED) {
55944
+ s3 = undefined;
55945
+ }
55946
+ else {
55947
+ peg$currPos = s3;
55948
+ s3 = peg$FAILED;
55949
+ }
55950
+ if (s3 !== peg$FAILED) {
55951
+ if (input.length > peg$currPos) {
55952
+ s4 = input.charAt(peg$currPos);
55953
+ peg$currPos++;
55954
+ }
55955
+ else {
55956
+ s4 = peg$FAILED;
55957
+ if (peg$silentFails === 0) {
55958
+ peg$fail(peg$e9);
55959
+ }
55960
+ }
55961
+ if (s4 !== peg$FAILED) {
55962
+ s3 = [s3, s4];
55963
+ s2 = s3;
55964
+ }
55965
+ else {
55966
+ peg$currPos = s2;
55967
+ s2 = peg$FAILED;
55968
+ }
55969
+ }
55970
+ else {
55971
+ peg$currPos = s2;
55972
+ s2 = peg$FAILED;
55973
+ }
55974
+ }
55975
+ s0 = input.substring(s0, peg$currPos);
55976
+ peg$silentFails--;
55977
+ s1 = peg$FAILED;
55978
+ if (peg$silentFails === 0) {
55979
+ peg$fail(peg$e7);
55980
+ }
55981
+ return s0;
55982
+ }
55983
+ function peg$parsesinkgroup() {
55984
+ var s0, s1, s2, s3, s4;
55985
+ peg$silentFails++;
55986
+ s0 = peg$currPos;
55987
+ s1 = [];
55988
+ s2 = peg$currPos;
55989
+ s3 = peg$currPos;
55990
+ peg$silentFails++;
55991
+ if (input.substr(peg$currPos, 5) === peg$c4) {
55992
+ s4 = peg$c4;
55993
+ peg$currPos += 5;
55994
+ }
55995
+ else {
55996
+ s4 = peg$FAILED;
55997
+ if (peg$silentFails === 0) {
55998
+ peg$fail(peg$e10);
55999
+ }
56000
+ }
56001
+ peg$silentFails--;
56002
+ if (s4 === peg$FAILED) {
56003
+ s3 = undefined;
56004
+ }
56005
+ else {
56006
+ peg$currPos = s3;
56007
+ s3 = peg$FAILED;
56008
+ }
56009
+ if (s3 !== peg$FAILED) {
56010
+ if (input.length > peg$currPos) {
56011
+ s4 = input.charAt(peg$currPos);
56012
+ peg$currPos++;
56013
+ }
56014
+ else {
56015
+ s4 = peg$FAILED;
56016
+ if (peg$silentFails === 0) {
56017
+ peg$fail(peg$e9);
56018
+ }
56019
+ }
56020
+ if (s4 !== peg$FAILED) {
56021
+ s3 = [s3, s4];
56022
+ s2 = s3;
56023
+ }
56024
+ else {
56025
+ peg$currPos = s2;
56026
+ s2 = peg$FAILED;
56027
+ }
56028
+ }
56029
+ else {
56030
+ peg$currPos = s2;
56031
+ s2 = peg$FAILED;
56032
+ }
56033
+ while (s2 !== peg$FAILED) {
56034
+ s1.push(s2);
56035
+ s2 = peg$currPos;
56036
+ s3 = peg$currPos;
56037
+ peg$silentFails++;
56038
+ if (input.substr(peg$currPos, 5) === peg$c4) {
56039
+ s4 = peg$c4;
56040
+ peg$currPos += 5;
56041
+ }
56042
+ else {
56043
+ s4 = peg$FAILED;
56044
+ if (peg$silentFails === 0) {
56045
+ peg$fail(peg$e10);
56046
+ }
56047
+ }
56048
+ peg$silentFails--;
56049
+ if (s4 === peg$FAILED) {
56050
+ s3 = undefined;
56051
+ }
56052
+ else {
56053
+ peg$currPos = s3;
56054
+ s3 = peg$FAILED;
56055
+ }
56056
+ if (s3 !== peg$FAILED) {
56057
+ if (input.length > peg$currPos) {
56058
+ s4 = input.charAt(peg$currPos);
56059
+ peg$currPos++;
56060
+ }
56061
+ else {
56062
+ s4 = peg$FAILED;
56063
+ if (peg$silentFails === 0) {
56064
+ peg$fail(peg$e9);
56065
+ }
56066
+ }
56067
+ if (s4 !== peg$FAILED) {
56068
+ s3 = [s3, s4];
56069
+ s2 = s3;
56070
+ }
56071
+ else {
56072
+ peg$currPos = s2;
56073
+ s2 = peg$FAILED;
56074
+ }
56075
+ }
56076
+ else {
56077
+ peg$currPos = s2;
56078
+ s2 = peg$FAILED;
56079
+ }
56080
+ }
56081
+ s0 = input.substring(s0, peg$currPos);
56082
+ peg$silentFails--;
56083
+ s1 = peg$FAILED;
56084
+ if (peg$silentFails === 0) {
56085
+ peg$fail(peg$e7);
56086
+ }
56087
+ return s0;
56088
+ }
55876
56089
  peg$result = peg$startRuleFunction();
55877
56090
  if (peg$result !== peg$FAILED && peg$currPos === input.length) {
55878
56091
  return peg$result;
@@ -56060,73 +56273,75 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56060
56273
  var peg$source = options.grammarSource;
56061
56274
  var peg$startRuleFunctions = { expr: peg$parseexpr };
56062
56275
  var peg$startRuleFunction = peg$parseexpr;
56063
- var peg$c0 = "month";
56276
+ var peg$c0 = "average";
56064
56277
  var peg$c1 = "months";
56065
- var peg$c2 = "year";
56066
- var peg$c3 = "years";
56067
- var peg$c4 = "hold";
56068
- var peg$c5 = "previous";
56069
- var peg$c6 = "spend";
56070
- var peg$c7 = "from";
56071
- var peg$c8 = "week";
56072
- var peg$c9 = "weeks";
56073
- var peg$c10 = "by";
56074
- var peg$c11 = "of";
56075
- var peg$c12 = "repeat";
56076
- var peg$c13 = "every";
56077
- var peg$c14 = "starting";
56078
- var peg$c15 = "up";
56079
- var peg$c16 = "to";
56080
- var peg$c17 = "schedule";
56081
- var peg$c18 = "full";
56082
- var peg$c19 = "-";
56083
- var peg$c20 = "remainder";
56084
- var peg$c21 = " ";
56085
- var peg$c22 = ".";
56086
- var peg$c23 = "%";
56278
+ var peg$c2 = "month";
56279
+ var peg$c3 = "year";
56280
+ var peg$c4 = "years";
56281
+ var peg$c5 = "hold";
56282
+ var peg$c6 = "previous";
56283
+ var peg$c7 = "spend";
56284
+ var peg$c8 = "from";
56285
+ var peg$c9 = "week";
56286
+ var peg$c10 = "weeks";
56287
+ var peg$c11 = "by";
56288
+ var peg$c12 = "of";
56289
+ var peg$c13 = "repeat";
56290
+ var peg$c14 = "every";
56291
+ var peg$c15 = "starting";
56292
+ var peg$c16 = "up";
56293
+ var peg$c17 = "to";
56294
+ var peg$c18 = "schedule";
56295
+ var peg$c19 = "full";
56296
+ var peg$c20 = "-";
56297
+ var peg$c21 = "remainder";
56298
+ var peg$c22 = " ";
56299
+ var peg$c23 = ".";
56300
+ var peg$c24 = "%";
56087
56301
  var peg$r0 = /^[0-9]/;
56088
56302
  var peg$r1 = /^[1-9]/;
56089
56303
  var peg$r2 = /^[^\r\n\t]/;
56090
- var peg$e0 = peg$otherExpectation("repeat interval");
56091
- var peg$e1 = peg$literalExpectation("month", true);
56092
- var peg$e2 = peg$literalExpectation("months", true);
56093
- var peg$e3 = peg$literalExpectation("year", true);
56094
- var peg$e4 = peg$literalExpectation("years", true);
56095
- var peg$e5 = peg$literalExpectation("hold", true);
56096
- var peg$e6 = peg$literalExpectation("previous", true);
56097
- var peg$e7 = peg$literalExpectation("spend", true);
56098
- var peg$e8 = peg$literalExpectation("from", true);
56099
- var peg$e9 = peg$literalExpectation("week", true);
56100
- var peg$e10 = peg$literalExpectation("weeks", true);
56101
- var peg$e11 = peg$literalExpectation("by", true);
56102
- var peg$e12 = peg$literalExpectation("of", true);
56103
- var peg$e13 = peg$literalExpectation("repeat", true);
56104
- var peg$e14 = peg$literalExpectation("every", true);
56105
- var peg$e15 = peg$literalExpectation("starting", true);
56106
- var peg$e16 = peg$literalExpectation("up", true);
56107
- var peg$e17 = peg$literalExpectation("to", true);
56108
- var peg$e18 = peg$literalExpectation("schedule", true);
56109
- var peg$e19 = peg$literalExpectation("full", true);
56110
- var peg$e20 = peg$literalExpectation("-", true);
56111
- var peg$e21 = peg$literalExpectation("remainder", true);
56112
- var peg$e22 = peg$otherExpectation("space");
56113
- var peg$e23 = peg$literalExpectation(" ", false);
56114
- var peg$e24 = peg$otherExpectation("digit");
56115
- var peg$e25 = peg$classExpectation([["0", "9"]], false, false);
56116
- var peg$e26 = peg$otherExpectation("number");
56117
- var peg$e27 = peg$classExpectation([["1", "9"]], false, false);
56118
- var peg$e28 = peg$otherExpectation("amount");
56119
- var peg$e29 = peg$literalExpectation(".", false);
56120
- var peg$e30 = peg$otherExpectation("percentage");
56121
- var peg$e31 = peg$literalExpectation("%", false);
56122
- var peg$e32 = peg$otherExpectation("year");
56123
- var peg$e33 = peg$otherExpectation("month");
56124
- var peg$e34 = peg$literalExpectation("-", false);
56125
- var peg$e35 = peg$otherExpectation("day");
56126
- var peg$e36 = peg$otherExpectation("currency symbol");
56127
- var peg$e37 = peg$anyExpectation();
56128
- var peg$e38 = peg$otherExpectation("Name");
56129
- var peg$e39 = peg$classExpectation(["\r", "\n", "\t"], true, false);
56304
+ var peg$e0 = peg$literalExpectation("average", true);
56305
+ var peg$e1 = peg$literalExpectation("months", true);
56306
+ var peg$e2 = peg$otherExpectation("repeat interval");
56307
+ var peg$e3 = peg$literalExpectation("month", true);
56308
+ var peg$e4 = peg$literalExpectation("year", true);
56309
+ var peg$e5 = peg$literalExpectation("years", true);
56310
+ var peg$e6 = peg$literalExpectation("hold", true);
56311
+ var peg$e7 = peg$literalExpectation("previous", true);
56312
+ var peg$e8 = peg$literalExpectation("spend", true);
56313
+ var peg$e9 = peg$literalExpectation("from", true);
56314
+ var peg$e10 = peg$literalExpectation("week", true);
56315
+ var peg$e11 = peg$literalExpectation("weeks", true);
56316
+ var peg$e12 = peg$literalExpectation("by", true);
56317
+ var peg$e13 = peg$literalExpectation("of", true);
56318
+ var peg$e14 = peg$literalExpectation("repeat", true);
56319
+ var peg$e15 = peg$literalExpectation("every", true);
56320
+ var peg$e16 = peg$literalExpectation("starting", true);
56321
+ var peg$e17 = peg$literalExpectation("up", true);
56322
+ var peg$e18 = peg$literalExpectation("to", true);
56323
+ var peg$e19 = peg$literalExpectation("schedule", true);
56324
+ var peg$e20 = peg$literalExpectation("full", true);
56325
+ var peg$e21 = peg$literalExpectation("-", true);
56326
+ var peg$e22 = peg$literalExpectation("remainder", true);
56327
+ var peg$e23 = peg$otherExpectation("space");
56328
+ var peg$e24 = peg$literalExpectation(" ", false);
56329
+ var peg$e25 = peg$otherExpectation("digit");
56330
+ var peg$e26 = peg$classExpectation([["0", "9"]], false, false);
56331
+ var peg$e27 = peg$otherExpectation("number");
56332
+ var peg$e28 = peg$classExpectation([["1", "9"]], false, false);
56333
+ var peg$e29 = peg$otherExpectation("amount");
56334
+ var peg$e30 = peg$literalExpectation(".", false);
56335
+ var peg$e31 = peg$otherExpectation("percentage");
56336
+ var peg$e32 = peg$literalExpectation("%", false);
56337
+ var peg$e33 = peg$otherExpectation("year");
56338
+ var peg$e34 = peg$otherExpectation("month");
56339
+ var peg$e35 = peg$literalExpectation("-", false);
56340
+ var peg$e36 = peg$otherExpectation("day");
56341
+ var peg$e37 = peg$otherExpectation("currency symbol");
56342
+ var peg$e38 = peg$anyExpectation();
56343
+ var peg$e39 = peg$otherExpectation("Name");
56344
+ var peg$e40 = peg$classExpectation(["\r", "\n", "\t"], true, false);
56130
56345
  var peg$f0 = function (priority, percentOf, category) { return { type: 'percentage', percent: +percentOf.percent, previous: percentOf.prev, category, priority: +priority }; };
56131
56346
  var peg$f1 = function (priority, amount, weeks, starting, limit) { return { type: 'week', amount, weeks, starting, limit, priority: +priority }; };
56132
56347
  var peg$f2 = function (priority, amount, month, from, repeat) {
@@ -56143,23 +56358,24 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56143
56358
  var peg$f4 = function (priority, limit) { return { type: 'simple', limit, priority: +priority }; };
56144
56359
  var peg$f5 = function (priority, full, name) { return { type: 'schedule', name, priority: +priority, full }; };
56145
56360
  var peg$f6 = function (priority, remainder) { return { type: 'remainder', priority: null, weight: remainder }; };
56146
- var peg$f7 = function () { return { annual: false }; };
56147
- var peg$f8 = function (months) { return { annual: false, repeat: +months }; };
56148
- var peg$f9 = function () { return { annual: true }; };
56149
- var peg$f10 = function (years) { return { annual: true, repeat: +years }; };
56150
- var peg$f11 = function (amount) { return { amount: amount, hold: true }; };
56151
- var peg$f12 = function (amount) { return { amount: amount, hold: false }; };
56152
- var peg$f13 = function (percent) { return { percent: percent, prev: true }; };
56153
- var peg$f14 = function (percent) { return { percent: percent, prev: false }; };
56154
- var peg$f15 = function () { return null; };
56155
- var peg$f16 = function (n) { return +n; };
56156
- var peg$f17 = function (month) { return month; };
56157
- var peg$f18 = function () { return true; };
56158
- var peg$f19 = function (number) { return number; };
56159
- var peg$f20 = function (weight) { return +weight || 1; };
56160
- var peg$f21 = function (amount) { return +amount; };
56161
- var peg$f22 = function (percent) { return +percent; };
56162
- var peg$f23 = function (symbol) { return /\p{Sc}/u.test(symbol); };
56361
+ var peg$f7 = function (priority, amount) { return { type: 'average', amount: +amount, priority: +priority }; };
56362
+ var peg$f8 = function () { return { annual: false }; };
56363
+ var peg$f9 = function (months) { return { annual: false, repeat: +months }; };
56364
+ var peg$f10 = function () { return { annual: true }; };
56365
+ var peg$f11 = function (years) { return { annual: true, repeat: +years }; };
56366
+ var peg$f12 = function (amount) { return { amount: amount, hold: true }; };
56367
+ var peg$f13 = function (amount) { return { amount: amount, hold: false }; };
56368
+ var peg$f14 = function (percent) { return { percent: percent, prev: true }; };
56369
+ var peg$f15 = function (percent) { return { percent: percent, prev: false }; };
56370
+ var peg$f16 = function () { return null; };
56371
+ var peg$f17 = function (n) { return +n; };
56372
+ var peg$f18 = function (month) { return month; };
56373
+ var peg$f19 = function () { return true; };
56374
+ var peg$f20 = function (number) { return number; };
56375
+ var peg$f21 = function (weight) { return +weight || 1; };
56376
+ var peg$f22 = function (amount) { return +amount; };
56377
+ var peg$f23 = function (percent) { return +percent; };
56378
+ var peg$f24 = function (symbol) { return /\p{Sc}/u.test(symbol); };
56163
56379
  var peg$currPos = 0;
56164
56380
  var peg$savedPos = 0;
56165
56381
  var peg$posDetailsCache = [{ line: 1, column: 1 }];
@@ -56573,6 +56789,69 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56573
56789
  peg$currPos = s0;
56574
56790
  s0 = peg$FAILED;
56575
56791
  }
56792
+ if (s0 === peg$FAILED) {
56793
+ s0 = peg$currPos;
56794
+ s1 = peg$parsepriority();
56795
+ if (s1 === peg$FAILED) {
56796
+ s1 = null;
56797
+ }
56798
+ s2 = peg$parse_();
56799
+ if (s2 === peg$FAILED) {
56800
+ s2 = null;
56801
+ }
56802
+ if (input.substr(peg$currPos, 7).toLowerCase() === peg$c0) {
56803
+ s3 = input.substr(peg$currPos, 7);
56804
+ peg$currPos += 7;
56805
+ }
56806
+ else {
56807
+ s3 = peg$FAILED;
56808
+ if (peg$silentFails === 0) {
56809
+ peg$fail(peg$e0);
56810
+ }
56811
+ }
56812
+ if (s3 !== peg$FAILED) {
56813
+ s4 = peg$parse_();
56814
+ if (s4 !== peg$FAILED) {
56815
+ s5 = peg$parsepositive();
56816
+ if (s5 !== peg$FAILED) {
56817
+ s6 = peg$parse_();
56818
+ if (s6 !== peg$FAILED) {
56819
+ if (input.substr(peg$currPos, 6).toLowerCase() === peg$c1) {
56820
+ s7 = input.substr(peg$currPos, 6);
56821
+ peg$currPos += 6;
56822
+ }
56823
+ else {
56824
+ s7 = peg$FAILED;
56825
+ if (peg$silentFails === 0) {
56826
+ peg$fail(peg$e1);
56827
+ }
56828
+ }
56829
+ if (s7 === peg$FAILED) {
56830
+ s7 = null;
56831
+ }
56832
+ peg$savedPos = s0;
56833
+ s0 = peg$f7(s1, s5);
56834
+ }
56835
+ else {
56836
+ peg$currPos = s0;
56837
+ s0 = peg$FAILED;
56838
+ }
56839
+ }
56840
+ else {
56841
+ peg$currPos = s0;
56842
+ s0 = peg$FAILED;
56843
+ }
56844
+ }
56845
+ else {
56846
+ peg$currPos = s0;
56847
+ s0 = peg$FAILED;
56848
+ }
56849
+ }
56850
+ else {
56851
+ peg$currPos = s0;
56852
+ s0 = peg$FAILED;
56853
+ }
56854
+ }
56576
56855
  }
56577
56856
  }
56578
56857
  }
@@ -56585,19 +56864,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56585
56864
  var s0, s1, s2, s3;
56586
56865
  peg$silentFails++;
56587
56866
  s0 = peg$currPos;
56588
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c0) {
56867
+ if (input.substr(peg$currPos, 5).toLowerCase() === peg$c2) {
56589
56868
  s1 = input.substr(peg$currPos, 5);
56590
56869
  peg$currPos += 5;
56591
56870
  }
56592
56871
  else {
56593
56872
  s1 = peg$FAILED;
56594
56873
  if (peg$silentFails === 0) {
56595
- peg$fail(peg$e1);
56874
+ peg$fail(peg$e3);
56596
56875
  }
56597
56876
  }
56598
56877
  if (s1 !== peg$FAILED) {
56599
56878
  peg$savedPos = s0;
56600
- s1 = peg$f7();
56879
+ s1 = peg$f8();
56601
56880
  }
56602
56881
  s0 = s1;
56603
56882
  if (s0 === peg$FAILED) {
@@ -56613,12 +56892,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56613
56892
  else {
56614
56893
  s3 = peg$FAILED;
56615
56894
  if (peg$silentFails === 0) {
56616
- peg$fail(peg$e2);
56895
+ peg$fail(peg$e1);
56617
56896
  }
56618
56897
  }
56619
56898
  if (s3 !== peg$FAILED) {
56620
56899
  peg$savedPos = s0;
56621
- s0 = peg$f8(s1);
56900
+ s0 = peg$f9(s1);
56622
56901
  }
56623
56902
  else {
56624
56903
  peg$currPos = s0;
@@ -56636,19 +56915,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56636
56915
  }
56637
56916
  if (s0 === peg$FAILED) {
56638
56917
  s0 = peg$currPos;
56639
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c2) {
56918
+ if (input.substr(peg$currPos, 4).toLowerCase() === peg$c3) {
56640
56919
  s1 = input.substr(peg$currPos, 4);
56641
56920
  peg$currPos += 4;
56642
56921
  }
56643
56922
  else {
56644
56923
  s1 = peg$FAILED;
56645
56924
  if (peg$silentFails === 0) {
56646
- peg$fail(peg$e3);
56925
+ peg$fail(peg$e4);
56647
56926
  }
56648
56927
  }
56649
56928
  if (s1 !== peg$FAILED) {
56650
56929
  peg$savedPos = s0;
56651
- s1 = peg$f9();
56930
+ s1 = peg$f10();
56652
56931
  }
56653
56932
  s0 = s1;
56654
56933
  if (s0 === peg$FAILED) {
@@ -56657,19 +56936,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56657
56936
  if (s1 !== peg$FAILED) {
56658
56937
  s2 = peg$parse_();
56659
56938
  if (s2 !== peg$FAILED) {
56660
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c3) {
56939
+ if (input.substr(peg$currPos, 5).toLowerCase() === peg$c4) {
56661
56940
  s3 = input.substr(peg$currPos, 5);
56662
56941
  peg$currPos += 5;
56663
56942
  }
56664
56943
  else {
56665
56944
  s3 = peg$FAILED;
56666
56945
  if (peg$silentFails === 0) {
56667
- peg$fail(peg$e4);
56946
+ peg$fail(peg$e5);
56668
56947
  }
56669
56948
  }
56670
56949
  if (s3 !== peg$FAILED) {
56671
56950
  peg$savedPos = s0;
56672
- s0 = peg$f10(s1);
56951
+ s0 = peg$f11(s1);
56673
56952
  }
56674
56953
  else {
56675
56954
  peg$currPos = s0;
@@ -56692,7 +56971,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56692
56971
  if (s0 === peg$FAILED) {
56693
56972
  s1 = peg$FAILED;
56694
56973
  if (peg$silentFails === 0) {
56695
- peg$fail(peg$e0);
56974
+ peg$fail(peg$e2);
56696
56975
  }
56697
56976
  }
56698
56977
  return s0;
@@ -56712,19 +56991,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56712
56991
  if (s4 !== peg$FAILED) {
56713
56992
  s5 = peg$parse_();
56714
56993
  if (s5 !== peg$FAILED) {
56715
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c4) {
56994
+ if (input.substr(peg$currPos, 4).toLowerCase() === peg$c5) {
56716
56995
  s6 = input.substr(peg$currPos, 4);
56717
56996
  peg$currPos += 4;
56718
56997
  }
56719
56998
  else {
56720
56999
  s6 = peg$FAILED;
56721
57000
  if (peg$silentFails === 0) {
56722
- peg$fail(peg$e5);
57001
+ peg$fail(peg$e6);
56723
57002
  }
56724
57003
  }
56725
57004
  if (s6 !== peg$FAILED) {
56726
57005
  peg$savedPos = s0;
56727
- s0 = peg$f11(s4);
57006
+ s0 = peg$f12(s4);
56728
57007
  }
56729
57008
  else {
56730
57009
  peg$currPos = s0;
@@ -56763,7 +57042,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56763
57042
  s4 = peg$parseamount();
56764
57043
  if (s4 !== peg$FAILED) {
56765
57044
  peg$savedPos = s0;
56766
- s0 = peg$f12(s4);
57045
+ s0 = peg$f13(s4);
56767
57046
  }
56768
57047
  else {
56769
57048
  peg$currPos = s0;
@@ -56793,21 +57072,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56793
57072
  if (s3 !== peg$FAILED) {
56794
57073
  s4 = peg$parse_();
56795
57074
  if (s4 !== peg$FAILED) {
56796
- if (input.substr(peg$currPos, 8).toLowerCase() === peg$c5) {
57075
+ if (input.substr(peg$currPos, 8).toLowerCase() === peg$c6) {
56797
57076
  s5 = input.substr(peg$currPos, 8);
56798
57077
  peg$currPos += 8;
56799
57078
  }
56800
57079
  else {
56801
57080
  s5 = peg$FAILED;
56802
57081
  if (peg$silentFails === 0) {
56803
- peg$fail(peg$e6);
57082
+ peg$fail(peg$e7);
56804
57083
  }
56805
57084
  }
56806
57085
  if (s5 !== peg$FAILED) {
56807
57086
  s6 = peg$parse_();
56808
57087
  if (s6 !== peg$FAILED) {
56809
57088
  peg$savedPos = s0;
56810
- s0 = peg$f13(s1);
57089
+ s0 = peg$f14(s1);
56811
57090
  }
56812
57091
  else {
56813
57092
  peg$currPos = s0;
@@ -56849,7 +57128,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56849
57128
  s4 = peg$parse_();
56850
57129
  if (s4 !== peg$FAILED) {
56851
57130
  peg$savedPos = s0;
56852
- s0 = peg$f14(s1);
57131
+ s0 = peg$f15(s1);
56853
57132
  }
56854
57133
  else {
56855
57134
  peg$currPos = s0;
@@ -56879,7 +57158,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56879
57158
  s1 = peg$parseweek();
56880
57159
  if (s1 !== peg$FAILED) {
56881
57160
  peg$savedPos = s0;
56882
- s1 = peg$f15();
57161
+ s1 = peg$f16();
56883
57162
  }
56884
57163
  s0 = s1;
56885
57164
  if (s0 === peg$FAILED) {
@@ -56891,7 +57170,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56891
57170
  s3 = peg$parseweeks();
56892
57171
  if (s3 !== peg$FAILED) {
56893
57172
  peg$savedPos = s0;
56894
- s0 = peg$f16(s1);
57173
+ s0 = peg$f17(s1);
56895
57174
  }
56896
57175
  else {
56897
57176
  peg$currPos = s0;
@@ -56915,27 +57194,27 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56915
57194
  s0 = peg$currPos;
56916
57195
  s1 = peg$parse_();
56917
57196
  if (s1 !== peg$FAILED) {
56918
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c6) {
57197
+ if (input.substr(peg$currPos, 5).toLowerCase() === peg$c7) {
56919
57198
  s2 = input.substr(peg$currPos, 5);
56920
57199
  peg$currPos += 5;
56921
57200
  }
56922
57201
  else {
56923
57202
  s2 = peg$FAILED;
56924
57203
  if (peg$silentFails === 0) {
56925
- peg$fail(peg$e7);
57204
+ peg$fail(peg$e8);
56926
57205
  }
56927
57206
  }
56928
57207
  if (s2 !== peg$FAILED) {
56929
57208
  s3 = peg$parse_();
56930
57209
  if (s3 !== peg$FAILED) {
56931
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c7) {
57210
+ if (input.substr(peg$currPos, 4).toLowerCase() === peg$c8) {
56932
57211
  s4 = input.substr(peg$currPos, 4);
56933
57212
  peg$currPos += 4;
56934
57213
  }
56935
57214
  else {
56936
57215
  s4 = peg$FAILED;
56937
57216
  if (peg$silentFails === 0) {
56938
- peg$fail(peg$e8);
57217
+ peg$fail(peg$e9);
56939
57218
  }
56940
57219
  }
56941
57220
  if (s4 !== peg$FAILED) {
@@ -56944,7 +57223,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56944
57223
  s6 = peg$parsemonth();
56945
57224
  if (s6 !== peg$FAILED) {
56946
57225
  peg$savedPos = s0;
56947
- s0 = peg$f17(s6);
57226
+ s0 = peg$f18(s6);
56948
57227
  }
56949
57228
  else {
56950
57229
  peg$currPos = s0;
@@ -56979,56 +57258,56 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
56979
57258
  }
56980
57259
  function peg$parseweek() {
56981
57260
  var s0;
56982
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c8) {
57261
+ if (input.substr(peg$currPos, 4).toLowerCase() === peg$c9) {
56983
57262
  s0 = input.substr(peg$currPos, 4);
56984
57263
  peg$currPos += 4;
56985
57264
  }
56986
57265
  else {
56987
57266
  s0 = peg$FAILED;
56988
57267
  if (peg$silentFails === 0) {
56989
- peg$fail(peg$e9);
57268
+ peg$fail(peg$e10);
56990
57269
  }
56991
57270
  }
56992
57271
  return s0;
56993
57272
  }
56994
57273
  function peg$parseweeks() {
56995
57274
  var s0;
56996
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c9) {
57275
+ if (input.substr(peg$currPos, 5).toLowerCase() === peg$c10) {
56997
57276
  s0 = input.substr(peg$currPos, 5);
56998
57277
  peg$currPos += 5;
56999
57278
  }
57000
57279
  else {
57001
57280
  s0 = peg$FAILED;
57002
57281
  if (peg$silentFails === 0) {
57003
- peg$fail(peg$e10);
57282
+ peg$fail(peg$e11);
57004
57283
  }
57005
57284
  }
57006
57285
  return s0;
57007
57286
  }
57008
57287
  function peg$parseby() {
57009
57288
  var s0;
57010
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c10) {
57289
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c11) {
57011
57290
  s0 = input.substr(peg$currPos, 2);
57012
57291
  peg$currPos += 2;
57013
57292
  }
57014
57293
  else {
57015
57294
  s0 = peg$FAILED;
57016
57295
  if (peg$silentFails === 0) {
57017
- peg$fail(peg$e11);
57296
+ peg$fail(peg$e12);
57018
57297
  }
57019
57298
  }
57020
57299
  return s0;
57021
57300
  }
57022
57301
  function peg$parseof() {
57023
57302
  var s0;
57024
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c11) {
57303
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c12) {
57025
57304
  s0 = input.substr(peg$currPos, 2);
57026
57305
  peg$currPos += 2;
57027
57306
  }
57028
57307
  else {
57029
57308
  s0 = peg$FAILED;
57030
57309
  if (peg$silentFails === 0) {
57031
- peg$fail(peg$e12);
57310
+ peg$fail(peg$e13);
57032
57311
  }
57033
57312
  }
57034
57313
  return s0;
@@ -57036,27 +57315,27 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57036
57315
  function peg$parserepeatEvery() {
57037
57316
  var s0, s1, s2, s3;
57038
57317
  s0 = peg$currPos;
57039
- if (input.substr(peg$currPos, 6).toLowerCase() === peg$c12) {
57318
+ if (input.substr(peg$currPos, 6).toLowerCase() === peg$c13) {
57040
57319
  s1 = input.substr(peg$currPos, 6);
57041
57320
  peg$currPos += 6;
57042
57321
  }
57043
57322
  else {
57044
57323
  s1 = peg$FAILED;
57045
57324
  if (peg$silentFails === 0) {
57046
- peg$fail(peg$e13);
57325
+ peg$fail(peg$e14);
57047
57326
  }
57048
57327
  }
57049
57328
  if (s1 !== peg$FAILED) {
57050
57329
  s2 = peg$parse_();
57051
57330
  if (s2 !== peg$FAILED) {
57052
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c13) {
57331
+ if (input.substr(peg$currPos, 5).toLowerCase() === peg$c14) {
57053
57332
  s3 = input.substr(peg$currPos, 5);
57054
57333
  peg$currPos += 5;
57055
57334
  }
57056
57335
  else {
57057
57336
  s3 = peg$FAILED;
57058
57337
  if (peg$silentFails === 0) {
57059
- peg$fail(peg$e14);
57338
+ peg$fail(peg$e15);
57060
57339
  }
57061
57340
  }
57062
57341
  if (s3 !== peg$FAILED) {
@@ -57081,14 +57360,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57081
57360
  }
57082
57361
  function peg$parsestarting() {
57083
57362
  var s0;
57084
- if (input.substr(peg$currPos, 8).toLowerCase() === peg$c14) {
57363
+ if (input.substr(peg$currPos, 8).toLowerCase() === peg$c15) {
57085
57364
  s0 = input.substr(peg$currPos, 8);
57086
57365
  peg$currPos += 8;
57087
57366
  }
57088
57367
  else {
57089
57368
  s0 = peg$FAILED;
57090
57369
  if (peg$silentFails === 0) {
57091
- peg$fail(peg$e15);
57370
+ peg$fail(peg$e16);
57092
57371
  }
57093
57372
  }
57094
57373
  return s0;
@@ -57096,27 +57375,27 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57096
57375
  function peg$parseupTo() {
57097
57376
  var s0, s1, s2, s3;
57098
57377
  s0 = peg$currPos;
57099
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c15) {
57378
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c16) {
57100
57379
  s1 = input.substr(peg$currPos, 2);
57101
57380
  peg$currPos += 2;
57102
57381
  }
57103
57382
  else {
57104
57383
  s1 = peg$FAILED;
57105
57384
  if (peg$silentFails === 0) {
57106
- peg$fail(peg$e16);
57385
+ peg$fail(peg$e17);
57107
57386
  }
57108
57387
  }
57109
57388
  if (s1 !== peg$FAILED) {
57110
57389
  s2 = peg$parse_();
57111
57390
  if (s2 !== peg$FAILED) {
57112
- if (input.substr(peg$currPos, 2).toLowerCase() === peg$c16) {
57391
+ if (input.substr(peg$currPos, 2).toLowerCase() === peg$c17) {
57113
57392
  s3 = input.substr(peg$currPos, 2);
57114
57393
  peg$currPos += 2;
57115
57394
  }
57116
57395
  else {
57117
57396
  s3 = peg$FAILED;
57118
57397
  if (peg$silentFails === 0) {
57119
- peg$fail(peg$e17);
57398
+ peg$fail(peg$e18);
57120
57399
  }
57121
57400
  }
57122
57401
  if (s3 !== peg$FAILED) {
@@ -57141,14 +57420,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57141
57420
  }
57142
57421
  function peg$parseschedule() {
57143
57422
  var s0;
57144
- if (input.substr(peg$currPos, 8).toLowerCase() === peg$c17) {
57423
+ if (input.substr(peg$currPos, 8).toLowerCase() === peg$c18) {
57145
57424
  s0 = input.substr(peg$currPos, 8);
57146
57425
  peg$currPos += 8;
57147
57426
  }
57148
57427
  else {
57149
57428
  s0 = peg$FAILED;
57150
57429
  if (peg$silentFails === 0) {
57151
- peg$fail(peg$e18);
57430
+ peg$fail(peg$e19);
57152
57431
  }
57153
57432
  }
57154
57433
  return s0;
@@ -57156,21 +57435,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57156
57435
  function peg$parsefull() {
57157
57436
  var s0, s1, s2;
57158
57437
  s0 = peg$currPos;
57159
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c18) {
57438
+ if (input.substr(peg$currPos, 4).toLowerCase() === peg$c19) {
57160
57439
  s1 = input.substr(peg$currPos, 4);
57161
57440
  peg$currPos += 4;
57162
57441
  }
57163
57442
  else {
57164
57443
  s1 = peg$FAILED;
57165
57444
  if (peg$silentFails === 0) {
57166
- peg$fail(peg$e19);
57445
+ peg$fail(peg$e20);
57167
57446
  }
57168
57447
  }
57169
57448
  if (s1 !== peg$FAILED) {
57170
57449
  s2 = peg$parse_();
57171
57450
  if (s2 !== peg$FAILED) {
57172
57451
  peg$savedPos = s0;
57173
- s0 = peg$f18();
57452
+ s0 = peg$f19();
57174
57453
  }
57175
57454
  else {
57176
57455
  peg$currPos = s0;
@@ -57186,14 +57465,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57186
57465
  function peg$parsepriority() {
57187
57466
  var s0, s1, s2, s3;
57188
57467
  s0 = peg$currPos;
57189
- if (input.substr(peg$currPos, 1).toLowerCase() === peg$c19) {
57468
+ if (input.substr(peg$currPos, 1).toLowerCase() === peg$c20) {
57190
57469
  s1 = input.charAt(peg$currPos);
57191
57470
  peg$currPos++;
57192
57471
  }
57193
57472
  else {
57194
57473
  s1 = peg$FAILED;
57195
57474
  if (peg$silentFails === 0) {
57196
- peg$fail(peg$e20);
57475
+ peg$fail(peg$e21);
57197
57476
  }
57198
57477
  }
57199
57478
  if (s1 !== peg$FAILED) {
@@ -57202,7 +57481,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57202
57481
  s3 = peg$parse_();
57203
57482
  if (s3 !== peg$FAILED) {
57204
57483
  peg$savedPos = s0;
57205
- s0 = peg$f19(s2);
57484
+ s0 = peg$f20(s2);
57206
57485
  }
57207
57486
  else {
57208
57487
  peg$currPos = s0;
@@ -57223,14 +57502,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57223
57502
  function peg$parseremainder() {
57224
57503
  var s0, s1, s2, s3;
57225
57504
  s0 = peg$currPos;
57226
- if (input.substr(peg$currPos, 9).toLowerCase() === peg$c20) {
57505
+ if (input.substr(peg$currPos, 9).toLowerCase() === peg$c21) {
57227
57506
  s1 = input.substr(peg$currPos, 9);
57228
57507
  peg$currPos += 9;
57229
57508
  }
57230
57509
  else {
57231
57510
  s1 = peg$FAILED;
57232
57511
  if (peg$silentFails === 0) {
57233
- peg$fail(peg$e21);
57512
+ peg$fail(peg$e22);
57234
57513
  }
57235
57514
  }
57236
57515
  if (s1 !== peg$FAILED) {
@@ -57243,7 +57522,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57243
57522
  s3 = null;
57244
57523
  }
57245
57524
  peg$savedPos = s0;
57246
- s0 = peg$f20(s3);
57525
+ s0 = peg$f21(s3);
57247
57526
  }
57248
57527
  else {
57249
57528
  peg$currPos = s0;
@@ -57256,26 +57535,26 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57256
57535
  peg$silentFails++;
57257
57536
  s0 = [];
57258
57537
  if (input.charCodeAt(peg$currPos) === 32) {
57259
- s1 = peg$c21;
57538
+ s1 = peg$c22;
57260
57539
  peg$currPos++;
57261
57540
  }
57262
57541
  else {
57263
57542
  s1 = peg$FAILED;
57264
57543
  if (peg$silentFails === 0) {
57265
- peg$fail(peg$e23);
57544
+ peg$fail(peg$e24);
57266
57545
  }
57267
57546
  }
57268
57547
  if (s1 !== peg$FAILED) {
57269
57548
  while (s1 !== peg$FAILED) {
57270
57549
  s0.push(s1);
57271
57550
  if (input.charCodeAt(peg$currPos) === 32) {
57272
- s1 = peg$c21;
57551
+ s1 = peg$c22;
57273
57552
  peg$currPos++;
57274
57553
  }
57275
57554
  else {
57276
57555
  s1 = peg$FAILED;
57277
57556
  if (peg$silentFails === 0) {
57278
- peg$fail(peg$e23);
57557
+ peg$fail(peg$e24);
57279
57558
  }
57280
57559
  }
57281
57560
  }
@@ -57287,7 +57566,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57287
57566
  if (s0 === peg$FAILED) {
57288
57567
  s1 = peg$FAILED;
57289
57568
  if (peg$silentFails === 0) {
57290
- peg$fail(peg$e22);
57569
+ peg$fail(peg$e23);
57291
57570
  }
57292
57571
  }
57293
57572
  return s0;
@@ -57302,14 +57581,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57302
57581
  else {
57303
57582
  s0 = peg$FAILED;
57304
57583
  if (peg$silentFails === 0) {
57305
- peg$fail(peg$e25);
57584
+ peg$fail(peg$e26);
57306
57585
  }
57307
57586
  }
57308
57587
  peg$silentFails--;
57309
57588
  if (s0 === peg$FAILED) {
57310
57589
  s1 = peg$FAILED;
57311
57590
  if (peg$silentFails === 0) {
57312
- peg$fail(peg$e24);
57591
+ peg$fail(peg$e25);
57313
57592
  }
57314
57593
  }
57315
57594
  return s0;
@@ -57339,7 +57618,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57339
57618
  if (s0 === peg$FAILED) {
57340
57619
  s1 = peg$FAILED;
57341
57620
  if (peg$silentFails === 0) {
57342
- peg$fail(peg$e26);
57621
+ peg$fail(peg$e27);
57343
57622
  }
57344
57623
  }
57345
57624
  return s0;
@@ -57355,7 +57634,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57355
57634
  else {
57356
57635
  s2 = peg$FAILED;
57357
57636
  if (peg$silentFails === 0) {
57358
- peg$fail(peg$e27);
57637
+ peg$fail(peg$e28);
57359
57638
  }
57360
57639
  }
57361
57640
  if (s2 !== peg$FAILED) {
@@ -57367,7 +57646,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57367
57646
  else {
57368
57647
  s4 = peg$FAILED;
57369
57648
  if (peg$silentFails === 0) {
57370
- peg$fail(peg$e25);
57649
+ peg$fail(peg$e26);
57371
57650
  }
57372
57651
  }
57373
57652
  while (s4 !== peg$FAILED) {
@@ -57379,7 +57658,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57379
57658
  else {
57380
57659
  s4 = peg$FAILED;
57381
57660
  if (peg$silentFails === 0) {
57382
- peg$fail(peg$e25);
57661
+ peg$fail(peg$e26);
57383
57662
  }
57384
57663
  }
57385
57664
  }
@@ -57426,13 +57705,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57426
57705
  if (s5 !== peg$FAILED) {
57427
57706
  s6 = peg$currPos;
57428
57707
  if (input.charCodeAt(peg$currPos) === 46) {
57429
- s7 = peg$c22;
57708
+ s7 = peg$c23;
57430
57709
  peg$currPos++;
57431
57710
  }
57432
57711
  else {
57433
57712
  s7 = peg$FAILED;
57434
57713
  if (peg$silentFails === 0) {
57435
- peg$fail(peg$e29);
57714
+ peg$fail(peg$e30);
57436
57715
  }
57437
57716
  }
57438
57717
  if (s7 !== peg$FAILED) {
@@ -57478,7 +57757,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57478
57757
  }
57479
57758
  if (s3 !== peg$FAILED) {
57480
57759
  peg$savedPos = s0;
57481
- s0 = peg$f21(s3);
57760
+ s0 = peg$f22(s3);
57482
57761
  }
57483
57762
  else {
57484
57763
  peg$currPos = s0;
@@ -57488,25 +57767,70 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57488
57767
  if (s0 === peg$FAILED) {
57489
57768
  s1 = peg$FAILED;
57490
57769
  if (peg$silentFails === 0) {
57491
- peg$fail(peg$e28);
57770
+ peg$fail(peg$e29);
57492
57771
  }
57493
57772
  }
57494
57773
  return s0;
57495
57774
  }
57496
57775
  function peg$parsepercent() {
57497
- var s0, s1, s2, s3;
57776
+ var s0, s1, s2, s3, s4, s5, s6, s7;
57498
57777
  peg$silentFails++;
57499
57778
  s0 = peg$currPos;
57500
57779
  s1 = peg$currPos;
57501
- s2 = [];
57502
- s3 = peg$parsed();
57780
+ s2 = peg$currPos;
57781
+ s3 = [];
57782
+ s4 = peg$parsed();
57783
+ if (s4 !== peg$FAILED) {
57784
+ while (s4 !== peg$FAILED) {
57785
+ s3.push(s4);
57786
+ s4 = peg$parsed();
57787
+ }
57788
+ }
57789
+ else {
57790
+ s3 = peg$FAILED;
57791
+ }
57503
57792
  if (s3 !== peg$FAILED) {
57504
- while (s3 !== peg$FAILED) {
57505
- s2.push(s3);
57506
- s3 = peg$parsed();
57793
+ s4 = peg$currPos;
57794
+ if (input.charCodeAt(peg$currPos) === 46) {
57795
+ s5 = peg$c23;
57796
+ peg$currPos++;
57507
57797
  }
57798
+ else {
57799
+ s5 = peg$FAILED;
57800
+ if (peg$silentFails === 0) {
57801
+ peg$fail(peg$e30);
57802
+ }
57803
+ }
57804
+ if (s5 !== peg$FAILED) {
57805
+ s6 = [];
57806
+ s7 = peg$parsed();
57807
+ if (s7 !== peg$FAILED) {
57808
+ while (s7 !== peg$FAILED) {
57809
+ s6.push(s7);
57810
+ s7 = peg$parsed();
57811
+ }
57812
+ }
57813
+ else {
57814
+ s6 = peg$FAILED;
57815
+ }
57816
+ if (s6 === peg$FAILED) {
57817
+ s6 = null;
57818
+ }
57819
+ s5 = [s5, s6];
57820
+ s4 = s5;
57821
+ }
57822
+ else {
57823
+ peg$currPos = s4;
57824
+ s4 = peg$FAILED;
57825
+ }
57826
+ if (s4 === peg$FAILED) {
57827
+ s4 = null;
57828
+ }
57829
+ s3 = [s3, s4];
57830
+ s2 = s3;
57508
57831
  }
57509
57832
  else {
57833
+ peg$currPos = s2;
57510
57834
  s2 = peg$FAILED;
57511
57835
  }
57512
57836
  if (s2 !== peg$FAILED) {
@@ -57521,18 +57845,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57521
57845
  s2 = null;
57522
57846
  }
57523
57847
  if (input.charCodeAt(peg$currPos) === 37) {
57524
- s3 = peg$c23;
57848
+ s3 = peg$c24;
57525
57849
  peg$currPos++;
57526
57850
  }
57527
57851
  else {
57528
57852
  s3 = peg$FAILED;
57529
57853
  if (peg$silentFails === 0) {
57530
- peg$fail(peg$e31);
57854
+ peg$fail(peg$e32);
57531
57855
  }
57532
57856
  }
57533
57857
  if (s3 !== peg$FAILED) {
57534
57858
  peg$savedPos = s0;
57535
- s0 = peg$f22(s1);
57859
+ s0 = peg$f23(s1);
57536
57860
  }
57537
57861
  else {
57538
57862
  peg$currPos = s0;
@@ -57547,7 +57871,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57547
57871
  if (s0 === peg$FAILED) {
57548
57872
  s1 = peg$FAILED;
57549
57873
  if (peg$silentFails === 0) {
57550
- peg$fail(peg$e30);
57874
+ peg$fail(peg$e31);
57551
57875
  }
57552
57876
  }
57553
57877
  return s0;
@@ -57597,7 +57921,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57597
57921
  if (s0 === peg$FAILED) {
57598
57922
  s1 = peg$FAILED;
57599
57923
  if (peg$silentFails === 0) {
57600
- peg$fail(peg$e32);
57924
+ peg$fail(peg$e33);
57601
57925
  }
57602
57926
  }
57603
57927
  return s0;
@@ -57610,13 +57934,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57610
57934
  s2 = peg$parseyear();
57611
57935
  if (s2 !== peg$FAILED) {
57612
57936
  if (input.charCodeAt(peg$currPos) === 45) {
57613
- s3 = peg$c19;
57937
+ s3 = peg$c20;
57614
57938
  peg$currPos++;
57615
57939
  }
57616
57940
  else {
57617
57941
  s3 = peg$FAILED;
57618
57942
  if (peg$silentFails === 0) {
57619
- peg$fail(peg$e34);
57943
+ peg$fail(peg$e35);
57620
57944
  }
57621
57945
  }
57622
57946
  if (s3 !== peg$FAILED) {
@@ -57656,7 +57980,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57656
57980
  if (s0 === peg$FAILED) {
57657
57981
  s1 = peg$FAILED;
57658
57982
  if (peg$silentFails === 0) {
57659
- peg$fail(peg$e33);
57983
+ peg$fail(peg$e34);
57660
57984
  }
57661
57985
  }
57662
57986
  return s0;
@@ -57692,7 +58016,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57692
58016
  if (s0 === peg$FAILED) {
57693
58017
  s1 = peg$FAILED;
57694
58018
  if (peg$silentFails === 0) {
57695
- peg$fail(peg$e35);
58019
+ peg$fail(peg$e36);
57696
58020
  }
57697
58021
  }
57698
58022
  return s0;
@@ -57704,13 +58028,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57704
58028
  s2 = peg$parsemonth();
57705
58029
  if (s2 !== peg$FAILED) {
57706
58030
  if (input.charCodeAt(peg$currPos) === 45) {
57707
- s3 = peg$c19;
58031
+ s3 = peg$c20;
57708
58032
  peg$currPos++;
57709
58033
  }
57710
58034
  else {
57711
58035
  s3 = peg$FAILED;
57712
58036
  if (peg$silentFails === 0) {
57713
- peg$fail(peg$e34);
58037
+ peg$fail(peg$e35);
57714
58038
  }
57715
58039
  }
57716
58040
  if (s3 !== peg$FAILED) {
@@ -57752,12 +58076,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57752
58076
  else {
57753
58077
  s1 = peg$FAILED;
57754
58078
  if (peg$silentFails === 0) {
57755
- peg$fail(peg$e37);
58079
+ peg$fail(peg$e38);
57756
58080
  }
57757
58081
  }
57758
58082
  if (s1 !== peg$FAILED) {
57759
58083
  peg$savedPos = peg$currPos;
57760
- s2 = peg$f23(s1);
58084
+ s2 = peg$f24(s1);
57761
58085
  if (s2) {
57762
58086
  s2 = undefined;
57763
58087
  }
@@ -57781,7 +58105,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57781
58105
  if (s0 === peg$FAILED) {
57782
58106
  s1 = peg$FAILED;
57783
58107
  if (peg$silentFails === 0) {
57784
- peg$fail(peg$e36);
58108
+ peg$fail(peg$e37);
57785
58109
  }
57786
58110
  }
57787
58111
  return s0;
@@ -57798,7 +58122,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57798
58122
  else {
57799
58123
  s2 = peg$FAILED;
57800
58124
  if (peg$silentFails === 0) {
57801
- peg$fail(peg$e39);
58125
+ peg$fail(peg$e40);
57802
58126
  }
57803
58127
  }
57804
58128
  if (s2 !== peg$FAILED) {
@@ -57811,7 +58135,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57811
58135
  else {
57812
58136
  s2 = peg$FAILED;
57813
58137
  if (peg$silentFails === 0) {
57814
- peg$fail(peg$e39);
58138
+ peg$fail(peg$e40);
57815
58139
  }
57816
58140
  }
57817
58141
  }
@@ -57829,7 +58153,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57829
58153
  if (s0 === peg$FAILED) {
57830
58154
  s1 = peg$FAILED;
57831
58155
  if (peg$silentFails === 0) {
57832
- peg$fail(peg$e38);
58156
+ peg$fail(peg$e39);
57833
58157
  }
57834
58158
  }
57835
58159
  return s0;